From 049a3e3d0cda2ceece1650e3809e7148fc365e9d Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Mon, 4 Jun 2018 12:04:41 +0000 Subject: [PATCH 0001/1023] [clang][tooling] Don't forget to link to clangToolingInclusions. Fixes build with shared libs, broken by rL333874. Some buildbot converage is sorely missing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333890 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Tooling/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt index 24feccc5c4..e9910fb87a 100644 --- a/unittests/Tooling/CMakeLists.txt +++ b/unittests/Tooling/CMakeLists.txt @@ -62,5 +62,6 @@ target_link_libraries(ToolingTests clangRewrite clangTooling clangToolingCore + clangToolingInclusions clangToolingRefactor ) -- GitLab From 9aed45542a597d01c4dcd48ced335ba28bb6063d Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Mon, 4 Jun 2018 14:25:58 +0000 Subject: [PATCH 0002/1023] Created a tiny SMT interface and make Z3ConstraintManager implement it Summary: This patch implements a simple SMTConstraintManager API, and requires the implementation of two methods for now: `addRangeConstraints` and `isModelFeasible`. Update Z3ConstraintManager to inherit it and implement required methods. I also moved the method to dump the SMT formula from D45517 to this patch. This patch was created based on the reviews from D47640. Reviewers: george.karpenkov, NoQ, ddcc, dcoughlin Reviewed By: george.karpenkov Differential Revision: https://reviews.llvm.org/D47689 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333899 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTConstraintManager.h | 43 +++++++++++++ .../Core/Z3ConstraintManager.cpp | 61 ++++++++++++++++++- 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h new file mode 100644 index 0000000000..277f25d2c5 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -0,0 +1,43 @@ +//== SMTConstraintManager.h -------------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a SMT generic API, which will be the base class for +// every SMT solver specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" + +namespace clang { +namespace ento { + +class SMTConstraintManager : public clang::ento::SimpleConstraintManager { + +public: + SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB) + : SimpleConstraintManager(SE, SB) {} + virtual ~SMTConstraintManager() = default; + + /// Converts the ranged constraints of a set of symbols to SMT + /// + /// \param CR The set of constraints. + virtual void addRangeConstraints(clang::ento::ConstraintRangeTy CR) = 0; + + /// Checks if the added constraints are satisfiable + virtual clang::ento::ConditionTruthVal isModelFeasible() = 0; + +}; // end class SMTConstraintManager + +} // namespace ento +} // namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index efc57a0b09..a9f67fc124 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -10,7 +10,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" #include "clang/Config/config.h" @@ -880,6 +880,12 @@ public: /// Reset the solver and remove all constraints. void reset() { Z3_solver_reset(Z3Context::ZC, Solver); } + + void print(raw_ostream &OS) const { + OS << Z3_solver_to_string(Z3Context::ZC, Solver); + } + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Solver void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) { @@ -887,16 +893,23 @@ void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) { llvm::Twine(Z3_get_error_msg_ex(Context, Error))); } -class Z3ConstraintManager : public SimpleConstraintManager { +class Z3ConstraintManager : public SMTConstraintManager { Z3Context Context; mutable Z3Solver Solver; public: Z3ConstraintManager(SubEngine *SE, SValBuilder &SB) - : SimpleConstraintManager(SE, SB), + : SMTConstraintManager(SE, SB), Solver(Z3_mk_simple_solver(Z3Context::ZC)) { Z3_set_error_handler(Z3Context::ZC, Z3ErrorHandler); } + //===------------------------------------------------------------------===// + // Implementation for Refutation. + //===------------------------------------------------------------------===// + + void addRangeConstraints(clang::ento::ConstraintRangeTy CR) override; + + ConditionTruthVal isModelFeasible() override; //===------------------------------------------------------------------===// // Implementation for interface from ConstraintManager. @@ -1242,6 +1255,48 @@ Z3ConstraintManager::removeDeadBindings(ProgramStateRef State, return State->set(CZ); } +void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { + for (const auto &I : CR) { + SymbolRef Sym = I.first; + + Z3Expr Constraints = Z3Expr::fromBoolean(false); + + for (const auto &Range : I.second) { + const llvm::APSInt &From = Range.From(); + const llvm::APSInt &To = Range.To(); + + QualType FromTy; + llvm::APSInt NewFromInt; + std::tie(NewFromInt, FromTy) = fixAPSInt(From); + Z3Expr FromExp = Z3Expr::fromAPSInt(NewFromInt); + QualType SymTy; + Z3Expr Exp = getZ3Expr(Sym, &SymTy); + bool IsSignedTy = SymTy->isSignedIntegerOrEnumerationType(); + QualType ToTy; + llvm::APSInt NewToInt; + std::tie(NewToInt, ToTy) = fixAPSInt(To); + Z3Expr ToExp = Z3Expr::fromAPSInt(NewToInt); + assert(FromTy == ToTy && "Range values have different types!"); + + Z3Expr LHS = + getZ3BinExpr(Exp, SymTy, BO_GE, FromExp, FromTy, /*RetTy=*/nullptr); + Z3Expr RHS = + getZ3BinExpr(Exp, SymTy, BO_LE, ToExp, FromTy, /*RetTy=*/nullptr); + Z3Expr SymRange = Z3Expr::fromBinOp(LHS, BO_LAnd, RHS, IsSignedTy); + Constraints = + Z3Expr::fromBinOp(Constraints, BO_LOr, SymRange, IsSignedTy); + } + Solver.addConstraint(Constraints); + } +} + +clang::ento::ConditionTruthVal Z3ConstraintManager::isModelFeasible() { + if (Solver.check() == Z3_L_FALSE) + return false; + + return ConditionTruthVal(); +} + //===------------------------------------------------------------------===// // Internal implementation. //===------------------------------------------------------------------===// -- GitLab From 9f72894e31a3b8c5042f221ace91727a81391d80 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Mon, 4 Jun 2018 14:40:44 +0000 Subject: [PATCH 0003/1023] [analyzer] False positive refutation with Z3 Summary: This is a prototype of a bug reporter visitor that invalidates bug reports by re-checking constraints of certain states on the bug path using the Z3 constraint manager backend. The functionality is available under the `crosscheck-with-z3` analyzer config flag. Reviewers: george.karpenkov, NoQ, dcoughlin, rnkovacs Reviewed By: george.karpenkov Subscribers: rnkovacs, NoQ, george.karpenkov, dcoughlin, xbolva00, ddcc, mikhail.ramalho, MTC, fhahn, whisperity, baloghadamsoftware, szepet, a.sidorin, gsd, dkrupp, xazax.hun, cfe-commits Differential Revision: https://reviews.llvm.org/D45517 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333903 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../StaticAnalyzer/Core/AnalyzerOptions.h | 10 ++++ .../Core/BugReporter/BugReporterVisitors.h | 22 ++++++++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 6 +++ lib/StaticAnalyzer/Core/BugReporter.cpp | 7 ++- .../Core/BugReporterVisitors.cpp | 44 ++++++++++++++++ test/Analysis/z3-crosscheck.c | 51 +++++++++++++++++++ 6 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 test/Analysis/z3-crosscheck.c diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 08c3365d19..a3f4c38944 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -280,6 +280,9 @@ private: /// \sa shouldSuppressFromCXXStandardLibrary Optional SuppressFromCXXStandardLibrary; + /// \sa shouldCrosscheckWithZ3 + Optional CrosscheckWithZ3; + /// \sa reportIssuesInMainSourceFile Optional ReportIssuesInMainSourceFile; @@ -575,6 +578,13 @@ public: /// which accepts the values "true" and "false". bool shouldSuppressFromCXXStandardLibrary(); + /// Returns whether bug reports should be crosschecked with the Z3 + /// constraint manager backend. + /// + /// This is controlled by the 'crosscheck-with-z3' config option, + /// which accepts the values "true" and "false". + bool shouldCrosscheckWithZ3(); + /// Returns whether or not the diagnostic report should be always reported /// in the main source file and not the headers. /// diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 2f53d6faab..80a6763783 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/STLExtras.h" @@ -359,6 +360,27 @@ public: BugReport &BR) override; }; +/// The bug visitor will walk all the nodes in a path and collect all the +/// constraints. When it reaches the root node, will create a refutation +/// manager and check if the constraints are satisfiable +class FalsePositiveRefutationBRVisitor final + : public BugReporterVisitorImpl { +private: + /// Holds the constraints in a given path + // TODO: should we use a set? + llvm::SmallVector Constraints; + +public: + FalsePositiveRefutationBRVisitor() = default; + + void Profile(llvm::FoldingSetNodeID &ID) const override; + + std::shared_ptr VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; +}; + namespace bugreporter { /// Attempts to add visitors to trace a null or undefined value back to its diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 33e482dd40..bddd4435a7 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -296,6 +296,12 @@ bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() { /* Default = */ true); } +bool AnalyzerOptions::shouldCrosscheckWithZ3() { + return getBooleanOption(CrosscheckWithZ3, + "crosscheck-with-z3", + /* Default = */ false); +} + bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() { return getBooleanOption(ReportIssuesInMainSourceFile, "report-in-main-source-file", diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 91d601b360..854e405fb9 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -3143,10 +3143,15 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); const ExplodedNode *N = ErrorGraph.ErrorNode; + // Register refutation visitors first, if they mark the bug invalid no + // further analysis is required + R->addVisitor(llvm::make_unique()); + if (getAnalyzerOptions().shouldCrosscheckWithZ3()) + R->addVisitor(llvm::make_unique()); + // Register additional node visitors. R->addVisitor(llvm::make_unique()); R->addVisitor(llvm::make_unique()); - R->addVisitor(llvm::make_unique()); R->addVisitor(llvm::make_unique()); BugReport::VisitorList visitors; diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 5d11dcd570..fe1a711a82 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -44,6 +44,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -2354,3 +2355,46 @@ TaintBugVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, return std::make_shared(L, "Taint originated here"); } + +static bool +areConstraintsUnfeasible(BugReporterContext &BRC, + const llvm::SmallVector &Cs) { + // Create a refutation manager + std::unique_ptr RefutationMgr = CreateZ3ConstraintManager( + BRC.getStateManager(), BRC.getStateManager().getOwningEngine()); + + SMTConstraintManager *SMTRefutationMgr = + static_cast(RefutationMgr.get()); + + // Add constraints to the solver + for (const auto &C : Cs) + SMTRefutationMgr->addRangeConstraints(C); + + // And check for satisfiability + return SMTRefutationMgr->isModelFeasible().isConstrainedFalse(); +} + +std::shared_ptr +FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) { + // Collect the constraint for the current state + const ConstraintRangeTy &CR = N->getState()->get(); + Constraints.push_back(CR); + + // If there are no predecessor, we reached the root node. In this point, + // a new refutation manager will be created and the path will be checked + // for reachability + if (PrevN->pred_size() == 0 && areConstraintsUnfeasible(BRC, Constraints)) { + BR.markInvalid("Infeasible constraints", N->getLocationContext()); + } + + return nullptr; +} + +void FalsePositiveRefutationBRVisitor::Profile( + llvm::FoldingSetNodeID &ID) const { + static int Tag = 0; + ID.AddPointer(&Tag); +} diff --git a/test/Analysis/z3-crosscheck.c b/test/Analysis/z3-crosscheck.c new file mode 100644 index 0000000000..66f778de8a --- /dev/null +++ b/test/Analysis/z3-crosscheck.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -DNO_CROSSCHECK -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config crosscheck-with-z3=true -verify %s +// REQUIRES: z3 + +int foo(int x) +{ + int *z = 0; + if ((x & 1) && ((x & 1) ^ 1)) +#ifdef NO_CROSSCHECK + return *z; // expected-warning {{Dereference of null pointer (loaded from variable 'z')}} +#else + return *z; // no-warning +#endif + return 0; +} + +void g(int d); + +void f(int *a, int *b) { + int c = 5; + if ((a - b) == 0) + c = 0; + if (a != b) +#ifdef NO_CROSSCHECK + g(3 / c); // expected-warning {{Division by zero}} +#else + g(3 / c); // no-warning +#endif +} + +_Bool nondet_bool(); + +void h(int d) { + int x, y, k, z = 1; +#ifdef NO_CROSSCHECK + while (z < k) { // expected-warning {{The right operand of '<' is a garbage value}} +#else + while (z < k) { // expected-warning {{The right operand of '<' is a garbage value}} +#endif + z = 2 * z; + } +} + +void i() { + _Bool c = nondet_bool(); + if (c) { + h(1); + } else { + h(2); + } +} -- GitLab From e59be5df58ccbd518855bcd3e3216e744b7071e9 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Mon, 4 Jun 2018 16:07:52 +0000 Subject: [PATCH 0004/1023] This diff includes changes for supporting the following types. // Primary fixed point types signed short _Accum s_short_accum; signed _Accum s_accum; signed long _Accum s_long_accum; unsigned short _Accum u_short_accum; unsigned _Accum u_accum; unsigned long _Accum u_long_accum; // Aliased fixed point types short _Accum short_accum; _Accum accum; long _Accum long_accum; This diff only allows for declaration of the fixed point types. Assignment and other operations done on fixed point types according to http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf will be added in future patches. The saturated versions of these types and the equivalent _Fract types will also be added in future patches. The tests included are for asserting that we can declare these types. Fixed the test that was failing by not checking for dso_local on some targets. Differential Revision: https://reviews.llvm.org/D46084 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333923 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 8 ++- include/clang/AST/ASTContext.h | 3 ++ include/clang/AST/BuiltinTypes.def | 20 +++++++ include/clang/Basic/DiagnosticCommonKinds.td | 2 + include/clang/Basic/LangOptions.def | 2 + include/clang/Basic/Specifiers.h | 1 + include/clang/Basic/TargetInfo.h | 18 +++++++ include/clang/Basic/TokenKinds.def | 3 ++ include/clang/Driver/Options.td | 5 ++ include/clang/Sema/DeclSpec.h | 1 + include/clang/Serialization/ASTBitCodes.h | 18 +++++++ lib/AST/ASTContext.cpp | 29 ++++++++++ lib/AST/ExprConstant.cpp | 5 ++ lib/AST/ItaniumMangle.cpp | 7 +++ lib/AST/MicrosoftMangle.cpp | 6 +++ lib/AST/NSAPI.cpp | 6 +++ lib/AST/Type.cpp | 12 +++++ lib/AST/TypeLoc.cpp | 6 +++ lib/Analysis/PrintfFormatString.cpp | 6 +++ lib/Basic/TargetInfo.cpp | 3 ++ lib/CodeGen/CGDebugInfo.cpp | 10 ++++ lib/CodeGen/CodeGenTypes.cpp | 6 +++ lib/CodeGen/ItaniumCXXABI.cpp | 6 +++ lib/Driver/ToolChains/Clang.cpp | 5 ++ lib/Frontend/CompilerInvocation.cpp | 5 ++ lib/Index/USRGeneration.cpp | 6 +++ lib/Parse/ParseDecl.cpp | 13 +++++ lib/Sema/DeclSpec.cpp | 15 ++++-- lib/Sema/SemaTemplateVariadic.cpp | 1 + lib/Sema/SemaType.cpp | 33 ++++++++++++ lib/Serialization/ASTCommon.cpp | 18 +++++++ lib/Serialization/ASTReader.cpp | 18 +++++++ test/Frontend/fixed_point.c | 57 ++++++++++++++++++++ test/Frontend/fixed_point_bit_widths.c | 46 ++++++++++++++++ test/Frontend/fixed_point_errors.c | 27 ++++++++++ test/Frontend/fixed_point_errors.cpp | 5 ++ test/Frontend/fixed_point_not_enabled.c | 15 ++++++ tools/libclang/CXType.cpp | 12 +++++ 38 files changed, 453 insertions(+), 6 deletions(-) create mode 100644 test/Frontend/fixed_point.c create mode 100644 test/Frontend/fixed_point_bit_widths.c create mode 100644 test/Frontend/fixed_point_errors.c create mode 100644 test/Frontend/fixed_point_errors.cpp create mode 100644 test/Frontend/fixed_point_not_enabled.c diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index ff14d6e729..0973783a45 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -3182,8 +3182,14 @@ enum CXTypeKind { CXType_Float128 = 30, CXType_Half = 31, CXType_Float16 = 32, + CXType_ShortAccum = 33, + CXType_Accum = 34, + CXType_LongAccum = 35, + CXType_UShortAccum = 36, + CXType_UAccum = 37, + CXType_ULongAccum = 38, CXType_FirstBuiltin = CXType_Void, - CXType_LastBuiltin = CXType_Float16, + CXType_LastBuiltin = CXType_ULongAccum, CXType_Complex = 100, CXType_Pointer = 101, diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index d70e455a5a..64160ebbac 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1007,6 +1007,9 @@ public: CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; + CanQualType ShortAccumTy, AccumTy, + LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension + CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index 4d4ed79220..b2fa49828a 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -122,6 +122,26 @@ SIGNED_TYPE(LongLong, LongLongTy) // '__int128_t' SIGNED_TYPE(Int128, Int128Ty) +//===- Fixed point types --------------------------------------------------===// + +// 'short _Accum' +SIGNED_TYPE(ShortAccum, ShortAccumTy) + +// '_Accum' +SIGNED_TYPE(Accum, AccumTy) + +// 'long _Accum' +SIGNED_TYPE(LongAccum, LongAccumTy) + +// 'unsigned short _Accum' +UNSIGNED_TYPE(UShortAccum, UnsignedShortAccumTy) + +// 'unsigned _Accum' +UNSIGNED_TYPE(UAccum, UnsignedAccumTy) + +// 'unsigned long _Accum' +UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy) + //===- Floating point types -----------------------------------------------===// // 'half' in OpenCL, '__fp16' in ARM NEON. diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 56c735a4b6..93f262361c 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -168,6 +168,8 @@ def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">, InGroup; def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">, InGroup; +def err_fixed_point_not_enabled : Error<"compile with " + "'-ffixed-point' to enable fixed point types">; // SEH def err_seh_expected_handler : Error< diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 8605286f28..6bd8958e36 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -302,6 +302,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions") +LANGOPT(FixedPoint, 1, 0, "fixed point types") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index ee57fc47fd..231b92ab79 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -54,6 +54,7 @@ namespace clang { TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 TST_Float16, // C11 extension ISO/IEC TS 18661-3 + TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension TST_float, TST_double, TST_float128, diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index b8e45e64d5..08e33f58f5 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -74,6 +74,9 @@ protected: unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; + unsigned char ShortAccumWidth, ShortAccumAlign; + unsigned char AccumWidth, AccumAlign; + unsigned char LongAccumWidth, LongAccumAlign; unsigned char SuitableAlign; unsigned char DefaultAlignForAttributeAligned; unsigned char MinGlobalAlign; @@ -358,6 +361,21 @@ public: unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } + /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and + /// 'unsigned short _Accum' for this target, in bits. + unsigned getShortAccumWidth() const { return ShortAccumWidth; } + unsigned getShortAccumAlign() const { return ShortAccumAlign; } + + /// getAccumWidth/Align - Return the size of 'signed _Accum' and + /// 'unsigned _Accum' for this target, in bits. + unsigned getAccumWidth() const { return AccumWidth; } + unsigned getAccumAlign() const { return AccumAlign; } + + /// getLongAccumWidth/Align - Return the size of 'signed long _Accum' and + /// 'unsigned long _Accum' for this target, in bits. + unsigned getLongAccumWidth() const { return LongAccumWidth; } + unsigned getLongAccumAlign() const { return LongAccumAlign; } + /// Determine whether the __int128 type is supported on this target. virtual bool hasInt128Type() const { return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index cc717f6128..867b8abfea 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -389,6 +389,9 @@ KEYWORD(char8_t , CHAR8SUPPORT) // C11 Extension KEYWORD(_Float16 , KEYALL) +// ISO/IEC JTC1 SC22 WG14 N1169 Extension +KEYWORD(_Accum , KEYNOCXX) + // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) KEYWORD(_Decimal64 , KEYALL) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 94a5310fba..093706f279 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -887,6 +887,11 @@ def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">, Group, Flags<[CC1Option]>, HelpText<"Disable support for int128_t type">; +def ffixed_point : Flag<["-"], "ffixed-point">, Group, + Flags<[CC1Option]>, HelpText<"Enable fixed point types">; +def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group, + HelpText<"Disable fixed point types">; + // Begin sanitizer flags. These should all be core options exposed in all driver // modes. let Flags = [CC1Option, CoreOption] in { diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 4ae317bafd..50881426fd 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -282,6 +282,7 @@ public: static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; static const TST TST_float16 = clang::TST_Float16; + static const TST TST_accum = clang::TST_Accum; static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 4ddffe1192..24bdb644de 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -939,6 +939,24 @@ namespace serialization { /// The C++ 'char8_t' type. PREDEF_TYPE_CHAR8_ID = 45, + /// \brief The 'short _Accum' type + PREDEF_TYPE_SHORT_ACCUM_ID = 46, + + /// \brief The '_Accum' type + PREDEF_TYPE_ACCUM_ID = 47, + + /// \brief The 'long _Accum' type + PREDEF_TYPE_LONG_ACCUM_ID = 48, + + /// \brief The 'unsigned short _Accum' type + PREDEF_TYPE_USHORT_ACCUM_ID = 49, + + /// \brief The 'unsigned _Accum' type + PREDEF_TYPE_UACCUM_ID = 50, + + /// \brief The 'unsigned long _Accum' type + PREDEF_TYPE_ULONG_ACCUM_ID = 51, + /// OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2eec05c439..4956710b4f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1134,6 +1134,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // C11 extension ISO/IEC TS 18661-3 InitBuiltinType(Float16Ty, BuiltinType::Float16); + // ISO/IEC JTC1 SC22 WG14 N1169 Extension + InitBuiltinType(ShortAccumTy, BuiltinType::ShortAccum); + InitBuiltinType(AccumTy, BuiltinType::Accum); + InitBuiltinType(LongAccumTy, BuiltinType::LongAccum); + InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum); + InitBuiltinType(UnsignedAccumTy, BuiltinType::UAccum); + InitBuiltinType(UnsignedLongAccumTy, BuiltinType::ULongAccum); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1785,6 +1793,21 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = 128; Align = 128; // int128_t is 128-bit aligned on all targets. break; + case BuiltinType::ShortAccum: + case BuiltinType::UShortAccum: + Width = Target->getShortAccumWidth(); + Align = Target->getShortAccumAlign(); + break; + case BuiltinType::Accum: + case BuiltinType::UAccum: + Width = Target->getAccumWidth(); + Align = Target->getAccumAlign(); + break; + case BuiltinType::LongAccum: + case BuiltinType::ULongAccum: + Width = Target->getLongAccumWidth(); + Align = Target->getLongAccumAlign(); + break; case BuiltinType::Float16: case BuiltinType::Half: Width = Target->getHalfWidth(); @@ -6222,6 +6245,12 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: // FIXME: potentially need @encodes for these! return ' '; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7140537915..590ebba997 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -7355,6 +7355,11 @@ EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { case BuiltinType::UInt128: return GCCTypeClass::Integer; + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + return GCCTypeClass::None; + case BuiltinType::NullPtr: case BuiltinType::ObjCId: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 1a656b5719..80b91dca7f 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2552,6 +2552,13 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Float16: Out << "DF16_"; break; + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + llvm_unreachable("Fixed point types are disabled for c++"); case BuiltinType::Half: Out << "Dh"; break; diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index f7b80d5b27..e947479196 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1926,6 +1926,12 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, mangleArtificalTagType(TTK_Struct, "_Half", {"__clang"}); break; + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: case BuiltinType::Char8: case BuiltinType::Float128: { DiagnosticsEngine &Diags = Context.getDiags(); diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index 030f2a0c9c..d61638e54a 100644 --- a/lib/AST/NSAPI.cpp +++ b/lib/AST/NSAPI.cpp @@ -441,6 +441,12 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::Char32: case BuiltinType::Int128: case BuiltinType::LongDouble: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: case BuiltinType::UInt128: case BuiltinType::Float16: case BuiltinType::Float128: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 065a77aa50..6615ea88b6 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2656,6 +2656,18 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "double"; case LongDouble: return "long double"; + case ShortAccum: + return "short _Accum"; + case Accum: + return "_Accum"; + case LongAccum: + return "long _Accum"; + case UShortAccum: + return "unsigned short _Accum"; + case UAccum: + return "unsigned _Accum"; + case ULongAccum: + return "unsigned long _Accum"; case Float16: return "_Float16"; case Float128: diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index dc325427b9..1aa7b5a3cd 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -344,6 +344,12 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::LongDouble: case BuiltinType::Float16: case BuiltinType::Float128: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 2043970ccd..5884d33136 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -655,6 +655,12 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, case BuiltinType::Half: case BuiltinType::Float16: case BuiltinType::Float128: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: // Various types which are non-trivial to correct. return false; diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index bacd85bc55..bf36effbe3 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -40,6 +40,9 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; + ShortAccumWidth = ShortAccumAlign = 16; + AccumWidth = AccumAlign = 32; + LongAccumWidth = LongAccumAlign = 64; SuitableAlign = 64; DefaultAlignForAttributeAligned = 128; MinGlobalAlign = 0; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 9e99a646b0..db6a82b415 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -702,6 +702,16 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { // floating point types of the same size. Encoding = llvm::dwarf::DW_ATE_float; break; + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + Encoding = llvm::dwarf::DW_ATE_signed_fixed; + break; + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + Encoding = llvm::dwarf::DW_ATE_unsigned_fixed; + break; } switch (BT->getKind()) { diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index ce1fdf9b12..c1ff9d2846 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -440,6 +440,12 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case BuiltinType::Char8: case BuiltinType::Char16: case BuiltinType::Char32: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: ResultType = llvm::IntegerType::get(getLLVMContext(), static_cast(Context.getTypeSize(T))); break; diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 3e2c461d6a..d84a10c6ba 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -2724,6 +2724,12 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLReserveID: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: return false; case BuiltinType::Dependent: diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 2347cfebf0..afcf45d9f8 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3756,6 +3756,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors); Args.AddLastArg(CmdArgs, options::OPT_w); + // Fixed point flags + if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point, + /*Default=*/false)) + Args.AddLastArg(CmdArgs, options::OPT_ffixed_point); + // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b5396dd758..46f8c9f235 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2333,6 +2333,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); + // -ffixed-point + Opts.FixedPoint = + Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) && + !Opts.CPlusPlus; + // Handle exception personalities Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp index ba536c748c..9c9600188f 100644 --- a/lib/Index/USRGeneration.cpp +++ b/lib/Index/USRGeneration.cpp @@ -709,6 +709,12 @@ void USRGenerator::VisitType(QualType T) { case BuiltinType::OCLQueue: case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: IgnoreResults = true; return; case BuiltinType::ObjCId: diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 456214f066..2b9c4afaaf 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3580,6 +3580,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Accum: + if (!getLangOpts().FixedPoint) { + DiagID = diag::err_fixed_point_not_enabled; + PrevSpec = ""; // Not used by diagnostic + isInvalid = true; + } else { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, + DiagID, Policy); + } + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -4606,6 +4616,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4683,6 +4694,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4841,6 +4853,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index dd2476ec37..aa5f197b54 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -339,6 +339,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_decimal32: case TST_decimal64: case TST_double: + case TST_Accum: case TST_Float16: case TST_float128: case TST_enum: @@ -510,6 +511,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_accum: return "_Accum"; case DeclSpec::TST_float16: return "_Float16"; case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; @@ -1100,12 +1102,13 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { } } - // signed/unsigned are only valid with int/char/wchar_t. + // signed/unsigned are only valid with int/char/wchar_t/_Accum. if (TypeSpecSign != TSS_unspecified) { if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. - else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && - TypeSpecType != TST_char && TypeSpecType != TST_wchar) { + else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && + TypeSpecType != TST_char && TypeSpecType != TST_wchar && + TypeSpecType != TST_accum) { S.Diag(TSSLoc, diag::err_invalid_sign_spec) << getSpecifierName((TST)TypeSpecType, Policy); // signed double -> double. @@ -1120,7 +1123,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { case TSW_longlong: // long long int if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. - else if (TypeSpecType != TST_int) { + else if (!(TypeSpecType == TST_int || + (TypeSpecType == TST_accum && TypeSpecWidth != TSW_longlong))) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; @@ -1130,7 +1134,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { case TSW_long: // long double, long int if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. - else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { + else if (TypeSpecType != TST_int && TypeSpecType != TST_double && + TypeSpecType != TST_accum) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index c58e648bb3..dc67c8ef19 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -830,6 +830,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_half: case TST_float: case TST_double: + case TST_Accum: case TST_Float16: case TST_float128: case TST_bool: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 6839dd7de2..ac85e016ba 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1391,6 +1391,39 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; } + case DeclSpec::TST_accum: { + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.ShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.AccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.LongAccumTy; + break; + case DeclSpec::TSW_longlong: + // Unreachable b/c this is caught in final analysis of the DeclSpec. + llvm_unreachable("Unable to specify long long as _Accum width"); + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.UnsignedShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.UnsignedAccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.UnsignedLongAccumTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable("Unable to specify long long as _Accum width"); + } + } + break; + } case DeclSpec::TST_int128: if (!S.Context.getTargetInfo().hasInt128Type()) S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index 54cea92042..f5584cc04d 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -91,6 +91,24 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; + case BuiltinType::ShortAccum: + ID = PREDEF_TYPE_SHORT_ACCUM_ID; + break; + case BuiltinType::Accum: + ID = PREDEF_TYPE_ACCUM_ID; + break; + case BuiltinType::LongAccum: + ID = PREDEF_TYPE_LONG_ACCUM_ID; + break; + case BuiltinType::UShortAccum: + ID = PREDEF_TYPE_USHORT_ACCUM_ID; + break; + case BuiltinType::UAccum: + ID = PREDEF_TYPE_UACCUM_ID; + break; + case BuiltinType::ULongAccum: + ID = PREDEF_TYPE_ULONG_ACCUM_ID; + break; case BuiltinType::Float16: ID = PREDEF_TYPE_FLOAT16_ID; break; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 391e350445..4dd7972027 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6819,6 +6819,24 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; + case PREDEF_TYPE_SHORT_ACCUM_ID: + T = Context.ShortAccumTy; + break; + case PREDEF_TYPE_ACCUM_ID: + T = Context.AccumTy; + break; + case PREDEF_TYPE_LONG_ACCUM_ID: + T = Context.LongAccumTy; + break; + case PREDEF_TYPE_USHORT_ACCUM_ID: + T = Context.UnsignedShortAccumTy; + break; + case PREDEF_TYPE_UACCUM_ID: + T = Context.UnsignedAccumTy; + break; + case PREDEF_TYPE_ULONG_ACCUM_ID: + T = Context.UnsignedLongAccumTy; + break; case PREDEF_TYPE_FLOAT16_ID: T = Context.Float16Ty; break; diff --git a/test/Frontend/fixed_point.c b/test/Frontend/fixed_point.c new file mode 100644 index 0000000000..d64bd55aa0 --- /dev/null +++ b/test/Frontend/fixed_point.c @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -x c -ffixed-point -ast-dump %s | FileCheck %s --strict-whitespace + +/* Various contexts where type _Accum can appear. */ + +// Primary fixed point types +signed short _Accum s_short_accum; +signed _Accum s_accum; +signed long _Accum s_long_accum; +unsigned short _Accum u_short_accum; +unsigned _Accum u_accum; +unsigned long _Accum u_long_accum; + +// Aliased fixed point types +short _Accum short_accum; +_Accum accum; +long _Accum long_accum; + +// CHECK: |-VarDecl {{.*}} s_short_accum 'short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum' +// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum' +// CHECK-NEXT: |-VarDecl {{.*}} long_accum 'long _Accum' + +#define MIX_TYPE_SPEC(SPEC, SIGN, SIZE, ID) \ + SPEC SIGN SIZE _Accum ID; \ + SIGN SPEC SIZE _Accum ID ## 2; \ + SIGN SIZE SPEC _Accum ID ## 3; \ + SIGN SIZE _Accum SPEC ID ## 4; + +/* Mixing fixed point types with other type specifiers */ + +#define MIX_VOLATILE(SIGN, SIZE, ID) MIX_TYPE_SPEC(volatile, SIGN, SIZE, ID) +#define MIX_ATOMIC(SIGN, SIZE, ID) MIX_TYPE_SPEC(_Atomic, SIGN, SIZE, ID) +#define MIX_CONST(SIGN, SIZE, ID) MIX_TYPE_SPEC(const, SIGN, SIZE, ID) + +MIX_VOLATILE(signed, short, vol_s_short_accum) +MIX_ATOMIC(signed, short, atm_s_short_accum) +MIX_CONST(signed, short, const_s_short_accum) + +// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum 'volatile short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum2 'volatile short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum3 'volatile short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} vol_s_short_accum4 'volatile short _Accum' + +// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum '_Atomic(short _Accum)' +// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum2 '_Atomic(short _Accum)' +// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum3 '_Atomic(short _Accum)' +// CHECK-NEXT: |-VarDecl {{.*}} atm_s_short_accum4 '_Atomic(short _Accum)' + +// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum 'const short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum2 'const short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum3 'const short _Accum' +// CHECK-NEXT: `-VarDecl {{.*}} const_s_short_accum4 'const short _Accum' diff --git a/test/Frontend/fixed_point_bit_widths.c b/test/Frontend/fixed_point_bit_widths.c new file mode 100644 index 0000000000..6b4eea90e6 --- /dev/null +++ b/test/Frontend/fixed_point_bit_widths.c @@ -0,0 +1,46 @@ +// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-ubuntu-fast %s | FileCheck %s +// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=ppc64 %s | FileCheck %s +// RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-windows10pro-fast %s | FileCheck %s + +int size_SsA = sizeof(signed short _Accum); +int size_SA = sizeof(signed _Accum); +int size_SlA = sizeof(signed long _Accum); +int align_SsA = __alignof(signed short _Accum); +int align_SA = __alignof(signed _Accum); +int align_SlA = __alignof(signed long _Accum); + +int size_UsA = sizeof(unsigned short _Accum); +int size_UA = sizeof(unsigned _Accum); +int size_UlA = sizeof(unsigned long _Accum); +int align_UsA = __alignof(unsigned short _Accum); +int align_UA = __alignof(unsigned _Accum); +int align_UlA = __alignof(unsigned long _Accum); + +int size_sA = sizeof(short _Accum); +int size_A = sizeof(_Accum); +int size_lA = sizeof(long _Accum); +int align_sA = __alignof(short _Accum); +int align_A = __alignof(_Accum); +int align_lA = __alignof(long _Accum); + +// CHECK: @size_SsA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SA = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SlA = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SsA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SA = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SlA = {{.*}}global i{{[0-9]+}} 8 + +// CHECK-NEXT: @size_UsA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_UA = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_UlA = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_UsA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_UA = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_UlA = {{.*}}global i{{[0-9]+}} 8 + +// CHECK-NEXT: @size_sA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_A = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_lA = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_sA = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_A = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_lA = {{.*}}global i{{[0-9]+}} 8 diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c new file mode 100644 index 0000000000..0158dc68c4 --- /dev/null +++ b/test/Frontend/fixed_point_errors.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -verify -ffixed-point %s + +/* We do not yet support long long. No recommended bit widths are given for this + * size. */ + +long long _Accum longlong_accum; // expected-error{{'long long _Accum' is invalid}} +unsigned long long _Accum u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} + +/* Although _Complex types work with floating point numbers, the extension + * provides no info for complex fixed point types. */ + +_Complex signed short _Accum cmplx_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex signed _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex signed long _Accum cmplx_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex unsigned short _Accum cmplx_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex unsigned _Accum cmplx_u_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex unsigned long _Accum cmplx_u_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex short _Accum cmplx_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex long _Accum cmplx_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} + +/* Bad combinations */ +float _Accum f_accum; // expected-error{{cannot combine with previous 'float' declaration specifier}} +double _Accum d_accum; // expected-error{{cannot combine with previous 'double' declaration specifier}} +_Bool _Accum b_accum; // expected-error{{cannot combine with previous '_Bool' declaration specifier}} +char _Accum c_accum; // expected-error{{cannot combine with previous 'char' declaration specifier}} +int _Accum i_accum; // expected-error{{cannot combine with previous 'int' declaration specifier}} diff --git a/test/Frontend/fixed_point_errors.cpp b/test/Frontend/fixed_point_errors.cpp new file mode 100644 index 0000000000..aa95bb10c5 --- /dev/null +++ b/test/Frontend/fixed_point_errors.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -x c++ -ffixed-point %s -verify + +// Name namgling is not provided for fixed point types in c++ + +_Accum accum; // expected-error{{unknown type name '_Accum'}} diff --git a/test/Frontend/fixed_point_not_enabled.c b/test/Frontend/fixed_point_not_enabled.c new file mode 100644 index 0000000000..e5c82f54b6 --- /dev/null +++ b/test/Frontend/fixed_point_not_enabled.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -x c -verify %s + +// Primary fixed point types +signed short _Accum s_short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +signed _Accum s_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +signed long _Accum s_long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +unsigned short _Accum u_short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +unsigned _Accum u_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +unsigned long _Accum u_long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} + +// Aliased fixed point types +short _Accum short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} +_Accum accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} + // expected-warning@-1{{type specifier missing, defaults to 'int'}} +long _Accum long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 0b678b0a2a..7c0f307944 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -53,6 +53,12 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) { BTCASE(Float); BTCASE(Double); BTCASE(LongDouble); + BTCASE(ShortAccum); + BTCASE(Accum); + BTCASE(LongAccum); + BTCASE(UShortAccum); + BTCASE(UAccum); + BTCASE(ULongAccum); BTCASE(Float16); BTCASE(Float128); BTCASE(NullPtr); @@ -546,6 +552,12 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) { TKIND(Float); TKIND(Double); TKIND(LongDouble); + TKIND(ShortAccum); + TKIND(Accum); + TKIND(LongAccum); + TKIND(UShortAccum); + TKIND(UAccum); + TKIND(ULongAccum); TKIND(Float16); TKIND(Float128); TKIND(NullPtr); -- GitLab From 415982d6f7663fc60802a85d21c658bd534a7b60 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 4 Jun 2018 18:23:00 +0000 Subject: [PATCH 0005/1023] Remove llvm::Triple argument from get***Personality() functions. NFC. Summary: Because `llvm::Triple` can be derived from `TargetInfo`, it is simpler to take only `TargetInfo` argument. Reviewers: sbc100 Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47620 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333938 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGException.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 769b615cd4..27f7eb8d30 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -114,8 +114,9 @@ EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr }; const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr }; -static const EHPersonality &getCPersonality(const llvm::Triple &T, +static const EHPersonality &getCPersonality(const TargetInfo &Target, const LangOptions &L) { + const llvm::Triple &T = Target.getTriple(); if (L.SjLjExceptions) return EHPersonality::GNU_C_SJLJ; if (L.DWARFExceptions) @@ -127,11 +128,12 @@ static const EHPersonality &getCPersonality(const llvm::Triple &T, return EHPersonality::GNU_C; } -static const EHPersonality &getObjCPersonality(const llvm::Triple &T, +static const EHPersonality &getObjCPersonality(const TargetInfo &Target, const LangOptions &L) { + const llvm::Triple &T = Target.getTriple(); switch (L.ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: - return getCPersonality(T, L); + return getCPersonality(Target, L); case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: @@ -153,9 +155,9 @@ static const EHPersonality &getObjCPersonality(const llvm::Triple &T, llvm_unreachable("bad runtime kind"); } -static const EHPersonality &getCXXPersonality(const llvm::Triple &T, - const LangOptions &L, - const TargetInfo &Target) { +static const EHPersonality &getCXXPersonality(const TargetInfo &Target, + const LangOptions &L) { + const llvm::Triple &T = Target.getTriple(); if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; if (L.DWARFExceptions) @@ -174,14 +176,13 @@ static const EHPersonality &getCXXPersonality(const llvm::Triple &T, /// Determines the personality function to use when both C++ /// and Objective-C exceptions are being caught. -static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T, - const LangOptions &L, - const TargetInfo &Target) { +static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, + const LangOptions &L) { switch (L.ObjCRuntime.getKind()) { // In the fragile ABI, just use C++ exception handling and hope // they're not doing crazy exception mixing. case ObjCRuntime::FragileMacOSX: - return getCXXPersonality(T, L, Target); + return getCXXPersonality(Target, L); // The ObjC personality defers to the C++ personality for non-ObjC // handlers. Unlike the C++ case, we use the same personality @@ -189,7 +190,7 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T, case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: - return getObjCPersonality(T, L); + return getObjCPersonality(Target, L); case ObjCRuntime::GNUstep: return EHPersonality::GNU_ObjCXX; @@ -198,7 +199,7 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T, // mixed EH. Use the ObjC personality just to avoid returning null. case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: - return getObjCPersonality(T, L); + return getObjCPersonality(Target, L); } llvm_unreachable("bad runtime kind"); } @@ -220,9 +221,10 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM, return getSEHPersonalityMSVC(T); if (L.ObjC1) - return L.CPlusPlus ? getObjCXXPersonality(T, L, Target) - : getObjCPersonality(T, L); - return L.CPlusPlus ? getCXXPersonality(T, L, Target) : getCPersonality(T, L); + return L.CPlusPlus ? getObjCXXPersonality(Target, L) + : getObjCPersonality(Target, L); + return L.CPlusPlus ? getCXXPersonality(Target, L) + : getCPersonality(Target, L); } const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) { @@ -318,8 +320,7 @@ void CodeGenModule::SimplifyPersonality() { return; const EHPersonality &ObjCXX = EHPersonality::get(*this, /*FD=*/nullptr); - const EHPersonality &CXX = - getCXXPersonality(getTarget().getTriple(), LangOpts, getTarget()); + const EHPersonality &CXX = getCXXPersonality(getTarget(), LangOpts); if (&ObjCXX == &CXX) return; -- GitLab From 51f877dbebe07f539f3f24acb88ef4f3f0737339 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 4 Jun 2018 18:56:25 +0000 Subject: [PATCH 0006/1023] [CFG] Fix automatic destructors when a member is bound to a reference. In code like const int &x = A().x; automatic destructor for the object A() lifetime-extended by reference 'x' was not present in the clang CFG due to ad-hoc pattern-matching in getReferenceInitTemporaryType(). Re-use skipRValueSubobjectAdjustments() again to find the lifetime-extended object in the AST and emit the correct destructor. Lifetime extension through aggregates with references still needs to be covered. Differential Revision: https://reviews.llvm.org/D44238 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333941 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFG.cpp | 62 ++-- test/Analysis/auto-obj-dtors-cfg-output.cpp | 295 +++++++++++++++++++- 2 files changed, 320 insertions(+), 37 deletions(-) diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 597bdd2b22..b02fbe1071 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1493,19 +1493,18 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { /// Retrieve the type of the temporary object whose lifetime was /// extended by a local reference with the given initializer. -static QualType getReferenceInitTemporaryType(ASTContext &Context, - const Expr *Init, +static QualType getReferenceInitTemporaryType(const Expr *Init, bool *FoundMTE = nullptr) { while (true) { // Skip parentheses. Init = Init->IgnoreParens(); - + // Skip through cleanups. if (const ExprWithCleanups *EWC = dyn_cast(Init)) { Init = EWC->getSubExpr(); continue; } - + // Skip through the temporary-materialization expression. if (const MaterializeTemporaryExpr *MTE = dyn_cast(Init)) { @@ -1514,26 +1513,17 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context, *FoundMTE = true; continue; } - - // Skip derived-to-base and no-op casts. - if (const CastExpr *CE = dyn_cast(Init)) { - if ((CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase || - CE->getCastKind() == CK_NoOp) && - Init->getType()->isRecordType()) { - Init = CE->getSubExpr(); - continue; - } - } - - // Skip member accesses into rvalues. - if (const MemberExpr *ME = dyn_cast(Init)) { - if (!ME->isArrow() && ME->getBase()->isRValue()) { - Init = ME->getBase(); - continue; - } + + // Skip sub-object accesses into rvalues. + SmallVector CommaLHSs; + SmallVector Adjustments; + const Expr *SkippedInit = + Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); + if (SkippedInit != Init) { + Init = SkippedInit; + continue; } - + break; } @@ -1682,7 +1672,7 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, // anything built thus far: control won't flow out of this block. QualType Ty = (*I)->getType(); if (Ty->isReferenceType()) { - Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); + Ty = getReferenceInitTemporaryType((*I)->getInit()); } Ty = Context->getBaseElementType(Ty); @@ -1795,7 +1785,7 @@ LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) { // Check for const references bound to temporary. Set type to pointee. QualType QT = VD->getType(); - if (QT.getTypePtr()->isReferenceType()) { + if (QT->isReferenceType()) { // Attempt to determine whether this declaration lifetime-extends a // temporary. // @@ -1805,12 +1795,16 @@ bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) { // MaterializeTemporaryExpr instead. const Expr *Init = VD->getInit(); - if (!Init) + if (!Init) { + // Probably an exception catch-by-reference variable. + // FIXME: It doesn't really mean that the object has a trivial destructor. + // Also are there other cases? return true; + } - // Lifetime-extending a temporary. + // Lifetime-extending a temporary? bool FoundMTE = false; - QT = getReferenceInitTemporaryType(*Context, Init, &FoundMTE); + QT = getReferenceInitTemporaryType(Init, &FoundMTE); if (!FoundMTE) return true; } @@ -4596,7 +4590,7 @@ CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { // temporary in an initializer expression. if (ty->isReferenceType()) { if (const Expr *Init = var->getInit()) { - ty = getReferenceInitTemporaryType(astContext, Init); + ty = getReferenceInitTemporaryType(Init); } } @@ -5061,10 +5055,12 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const VarDecl *VD = DE->getVarDecl(); Helper.handleDecl(VD, OS); - const Type* T = VD->getType().getTypePtr(); - if (const ReferenceType* RT = T->getAs()) - T = RT->getPointeeType().getTypePtr(); - T = T->getBaseElementTypeUnsafe(); + ASTContext &ACtx = VD->getASTContext(); + QualType T = VD->getType(); + if (T->isReferenceType()) + T = getReferenceInitTemporaryType(VD->getInit(), nullptr); + if (const ArrayType *AT = ACtx.getAsArrayType(T)) + T = ACtx.getBaseElementType(AT); OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; OS << " (Implicit destructor)\n"; diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp index 43a21dd943..cd87d3c443 100644 --- a/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -1,7 +1,11 @@ -// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s -// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s +// RUN: %clang_analyze_cc1 -std=c++98 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,WARNINGS,CXX98-WARNINGS %s +// RUN: %clang_analyze_cc1 -std=c++98 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,ANALYZER,CXX98-ANALYZER %s +// RUN: %clang_analyze_cc1 -std=c++11 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,WARNINGS,CXX11-WARNINGS %s +// RUN: %clang_analyze_cc1 -std=c++11 -fcxx-exceptions -fexceptions -analyzer-checker=debug.DumpCFG -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ANALYZER,CXX11-ANALYZER %s // This file tests how we construct two different flavors of the Clang CFG - // the CFG used by the Sema analysis-based warnings and the CFG used by the @@ -14,6 +18,8 @@ class A { public: + int x; + // CHECK: [B1 (ENTRY)] // CHECK-NEXT: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -67,6 +73,287 @@ void test_const_ref() { const A& c = A(); } +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A) +// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) +// CHECK-NEXT: 2: [B1.1] (BindTemporary) +// CXX98-NEXT: 3: [B1.2].x +// CXX98-NEXT: 4: [B1.3] +// CXX98-NEXT: 5: const int &x = A().x; +// CXX98-NEXT: 6: [B1.5].~A() (Implicit destructor) +// CXX11-NEXT: 3: [B1.2] +// CXX11-NEXT: 4: [B1.3].x +// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const int) +// CXX11-NEXT: 6: const int &x = A().x; +// CXX11-NEXT: 7: [B1.6].~A() (Implicit destructor) +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_const_ref_to_field() { + const int &x = A().x; +} + +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A) +// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) +// CHECK-NEXT: 2: [B1.1] (BindTemporary) +// CXX98-NEXT: 3: A::x +// CXX98-NEXT: 4: &[B1.3] +// CXX98-NEXT: 5: [B1.2] .* [B1.4] +// CXX98-NEXT: 6: [B1.5] +// CXX98-NEXT: 7: const int &x = A() .* &A::x; +// CXX98-NEXT: 8: [B1.7].~A() (Implicit destructor) +// CXX11-NEXT: 3: [B1.2] +// CXX11-NEXT: 4: A::x +// CXX11-NEXT: 5: &[B1.4] +// CXX11-NEXT: 6: [B1.3] .* [B1.5] +// CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const int) +// CXX11-NEXT: 8: const int &x = A() .* &A::x; +// CXX11-NEXT: 9: [B1.8].~A() (Implicit destructor) +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_pointer_to_member() { + const int &x = A().*&A::x; +} + +// FIXME: There should be automatic destructors at the end of scope. +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// CHECK-NEXT: 2: [B1.1] (BindTemporary) +// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 4: [B1.3] +// CHECK-NEXT: 5: {[B1.4]} +// CHECK-NEXT: 6: B b = {A()}; +// WARNINGS-NEXT: 7: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 7: A() (CXXConstructExpr, [B1.8], [B1.10], class A) +// CHECK-NEXT: 8: [B1.7] (BindTemporary) +// CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 10: [B1.9] +// CHECK-NEXT: 11: {[B1.10]} +// WARNINGS-NEXT: 12: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 12: A() (CXXConstructExpr, [B1.13], [B1.15], class A) +// CHECK-NEXT: 13: [B1.12] (BindTemporary) +// CHECK-NEXT: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 15: [B1.14] +// CHECK-NEXT: 16: {[B1.15]} +// CHECK-NEXT: 17: {[B1.10], [B1.15]} +// CHECK-NEXT: 18: B bb[2] = {A(), A()}; +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_aggregate_lifetime_extension() { + struct B { + const A &x; + }; + + B b = {A()}; + B bb[2] = {A(), A()}; +} + +// In C++98 such class 'C' will not be an aggregate. +#if __cplusplus >= 201103L +// FIXME: There should be automatic destructors at the end of the scope. +// CXX11: [B2 (ENTRY)] +// CXX11-NEXT: Succs (1): B1 +// CXX11: [B1] +// CXX11-WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// CXX11-NEXT: 2: [B1.1] (BindTemporary) +// CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 4: [B1.3] +// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, const class A) +// CXX11-WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.7], [B1.9], class A) +// CXX11-NEXT: 7: [B1.6] (BindTemporary) +// CXX11-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 9: [B1.8] +// CXX11-NEXT: 10: [B1.9] (CXXConstructExpr, const class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CXX11-NEXT: 11: {[B1.2], [B1.7]} +// CXX11-NEXT: 12: [B1.11] (BindTemporary) +// CXX11-NEXT: 13: [B1.12] +// CXX11-NEXT: 14: {[B1.13]} +// Double curly braces trigger regexps, escape as per FileCheck manual. +// CXX11-NEXT: 15: C c = {{[{][{]}}A(), A(){{[}][}]}}; +// CXX11-NEXT: 16: ~A() (Temporary object destructor) +// CXX11-NEXT: 17: ~A() (Temporary object destructor) +// CXX11-WARNINGS-NEXT: 18: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 18: A() (CXXConstructExpr, [B1.19], [B1.21], class A) +// CXX11-NEXT: 19: [B1.18] (BindTemporary) +// CXX11-NEXT: 20: [B1.19] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 21: [B1.20] +// CXX11-NEXT: 22: [B1.21] (CXXConstructExpr, const class A) +// CXX11-WARNINGS-NEXT: 23: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 23: A() (CXXConstructExpr, [B1.24], [B1.26], class A) +// CXX11-NEXT: 24: [B1.23] (BindTemporary) +// CXX11-NEXT: 25: [B1.24] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 26: [B1.25] +// CXX11-NEXT: 27: [B1.26] (CXXConstructExpr, const class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CXX11-NEXT: 28: {[B1.19], [B1.24]} +// CXX11-NEXT: 29: [B1.28] (BindTemporary) +// CXX11-NEXT: 30: [B1.29] +// CXX11-NEXT: 31: {[B1.30]} +// CXX11-WARNINGS-NEXT: 32: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 32: A() (CXXConstructExpr, [B1.33], [B1.35], class A) +// CXX11-NEXT: 33: [B1.32] (BindTemporary) +// CXX11-NEXT: 34: [B1.33] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 35: [B1.34] +// CXX11-NEXT: 36: [B1.35] (CXXConstructExpr, const class A) +// CXX11-WARNINGS-NEXT: 37: A() (CXXConstructExpr, class A) +// CXX11-ANALYZER-NEXT: 37: A() (CXXConstructExpr, [B1.38], [B1.40], class A) +// CXX11-NEXT: 38: [B1.37] (BindTemporary) +// CXX11-NEXT: 39: [B1.38] (ImplicitCastExpr, NoOp, const class A) +// CXX11-NEXT: 40: [B1.39] +// CXX11-NEXT: 41: [B1.40] (CXXConstructExpr, const class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CXX11-NEXT: 42: {[B1.33], [B1.38]} +// CXX11-NEXT: 43: [B1.42] (BindTemporary) +// CXX11-NEXT: 44: [B1.43] +// CXX11-NEXT: 45: {[B1.44]} +// Double curly braces trigger regexps, escape as per FileCheck manual. +// CXX11-NEXT: 46: {{[{][{]}}[B1.30]}, {[B1.44]{{[}][}]}} +// Double curly braces trigger regexps, escape as per FileCheck manual. +// CXX11-NEXT: 47: C cc[2] = {{[{][{][{]}}A(), A(){{[}][}]}}, {{[{][{]}}A(), A(){{[}][}][}]}}; +// CXX11-NEXT: 48: ~A() (Temporary object destructor) +// CXX11-NEXT: 49: ~A() (Temporary object destructor) +// CXX11-NEXT: 50: ~A() (Temporary object destructor) +// CXX11-NEXT: 51: ~A() (Temporary object destructor) +// CXX11-NEXT: Preds (1): B2 +// CXX11-NEXT: Succs (1): B0 +// CXX11: [B0 (EXIT)] +// CXX11-NEXT: Preds (1): B1 +void test_aggregate_array_lifetime_extension() { + struct C { + const A (&z)[2]; + }; + + // Until C++17 there are elidable copies here, so there should be 9 temporary + // destructors of A()s. There are no destructors of 'c' and 'cc' because this + // aggregate has no destructor. Instead, arrays are lifetime-extended, + // and copies of A()s within them need to be destroyed via automatic + // destructors. + C c = {{A(), A()}}; + C cc[2] = {{{A(), A()}}, {{A(), A()}}}; +} +#endif + +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// CHECK-NEXT: 2: [B1.1] (BindTemporary) +// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 4: [B1.3] +// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.7], [B1.9], class A) +// CHECK-NEXT: 7: [B1.6] (BindTemporary) +// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 9: [B1.8] +// CHECK-NEXT: 10: [B1.9] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 11: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 11: A() (CXXConstructExpr, [B1.12], [B1.14], class A) +// CHECK-NEXT: 12: [B1.11] (BindTemporary) +// CHECK-NEXT: 13: [B1.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 14: [B1.13] +// CHECK-NEXT: 15: [B1.14] (CXXConstructExpr, class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 16: {[B1.7], [B1.12]} +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 17: {[B1.2], {[B1.7], [B1.12]}} +// CHECK-NEXT: 18: D d = {A(), {A(), A()}}; +// CHECK-NEXT: 19: ~A() (Temporary object destructor) +// CHECK-NEXT: 20: ~A() (Temporary object destructor) +// CHECK-NEXT: 21: ~A() (Temporary object destructor) +// WARNINGS-NEXT: 22: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 22: A() (CXXConstructExpr, [B1.23], [B1.25], class A) +// CHECK-NEXT: 23: [B1.22] (BindTemporary) +// CHECK-NEXT: 24: [B1.23] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 25: [B1.24] +// CHECK-NEXT: 26: [B1.25] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 27: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 27: A() (CXXConstructExpr, [B1.28], [B1.30], class A) +// CHECK-NEXT: 28: [B1.27] (BindTemporary) +// CHECK-NEXT: 29: [B1.28] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 30: [B1.29] +// CHECK-NEXT: 31: [B1.30] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 32: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 32: A() (CXXConstructExpr, [B1.33], [B1.35], class A) +// CHECK-NEXT: 33: [B1.32] (BindTemporary) +// CHECK-NEXT: 34: [B1.33] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 35: [B1.34] +// CHECK-NEXT: 36: [B1.35] (CXXConstructExpr, class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 37: {[B1.28], [B1.33]} +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 38: {[B1.23], {[B1.28], [B1.33]}} +// WARNINGS-NEXT: 39: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 39: A() (CXXConstructExpr, [B1.40], [B1.42], class A) +// CHECK-NEXT: 40: [B1.39] (BindTemporary) +// CHECK-NEXT: 41: [B1.40] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 42: [B1.41] +// CHECK-NEXT: 43: [B1.42] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 44: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 44: A() (CXXConstructExpr, [B1.45], [B1.47], class A) +// CHECK-NEXT: 45: [B1.44] (BindTemporary) +// CHECK-NEXT: 46: [B1.45] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 47: [B1.46] +// CHECK-NEXT: 48: [B1.47] (CXXConstructExpr, class A) +// WARNINGS-NEXT: 49: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 49: A() (CXXConstructExpr, [B1.50], [B1.52], class A) +// CHECK-NEXT: 50: [B1.49] (BindTemporary) +// CHECK-NEXT: 51: [B1.50] (ImplicitCastExpr, NoOp, const class A) +// CHECK-NEXT: 52: [B1.51] +// CHECK-NEXT: 53: [B1.52] (CXXConstructExpr, class A) +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 54: {[B1.45], [B1.50]} +// FIXME: Why does it look as if the initializer list consumes uncopied objects? +// CHECK-NEXT: 55: {[B1.40], {[B1.45], [B1.50]}} +// Double curly braces trigger regexps, escape as per FileCheck manual. +// CHECK-NEXT: 56: {{[{][{]}}[B1.23], {[B1.28], [B1.33]{{[}][}]}}, {[B1.40], {[B1.45], [B1.50]{{[}][}][}]}} +// Double curly braces trigger regexps, escape as per FileCheck manual. +// CHECK-NEXT: 57: D dd[2] = {{[{][{]}}A(), {A(), A(){{[}][}]}}, {A(), {A(), A(){{[}][}][}]}}; +// CHECK-NEXT: 58: ~A() (Temporary object destructor) +// CHECK-NEXT: 59: ~A() (Temporary object destructor) +// CHECK-NEXT: 60: ~A() (Temporary object destructor) +// CHECK-NEXT: 61: ~A() (Temporary object destructor) +// CHECK-NEXT: 62: ~A() (Temporary object destructor) +// CHECK-NEXT: 63: ~A() (Temporary object destructor) +// CHECK-NEXT: 64: [B1.57].~D() (Implicit destructor) +// CHECK-NEXT: 65: [B1.18].~D() (Implicit destructor) +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_aggregate_with_nontrivial_own_destructor() { + struct D { + A y; + A w[2]; + }; + + // Until C++17 there are elidable copies here, so there should be 9 temporary + // destructors of A()s. Destructors of 'd' and 'dd' should implicitly + // take care of the copies, so there should not be automatic destructors + // for copies of A()s. + D d = {A(), {A(), A()}}; + D dd[2] = {{A(), {A(), A()}}, {A(), {A(), A()}}}; +} + // CHECK: [B2 (ENTRY)] // CHECK-NEXT: Succs (1): B1 // CHECK: [B1] -- GitLab From edfb78dee78bc88f0e0aa12f1967b24f5d8f45ee Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 4 Jun 2018 19:28:09 +0000 Subject: [PATCH 0007/1023] [X86] Avoid passing _mm_undefined* to builtin_shufflevector if we are able to pass the first input a second time. This is more consistent with other usages of builtin_shufflevector. Later optimization passes or codegen will detect the duplicate vector and replace it with undef. Using _mm_undefined just puts a zeroinitializer that still needs to be optimized out later. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333944 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512bwintrin.h | 6 ++---- lib/Headers/avx512dqintrin.h | 6 ++---- lib/Headers/avx512fintrin.h | 12 ++++-------- lib/Headers/avx512vldqintrin.h | 9 +++------ test/CodeGen/avx512bw-builtins.c | 12 ++++++------ test/CodeGen/avx512dq-builtins.c | 12 ++++++------ test/CodeGen/avx512f-builtins.c | 24 ++++++++++++------------ test/CodeGen/avx512vldq-builtins.c | 18 +++++++++--------- 8 files changed, 44 insertions(+), 55 deletions(-) diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index fcdae9aa3c..f392b250b7 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -1889,8 +1889,7 @@ _mm512_movm_epi16 (__mmask32 __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_broadcastb_epi8 (__m128i __A) { - return (__m512i)__builtin_shufflevector((__v16qi) __A, - (__v16qi)_mm_undefined_si128(), + return (__m512i)__builtin_shufflevector((__v16qi) __A, (__v16qi) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1932,8 +1931,7 @@ _mm512_maskz_set1_epi16 (__mmask32 __M, short __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_broadcastw_epi16 (__m128i __A) { - return (__m512i)__builtin_shufflevector((__v8hi) __A, - (__v8hi)_mm_undefined_si128(), + return (__m512i)__builtin_shufflevector((__v8hi) __A, (__v8hi) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h index 6695a0bb5b..9ef78041d1 100644 --- a/lib/Headers/avx512dqintrin.h +++ b/lib/Headers/avx512dqintrin.h @@ -963,8 +963,7 @@ _mm512_movepi64_mask (__m512i __A) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_broadcast_f32x2 (__m128 __A) { - return (__m512)__builtin_shufflevector((__v4sf)__A, - (__v4sf)_mm_undefined_ps(), + return (__m512)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1); } @@ -1035,8 +1034,7 @@ _mm512_maskz_broadcast_f64x2(__mmask8 __M, __m128d __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_broadcast_i32x2 (__m128i __A) { - return (__m512i)__builtin_shufflevector((__v4si)__A, - (__v4si)_mm_undefined_si128(), + return (__m512i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1); } diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index abf2da25f2..9f514bc41a 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -212,8 +212,7 @@ _mm512_undefined_epi32(void) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_broadcastd_epi32 (__m128i __A) { - return (__m512i)__builtin_shufflevector((__v4si) __A, - (__v4si)_mm_undefined_si128(), + return (__m512i)__builtin_shufflevector((__v4si) __A, (__v4si) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } @@ -236,8 +235,7 @@ _mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_broadcastq_epi64 (__m128i __A) { - return (__m512i)__builtin_shufflevector((__v2di) __A, - (__v2di) _mm_undefined_si128(), + return (__m512i)__builtin_shufflevector((__v2di) __A, (__v2di) __A, 0, 0, 0, 0, 0, 0, 0, 0); } @@ -344,8 +342,7 @@ _mm512_maskz_set1_epi64(__mmask8 __M, long long __A) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_broadcastss_ps(__m128 __A) { - return (__m512)__builtin_shufflevector((__v4sf) __A, - (__v4sf)_mm_undefined_ps(), + return (__m512)__builtin_shufflevector((__v4sf) __A, (__v4sf) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } @@ -395,8 +392,7 @@ _mm512_set4_ps (float __A, float __B, float __C, float __D) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_broadcastsd_pd(__m128d __A) { - return (__m512d)__builtin_shufflevector((__v2df) __A, - (__v2df) _mm_undefined_pd(), + return (__m512d)__builtin_shufflevector((__v2df) __A, (__v2df) __A, 0, 0, 0, 0, 0, 0, 0, 0); } diff --git a/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h index 96836527da..60571adb5e 100644 --- a/lib/Headers/avx512vldqintrin.h +++ b/lib/Headers/avx512vldqintrin.h @@ -970,8 +970,7 @@ _mm256_movepi64_mask (__m256i __A) static __inline__ __m256 __DEFAULT_FN_ATTRS _mm256_broadcast_f32x2 (__m128 __A) { - return (__m256)__builtin_shufflevector((__v4sf)__A, - (__v4sf)_mm_undefined_ps(), + return (__m256)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A, 0, 1, 0, 1, 0, 1, 0, 1); } @@ -1017,8 +1016,7 @@ _mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_broadcast_i32x2 (__m128i __A) { - return (__m128i)__builtin_shufflevector((__v4si)__A, - (__v4si)_mm_undefined_si128(), + return (__m128i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 0, 1); } @@ -1041,8 +1039,7 @@ _mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_broadcast_i32x2 (__m128i __A) { - return (__m256i)__builtin_shufflevector((__v4si)__A, - (__v4si)_mm_undefined_si128(), + return (__m256i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 0, 1, 0, 1, 0, 1); } diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c index 4deb64f0eb..600eccd914 100644 --- a/test/CodeGen/avx512bw-builtins.c +++ b/test/CodeGen/avx512bw-builtins.c @@ -1778,40 +1778,40 @@ __m512i test_mm512_movm_epi16(__mmask32 __A) { __m512i test_mm512_broadcastb_epi8(__m128i __A) { // CHECK-LABEL: @test_mm512_broadcastb_epi8 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer + // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer return _mm512_broadcastb_epi8(__A); } __m512i test_mm512_mask_broadcastb_epi8(__m512i __O, __mmask64 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_mask_broadcastb_epi8 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer + // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} return _mm512_mask_broadcastb_epi8(__O, __M, __A); } __m512i test_mm512_maskz_broadcastb_epi8(__mmask64 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastb_epi8 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <64 x i32> zeroinitializer + // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <64 x i32> zeroinitializer // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}} return _mm512_maskz_broadcastb_epi8(__M, __A); } __m512i test_mm512_broadcastw_epi16(__m128i __A) { // CHECK-LABEL: @test_mm512_broadcastw_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer return _mm512_broadcastw_epi16(__A); } __m512i test_mm512_mask_broadcastw_epi16(__m512i __O, __mmask32 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_mask_broadcastw_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_broadcastw_epi16(__O, __M, __A); } __m512i test_mm512_maskz_broadcastw_epi16(__mmask32 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastw_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> zeroinitializer, <32 x i32> zeroinitializer + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <32 x i32> zeroinitializer // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_broadcastw_epi16(__M, __A); } diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c index aff5ca4cc5..756ecf3e6c 100644 --- a/test/CodeGen/avx512dq-builtins.c +++ b/test/CodeGen/avx512dq-builtins.c @@ -955,20 +955,20 @@ __mmask8 test_mm512_movepi64_mask(__m512i __A) { __m512 test_mm512_broadcast_f32x2(__m128 __A) { // CHECK-LABEL: @test_mm512_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> return _mm512_broadcast_f32x2(__A); } __m512 test_mm512_mask_broadcast_f32x2(__m512 __O, __mmask16 __M, __m128 __A) { // CHECK-LABEL: @test_mm512_mask_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_broadcast_f32x2(__O, __M, __A); } __m512 test_mm512_maskz_broadcast_f32x2(__mmask16 __M, __m128 __A) { // CHECK-LABEL: @test_mm512_maskz_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_broadcast_f32x2(__M, __A); } @@ -1015,20 +1015,20 @@ __m512d test_mm512_maskz_broadcast_f64x2(__mmask8 __M, double const* __A) { __m512i test_mm512_broadcast_i32x2(__m128i __A) { // CHECK-LABEL: @test_mm512_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> return _mm512_broadcast_i32x2(__A); } __m512i test_mm512_mask_broadcast_i32x2(__m512i __O, __mmask16 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_mask_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_broadcast_i32x2(__O, __M, __A); } __m512i test_mm512_maskz_broadcast_i32x2(__mmask16 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_maskz_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_broadcast_i32x2(__M, __A); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index e58c29b864..cd773791a2 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -5072,80 +5072,80 @@ __m512i test_mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i const* __A) { __m512d test_mm512_broadcastsd_pd(__m128d __A) { // CHECK-LABEL: @test_mm512_broadcastsd_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer return _mm512_broadcastsd_pd(__A); } __m512d test_mm512_mask_broadcastsd_pd(__m512d __O, __mmask8 __M, __m128d __A) { // CHECK-LABEL: @test_mm512_mask_broadcastsd_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_broadcastsd_pd(__O, __M, __A); } __m512d test_mm512_maskz_broadcastsd_pd(__mmask8 __M, __m128d __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastsd_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <8 x i32> zeroinitializer // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_broadcastsd_pd(__M, __A); } __m512 test_mm512_broadcastss_ps(__m128 __A) { // CHECK-LABEL: @test_mm512_broadcastss_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer return _mm512_broadcastss_ps(__A); } __m512 test_mm512_mask_broadcastss_ps(__m512 __O, __mmask16 __M, __m128 __A) { // CHECK-LABEL: @test_mm512_mask_broadcastss_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_broadcastss_ps(__O, __M, __A); } __m512 test_mm512_maskz_broadcastss_ps(__mmask16 __M, __m128 __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastss_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <16 x i32> zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_broadcastss_ps(__M, __A); } __m512i test_mm512_broadcastd_epi32(__m128i __A) { // CHECK-LABEL: @test_mm512_broadcastd_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer return _mm512_broadcastd_epi32(__A); } __m512i test_mm512_mask_broadcastd_epi32(__m512i __O, __mmask16 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_mask_broadcastd_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_broadcastd_epi32(__O, __M, __A); } __m512i test_mm512_maskz_broadcastd_epi32(__mmask16 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastd_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <16 x i32> zeroinitializer + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <16 x i32> zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_broadcastd_epi32(__M, __A); } __m512i test_mm512_broadcastq_epi64(__m128i __A) { // CHECK-LABEL: @test_mm512_broadcastq_epi64 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer return _mm512_broadcastq_epi64(__A); } __m512i test_mm512_mask_broadcastq_epi64(__m512i __O, __mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_mask_broadcastq_epi64 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_broadcastq_epi64(__O, __M, __A); } __m512i test_mm512_maskz_broadcastq_epi64(__mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm512_maskz_broadcastq_epi64 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> zeroinitializer, <8 x i32> zeroinitializer + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <8 x i32> zeroinitializer // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_broadcastq_epi64(__M, __A); } diff --git a/test/CodeGen/avx512vldq-builtins.c b/test/CodeGen/avx512vldq-builtins.c index cbfd8d1866..ea9db6ecc8 100644 --- a/test/CodeGen/avx512vldq-builtins.c +++ b/test/CodeGen/avx512vldq-builtins.c @@ -924,20 +924,20 @@ __mmask8 test_mm256_movepi64_mask(__m256i __A) { __m256 test_mm256_broadcast_f32x2(__m128 __A) { // CHECK-LABEL: @test_mm256_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> return _mm256_broadcast_f32x2(__A); } __m256 test_mm256_mask_broadcast_f32x2(__m256 __O, __mmask8 __M, __m128 __A) { // CHECK-LABEL: @test_mm256_mask_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_broadcast_f32x2(__O, __M, __A); } __m256 test_mm256_maskz_broadcast_f32x2(__mmask8 __M, __m128 __A) { // CHECK-LABEL: @test_mm256_maskz_broadcast_f32x2 - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_broadcast_f32x2(__M, __A); } @@ -964,40 +964,40 @@ __m256d test_mm256_maskz_broadcast_f64x2(__mmask8 __M, double const* __A) { __m128i test_mm_broadcast_i32x2(__m128i __A) { // CHECK-LABEL: @test_mm_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> return _mm_broadcast_i32x2(__A); } __m128i test_mm_mask_broadcast_i32x2(__m128i __O, __mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm_mask_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_broadcast_i32x2(__O, __M, __A); } __m128i test_mm_maskz_broadcast_i32x2(__mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_broadcast_i32x2(__M, __A); } __m256i test_mm256_broadcast_i32x2(__m128i __A) { // CHECK-LABEL: @test_mm256_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> return _mm256_broadcast_i32x2(__A); } __m256i test_mm256_mask_broadcast_i32x2(__m256i __O, __mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm256_mask_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_broadcast_i32x2(__O, __M, __A); } __m256i test_mm256_maskz_broadcast_i32x2(__mmask8 __M, __m128i __A) { // CHECK-LABEL: @test_mm256_maskz_broadcast_i32x2 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> zeroinitializer, <8 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_broadcast_i32x2(__M, __A); } -- GitLab From 01f66df781bfe1c328d807dcc2a93b44f644afe6 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 4 Jun 2018 20:18:37 +0000 Subject: [PATCH 0008/1023] [analyzer] Re-enable constructors when lifetime extension through fields occurs. Temporary object constructor inlining was disabled in r326240 for code like const int &x = A().x; because automatic destructor for the lifetime-extended object A() was not working correctly in CFG. CFG was fixed in r333941, so inlining can be re-enabled. CFG for lifetime extension through aggregates still needs to be fixed. Differential Revision: https://reviews.llvm.org/D44239 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333946 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/ExprEngine.h | 5 ---- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 19 ++++----------- .../Core/ExprEngineCallAndReturn.cpp | 7 +----- test/Analysis/lifetime-extension.cpp | 24 ++++++++++++++----- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 5f7b7e1a96..1f2fef0b2d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -105,11 +105,6 @@ public: /// This call is a constructor or a destructor of a temporary value. bool IsTemporaryCtorOrDtor = false; - /// This call is a constructor for a temporary that is lifetime-extended - /// by binding a smaller object within it to a reference, for example - /// 'const int &x = C().x;'. - bool IsTemporaryLifetimeExtendedViaSubobject = false; - /// This call is a constructor for a temporary that is lifetime-extended /// by binding it to a reference-type field within an aggregate, /// for example 'A { const C &c; }; A a = { C() };' diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 997ff6a5a2..4fa05cb1b8 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -181,22 +181,13 @@ SVal ExprEngine::getLocationForConstructedObject(const CXXConstructExpr *CE, const auto *TOCC = cast(CC); if (const auto *MTE = TOCC->getMaterializedTemporaryExpr()) { if (const ValueDecl *VD = MTE->getExtendingDecl()) { - // Pattern-match various forms of lifetime extension that aren't - // currently supported by the CFG. - // FIXME: Is there a better way to retrieve this information from - // the MaterializeTemporaryExpr? assert(MTE->getStorageDuration() != SD_FullExpression); - if (VD->getType()->isReferenceType()) { - assert(VD->getType()->isReferenceType()); - if (VD->getType()->getPointeeType().getCanonicalType() != - MTE->GetTemporaryExpr()->getType().getCanonicalType()) { - // We're lifetime-extended via our field. Automatic destructors - // aren't quite working in this case. - CallOpts.IsTemporaryLifetimeExtendedViaSubobject = true; - } - } else { + if (!VD->getType()->isReferenceType()) { // We're lifetime-extended by a surrounding aggregate. - // Automatic destructors aren't quite working in this case. + // Automatic destructors aren't quite working in this case + // on the CFG side. We should warn the caller about that. + // FIXME: Is there a better way to retrieve this information from + // the MaterializeTemporaryExpr? CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true; } } diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 1a5dabfc67..44f8eebe2b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -696,12 +696,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) return CIP_DisallowedOnce; - // If the temporary is lifetime-extended by binding a smaller object - // within it to a reference, automatic destructors don't work properly. - if (CallOpts.IsTemporaryLifetimeExtendedViaSubobject) - return CIP_DisallowedOnce; - - // If the temporary is lifetime-extended by binding it to a reference-typ + // If the temporary is lifetime-extended by binding it to a reference-type // field within an aggregate, automatic destructors don't work properly. if (CallOpts.IsTemporaryLifetimeExtendedViaAggregate) return CIP_DisallowedOnce; diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp index 9173129ac1..1bad166d2d 100644 --- a/test/Analysis/lifetime-extension.cpp +++ b/test/Analysis/lifetime-extension.cpp @@ -46,10 +46,18 @@ void f() { const int &y = A().j[1]; // no-crash const int &z = (A().j[1], A().j[0]); // no-crash - // FIXME: All of these should be TRUE, but constructors aren't inlined. - clang_analyzer_eval(x == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(y == 3); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(z == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(x == 1); + clang_analyzer_eval(y == 3); + clang_analyzer_eval(z == 2); +#ifdef TEMPORARIES + // expected-warning@-4{{TRUE}} + // expected-warning@-4{{TRUE}} + // expected-warning@-4{{TRUE}} +#else + // expected-warning@-8{{UNKNOWN}} + // expected-warning@-8{{UNKNOWN}} + // expected-warning@-8{{UNKNOWN}} +#endif } } // end namespace pr19539_crash_on_destroying_an_integer @@ -144,8 +152,12 @@ void f5() { { const bool &x = C(true, &after, &before).x; // no-crash } - // FIXME: Should be TRUE. Should not warn about garbage value. - clang_analyzer_eval(after == before); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(after == before); +#ifdef TEMPORARIES + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif } struct A { // A is an aggregate. -- GitLab From 6d27f13d42457bbec41fc9cd1c0aac0d42358bf7 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 4 Jun 2018 21:23:29 +0000 Subject: [PATCH 0009/1023] Update for an LLVM header file move git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333955 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 537f3a36ca..2d8339ef69 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -29,7 +29,7 @@ #include "clang/CodeGen/SwiftCallingConv.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Analysis/Utils/Local.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" -- GitLab From faf42a8ee2def65865caf64877b20c6654ae0846 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 4 Jun 2018 21:39:20 +0000 Subject: [PATCH 0010/1023] Revert r333791 "Cap "voluntary" vector alignment at 16 for all Darwin platforms." Adding __attribute__((aligned(32))) to __m256 breaks the implementation of _mm256_loadu_ps on Windows. On Windows, alignment attributes have higher precedence than packing attributes. We also might want to carefully consider the consequences of changing our vector typedefs, since many users copy them and invent their own new, non-Intel specific vector type names. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333958 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/OSTargets.h | 3 - lib/Basic/Targets/X86.h | 7 ++ lib/CodeGen/CGBuiltin.cpp | 37 ++++---- lib/Headers/avx512fintrin.h | 42 +++++----- lib/Headers/avxintrin.h | 37 ++++---- test/CodeGen/arm-swiftcall.c | 4 +- test/CodeGen/vector-alignment.c | 84 ++++++------------- .../CodeGenCXX/align-avx-complete-objects.cpp | 6 +- 8 files changed, 97 insertions(+), 123 deletions(-) diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h index 6cc3c09555..18239a2ec7 100644 --- a/lib/Basic/Targets/OSTargets.h +++ b/lib/Basic/Targets/OSTargets.h @@ -113,9 +113,6 @@ public: } this->MCountName = "\01mcount"; - - // Cap vector alignment at 16 bytes for all Darwin platforms. - this->MaxVectorAlign = 128; } std::string isValidSectionSpecifier(StringRef SR) const override { diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h index 9d277e94cc..5b862face9 100644 --- a/lib/Basic/Targets/X86.h +++ b/lib/Basic/Targets/X86.h @@ -421,6 +421,7 @@ public: LongDoubleWidth = 128; LongDoubleAlign = 128; SuitableAlign = 128; + MaxVectorAlign = 256; // The watchOS simulator uses the builtin bool type for Objective-C. llvm::Triple T = llvm::Triple(Triple); if (T.isWatchOS()) @@ -436,6 +437,9 @@ public: if (!DarwinTargetInfo::handleTargetFeatures(Features, Diags)) return false; + // We now know the features we have: we can decide how to align vectors. + MaxVectorAlign = + hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128; return true; } }; @@ -798,6 +802,9 @@ public: if (!DarwinTargetInfo::handleTargetFeatures(Features, Diags)) return false; + // We now know the features we have: we can decide how to align vectors. + MaxVectorAlign = + hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128; return true; } }; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index dd0e351075..8793f83e29 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8885,20 +8885,18 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_movdqa64store128_mask: case X86::BI__builtin_ia32_storeaps128_mask: case X86::BI__builtin_ia32_storeapd128_mask: - return EmitX86MaskedStore(*this, Ops, 16); - case X86::BI__builtin_ia32_movdqa32store256_mask: case X86::BI__builtin_ia32_movdqa64store256_mask: case X86::BI__builtin_ia32_storeaps256_mask: case X86::BI__builtin_ia32_storeapd256_mask: - return EmitX86MaskedStore(*this, Ops, 32); - case X86::BI__builtin_ia32_movdqa32store512_mask: case X86::BI__builtin_ia32_movdqa64store512_mask: case X86::BI__builtin_ia32_storeaps512_mask: - case X86::BI__builtin_ia32_storeapd512_mask: - return EmitX86MaskedStore(*this, Ops, 64); - + case X86::BI__builtin_ia32_storeapd512_mask: { + unsigned Align = + getContext().getTypeAlignInChars(E->getArg(1)->getType()).getQuantity(); + return EmitX86MaskedStore(*this, Ops, Align); + } case X86::BI__builtin_ia32_loadups128_mask: case X86::BI__builtin_ia32_loadups256_mask: case X86::BI__builtin_ia32_loadups512_mask: @@ -8919,25 +8917,26 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_loaddqudi512_mask: return EmitX86MaskedLoad(*this, Ops, 1); - case X86::BI__builtin_ia32_loadaps128_mask: - case X86::BI__builtin_ia32_loadapd128_mask: case X86::BI__builtin_ia32_loadss128_mask: case X86::BI__builtin_ia32_loadsd128_mask: - case X86::BI__builtin_ia32_movdqa32load128_mask: - case X86::BI__builtin_ia32_movdqa64load128_mask: - return EmitX86MaskedLoad(*this, Ops, 16); + return EmitX86MaskedLoad(*this, Ops, 1); + case X86::BI__builtin_ia32_loadaps128_mask: case X86::BI__builtin_ia32_loadaps256_mask: - case X86::BI__builtin_ia32_loadapd256_mask: - case X86::BI__builtin_ia32_movdqa32load256_mask: - case X86::BI__builtin_ia32_movdqa64load256_mask: - return EmitX86MaskedLoad(*this, Ops, 32); - case X86::BI__builtin_ia32_loadaps512_mask: + case X86::BI__builtin_ia32_loadapd128_mask: + case X86::BI__builtin_ia32_loadapd256_mask: case X86::BI__builtin_ia32_loadapd512_mask: + case X86::BI__builtin_ia32_movdqa32load128_mask: + case X86::BI__builtin_ia32_movdqa32load256_mask: case X86::BI__builtin_ia32_movdqa32load512_mask: - case X86::BI__builtin_ia32_movdqa64load512_mask: - return EmitX86MaskedLoad(*this, Ops, 64); + case X86::BI__builtin_ia32_movdqa64load128_mask: + case X86::BI__builtin_ia32_movdqa64load256_mask: + case X86::BI__builtin_ia32_movdqa64load512_mask: { + unsigned Align = + getContext().getTypeAlignInChars(E->getArg(1)->getType()).getQuantity(); + return EmitX86MaskedLoad(*this, Ops, Align); + } case X86::BI__builtin_ia32_storehps: case X86::BI__builtin_ia32_storelps: { diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 9f514bc41a..2b3633e377 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -27,22 +27,22 @@ #ifndef __AVX512FINTRIN_H #define __AVX512FINTRIN_H -typedef char __v64qi __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef short __v32hi __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef double __v8df __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef float __v16sf __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef long long __v8di __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef int __v16si __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); +typedef char __v64qi __attribute__((__vector_size__(64))); +typedef short __v32hi __attribute__((__vector_size__(64))); +typedef double __v8df __attribute__((__vector_size__(64))); +typedef float __v16sf __attribute__((__vector_size__(64))); +typedef long long __v8di __attribute__((__vector_size__(64))); +typedef int __v16si __attribute__((__vector_size__(64))); /* Unsigned types */ -typedef unsigned char __v64qu __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef unsigned short __v32hu __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef unsigned long long __v8du __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef unsigned int __v16su __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); +typedef unsigned char __v64qu __attribute__((__vector_size__(64))); +typedef unsigned short __v32hu __attribute__((__vector_size__(64))); +typedef unsigned long long __v8du __attribute__((__vector_size__(64))); +typedef unsigned int __v16su __attribute__((__vector_size__(64))); -typedef float __m512 __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef double __m512d __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); -typedef long long __m512i __attribute__((__vector_size__(64))) __attribute__((__aligned__(64))); +typedef float __m512 __attribute__((__vector_size__(64))); +typedef double __m512d __attribute__((__vector_size__(64))); +typedef long long __m512i __attribute__((__vector_size__(64))); typedef unsigned char __mmask8; typedef unsigned short __mmask16; @@ -4810,7 +4810,7 @@ _mm512_mask_store_pd(void *__P, __mmask8 __U, __m512d __A) static __inline void __DEFAULT_FN_ATTRS _mm512_store_pd(void *__P, __m512d __A) { - *(__m512d *) __P = __A; + *(__m512d*)__P = __A; } static __inline void __DEFAULT_FN_ATTRS @@ -4823,7 +4823,7 @@ _mm512_mask_store_ps(void *__P, __mmask16 __U, __m512 __A) static __inline void __DEFAULT_FN_ATTRS _mm512_store_ps(void *__P, __m512 __A) { - *(__m512 *) __P = __A; + *(__m512*)__P = __A; } static __inline void __DEFAULT_FN_ATTRS @@ -8777,25 +8777,29 @@ _mm512_kxor (__mmask16 __A, __mmask16 __B) static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_si512 (__m512i * __P, __m512i __A) { - __builtin_nontemporal_store((__v8di)__A, (__v8di*)__P); + typedef __v8di __v8di_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v8di_aligned)__A, (__v8di_aligned*)__P); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_stream_load_si512 (void const *__P) { - return (__m512i) __builtin_nontemporal_load((const __v8di *)__P); + typedef __v8di __v8di_aligned __attribute__((aligned(64))); + return (__m512i) __builtin_nontemporal_load((const __v8di_aligned *)__P); } static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_pd (double *__P, __m512d __A) { - __builtin_nontemporal_store((__v8df)__A, (__v8df*)__P); + typedef __v8df __v8df_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v8df_aligned)__A, (__v8df_aligned*)__P); } static __inline__ void __DEFAULT_FN_ATTRS _mm512_stream_ps (float *__P, __m512 __A) { - __builtin_nontemporal_store((__v16sf)__A, (__v16sf*)__P); + typedef __v16sf __v16sf_aligned __attribute__((aligned(64))); + __builtin_nontemporal_store((__v16sf_aligned)__A, (__v16sf_aligned*)__P); } static __inline__ __m512d __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 908359fd1e..64a4d94aa9 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -28,26 +28,26 @@ #ifndef __AVXINTRIN_H #define __AVXINTRIN_H -typedef double __v4df __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef float __v8sf __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef long long __v4di __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef int __v8si __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef short __v16hi __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef char __v32qi __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); +typedef double __v4df __attribute__ ((__vector_size__ (32))); +typedef float __v8sf __attribute__ ((__vector_size__ (32))); +typedef long long __v4di __attribute__ ((__vector_size__ (32))); +typedef int __v8si __attribute__ ((__vector_size__ (32))); +typedef short __v16hi __attribute__ ((__vector_size__ (32))); +typedef char __v32qi __attribute__ ((__vector_size__ (32))); /* Unsigned types */ -typedef unsigned long long __v4du __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef unsigned int __v8su __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef unsigned short __v16hu __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef unsigned char __v32qu __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); +typedef unsigned long long __v4du __attribute__ ((__vector_size__ (32))); +typedef unsigned int __v8su __attribute__ ((__vector_size__ (32))); +typedef unsigned short __v16hu __attribute__ ((__vector_size__ (32))); +typedef unsigned char __v32qu __attribute__ ((__vector_size__ (32))); /* We need an explicitly signed variant for char. Note that this shouldn't * appear in the interface though. */ -typedef signed char __v32qs __attribute__((__vector_size__(32))) __attribute__((__aligned__(32))); +typedef signed char __v32qs __attribute__((__vector_size__(32))); -typedef float __m256 __attribute__ ((__vector_size__ (32))) __attribute__((__aligned__(32))); -typedef double __m256d __attribute__((__vector_size__(32))) __attribute__((__aligned__(32))); -typedef long long __m256i __attribute__((__vector_size__(32))) __attribute__((__aligned__(32))); +typedef float __m256 __attribute__ ((__vector_size__ (32))); +typedef double __m256d __attribute__((__vector_size__(32))); +typedef long long __m256i __attribute__((__vector_size__(32))); /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx"))) @@ -3593,7 +3593,8 @@ _mm_maskstore_ps(float *__p, __m128i __m, __m128 __a) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_si256(__m256i *__a, __m256i __b) { - __builtin_nontemporal_store((__v4di)__b, (__v4di*)__a); + typedef __v4di __v4di_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v4di_aligned)__b, (__v4di_aligned*)__a); } /// Moves double-precision values from a 256-bit vector of [4 x double] @@ -3612,7 +3613,8 @@ _mm256_stream_si256(__m256i *__a, __m256i __b) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_pd(double *__a, __m256d __b) { - __builtin_nontemporal_store((__v4df)__b, (__v4df*)__a); + typedef __v4df __v4df_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v4df_aligned)__b, (__v4df_aligned*)__a); } /// Moves single-precision floating point values from a 256-bit vector @@ -3632,7 +3634,8 @@ _mm256_stream_pd(double *__a, __m256d __b) static __inline void __DEFAULT_FN_ATTRS _mm256_stream_ps(float *__p, __m256 __a) { - __builtin_nontemporal_store((__v8sf)__a, (__v8sf*)__p); + typedef __v8sf __v8sf_aligned __attribute__((aligned(32))); + __builtin_nontemporal_store((__v8sf_aligned)__a, (__v8sf_aligned*)__p); } /* Create vectors */ diff --git a/test/CodeGen/arm-swiftcall.c b/test/CodeGen/arm-swiftcall.c index 75229c40a1..53109a3f68 100644 --- a/test/CodeGen/arm-swiftcall.c +++ b/test/CodeGen/arm-swiftcall.c @@ -64,8 +64,8 @@ typedef double double2 __attribute__((ext_vector_type(2))); typedef double double4 __attribute__((ext_vector_type(4))); typedef int int3 __attribute__((ext_vector_type(3))); typedef int int4 __attribute__((ext_vector_type(4))); -typedef int int5 __attribute__((ext_vector_type(5))) __attribute__((aligned(32))); -typedef int int8 __attribute__((ext_vector_type(8))) __attribute__((aligned(32))); +typedef int int5 __attribute__((ext_vector_type(5))); +typedef int int8 __attribute__((ext_vector_type(8))); typedef char char16 __attribute__((ext_vector_type(16))); typedef short short8 __attribute__((ext_vector_type(8))); typedef long long long2 __attribute__((ext_vector_type(2))); diff --git a/test/CodeGen/vector-alignment.c b/test/CodeGen/vector-alignment.c index 425819b5a0..d1fd771fb7 100644 --- a/test/CodeGen/vector-alignment.c +++ b/test/CodeGen/vector-alignment.c @@ -1,68 +1,38 @@ // RUN: %clang_cc1 -w -triple x86_64-apple-darwin10 \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_SSE +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=SSE // RUN: %clang_cc1 -w -triple i386-apple-darwin10 \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_SSE +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=SSE // RUN: %clang_cc1 -w -triple x86_64-apple-darwin10 -target-feature +avx \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_AVX +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=AVX // RUN: %clang_cc1 -w -triple i386-apple-darwin10 -target-feature +avx \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_AVX +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=AVX // RUN: %clang_cc1 -w -triple x86_64-apple-darwin10 -target-feature +avx512f \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_AVX512 +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=AVX512 // RUN: %clang_cc1 -w -triple i386-apple-darwin10 -target-feature +avx512f \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_AVX512 -// RUN: %clang_cc1 -w -triple armv7-apple-ios10 \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_ARM32 -// RUN: %clang_cc1 -w -triple arm64-apple-ios10 \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=DARWIN_ARM64 - -// RUN: %clang_cc1 -w -triple x86_64-pc-linux \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC -// RUN: %clang_cc1 -w -triple i386-pc-linux \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC -// RUN: %clang_cc1 -w -triple x86_64-pc-linux -target-feature +avx \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC -// RUN: %clang_cc1 -w -triple i386-pc-linux -target-feature +avx \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC -// RUN: %clang_cc1 -w -triple x86_64-pc-linux -target-feature +avx512f \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC -// RUN: %clang_cc1 -w -triple i386-pc-linux -target-feature +avx512f \ -// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC - +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=ALL --check-prefix=AVX512 // rdar://11759609 // At or below target max alignment with no aligned attribute should align based // on the size of vector. double __attribute__((vector_size(16))) v1; -// DARWIN_SSE: @v1 {{.*}}, align 16 -// DARWIN_AVX: @v1 {{.*}}, align 16 -// DARWIN_AVX512: @v1 {{.*}}, align 16 -// DARWIN_ARM32: @v1 {{.*}}, align 16 -// DARWIN_ARM64: @v1 {{.*}}, align 16 -// GENERIC: @v1 {{.*}}, align 16 +// SSE: @v1 {{.*}}, align 16 +// AVX: @v1 {{.*}}, align 16 +// AVX512: @v1 {{.*}}, align 16 double __attribute__((vector_size(32))) v2; -// DARWIN_SSE: @v2 {{.*}}, align 16 -// DARWIN_AVX: @v2 {{.*}}, align 16 -// DARWIN_AVX512: @v2 {{.*}}, align 16 -// DARWIN_ARM32: @v2 {{.*}}, align 16 -// DARWIN_ARM64: @v2 {{.*}}, align 16 -// GENERIC: @v2 {{.*}}, align 32 +// SSE: @v2 {{.*}}, align 16 +// AVX: @v2 {{.*}}, align 32 +// AVX512: @v2 {{.*}}, align 32 // Alignment above target max alignment with no aligned attribute should align // based on the target max. double __attribute__((vector_size(64))) v3; -// DARWIN_SSE: @v3 {{.*}}, align 16 -// DARWIN_AVX: @v3 {{.*}}, align 16 -// DARWIN_AVX512: @v3 {{.*}}, align 16 -// DARWIN_ARM32: @v3 {{.*}}, align 16 -// DARWIN_ARM64: @v3 {{.*}}, align 16 -// GENERIC: @v3 {{.*}}, align 64 +// SSE: @v3 {{.*}}, align 16 +// AVX: @v3 {{.*}}, align 32 +// AVX512: @v3 {{.*}}, align 64 double __attribute__((vector_size(1024))) v4; -// DARWIN_SSE: @v4 {{.*}}, align 16 -// DARWIN_AVX: @v4 {{.*}}, align 16 -// DARWIN_AVX512: @v4 {{.*}}, align 16 -// DARWIN_ARM32: @v4 {{.*}}, align 16 -// DARWIN_ARM64: @v4 {{.*}}, align 16 -// GENERIC: @v4 {{.*}}, align 1024 +// SSE: @v4 {{.*}}, align 16 +// AVX: @v4 {{.*}}, align 32 +// AVX512: @v4 {{.*}}, align 64 // Aliged attribute should always override. double __attribute__((vector_size(16), aligned(16))) v5; @@ -76,19 +46,13 @@ double __attribute__((vector_size(32), aligned(64))) v8; // Check non-power of 2 widths. double __attribute__((vector_size(24))) v9; -// DARWIN_SSE: @v9 {{.*}}, align 16 -// DARWIN_AVX: @v9 {{.*}}, align 16 -// DARWIN_AVX512: @v9 {{.*}}, align 16 -// DARWIN_ARM32: @v9 {{.*}}, align 16 -// DARWIN_ARM64: @v9 {{.*}}, align 16 -// GENERIC: @v9 {{.*}}, align 32 +// SSE: @v9 {{.*}}, align 16 +// AVX: @v9 {{.*}}, align 32 +// AVX512: @v9 {{.*}}, align 32 double __attribute__((vector_size(40))) v10; -// DARWIN_SSE: @v10 {{.*}}, align 16 -// DARWIN_AVX: @v10 {{.*}}, align 16 -// DARWIN_AVX512: @v10 {{.*}}, align 16 -// DARWIN_ARM32: @v10 {{.*}}, align 16 -// DARWIN_ARM64: @v10 {{.*}}, align 16 -// GENERIC: @v10 {{.*}}, align 64 +// SSE: @v10 {{.*}}, align 16 +// AVX: @v10 {{.*}}, align 32 +// AVX512: @v10 {{.*}}, align 64 // Check non-power of 2 widths with aligned attribute. double __attribute__((vector_size(24), aligned(64))) v11; diff --git a/test/CodeGenCXX/align-avx-complete-objects.cpp b/test/CodeGenCXX/align-avx-complete-objects.cpp index 1271e021fc..ad4a91428d 100644 --- a/test/CodeGenCXX/align-avx-complete-objects.cpp +++ b/test/CodeGenCXX/align-avx-complete-objects.cpp @@ -12,7 +12,7 @@ volatile float TestAlign(void) return r[0]; } -// CHECK: [[R:%.*]] = alloca <8 x float>, align 16 +// CHECK: [[R:%.*]] = alloca <8 x float>, align 32 // CHECK-NEXT: [[CALL:%.*]] = call i8* @_Znwm(i64 32) // CHECK-NEXT: [[ZERO:%.*]] = bitcast i8* [[CALL]] to <8 x float>* // CHECK-NEXT: store <8 x float>* [[ZERO]], <8 x float>** [[P:%.*]], align 8 @@ -22,8 +22,8 @@ volatile float TestAlign(void) // CHECK-NEXT: store volatile <8 x float> [[TWO]], <8 x float>* [[THREE]], align 16 // CHECK-NEXT: [[FOUR:%.*]] = load <8 x float>*, <8 x float>** [[P]], align 8 // CHECK-NEXT: [[FIVE:%.*]] = load volatile <8 x float>, <8 x float>* [[FOUR]], align 16 -// CHECK-NEXT: store <8 x float> [[FIVE]], <8 x float>* [[R]], align 16 -// CHECK-NEXT: [[SIX:%.*]] = load <8 x float>, <8 x float>* [[R]], align 16 +// CHECK-NEXT: store <8 x float> [[FIVE]], <8 x float>* [[R]], align 32 +// CHECK-NEXT: [[SIX:%.*]] = load <8 x float>, <8 x float>* [[R]], align 32 // CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x float> [[SIX]], i32 0 // CHECK-NEXT: ret float [[VECEXT]] -- GitLab From 804656e720e548d443c0df7a01ef29a753572f1e Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Mon, 4 Jun 2018 23:05:24 +0000 Subject: [PATCH 0011/1023] [ThinLTO] Add testing of new summary index format to a couple CFI tests Summary: Adds testing of combined index summary entries in disassembly format to CFI tests that were already testing the bitcode format. Depends on D46699. Reviewers: pcc Subscribers: mehdi_amini, inglorion, eraman, cfe-commits Differential Revision: https://reviews.llvm.org/D46700 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333966 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/thinlto-distributed-cfi-devirt.ll | 5 +++++ test/CodeGen/thinlto-distributed-cfi.ll | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/test/CodeGen/thinlto-distributed-cfi-devirt.ll b/test/CodeGen/thinlto-distributed-cfi-devirt.ll index aaec1aeb6c..c4a3164497 100644 --- a/test/CodeGen/thinlto-distributed-cfi-devirt.ll +++ b/test/CodeGen/thinlto-distributed-cfi-devirt.ll @@ -29,6 +29,11 @@ ; CHECK: blob data = '_ZTS1A_ZN1A1nEi' ; CHECK-LABEL: Date: Tue, 5 Jun 2018 00:11:41 +0000 Subject: [PATCH 0012/1023] [clang-proto-fuzzer] Refactored LLVMFuzzerInitialize into its own file. Copied and renamed some files in preparation for new loop-proto-fuzzer. Patch By: emmettneyman Differential Revision: https://reviews.llvm.org/D47666 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333969 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/CMakeLists.txt | 4 ++ .../clang-fuzzer/ExampleClangProtoFuzzer.cpp | 20 +-------- .../fuzzer-initialize/CMakeLists.txt | 3 ++ .../fuzzer-initialize/fuzzer_initialize.cpp | 43 +++++++++++++++++++ .../fuzzer-initialize/fuzzer_initialize.h | 19 ++++++++ 5 files changed, 71 insertions(+), 18 deletions(-) create mode 100644 tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt create mode 100644 tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp create mode 100644 tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h diff --git a/tools/clang-fuzzer/CMakeLists.txt b/tools/clang-fuzzer/CMakeLists.txt index 96fe1fabbf..cc9266c4db 100644 --- a/tools/clang-fuzzer/CMakeLists.txt +++ b/tools/clang-fuzzer/CMakeLists.txt @@ -40,6 +40,9 @@ if(CLANG_ENABLE_PROTO_FUZZER) # Build the protobuf->C++ translation library and driver. add_clang_subdirectory(proto-to-cxx) + # Build the fuzzer initialization library. + add_clang_subdirectory(fuzzer-initialize) + # Build the protobuf fuzzer add_clang_executable(clang-proto-fuzzer ${DUMMY_MAIN} @@ -52,6 +55,7 @@ if(CLANG_ENABLE_PROTO_FUZZER) ${PROTOBUF_LIBRARIES} ${LLVM_LIB_FUZZING_ENGINE} clangCXXProto + clangFuzzerInitialize clangHandleCXX clangProtoToCXX ) diff --git a/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp index 53249cafbe..159ded3ca1 100644 --- a/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp +++ b/tools/clang-fuzzer/ExampleClangProtoFuzzer.cpp @@ -17,28 +17,12 @@ #include "cxx_proto.pb.h" #include "handle-cxx/handle_cxx.h" #include "proto-to-cxx/proto_to_cxx.h" - +#include "fuzzer-initialize/fuzzer_initialize.h" #include "src/libfuzzer/libfuzzer_macro.h" -#include - using namespace clang_fuzzer; -static std::vector CLArgs; - -extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { - CLArgs.push_back("-O2"); - for (int I = 1; I < *argc; I++) { - if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) { - for (I++; I < *argc; I++) - CLArgs.push_back((*argv)[I]); - break; - } - } - return 0; -} - DEFINE_BINARY_PROTO_FUZZER(const Function& input) { auto S = FunctionToString(input); - HandleCXX(S, CLArgs); + HandleCXX(S, GetCLArgs()); } diff --git a/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt b/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt new file mode 100644 index 0000000000..c149fb3d4b --- /dev/null +++ b/tools/clang-fuzzer/fuzzer-initialize/CMakeLists.txt @@ -0,0 +1,3 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support) + +add_clang_library(clangFuzzerInitialize fuzzer_initialize.cpp) diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp new file mode 100644 index 0000000000..08bc242b88 --- /dev/null +++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp @@ -0,0 +1,43 @@ +//===-- fuzzer_initialize.cpp - Fuzz Clang --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements two functions: one that returns the command line +/// arguments for a given call to the fuzz target and one that initializes +/// the fuzzer with the correct command line arguments. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzer_initialize.h" +#include + +using namespace clang_fuzzer; + + +namespace clang_fuzzer { + +static std::vector CLArgs; + +const std::vector& GetCLArgs() { + return CLArgs; +} + +} + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + CLArgs.push_back("-O2"); + for (int I = 1; I < *argc; I++) { + if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) { + for (I++; I < *argc; I++) + CLArgs.push_back((*argv)[I]); + break; + } + } + return 0; +} diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h new file mode 100644 index 0000000000..83a5cf9dc5 --- /dev/null +++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.h @@ -0,0 +1,19 @@ +//==-- fuzzer_initialize.h - Fuzz Clang ------------------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a function that returns the command line arguments for a specific +// call to the fuzz target. +// +//===----------------------------------------------------------------------===// + +#include + +namespace clang_fuzzer { +const std::vector& GetCLArgs(); +} -- GitLab From ce9d274375110045b504004b133b54711112966d Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 5 Jun 2018 01:33:40 +0000 Subject: [PATCH 0013/1023] Reimplement the bittest intrinsic family as builtins with inline asm We need to implement _interlockedbittestandset as a builtin for windows.h, so we might as well do the whole family. It reduces code duplication anyway. Fixes PR33188, a long standing bug in our bittest implementation encountered by Chakra. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333978 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 13 ++++- lib/CodeGen/CGBuiltin.cpp | 75 ++++++++++++++++++++------- lib/Headers/intrin.h | 81 ------------------------------ test/CodeGen/bittest-intrin.c | 35 +++++++++++++ test/CodeGen/ms-intrinsics-other.c | 11 ---- test/CodeGen/ms-intrinsics.c | 11 ---- 6 files changed, 103 insertions(+), 123 deletions(-) create mode 100644 test/CodeGen/bittest-intrin.c diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 510b143d5b..ed2190dac4 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -744,6 +744,14 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn") LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES) LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittest, "UcNiC*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandcomplement, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandreset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittest64, "UcWiC*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandcomplement64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandreset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) @@ -783,7 +791,10 @@ LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 8793f83e29..c6c9df460e 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -484,6 +484,37 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown}); } +static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, const CallExpr *E, + char TestAnd, char Size, + bool Locked = false) { + Value *BitBase = CGF.EmitScalarExpr(E->getArg(0)); + Value *BitPos = CGF.EmitScalarExpr(E->getArg(1)); + + // Build the assembly. + SmallString<64> Asm; + raw_svector_ostream AsmOS(Asm); + if (Locked) + AsmOS << "lock "; + AsmOS << "bt"; + if (TestAnd) + AsmOS << TestAnd; + AsmOS << Size << " $2, ($1)\n\tsetc ${0:b}"; + + // Build the constraints. FIXME: We should support immediates when possible. + std::string Constraints = "=r,r,r,~{cc},~{flags},~{memory},~{fpsr}"; + llvm::IntegerType *IntType = llvm::IntegerType::get( + CGF.getLLVMContext(), + CGF.getContext().getTypeSize(E->getArg(1)->getType())); + llvm::Type *IntPtrType = IntType->getPointerTo(); + llvm::FunctionType *FTy = + llvm::FunctionType::get(CGF.Int8Ty, {IntPtrType, IntType}, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); + CallSite CS = CGF.Builder.CreateCall(IA, {BitBase, BitPos}); + return RValue::get(CS.getInstruction()); +} + // Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we // handle them here. enum class CodeGenFunction::MSVCIntrin { @@ -497,7 +528,6 @@ enum class CodeGenFunction::MSVCIntrin { _InterlockedIncrement, _InterlockedOr, _InterlockedXor, - _interlockedbittestandset, __fastfail, }; @@ -565,22 +595,6 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, case MSVCIntrin::_InterlockedXor: return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E); - case MSVCIntrin::_interlockedbittestandset: { - llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); - llvm::Value *Bit = EmitScalarExpr(E->getArg(1)); - AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( - AtomicRMWInst::Or, Addr, - Builder.CreateShl(ConstantInt::get(Bit->getType(), 1), Bit), - llvm::AtomicOrdering::SequentiallyConsistent); - // Shift the relevant bit to the least significant position, truncate to - // the result type, and test the low bit. - llvm::Value *Shifted = Builder.CreateLShr(RMWI, Bit); - llvm::Value *Truncated = - Builder.CreateTrunc(Shifted, ConvertType(E->getType())); - return Builder.CreateAnd(Truncated, - ConstantInt::get(Truncated->getType(), 1)); - } - case MSVCIntrin::_InterlockedDecrement: { llvm::Type *IntTy = ConvertType(E->getType()); AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( @@ -2791,9 +2805,32 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI_InterlockedXor16: case Builtin::BI_InterlockedXor: return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E)); + + case Builtin::BI_bittest: + return EmitBitTestIntrinsic(*this, E, '\0', 'l'); + case Builtin::BI_bittestandcomplement: + return EmitBitTestIntrinsic(*this, E, 'c', 'l'); + case Builtin::BI_bittestandreset: + return EmitBitTestIntrinsic(*this, E, 'r', 'l'); + case Builtin::BI_bittestandset: + return EmitBitTestIntrinsic(*this, E, 's', 'l'); + case Builtin::BI_interlockedbittestandreset: + return EmitBitTestIntrinsic(*this, E, 'r', 'l', /*Locked=*/true); case Builtin::BI_interlockedbittestandset: - return RValue::get( - EmitMSVCBuiltinExpr(MSVCIntrin::_interlockedbittestandset, E)); + return EmitBitTestIntrinsic(*this, E, 's', 'l', /*Locked=*/true); + + case Builtin::BI_bittest64: + return EmitBitTestIntrinsic(*this, E, '\0', 'q'); + case Builtin::BI_bittestandcomplement64: + return EmitBitTestIntrinsic(*this, E, 'c', 'q'); + case Builtin::BI_bittestandreset64: + return EmitBitTestIntrinsic(*this, E, 'r', 'q'); + case Builtin::BI_bittestandset64: + return EmitBitTestIntrinsic(*this, E, 's', 'q'); + case Builtin::BI_interlockedbittestandreset64: + return EmitBitTestIntrinsic(*this, E, 'r', 'q', /*Locked=*/true); + case Builtin::BI_interlockedbittestandset64: + return EmitBitTestIntrinsic(*this, E, 's', 'q', /*Locked=*/true); case Builtin::BI__exception_code: case Builtin::BI_exception_code: diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index b30aa215a4..4600942016 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -161,13 +161,9 @@ static __inline__ unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); static __inline__ unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); -static __inline__ unsigned char _bittest(long const *, long); -static __inline__ unsigned char _bittestandcomplement(long *, long); -static __inline__ unsigned char _bittestandreset(long *, long); -static __inline__ unsigned char _bittestandset(long *, long); void __cdecl _disable(void); void __cdecl _enable(void); @@ -260,20 +256,15 @@ static __inline__ unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); static __inline__ unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); -static __inline__ unsigned char _bittest64(__int64 const *, __int64); -static __inline__ unsigned char _bittestandcomplement64(__int64 *, __int64); -static __inline__ unsigned char _bittestandreset64(__int64 *, __int64); -static __inline__ unsigned char _bittestandset64(__int64 *, __int64); long _InterlockedAnd_np(long volatile *_Value, long _Mask); short _InterlockedAnd16_np(short volatile *_Value, short _Mask); __int64 _InterlockedAnd64_np(__int64 volatile *_Value, __int64 _Mask); char _InterlockedAnd8_np(char volatile *_Value, char _Mask); unsigned char _interlockedbittestandreset64(__int64 volatile *, __int64); -static __inline__ unsigned char _interlockedbittestandset64(__int64 volatile *, __int64); long _InterlockedCompareExchange_np(long volatile *_Destination, long _Exchange, long _Comparand); @@ -341,78 +332,6 @@ __int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask); #endif -/*----------------------------------------------------------------------------*\ -|* Bit Counting and Testing -\*----------------------------------------------------------------------------*/ -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittest(long const *_BitBase, long _BitPos) { - return (*_BitBase >> _BitPos) & 1; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandcomplement(long *_BitBase, long _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase ^ (1 << _BitPos); - return _Res; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandreset(long *_BitBase, long _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase & ~(1 << _BitPos); - return _Res; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandset(long *_BitBase, long _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase | (1 << _BitPos); - return _Res; -} -#if defined(__arm__) || defined(__aarch64__) -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_interlockedbittestandset_acq(long volatile *_BitBase, long _BitPos) { - long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_ACQUIRE); - return (_PrevVal >> _BitPos) & 1; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_interlockedbittestandset_nf(long volatile *_BitBase, long _BitPos) { - long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELAXED); - return (_PrevVal >> _BitPos) & 1; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_interlockedbittestandset_rel(long volatile *_BitBase, long _BitPos) { - long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELEASE); - return (_PrevVal >> _BitPos) & 1; -} -#endif -#ifdef __x86_64__ -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittest64(__int64 const *_BitBase, __int64 _BitPos) { - return (*_BitBase >> _BitPos) & 1; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandcomplement64(__int64 *_BitBase, __int64 _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase ^ (1ll << _BitPos); - return _Res; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandreset64(__int64 *_BitBase, __int64 _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase & ~(1ll << _BitPos); - return _Res; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_bittestandset64(__int64 *_BitBase, __int64 _BitPos) { - unsigned char _Res = (*_BitBase >> _BitPos) & 1; - *_BitBase = *_BitBase | (1ll << _BitPos); - return _Res; -} -static __inline__ unsigned char __DEFAULT_FN_ATTRS -_interlockedbittestandset64(__int64 volatile *_BitBase, __int64 _BitPos) { - long long _PrevVal = - __atomic_fetch_or(_BitBase, 1ll << _BitPos, __ATOMIC_SEQ_CST); - return (_PrevVal >> _BitPos) & 1; -} -#endif /*----------------------------------------------------------------------------*\ |* Interlocked Exchange Add \*----------------------------------------------------------------------------*/ diff --git a/test/CodeGen/bittest-intrin.c b/test/CodeGen/bittest-intrin.c new file mode 100644 index 0000000000..839d5656a9 --- /dev/null +++ b/test/CodeGen/bittest-intrin.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s + +volatile unsigned char sink = 0; +void test32(long *base, long idx) { + sink = _bittest(base, idx); + sink = _bittestandcomplement(base, idx); + sink = _bittestandreset(base, idx); + sink = _bittestandset(base, idx); + sink = _interlockedbittestandreset(base, idx); + sink = _interlockedbittestandset(base, idx); +} +void test64(__int64 *base, __int64 idx) { + sink = _bittest64(base, idx); + sink = _bittestandcomplement64(base, idx); + sink = _bittestandreset64(base, idx); + sink = _bittestandset64(base, idx); + sink = _interlockedbittestandreset64(base, idx); + sink = _interlockedbittestandset64(base, idx); +} + +// CHECK-LABEL: define dso_local void @test32(i32* %base, i32 %idx) +// CHECK: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// CHECK: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// CHECK: call i8 asm sideeffect "btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// CHECK: call i8 asm sideeffect "btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// CHECK: call i8 asm sideeffect "lock btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// CHECK: call i8 asm sideeffect "lock btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) + +// CHECK-LABEL: define dso_local void @test64(i64* %base, i64 %idx) +// CHECK: call i8 asm sideeffect "btq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// CHECK: call i8 asm sideeffect "btcq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// CHECK: call i8 asm sideeffect "btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// CHECK: call i8 asm sideeffect "btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// CHECK: call i8 asm sideeffect "lock btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// CHECK: call i8 asm sideeffect "lock btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) diff --git a/test/CodeGen/ms-intrinsics-other.c b/test/CodeGen/ms-intrinsics-other.c index d23bc73018..65d7670584 100644 --- a/test/CodeGen/ms-intrinsics-other.c +++ b/test/CodeGen/ms-intrinsics-other.c @@ -148,14 +148,3 @@ LONG test_InterlockedDecrement(LONG volatile *Addend) { // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK: ret i32 [[RESULT]] // CHECK: } - -unsigned char test_interlockedbittestandset(volatile LONG *ptr, LONG bit) { - return _interlockedbittestandset(ptr, bit); -} -// CHECK-LABEL: define{{.*}} i8 @test_interlockedbittestandset -// CHECK: [[MASKBIT:%[0-9]+]] = shl i32 1, %bit -// CHECK: [[OLD:%[0-9]+]] = atomicrmw or i32* %ptr, i32 [[MASKBIT]] seq_cst -// CHECK: [[SHIFT:%[0-9]+]] = lshr i32 [[OLD]], %bit -// CHECK: [[TRUNC:%[0-9]+]] = trunc i32 [[SHIFT]] to i8 -// CHECK: [[AND:%[0-9]+]] = and i8 [[TRUNC]], 1 -// CHECK: ret i8 [[AND]] diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c index 7f434b4eaf..632fa18060 100644 --- a/test/CodeGen/ms-intrinsics.c +++ b/test/CodeGen/ms-intrinsics.c @@ -455,17 +455,6 @@ __int64 test_InterlockedDecrement64(__int64 volatile *Addend) { #endif -unsigned char test_interlockedbittestandset(volatile long *ptr, long bit) { - return _interlockedbittestandset(ptr, bit); -} -// CHECK-LABEL: define{{.*}} i8 @test_interlockedbittestandset -// CHECK: [[MASKBIT:%[0-9]+]] = shl i32 1, %bit -// CHECK: [[OLD:%[0-9]+]] = atomicrmw or i32* %ptr, i32 [[MASKBIT]] seq_cst -// CHECK: [[SHIFT:%[0-9]+]] = lshr i32 [[OLD]], %bit -// CHECK: [[TRUNC:%[0-9]+]] = trunc i32 [[SHIFT]] to i8 -// CHECK: [[AND:%[0-9]+]] = and i8 [[TRUNC]], 1 -// CHECK: ret i8 [[AND]] - void test__fastfail() { __fastfail(42); } -- GitLab From 3bdaf7fb5d05378f73c19d9d051ce4690a811d3c Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 5 Jun 2018 01:50:59 +0000 Subject: [PATCH 0014/1023] [Driver][Fuchsia] Pass LTO flags to linker Even though we use lld by default for Fuchsia, we use Gold plugin arguments like all other drivers as lld supports Gold plugin options. Differential Revision: https://reviews.llvm.org/D47668 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333979 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Fuchsia.cpp | 6 ++++++ test/Driver/fuchsia.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index cfdb3d80a5..c54cf60ef8 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -100,6 +100,12 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.AddFilePathLibArgs(Args, CmdArgs); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + addSanitizerRuntimes(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c index 1ec7935641..c2b02522ab 100644 --- a/test/Driver/fuchsia.c +++ b/test/Driver/fuchsia.c @@ -114,3 +114,16 @@ // RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED // CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo" // CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo-x86_64.so" + +// RUN: %clang %s -### --target=aarch64-fuchsia \ +// RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-LTO +// CHECK-LTO: "-plugin-opt=mcpu=cortex-a53" +// CHECK-LTO: "-plugin-opt=O3" + +// RUN: %clang %s -### --target=x86_64-fuchsia \ +// RUN: -flto=thin -flto-jobs=8 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO +// CHECK-THINLTO: "-plugin-opt=mcpu=x86-64" +// CHECK-THINLTO: "-plugin-opt=thinlto" +// CHECK-THINLTO: "-plugin-opt=jobs=8" -- GitLab From e6a11c7e15ecd187649506497b60609bfb8f96e2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 5 Jun 2018 03:12:14 +0000 Subject: [PATCH 0015/1023] [X86] Mark all the builtins and intrinsics that require MMX and an SSE feature as requiring both mmx and the sse feature. Previously we only checked the sse feature, but this means that if you passed -mno-mmx, the builtins/intrinsics wouldn't be disabled in the frontend and would instead fail backend isel. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333980 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 74 ++++++++++++++--------------- lib/Headers/emmintrin.h | 14 +++--- lib/Headers/tmmintrin.h | 32 +++++++------ lib/Headers/xmmintrin.h | 50 +++++++++---------- 4 files changed, 88 insertions(+), 82 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 7710b621de..6f7ecaf28c 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -145,47 +145,47 @@ TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "nc", "mmx") TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "nc", "mmx") // MMX2 (MMX+SSE) intrinsics -TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "nc", "sse") +TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "nc", "mmx,sse") // MMX+SSE2 -TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "nc", "mmx,sse2") // MMX+SSSE3 -TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "nc", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "nc", "mmx,ssse3") // SSE intrinsics. TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "nc", "sse") diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index c5fb2362ad..1af1fcb377 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -46,6 +46,7 @@ typedef signed char __v16qs __attribute__((__vector_size__(16))); /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2"))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse2"))) /// Adds lower double-precision values in both operands and returns the /// sum in the lower 64 bits of the result. The upper 64 bits of the result @@ -1514,7 +1515,7 @@ _mm_cvttsd_si32(__m128d __a) /// \param __a /// A 128-bit vector of [2 x double]. /// \returns A 64-bit vector of [2 x i32] containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtpd_pi32(__m128d __a) { return (__m64)__builtin_ia32_cvtpd2pi((__v2df)__a); @@ -1534,7 +1535,7 @@ _mm_cvtpd_pi32(__m128d __a) /// \param __a /// A 128-bit vector of [2 x double]. /// \returns A 64-bit vector of [2 x i32] containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvttpd_pi32(__m128d __a) { return (__m64)__builtin_ia32_cvttpd2pi((__v2df)__a); @@ -1551,7 +1552,7 @@ _mm_cvttpd_pi32(__m128d __a) /// \param __a /// A 64-bit vector of [2 x i32]. /// \returns A 128-bit vector of [2 x double] containing the converted values. -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS_MMX _mm_cvtpi32_pd(__m64 __a) { return __builtin_ia32_cvtpi2pd((__v2si)__a); @@ -2142,7 +2143,7 @@ _mm_add_epi32(__m128i __a, __m128i __b) /// \param __b /// A 64-bit integer. /// \returns A 64-bit integer containing the sum of both parameters. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_add_si64(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_paddq((__v1di)__a, (__v1di)__b); @@ -2482,7 +2483,7 @@ _mm_mullo_epi16(__m128i __a, __m128i __b) /// \param __b /// A 64-bit integer containing one of the source operands. /// \returns A 64-bit integer vector containing the product of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_mul_su32(__m64 __a, __m64 __b) { return __builtin_ia32_pmuludq((__v2si)__a, (__v2si)__b); @@ -2596,7 +2597,7 @@ _mm_sub_epi32(__m128i __a, __m128i __b) /// A 64-bit integer vector containing the subtrahend. /// \returns A 64-bit integer vector containing the difference of the values in /// the operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_sub_si64(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_psubq((__v1di)__a, (__v1di)__b); @@ -4935,6 +4936,7 @@ void _mm_pause(void); } // extern "C" #endif #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS_MMX #define _MM_SHUFFLE2(x, y) (((x) << 1) | (y)) diff --git a/lib/Headers/tmmintrin.h b/lib/Headers/tmmintrin.h index b0d5f2a3d4..a3d11b90a4 100644 --- a/lib/Headers/tmmintrin.h +++ b/lib/Headers/tmmintrin.h @@ -28,6 +28,7 @@ /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3"))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,ssse3"))) /// Computes the absolute value of each of the packed 8-bit signed /// integers in the source operand and stores the 8-bit unsigned integer @@ -41,7 +42,7 @@ /// A 64-bit vector of [8 x i8]. /// \returns A 64-bit integer vector containing the absolute values of the /// elements in the operand. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_abs_pi8(__m64 __a) { return (__m64)__builtin_ia32_pabsb((__v8qi)__a); @@ -77,7 +78,7 @@ _mm_abs_epi8(__m128i __a) /// A 64-bit vector of [4 x i16]. /// \returns A 64-bit integer vector containing the absolute values of the /// elements in the operand. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_abs_pi16(__m64 __a) { return (__m64)__builtin_ia32_pabsw((__v4hi)__a); @@ -113,7 +114,7 @@ _mm_abs_epi16(__m128i __a) /// A 64-bit vector of [2 x i32]. /// \returns A 64-bit integer vector containing the absolute values of the /// elements in the operand. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_abs_pi32(__m64 __a) { return (__m64)__builtin_ia32_pabsd((__v2si)__a); @@ -246,7 +247,7 @@ _mm_hadd_epi32(__m128i __a, __m128i __b) /// destination. /// \returns A 64-bit vector of [4 x i16] containing the horizontal sums of both /// operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hadd_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phaddw((__v4hi)__a, (__v4hi)__b); @@ -269,7 +270,7 @@ _mm_hadd_pi16(__m64 __a, __m64 __b) /// destination. /// \returns A 64-bit vector of [2 x i32] containing the horizontal sums of both /// operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hadd_pi32(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phaddd((__v2si)__a, (__v2si)__b); @@ -319,7 +320,7 @@ _mm_hadds_epi16(__m128i __a, __m128i __b) /// destination. /// \returns A 64-bit vector of [4 x i16] containing the horizontal saturated /// sums of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hadds_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phaddsw((__v4hi)__a, (__v4hi)__b); @@ -388,7 +389,7 @@ _mm_hsub_epi32(__m128i __a, __m128i __b) /// the destination. /// \returns A 64-bit vector of [4 x i16] containing the horizontal differences /// of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hsub_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phsubw((__v4hi)__a, (__v4hi)__b); @@ -411,7 +412,7 @@ _mm_hsub_pi16(__m64 __a, __m64 __b) /// the destination. /// \returns A 64-bit vector of [2 x i32] containing the horizontal differences /// of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hsub_pi32(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phsubd((__v2si)__a, (__v2si)__b); @@ -461,7 +462,7 @@ _mm_hsubs_epi16(__m128i __a, __m128i __b) /// the destination. /// \returns A 64-bit vector of [4 x i16] containing the horizontal saturated /// differences of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_hsubs_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_phsubsw((__v4hi)__a, (__v4hi)__b); @@ -525,7 +526,7 @@ _mm_maddubs_epi16(__m128i __a, __m128i __b) /// \a R1 := (\a __a2 * \a __b2) + (\a __a3 * \a __b3) \n /// \a R2 := (\a __a4 * \a __b4) + (\a __a5 * \a __b5) \n /// \a R3 := (\a __a6 * \a __b6) + (\a __a7 * \a __b7) -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_maddubs_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pmaddubsw((__v8qi)__a, (__v8qi)__b); @@ -565,7 +566,7 @@ _mm_mulhrs_epi16(__m128i __a, __m128i __b) /// A 64-bit vector of [4 x i16] containing one of the source operands. /// \returns A 64-bit vector of [4 x i16] containing the rounded and scaled /// products of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_mulhrs_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pmulhrsw((__v4hi)__a, (__v4hi)__b); @@ -616,7 +617,7 @@ _mm_shuffle_epi8(__m128i __a, __m128i __b) /// destination. \n /// Bits [3:0] select the source byte to be copied. /// \returns A 64-bit integer vector containing the copied or cleared values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_shuffle_pi8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pshufb((__v8qi)__a, (__v8qi)__b); @@ -720,7 +721,7 @@ _mm_sign_epi32(__m128i __a, __m128i __b) /// A 64-bit integer vector containing control bytes corresponding to /// positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_sign_pi8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_psignb((__v8qi)__a, (__v8qi)__b); @@ -746,7 +747,7 @@ _mm_sign_pi8(__m64 __a, __m64 __b) /// A 64-bit integer vector containing control words corresponding to /// positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_sign_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_psignw((__v4hi)__a, (__v4hi)__b); @@ -772,12 +773,13 @@ _mm_sign_pi16(__m64 __a, __m64 __b) /// A 64-bit integer vector containing two control doublewords corresponding /// to positions in the destination. /// \returns A 64-bit integer vector containing the resultant values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_sign_pi32(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_psignd((__v2si)__a, (__v2si)__b); } #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS_MMX #endif /* __TMMINTRIN_H */ diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 1e5d02ad6c..92db4779be 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -41,6 +41,7 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16))); /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse"))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse"))) /// Adds the 32-bit float values in the low-order bits of the operands. /// @@ -1365,7 +1366,7 @@ _mm_cvtss_si64(__m128 __a) /// \param __a /// A 128-bit vector of [4 x float]. /// \returns A 64-bit integer vector containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtps_pi32(__m128 __a) { return (__m64)__builtin_ia32_cvtps2pi((__v4sf)__a); @@ -1381,7 +1382,7 @@ _mm_cvtps_pi32(__m128 __a) /// \param __a /// A 128-bit vector of [4 x float]. /// \returns A 64-bit integer vector containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvt_ps2pi(__m128 __a) { return _mm_cvtps_pi32(__a); @@ -1458,7 +1459,7 @@ _mm_cvttss_si64(__m128 __a) /// \param __a /// A 128-bit vector of [4 x float]. /// \returns A 64-bit integer vector containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvttps_pi32(__m128 __a) { return (__m64)__builtin_ia32_cvttps2pi((__v4sf)__a); @@ -1475,7 +1476,7 @@ _mm_cvttps_pi32(__m128 __a) /// \param __a /// A 128-bit vector of [4 x float]. /// \returns A 64-bit integer vector containing the converted values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtt_ps2pi(__m128 __a) { return _mm_cvttps_pi32(__a); @@ -1570,7 +1571,7 @@ _mm_cvtsi64_ss(__m128 __a, long long __b) /// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the /// converted value of the second operand. The upper 64 bits are copied from /// the upper 64 bits of the first operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpi32_ps(__m128 __a, __m64 __b) { return __builtin_ia32_cvtpi2ps((__v4sf)__a, (__v2si)__b); @@ -1593,7 +1594,7 @@ _mm_cvtpi32_ps(__m128 __a, __m64 __b) /// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the /// converted value from the second operand. The upper 64 bits are copied /// from the upper 64 bits of the first operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvt_pi2ps(__m128 __a, __m64 __b) { return _mm_cvtpi32_ps(__a, __b); @@ -2119,7 +2120,7 @@ _mm_storer_ps(float *__p, __m128 __a) /// A pointer to an aligned memory location used to store the register value. /// \param __a /// A 64-bit integer containing the value to be stored. -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS_MMX _mm_stream_pi(__m64 *__p, __m64 __a) { __builtin_ia32_movntq(__p, __a); @@ -2230,7 +2231,7 @@ void _mm_sfence(void); /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the comparison results. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_max_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pmaxsw((__v4hi)__a, (__v4hi)__b); @@ -2249,7 +2250,7 @@ _mm_max_pi16(__m64 __a, __m64 __b) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the comparison results. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_max_pu8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pmaxub((__v8qi)__a, (__v8qi)__b); @@ -2268,7 +2269,7 @@ _mm_max_pu8(__m64 __a, __m64 __b) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the comparison results. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_min_pi16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pminsw((__v4hi)__a, (__v4hi)__b); @@ -2287,7 +2288,7 @@ _mm_min_pi16(__m64 __a, __m64 __b) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the comparison results. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_min_pu8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pminub((__v8qi)__a, (__v8qi)__b); @@ -2305,7 +2306,7 @@ _mm_min_pu8(__m64 __a, __m64 __b) /// A 64-bit integer vector containing the values with bits to be extracted. /// \returns The most significant bit from each 8-bit element in \a __a, /// written to bits [7:0]. -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS_MMX _mm_movemask_pi8(__m64 __a) { return __builtin_ia32_pmovmskb((__v8qi)__a); @@ -2324,7 +2325,7 @@ _mm_movemask_pi8(__m64 __a) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the products of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_mulhi_pu16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pmulhuw((__v4hi)__a, (__v4hi)__b); @@ -2387,7 +2388,7 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b) /// A pointer to a 64-bit memory location that will receive the conditionally /// copied integer values. The address of the memory location does not have /// to be aligned. -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS_MMX _mm_maskmove_si64(__m64 __d, __m64 __n, char *__p) { __builtin_ia32_maskmovq((__v8qi)__d, (__v8qi)__n, __p); @@ -2406,7 +2407,7 @@ _mm_maskmove_si64(__m64 __d, __m64 __n, char *__p) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the averages of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_avg_pu8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pavgb((__v8qi)__a, (__v8qi)__b); @@ -2425,7 +2426,7 @@ _mm_avg_pu8(__m64 __a, __m64 __b) /// \param __b /// A 64-bit integer vector containing one of the source operands. /// \returns A 64-bit integer vector containing the averages of both operands. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_avg_pu16(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_pavgw((__v4hi)__a, (__v4hi)__b); @@ -2447,7 +2448,7 @@ _mm_avg_pu16(__m64 __a, __m64 __b) /// \returns A 64-bit integer vector whose lower 16 bits contain the sums of the /// sets of absolute differences between both operands. The upper bits are /// cleared. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_sad_pu8(__m64 __a, __m64 __b) { return (__m64)__builtin_ia32_psadbw((__v8qi)__a, (__v8qi)__b); @@ -2730,7 +2731,7 @@ _mm_movelh_ps(__m128 __a, __m128 __b) /// from the corresponding elements in this operand. /// \returns A 128-bit vector of [4 x float] containing the copied and converted /// values from the operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpi16_ps(__m64 __a) { __m64 __b, __c; @@ -2760,7 +2761,7 @@ _mm_cvtpi16_ps(__m64 __a) /// destination are copied from the corresponding elements in this operand. /// \returns A 128-bit vector of [4 x float] containing the copied and converted /// values from the operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpu16_ps(__m64 __a) { __m64 __b, __c; @@ -2789,7 +2790,7 @@ _mm_cvtpu16_ps(__m64 __a) /// from the corresponding lower 4 elements in this operand. /// \returns A 128-bit vector of [4 x float] containing the copied and converted /// values from the operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpi8_ps(__m64 __a) { __m64 __b; @@ -2814,7 +2815,7 @@ _mm_cvtpi8_ps(__m64 __a) /// operand. /// \returns A 128-bit vector of [4 x float] containing the copied and converted /// values from the source operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpu8_ps(__m64 __a) { __m64 __b; @@ -2841,7 +2842,7 @@ _mm_cvtpu8_ps(__m64 __a) /// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the /// copied and converted values from the first operand. The upper 64 bits /// contain the copied and converted values from the second operand. -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS_MMX _mm_cvtpi32x2_ps(__m64 __a, __m64 __b) { __m128 __c; @@ -2870,7 +2871,7 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b) /// A 128-bit floating-point vector of [4 x float]. /// \returns A 64-bit integer vector of [4 x i16] containing the converted /// values. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtps_pi16(__m128 __a) { __m64 __b, __c; @@ -2900,7 +2901,7 @@ _mm_cvtps_pi16(__m128 __a) /// 128-bit floating-point vector of [4 x float]. /// \returns A 64-bit integer vector of [8 x i8]. The lower 32 bits contain the /// converted values and the uppper 32 bits are set to zero. -static __inline__ __m64 __DEFAULT_FN_ATTRS +static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtps_pi8(__m128 __a) { __m64 __b, __c; @@ -3003,6 +3004,7 @@ do { \ #define _m_ _mm_ #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS_MMX /* Ugly hack for backwards-compatibility (compatible with gcc) */ #if defined(__SSE2__) && !__building_module(_Builtin_intrinsics) -- GitLab From 2cf50762e034228e6a72cb37c61e959f04105404 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Tue, 5 Jun 2018 09:18:26 +0000 Subject: [PATCH 0016/1023] Detect an incompatible VLA pointer assignment For pointer assignments of VLA types, Clang currently detects when array dimensions _lower_ than a variable dimension differ, and reports a warning. However it does not do the same when the _higher_ dimensions differ, a case that GCC does catch. These two pointer types int (*foo)[1][bar][3]; int (*baz)[1][2][3]; are compatible with each another, and the program is well formed if bar == 2, a matter that is the programmers problem. However the following: int (*qux)[2][2][3]; would not be compatible with either, because the upper dimension differs in size. Clang reports baz is incompatible with qux, but not that foo is incompatible with qux because it doesn't check those higher dimensions. Fix this by comparing array sizes on higher dimensions: if both are constants but unequal then report incompatibility; if either dimension is variable then we can't know either way. Differential Revision: https://reviews.llvm.org/D47628 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333989 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 34 ++++++++++++++++++++++++++++++++-- test/Sema/vla.c | 13 +++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4956710b4f..c759c96be5 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -8601,6 +8601,38 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified); if (ResultType.isNull()) return {}; + + const VariableArrayType* LVAT = getAsVariableArrayType(LHS); + const VariableArrayType* RVAT = getAsVariableArrayType(RHS); + + // If either side is a variable array, and both are complete, check whether + // the current dimension is definite. + if (LVAT || RVAT) { + auto SizeFetch = [this](const VariableArrayType* VAT, + const ConstantArrayType* CAT) + -> std::pair { + if (VAT) { + llvm::APSInt TheInt; + Expr *E = VAT->getSizeExpr(); + if (E && E->isIntegerConstantExpr(TheInt, *this)) + return std::make_pair(true, TheInt); + else + return std::make_pair(false, TheInt); + } else if (CAT) { + return std::make_pair(true, CAT->getSize()); + } else { + return std::make_pair(false, llvm::APInt()); + } + }; + + bool HaveLSize, HaveRSize; + llvm::APInt LSize, RSize; + std::tie(HaveLSize, LSize) = SizeFetch(LVAT, LCAT); + std::tie(HaveRSize, RSize) = SizeFetch(RVAT, RCAT); + if (HaveLSize && HaveRSize && !llvm::APInt::isSameValue(LSize, RSize)) + return {}; // Definite, but unequal, array dimension + } + if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS; if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType)) @@ -8609,8 +8641,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, ArrayType::ArraySizeModifier(), 0); if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(), ArrayType::ArraySizeModifier(), 0); - const VariableArrayType* LVAT = getAsVariableArrayType(LHS); - const VariableArrayType* RVAT = getAsVariableArrayType(RHS); if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS; if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType)) diff --git a/test/Sema/vla.c b/test/Sema/vla.c index c962749d06..8d83100b9d 100644 --- a/test/Sema/vla.c +++ b/test/Sema/vla.c @@ -76,3 +76,16 @@ struct { ]; }; int (*use_implicitly_declared)() = implicitly_declared; // ok, was implicitly declared at file scope + +void VLAPtrAssign(int size) { + int array[1][2][3][size][4][5]; + // This is well formed + int (*p)[2][3][size][4][5] = array; + // Last array dimension too large + int (*p2)[2][3][size][4][6] = array; // expected-warning {{incompatible pointer types}} + // Second array dimension too large + int (*p3)[20][3][size][4][5] = array; // expected-warning {{incompatible pointer types}} + + // Not illegal in C, program _might_ be well formed if size == 3. + int (*p4)[2][size][3][4][5] = array; +} -- GitLab From 571a2502f2d7ee604a60058b81301ee1875d499e Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 5 Jun 2018 15:11:02 +0000 Subject: [PATCH 0017/1023] [CUDA][HIP] Do not emit type info when compiling for device CUDA/HIP does not support RTTI on device side, therefore there is no point of emitting type info when compiling for device. Emitting type info for device not only clutters the IR with useless global variables, but also causes undefined symbol at linking since vtable for cxxabiv1::class_type_info has external linkage. Differential Revision: https://reviews.llvm.org/D47694 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334021 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 2 +- test/CodeGenCUDA/device-vtable.cu | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3098e0f984..b57004f7e1 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -4900,7 +4900,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, // Return a bogus pointer if RTTI is disabled, unless it's for EH. // FIXME: should we even be calling this method if RTTI is disabled // and it's not for EH? - if (!ForEH && !getLangOpts().RTTI) + if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice) return llvm::Constant::getNullValue(Int8PtrTy); if (ForEH && Ty->isObjCObjectPointerType() && diff --git a/test/CodeGenCUDA/device-vtable.cu b/test/CodeGenCUDA/device-vtable.cu index 9730e404ca..a7307dcdaf 100644 --- a/test/CodeGenCUDA/device-vtable.cu +++ b/test/CodeGenCUDA/device-vtable.cu @@ -19,7 +19,9 @@ struct H { //CHECK-HOST: @_ZTV1H = //CHECK-HOST-SAME: @_ZN1H6methodEv //CHECK-DEVICE-NOT: @_ZTV1H = - +//CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE +//CHECK-DEVICE-NOT: @_ZTS1H +//CHECK-DEVICE-NOT: @_ZTI1H struct D { __device__ virtual void method(); }; @@ -27,7 +29,9 @@ struct D { //CHECK-DEVICE: @_ZTV1D //CHECK-DEVICE-SAME: @_ZN1D6methodEv //CHECK-HOST-NOT: @_ZTV1D - +//CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE +//CHECK-DEVICE-NOT: @_ZTS1D +//CHECK-DEVICE-NOT: @_ZTI1D // This is the case with mixed host and device virtual methods. It's // impossible to emit a valid vtable in that case because only host or // only device methods would be available during host or device @@ -45,6 +49,9 @@ struct HD { // CHECK-HOST-NOT: @_ZN2HD8d_methodEv // CHECK-HOST-SAME: null // CHECK-BOTH-SAME: ] +// CHECK-DEVICE-NOT: @_ZTVN10__cxxabiv117__class_type_infoE +// CHECK-DEVICE-NOT: @_ZTS2HD +// CHECK-DEVICE-NOT: @_ZTI2HD void H::method() {} //CHECK-HOST: define void @_ZN1H6methodEv -- GitLab From 3faed8de6341a01c63c410891211a0cf488f5755 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 5 Jun 2018 21:54:35 +0000 Subject: [PATCH 0018/1023] [X86] Make __builtin_ia32_vec_ext_v2si require ICE for its index argument. Add warnings for out of range indices for __builtin_ia32_vec_ext_v2si, __builtin_ia32_vec_ext_v4hi, and __builtin_ia32_vec_set_v4hi. These should take a constant value for an index and that constant should be a valid element number. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334051 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 2 +- lib/Sema/SemaChecking.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 6f7ecaf28c..0657354bd5 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -142,7 +142,7 @@ TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "n", "mmx") TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "nc", "mmx") TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "nc", "mmx") TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "nc", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2iIi", "nc", "mmx") // MMX2 (MMX+SSE) intrinsics TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "nc", "mmx,sse") diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7b9975e6ab..643c103c8a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2555,7 +2555,14 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI_mm_prefetch: i = 1; l = 0; u = 7; break; + case X86::BI__builtin_ia32_vec_ext_v2si: + i = 1; l = 0; u = 1; + break; + case X86::BI__builtin_ia32_vec_ext_v4hi: + i = 1; l = 0; u = 3; + break; case X86::BI__builtin_ia32_sha1rnds4: + case X86::BI__builtin_ia32_vec_set_v4hi: i = 2; l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: -- GitLab From b5a0e0ac7dc6e30aa1c9bf57b11d16f8fa4f7a29 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 5 Jun 2018 22:40:03 +0000 Subject: [PATCH 0019/1023] [X86] Implement __builtin_ia32_vec_ext_v2si correctly even though we only use it with an index of 0. This builtin takes an index as its second operand, but the codegen hardcodes an index of 0 and doesn't use the operand. The only use of the builtin in the header file passes 0 to the operand so this works for that usage. But its more correct to use the real operand. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334054 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index c6c9df460e..6379f53d17 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8779,7 +8779,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, llvm::Type::getX86_MMXTy(getLLVMContext())); case X86::BI__builtin_ia32_vec_ext_v2si: return Builder.CreateExtractElement(Ops[0], - llvm::ConstantInt::get(Ops[1]->getType(), 0)); + cast(Ops[1])->getZExtValue()); case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { Address Tmp = CreateMemTemp(E->getArg(0)->getType()); -- GitLab From 26b20caa52ce8f4a08d1f8b6e2e927a490ae5e0c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 6 Jun 2018 00:24:55 +0000 Subject: [PATCH 0020/1023] [X86] Add builtins for vector element insert and extract for different 128 and 256 bit vector types. Use them to implement the extract and insert intrinsics. Previously we were just using extended vector operations in the header file. This unfortunately allowed non-constant indices to be used with the intrinsics. This is incompatible with gcc, icc, and MSVC. It also introduces a different performance characteristic because non-constant index gets lowered to a vector store and an element sized load. By adding the builtins we can check for the index to be a constant and ensure its in range of the vector element count. User code still has the option to use extended vector operations themselves if they need non-constant indexing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 17 ++++++ lib/CodeGen/CGBuiltin.cpp | 25 ++++++++- lib/Headers/avxintrin.h | 74 ++++++++------------------ lib/Headers/emmintrin.h | 19 +++---- lib/Headers/smmintrin.h | 48 ++++++++--------- lib/Sema/SemaChecking.cpp | 27 ++++++++-- test/CodeGen/avx-builtins.c | 34 +++++------- test/CodeGen/sse2-builtins.c | 10 ++-- test/CodeGen/sse41-builtins.c | 12 ++--- test/CodeGen/target-features-error-2.c | 2 +- test/CodeGen/vector.c | 2 +- 11 files changed, 138 insertions(+), 132 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 0657354bd5..04646b8fd8 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -272,6 +272,11 @@ TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "nc", "sse3") TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "nc", "sse3") @@ -387,6 +392,10 @@ TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "nc", "sse4.1") // SSE 4.2 TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "nc", "sse4.2") @@ -519,6 +528,14 @@ TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "n", "avx") TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "n", "avx") TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "n", "avx") TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "n", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "nc", "avx") // AVX2 TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "nc", "avx2") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 6379f53d17..ad2e1cf3b4 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8778,8 +8778,29 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return Builder.CreateBitCast(BuildVector(Ops), llvm::Type::getX86_MMXTy(getLLVMContext())); case X86::BI__builtin_ia32_vec_ext_v2si: - return Builder.CreateExtractElement(Ops[0], - cast(Ops[1])->getZExtValue()); + case X86::BI__builtin_ia32_vec_ext_v16qi: + case X86::BI__builtin_ia32_vec_ext_v8hi: + case X86::BI__builtin_ia32_vec_ext_v4si: + case X86::BI__builtin_ia32_vec_ext_v4sf: + case X86::BI__builtin_ia32_vec_ext_v2di: + case X86::BI__builtin_ia32_vec_ext_v32qi: + case X86::BI__builtin_ia32_vec_ext_v16hi: + case X86::BI__builtin_ia32_vec_ext_v8si: + case X86::BI__builtin_ia32_vec_ext_v4di: + // These builtins exist so we can ensure the index is an ICE and in range. + // Otherwise we could just do this in the header file. + return Builder.CreateExtractElement(Ops[0], Ops[1]); + case X86::BI__builtin_ia32_vec_set_v16qi: + case X86::BI__builtin_ia32_vec_set_v8hi: + case X86::BI__builtin_ia32_vec_set_v4si: + case X86::BI__builtin_ia32_vec_set_v2di: + case X86::BI__builtin_ia32_vec_set_v32qi: + case X86::BI__builtin_ia32_vec_set_v16hi: + case X86::BI__builtin_ia32_vec_set_v8si: + case X86::BI__builtin_ia32_vec_set_v4di: + // These builtins exist so we can ensure the index is an ICE and in range. + // Otherwise we could just do this in the header file. + return Builder.CreateInsertElement(Ops[0], Ops[1], Ops[2]); case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { Address Tmp = CreateMemTemp(E->getArg(0)->getType()); diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 64a4d94aa9..883b2e350d 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -2015,12 +2015,8 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// element is extracted and returned. /// \returns A 32-bit integer containing the extracted 32 bits of extended /// packed data. -static __inline int __DEFAULT_FN_ATTRS -_mm256_extract_epi32(__m256i __a, const int __imm) -{ - __v8si __b = (__v8si)__a; - return __b[__imm & 7]; -} +#define _mm256_extract_epi32(X, N) \ + (int)__builtin_ia32_vec_ext_v8si((__v8si)(__m256i)(X), (int)(N)) /// Takes a [16 x i16] vector and returns the vector element value /// indexed by the immediate constant operand. @@ -2037,12 +2033,9 @@ _mm256_extract_epi32(__m256i __a, const int __imm) /// element is extracted and returned. /// \returns A 32-bit integer containing the extracted 16 bits of zero extended /// packed data. -static __inline int __DEFAULT_FN_ATTRS -_mm256_extract_epi16(__m256i __a, const int __imm) -{ - __v16hi __b = (__v16hi)__a; - return (unsigned short)__b[__imm & 15]; -} +#define _mm256_extract_epi16(X, N) \ + (int)(unsigned short)__builtin_ia32_vec_ext_v16hi((__v16hi)(__m256i)(X), \ + (int)(N)) /// Takes a [32 x i8] vector and returns the vector element value /// indexed by the immediate constant operand. @@ -2059,12 +2052,9 @@ _mm256_extract_epi16(__m256i __a, const int __imm) /// element is extracted and returned. /// \returns A 32-bit integer containing the extracted 8 bits of zero extended /// packed data. -static __inline int __DEFAULT_FN_ATTRS -_mm256_extract_epi8(__m256i __a, const int __imm) -{ - __v32qi __b = (__v32qi)__a; - return (unsigned char)__b[__imm & 31]; -} +#define _mm256_extract_epi8(X, N) \ + (int)(unsigned char)__builtin_ia32_vec_ext_v32qi((__v32qi)(__m256i)(X), \ + (int)(N)) #ifdef __x86_64__ /// Takes a [4 x i64] vector and returns the vector element value @@ -2082,12 +2072,8 @@ _mm256_extract_epi8(__m256i __a, const int __imm) /// element is extracted and returned. /// \returns A 64-bit integer containing the extracted 64 bits of extended /// packed data. -static __inline long long __DEFAULT_FN_ATTRS -_mm256_extract_epi64(__m256i __a, const int __imm) -{ - __v4di __b = (__v4di)__a; - return __b[__imm & 3]; -} +#define _mm256_extract_epi64(X, N) \ + (long long)__builtin_ia32_vec_ext_v4di((__v4di)(__m256i)(X), (int)(N)) #endif /// Takes a [8 x i32] vector and replaces the vector element value @@ -2108,13 +2094,9 @@ _mm256_extract_epi64(__m256i __a, const int __imm) /// replaced. /// \returns A copy of vector \a __a, after replacing its element indexed by /// \a __imm with \a __b. -static __inline __m256i __DEFAULT_FN_ATTRS -_mm256_insert_epi32(__m256i __a, int __b, int const __imm) -{ - __v8si __c = (__v8si)__a; - __c[__imm & 7] = __b; - return (__m256i)__c; -} +#define _mm256_insert_epi32(X, I, N) \ + (__m256i)__builtin_ia32_vec_set_v8si((__v8si)(__m256i)(X), \ + (int)(I), (int)(N)) /// Takes a [16 x i16] vector and replaces the vector element value @@ -2135,13 +2117,9 @@ _mm256_insert_epi32(__m256i __a, int __b, int const __imm) /// replaced. /// \returns A copy of vector \a __a, after replacing its element indexed by /// \a __imm with \a __b. -static __inline __m256i __DEFAULT_FN_ATTRS -_mm256_insert_epi16(__m256i __a, int __b, int const __imm) -{ - __v16hi __c = (__v16hi)__a; - __c[__imm & 15] = __b; - return (__m256i)__c; -} +#define _mm256_insert_epi16(X, I, N) \ + (__m256i)__builtin_ia32_vec_set_v16hi((__v16hi)(__m256i)(X), \ + (int)(I), (int)(N)) /// Takes a [32 x i8] vector and replaces the vector element value /// indexed by the immediate constant operand with a new value. Returns the @@ -2161,13 +2139,9 @@ _mm256_insert_epi16(__m256i __a, int __b, int const __imm) /// replaced. /// \returns A copy of vector \a __a, after replacing its element indexed by /// \a __imm with \a __b. -static __inline __m256i __DEFAULT_FN_ATTRS -_mm256_insert_epi8(__m256i __a, int __b, int const __imm) -{ - __v32qi __c = (__v32qi)__a; - __c[__imm & 31] = __b; - return (__m256i)__c; -} +#define _mm256_insert_epi8(X, I, N) \ + (__m256i)__builtin_ia32_vec_set_v32qi((__v32qi)(__m256i)(X), \ + (int)(I), (int)(N)) #ifdef __x86_64__ /// Takes a [4 x i64] vector and replaces the vector element value @@ -2188,13 +2162,9 @@ _mm256_insert_epi8(__m256i __a, int __b, int const __imm) /// replaced. /// \returns A copy of vector \a __a, after replacing its element indexed by /// \a __imm with \a __b. -static __inline __m256i __DEFAULT_FN_ATTRS -_mm256_insert_epi64(__m256i __a, long long __b, int const __imm) -{ - __v4di __c = (__v4di)__a; - __c[__imm & 3] = __b; - return (__m256i)__c; -} +#define _mm256_insert_epi64(X, I, N) \ + (__m256i)__builtin_ia32_vec_set_v4di((__v4di)(__m256i)(X), \ + (long long)(I), (int)(N)) #endif /* Conversion */ diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index 1af1fcb377..605fb7993f 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -4304,12 +4304,9 @@ _mm_packus_epi16(__m128i __a, __m128i __b) /// 111: assign values from bits [127:112] of \a __a. /// \returns An integer, whose lower 16 bits are selected from the 128-bit /// integer vector parameter and the remaining bits are assigned zeros. -static __inline__ int __DEFAULT_FN_ATTRS -_mm_extract_epi16(__m128i __a, int __imm) -{ - __v8hi __b = (__v8hi)__a; - return (unsigned short)__b[__imm & 7]; -} +#define _mm_extract_epi16(a, imm) \ + (int)(unsigned short)__builtin_ia32_vec_ext_v8hi((__v8hi)(__m128i)(a), \ + (int)(imm)) /// Constructs a 128-bit integer vector by first making a copy of the /// 128-bit integer vector parameter, and then inserting the lower 16 bits @@ -4331,13 +4328,9 @@ _mm_extract_epi16(__m128i __a, int __imm) /// An immediate value specifying the bit offset in the result at which the /// lower 16 bits of \a __b are written. /// \returns A 128-bit integer vector containing the constructed values. -static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_insert_epi16(__m128i __a, int __b, int __imm) -{ - __v8hi __c = (__v8hi)__a; - __c[__imm & 7] = __b; - return (__m128i)__c; -} +#define _mm_insert_epi16(a, b, imm) \ + (__m128i)__builtin_ia32_vec_set_v8hi((__v8hi)(__m128i)(a), (int)(b), \ + (int)(imm)) /// Copies the values of the most significant bits from each 8-bit /// element in a 128-bit integer vector of [16 x i8] to create a 16-bit mask diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h index 494e21bea3..b3084562a0 100644 --- a/lib/Headers/smmintrin.h +++ b/lib/Headers/smmintrin.h @@ -893,15 +893,14 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 11: Bits [127:96] of parameter \a X are returned. /// \returns A 32-bit integer containing the extracted 32 bits of float data. #define _mm_extract_ps(X, N) (__extension__ \ - ({ union { int __i; float __f; } __t; \ - __v4sf __a = (__v4sf)(__m128)(X); \ - __t.__f = __a[(N) & 3]; \ - __t.__i;})) + ({ union { int __i; float __f; } __t; \ + __t.__f = __builtin_ia32_vec_ext_v4sf((__v4sf)(__m128)(X), (int)(N)); \ + __t.__i;})) /* Miscellaneous insert and extract macros. */ /* Extract a single-precision float from X at index N into D. */ -#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)(X); \ - (D) = __a[N]; })) +#define _MM_EXTRACT_FLOAT(D, X, N) \ + { (D) = __builtin_ia32_vec_ext_v4sf((__v4sf)(__m128)(X), (int)(N)); } /* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create an index suitable for _mm_insert_ps. */ @@ -952,10 +951,9 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 1110: Bits [119:112] of the result are used for insertion. \n /// 1111: Bits [127:120] of the result are used for insertion. /// \returns A 128-bit integer vector containing the constructed values. -#define _mm_insert_epi8(X, I, N) (__extension__ \ - ({ __v16qi __a = (__v16qi)(__m128i)(X); \ - __a[(N) & 15] = (I); \ - (__m128i)__a;})) +#define _mm_insert_epi8(X, I, N) \ + (__m128i)__builtin_ia32_vec_set_v16qi((__v16qi)(__m128i)(X), \ + (int)(I), (int)(N)) /// Constructs a 128-bit vector of [4 x i32] by first making a copy of /// the 128-bit integer vector parameter, and then inserting the 32-bit @@ -985,10 +983,9 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 10: Bits [95:64] of the result are used for insertion. \n /// 11: Bits [127:96] of the result are used for insertion. /// \returns A 128-bit integer vector containing the constructed values. -#define _mm_insert_epi32(X, I, N) (__extension__ \ - ({ __v4si __a = (__v4si)(__m128i)(X); \ - __a[(N) & 3] = (I); \ - (__m128i)__a;})) +#define _mm_insert_epi32(X, I, N) \ + (__m128i)__builtin_ia32_vec_set_v4si((__v4si)(__m128i)(X), \ + (int)(I), (int)(N)) #ifdef __x86_64__ /// Constructs a 128-bit vector of [2 x i64] by first making a copy of @@ -1017,10 +1014,9 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 0: Bits [63:0] of the result are used for insertion. \n /// 1: Bits [127:64] of the result are used for insertion. \n /// \returns A 128-bit integer vector containing the constructed values. -#define _mm_insert_epi64(X, I, N) (__extension__ \ - ({ __v2di __a = (__v2di)(__m128i)(X); \ - __a[(N) & 1] = (I); \ - (__m128i)__a;})) +#define _mm_insert_epi64(X, I, N) \ + (__m128i)__builtin_ia32_vec_set_v2di((__v2di)(__m128i)(X), \ + (long long)(I), (int)(N)) #endif /* __x86_64__ */ /* Extract int from packed integer array at index. This returns the element @@ -1061,9 +1057,9 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// \returns An unsigned integer, whose lower 8 bits are selected from the /// 128-bit integer vector parameter and the remaining bits are assigned /// zeros. -#define _mm_extract_epi8(X, N) (__extension__ \ - ({ __v16qi __a = (__v16qi)(__m128i)(X); \ - (int)(unsigned char) __a[(N) & 15];})) +#define _mm_extract_epi8(X, N) \ + (int)(unsigned char)__builtin_ia32_vec_ext_v16qi((__v16qi)(__m128i)(X), \ + (int)(N)) /// Extracts a 32-bit element from the 128-bit integer vector of /// [4 x i32], using the immediate value parameter \a N as a selector. @@ -1087,9 +1083,8 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 11: Bits [127:96] of the parameter \a X are exracted. /// \returns An integer, whose lower 32 bits are selected from the 128-bit /// integer vector parameter and the remaining bits are assigned zeros. -#define _mm_extract_epi32(X, N) (__extension__ \ - ({ __v4si __a = (__v4si)(__m128i)(X); \ - (int)__a[(N) & 3];})) +#define _mm_extract_epi32(X, N) \ + (int)__builtin_ia32_vec_ext_v4si((__v4si)(__m128i)(X), (int)(N)) #ifdef __x86_64__ /// Extracts a 64-bit element from the 128-bit integer vector of @@ -1111,9 +1106,8 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2) /// 0: Bits [63:0] are returned. \n /// 1: Bits [127:64] are returned. \n /// \returns A 64-bit integer. -#define _mm_extract_epi64(X, N) (__extension__ \ - ({ __v2di __a = (__v2di)(__m128i)(X); \ - (long long)__a[(N) & 1];})) +#define _mm_extract_epi64(X, N) \ + (long long)__builtin_ia32_vec_ext_v2di((__v2di)(__m128i)(X), (int)(N)) #endif /* __x86_64 */ /* SSE4 128-bit Packed Integer Comparisons. */ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 643c103c8a..b4fdcc0f7e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2552,17 +2552,28 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { default: return false; - case X86::BI_mm_prefetch: - i = 1; l = 0; u = 7; - break; case X86::BI__builtin_ia32_vec_ext_v2si: + case X86::BI__builtin_ia32_vec_ext_v2di: i = 1; l = 0; u = 1; break; + case X86::BI__builtin_ia32_vec_set_v2di: + i = 2; l = 0; u = 1; + break; case X86::BI__builtin_ia32_vec_ext_v4hi: + case X86::BI__builtin_ia32_vec_ext_v4si: + case X86::BI__builtin_ia32_vec_ext_v4sf: + case X86::BI__builtin_ia32_vec_ext_v4di: i = 1; l = 0; u = 3; break; + case X86::BI_mm_prefetch: + case X86::BI__builtin_ia32_vec_ext_v8hi: + case X86::BI__builtin_ia32_vec_ext_v8si: + i = 1; l = 0; u = 7; + break; case X86::BI__builtin_ia32_sha1rnds4: case X86::BI__builtin_ia32_vec_set_v4hi: + case X86::BI__builtin_ia32_vec_set_v4si: + case X86::BI__builtin_ia32_vec_set_v4di: i = 2; l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: @@ -2603,12 +2614,16 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vpcomw: case X86::BI__builtin_ia32_vpcomd: case X86::BI__builtin_ia32_vpcomq: + case X86::BI__builtin_ia32_vec_set_v8hi: + case X86::BI__builtin_ia32_vec_set_v8si: i = 2; l = 0; u = 7; break; case X86::BI__builtin_ia32_roundps: case X86::BI__builtin_ia32_roundpd: case X86::BI__builtin_ia32_roundps256: case X86::BI__builtin_ia32_roundpd256: + case X86::BI__builtin_ia32_vec_ext_v16qi: + case X86::BI__builtin_ia32_vec_ext_v16hi: i = 1; l = 0; u = 15; break; case X86::BI__builtin_ia32_roundss: @@ -2621,8 +2636,13 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_rangeps512_mask: case X86::BI__builtin_ia32_getmantsd_round_mask: case X86::BI__builtin_ia32_getmantss_round_mask: + case X86::BI__builtin_ia32_vec_set_v16qi: + case X86::BI__builtin_ia32_vec_set_v16hi: i = 2; l = 0; u = 15; break; + case X86::BI__builtin_ia32_vec_ext_v32qi: + i = 1; l = 0; u = 31; + break; case X86::BI__builtin_ia32_cmpps: case X86::BI__builtin_ia32_cmpss: case X86::BI__builtin_ia32_cmppd: @@ -2637,6 +2657,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_cmppd512_mask: case X86::BI__builtin_ia32_cmpsd_mask: case X86::BI__builtin_ia32_cmpss_mask: + case X86::BI__builtin_ia32_vec_set_v32qi: i = 2; l = 0; u = 31; break; case X86::BI__builtin_ia32_vcvtps2ph: diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index 4c904ee71f..43c502f47f 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -316,32 +316,28 @@ __m256 test_mm256_dp_ps(__m256 A, __m256 B) { int test_mm256_extract_epi8(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi8 - // CHECK: and i32 %{{.*}}, 31 - // CHECK: extractelement <32 x i8> %{{.*}}, i32 %{{.*}} + // CHECK: extractelement <32 x i8> %{{.*}}, i32 31 // CHECK: zext i8 %{{.*}} to i32 - return _mm256_extract_epi8(A, 32); + return _mm256_extract_epi8(A, 31); } int test_mm256_extract_epi16(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi16 - // CHECK: and i32 %{{.*}}, 15 - // CHECK: extractelement <16 x i16> %{{.*}}, i32 %{{.*}} + // CHECK: extractelement <16 x i16> %{{.*}}, i32 15 // CHECK: zext i16 %{{.*}} to i32 - return _mm256_extract_epi16(A, 16); + return _mm256_extract_epi16(A, 15); } int test_mm256_extract_epi32(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi32 - // CHECK: and i32 %{{.*}}, 7 - // CHECK: extractelement <8 x i32> %{{.*}}, i32 %{{.*}} - return _mm256_extract_epi32(A, 8); + // CHECK: extractelement <8 x i32> %{{.*}}, i32 7 + return _mm256_extract_epi32(A, 7); } long long test_mm256_extract_epi64(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi64 - // CHECK: and i32 %{{.*}}, 3 - // CHECK: extractelement <4 x i64> %{{.*}}, i32 %{{.*}} - return _mm256_extract_epi64(A, 5); + // CHECK: extractelement <4 x i64> %{{.*}}, i32 3 + return _mm256_extract_epi64(A, 3); } __m128d test_mm256_extractf128_pd(__m256d A) { @@ -400,29 +396,25 @@ __m256 test_mm256_hsub_ps(__m256 A, __m256 B) { __m256i test_mm256_insert_epi8(__m256i x, char b) { // CHECK-LABEL: test_mm256_insert_epi8 - // CHECK: and i32 %{{.*}}, 31 - // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, i32 %{{.*}} - return _mm256_insert_epi8(x, b, 17); + // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, i32 14 + return _mm256_insert_epi8(x, b, 14); } __m256i test_mm256_insert_epi16(__m256i x, int b) { // CHECK-LABEL: test_mm256_insert_epi16 - // CHECK: and i32 %{{.*}}, 15 - // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, i32 %{{.*}} + // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, i32 4 return _mm256_insert_epi16(x, b, 4); } __m256i test_mm256_insert_epi32(__m256i x, int b) { // CHECK-LABEL: test_mm256_insert_epi32 - // CHECK: and i32 %{{.*}}, 7 - // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, i32 %{{.*}} + // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, i32 5 return _mm256_insert_epi32(x, b, 5); } __m256i test_mm256_insert_epi64(__m256i x, long long b) { // CHECK-LABEL: test_mm256_insert_epi64 - // CHECK: and i32 %{{.*}}, 3 - // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, i32 %{{.*}} + // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, i32 2 return _mm256_insert_epi64(x, b, 2); } diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index f7094b2fbd..c0a44795bf 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -613,17 +613,15 @@ __m128d test_mm_div_sd(__m128d A, __m128d B) { // Lowering to pextrw requires optimization. int test_mm_extract_epi16(__m128i A) { // CHECK-LABEL: test_mm_extract_epi16 - // CHECK: [[x:%.*]] = and i32 %{{.*}}, 7 - // CHECK: extractelement <8 x i16> %{{.*}}, i32 [[x]] + // CHECK: extractelement <8 x i16> %{{.*}}, i32 1 // CHECK: zext i16 %{{.*}} to i32 - return _mm_extract_epi16(A, 9); + return _mm_extract_epi16(A, 1); } __m128i test_mm_insert_epi16(__m128i A, int B) { // CHECK-LABEL: test_mm_insert_epi16 - // CHECK: [[x:%.*]] = and i32 %{{.*}}, 7 - // CHECK: insertelement <8 x i16> %{{.*}}, i32 [[x]] - return _mm_insert_epi16(A, B, 8); + // CHECK: insertelement <8 x i16> %{{.*}}, i32 0 + return _mm_insert_epi16(A, B, 0); } void test_mm_lfence() { diff --git a/test/CodeGen/sse41-builtins.c b/test/CodeGen/sse41-builtins.c index a99ecdabe4..6d6e11e962 100644 --- a/test/CodeGen/sse41-builtins.c +++ b/test/CodeGen/sse41-builtins.c @@ -220,20 +220,20 @@ __m128 test_mm_floor_ss(__m128 x, __m128 y) { __m128i test_mm_insert_epi8(__m128i x, char b) { // CHECK-LABEL: test_mm_insert_epi8 - // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 0 - return _mm_insert_epi8(x, b, 16); + // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 1 + return _mm_insert_epi8(x, b, 1); } __m128i test_mm_insert_epi32(__m128i x, int b) { // CHECK-LABEL: test_mm_insert_epi32 - // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 0 - return _mm_insert_epi32(x, b, 4); + // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 1 + return _mm_insert_epi32(x, b, 1); } __m128i test_mm_insert_epi64(__m128i x, long long b) { // CHECK-LABEL: test_mm_insert_epi64 - // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 0 - return _mm_insert_epi64(x, b, 2); + // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 1 + return _mm_insert_epi64(x, b, 1); } __m128 test_mm_insert_ps(__m128 x, __m128 y) { diff --git a/test/CodeGen/target-features-error-2.c b/test/CodeGen/target-features-error-2.c index 683d9ab99e..40279fb6de 100644 --- a/test/CodeGen/target-features-error-2.c +++ b/test/CodeGen/target-features-error-2.c @@ -9,7 +9,7 @@ #if NEED_SSE42 int baz(__m256i a) { - return _mm256_extract_epi32(a, 3); // expected-error {{always_inline function '_mm256_extract_epi32' requires target feature 'sse4.2', but would be inlined into function 'baz' that is compiled without support for 'sse4.2'}} + return _mm256_extract_epi32(a, 3); // expected-error {{'__builtin_ia32_vec_ext_v8si' needs target feature avx}} } #endif diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c index ebaea841aa..98dd82a28a 100644 --- a/test/CodeGen/vector.c +++ b/test/CodeGen/vector.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -ffreestanding -triple i386-apple-darwin9 -O1 -target-cpu core2 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -triple i386-apple-darwin9 -O1 -target-cpu corei7 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s typedef short __v4hi __attribute__ ((__vector_size__ (8))); void test1() { -- GitLab From 09fc95cbbcf39afa3be6d98116b01a8cb4baa2bd Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 6 Jun 2018 01:35:08 +0000 Subject: [PATCH 0021/1023] Implement bittest intrinsics generically for non-x86 platforms I tested these locally on an x86 machine by disabling the inline asm codepath and confirming that it does the same bitflips as we do with the inline asm. Addresses code review feedback. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334059 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 168 ++++++++++++++++++++++++++++------ test/CodeGen/bittest-intrin.c | 121 ++++++++++++++++++++---- 2 files changed, 247 insertions(+), 42 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index ad2e1cf3b4..f65230a0f2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -484,11 +484,48 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown}); } -static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, const CallExpr *E, - char TestAnd, char Size, - bool Locked = false) { - Value *BitBase = CGF.EmitScalarExpr(E->getArg(0)); - Value *BitPos = CGF.EmitScalarExpr(E->getArg(1)); +// Get properties of an X86 BT* assembly instruction. The first returned value +// is the action character code, which can be for complement, reset, or set. The +// second is the size suffix which our assembler needs. The last is whether to +// add the lock prefix. +static std::tuple +getBitTestActionSizeAndLocking(unsigned BuiltinID) { + switch (BuiltinID) { + case Builtin::BI_bittest: + return {'\0', 'l', false}; + case Builtin::BI_bittestandcomplement: + return {'c', 'l', false}; + case Builtin::BI_bittestandreset: + return {'r', 'l', false}; + case Builtin::BI_bittestandset: + return {'s', 'l', false}; + case Builtin::BI_interlockedbittestandreset: + return {'r', 'l', /*Locked=*/true}; + case Builtin::BI_interlockedbittestandset: + return {'s', 'l', /*Locked=*/true}; + + case Builtin::BI_bittest64: + return {'\0', 'q', false}; + case Builtin::BI_bittestandcomplement64: + return {'c', 'q', false}; + case Builtin::BI_bittestandreset64: + return {'r', 'q', false}; + case Builtin::BI_bittestandset64: + return {'s', 'q', false}; + case Builtin::BI_interlockedbittestandreset64: + return {'r', 'q', /*Locked=*/true}; + case Builtin::BI_interlockedbittestandset64: + return {'s', 'q', /*Locked=*/true}; + } + llvm_unreachable("expected only bittest builtins"); +} + +static RValue EmitX86BitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, + const CallExpr *E, Value *BitBase, + Value *BitPos) { + char Action, Size; + bool Locked; + std::tie(Action, Size, Locked) = getBitTestActionSizeAndLocking(BuiltinID); // Build the assembly. SmallString<64> Asm; @@ -496,12 +533,12 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, const CallExpr *E, if (Locked) AsmOS << "lock "; AsmOS << "bt"; - if (TestAnd) - AsmOS << TestAnd; + if (Action) + AsmOS << Action; AsmOS << Size << " $2, ($1)\n\tsetc ${0:b}"; // Build the constraints. FIXME: We should support immediates when possible. - std::string Constraints = "=r,r,r,~{cc},~{flags},~{memory},~{fpsr}"; + std::string Constraints = "=r,r,r,~{cc},~{flags},~{fpsr}"; llvm::IntegerType *IntType = llvm::IntegerType::get( CGF.getLLVMContext(), CGF.getContext().getTypeSize(E->getArg(1)->getType())); @@ -515,6 +552,97 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, const CallExpr *E, return RValue::get(CS.getInstruction()); } +/// Emit a _bittest* intrinsic. These intrinsics take a pointer to an array of +/// bits and a bit position and read and optionally modify the bit at that +/// position. The position index can be arbitrarily large, i.e. it can be larger +/// than 31 or 63, so we need an indexed load in the general case. +static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, + const CallExpr *E) { + Value *BitBase = CGF.EmitScalarExpr(E->getArg(0)); + Value *BitPos = CGF.EmitScalarExpr(E->getArg(1)); + + // X86 has special BT, BTC, BTR, and BTS instructions that handle the array + // indexing operation internally. Use them if possible. + llvm::Triple::ArchType Arch = CGF.getTarget().getTriple().getArch(); + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) + return EmitX86BitTestIntrinsic(CGF, BuiltinID, E, BitBase, BitPos); + + // Otherwise, use generic code to load one byte and test the bit. Use all but + // the bottom three bits as the array index, and the bottom three bits to form + // a mask. + // Bit = BitBaseI8[BitPos >> 3] & (1 << (BitPos & 0x7)) != 0; + Value *ByteIndex = CGF.Builder.CreateAShr( + BitPos, llvm::ConstantInt::get(BitPos->getType(), 3), "bittest.byteidx"); + Value *BitBaseI8 = CGF.Builder.CreatePointerCast(BitBase, CGF.Int8PtrTy); + Address ByteAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BitBaseI8, + ByteIndex, "bittest.byteaddr"), + CharUnits::One()); + Value *PosLow = + CGF.Builder.CreateAnd(CGF.Builder.CreateTrunc(BitPos, CGF.Int8Ty), + llvm::ConstantInt::get(CGF.Int8Ty, 0x7)); + + // The updating instructions will need a mask. + Value *Mask = nullptr; + if (BuiltinID != Builtin::BI_bittest && BuiltinID != Builtin::BI_bittest64) { + Mask = CGF.Builder.CreateShl(llvm::ConstantInt::get(CGF.Int8Ty, 1), PosLow, + "bittest.mask"); + } + + // Emit a combined atomicrmw load/store operation for the interlocked + // intrinsics. + Value *OldByte = nullptr; + switch (BuiltinID) { + case Builtin::BI_interlockedbittestandreset: + case Builtin::BI_interlockedbittestandreset64: + OldByte = CGF.Builder.CreateAtomicRMW( + AtomicRMWInst::And, ByteAddr.getPointer(), CGF.Builder.CreateNot(Mask), + llvm::AtomicOrdering::SequentiallyConsistent); + break; + case Builtin::BI_interlockedbittestandset: + case Builtin::BI_interlockedbittestandset64: + OldByte = CGF.Builder.CreateAtomicRMW( + AtomicRMWInst::Or, ByteAddr.getPointer(), Mask, + llvm::AtomicOrdering::SequentiallyConsistent); + break; + default: + break; + } + + // Emit a plain load for the non-interlocked intrinsics. + if (!OldByte) { + OldByte = CGF.Builder.CreateLoad(ByteAddr, "bittest.byte"); + Value *NewByte = nullptr; + switch (BuiltinID) { + case Builtin::BI_bittest: + case Builtin::BI_bittest64: + // Don't store anything. + break; + case Builtin::BI_bittestandcomplement: + case Builtin::BI_bittestandcomplement64: + NewByte = CGF.Builder.CreateXor(OldByte, Mask); + break; + case Builtin::BI_bittestandreset: + case Builtin::BI_bittestandreset64: + NewByte = CGF.Builder.CreateAnd(OldByte, CGF.Builder.CreateNot(Mask)); + break; + case Builtin::BI_bittestandset: + case Builtin::BI_bittestandset64: + NewByte = CGF.Builder.CreateOr(OldByte, Mask); + break; + default: + llvm_unreachable("non bittest family builtin"); + } + if (NewByte) + CGF.Builder.CreateStore(NewByte, ByteAddr); + } + + // However we loaded the old byte, either by plain load or atomicrmw, shift + // the bit into the low position and mask it to 0 or 1. + Value *ShiftedByte = CGF.Builder.CreateLShr(OldByte, PosLow, "bittest.shr"); + return RValue::get(CGF.Builder.CreateAnd( + ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res")); +} + // Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we // handle them here. enum class CodeGenFunction::MSVCIntrin { @@ -2806,31 +2934,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI_InterlockedXor: return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E)); + case Builtin::BI_bittest64: case Builtin::BI_bittest: - return EmitBitTestIntrinsic(*this, E, '\0', 'l'); + case Builtin::BI_bittestandcomplement64: case Builtin::BI_bittestandcomplement: - return EmitBitTestIntrinsic(*this, E, 'c', 'l'); + case Builtin::BI_bittestandreset64: case Builtin::BI_bittestandreset: - return EmitBitTestIntrinsic(*this, E, 'r', 'l'); + case Builtin::BI_bittestandset64: case Builtin::BI_bittestandset: - return EmitBitTestIntrinsic(*this, E, 's', 'l'); case Builtin::BI_interlockedbittestandreset: - return EmitBitTestIntrinsic(*this, E, 'r', 'l', /*Locked=*/true); - case Builtin::BI_interlockedbittestandset: - return EmitBitTestIntrinsic(*this, E, 's', 'l', /*Locked=*/true); - - case Builtin::BI_bittest64: - return EmitBitTestIntrinsic(*this, E, '\0', 'q'); - case Builtin::BI_bittestandcomplement64: - return EmitBitTestIntrinsic(*this, E, 'c', 'q'); - case Builtin::BI_bittestandreset64: - return EmitBitTestIntrinsic(*this, E, 'r', 'q'); - case Builtin::BI_bittestandset64: - return EmitBitTestIntrinsic(*this, E, 's', 'q'); case Builtin::BI_interlockedbittestandreset64: - return EmitBitTestIntrinsic(*this, E, 'r', 'q', /*Locked=*/true); case Builtin::BI_interlockedbittestandset64: - return EmitBitTestIntrinsic(*this, E, 's', 'q', /*Locked=*/true); + case Builtin::BI_interlockedbittestandset: + return EmitBitTestIntrinsic(*this, BuiltinID, E); case Builtin::BI__exception_code: case Builtin::BI_exception_code: diff --git a/test/CodeGen/bittest-intrin.c b/test/CodeGen/bittest-intrin.c index 839d5656a9..21a26efa10 100644 --- a/test/CodeGen/bittest-intrin.c +++ b/test/CodeGen/bittest-intrin.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 -fms-extensions -triple thumbv7-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM +// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM volatile unsigned char sink = 0; void test32(long *base, long idx) { @@ -18,18 +20,105 @@ void test64(__int64 *base, __int64 idx) { sink = _interlockedbittestandset64(base, idx); } -// CHECK-LABEL: define dso_local void @test32(i32* %base, i32 %idx) -// CHECK: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) -// CHECK: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) -// CHECK: call i8 asm sideeffect "btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) -// CHECK: call i8 asm sideeffect "btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) -// CHECK: call i8 asm sideeffect "lock btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) -// CHECK: call i8 asm sideeffect "lock btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) - -// CHECK-LABEL: define dso_local void @test64(i64* %base, i64 %idx) -// CHECK: call i8 asm sideeffect "btq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) -// CHECK: call i8 asm sideeffect "btcq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) -// CHECK: call i8 asm sideeffect "btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) -// CHECK: call i8 asm sideeffect "btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) -// CHECK: call i8 asm sideeffect "lock btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) -// CHECK: call i8 asm sideeffect "lock btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64-LABEL: define dso_local void @test32(i32* %base, i32 %idx) +// X64: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// X64: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// X64: call i8 asm sideeffect "btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// X64: call i8 asm sideeffect "btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// X64: call i8 asm sideeffect "lock btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) +// X64: call i8 asm sideeffect "lock btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) + +// X64-LABEL: define dso_local void @test64(i64* %base, i64 %idx) +// X64: call i8 asm sideeffect "btq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64: call i8 asm sideeffect "btcq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64: call i8 asm sideeffect "btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64: call i8 asm sideeffect "btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64: call i8 asm sideeffect "lock btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) +// X64: call i8 asm sideeffect "lock btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}}) + +// ARM-LABEL: define dso_local {{.*}}void @test32(i32* %base, i32 %idx) +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]] +// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 +// ARM: %[[NEWBYTE:[^ ]*]] = xor i8 %[[BYTE]], %[[MASK]] +// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1 +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]] +// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 +// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1 +// ARM: %[[NEWBYTE:[^ ]*]] = and i8 %[[BYTE]], %[[NOTMASK]] +// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1 +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]] +// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 +// ARM: %[[NEWBYTE:[^ ]*]] = or i8 %[[BYTE]], %[[MASK]] +// ARM store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1 +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]] +// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1 +// ARM: %[[BYTE:[^ ]*]] = atomicrmw and i8* %[[BYTEADDR]], i8 %[[NOTMASK]] seq_cst +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]] +// ARM: %[[BYTE:[^ ]*]] = atomicrmw or i8* %[[BYTEADDR]], i8 %[[MASK]] seq_cst +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ARM-LABEL: define dso_local {{.*}}void @test64(i64* %base, i64 %idx) +// ARM: %[[IDXHI:[^ ]*]] = ashr i64 %{{.*}}, 3 +// ARM: %[[BASE:[^ ]*]] = bitcast i64* %{{.*}} to i8* +// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i64 %[[IDXHI]] +// ARM: %[[IDX8:[^ ]*]] = trunc i64 %{{.*}} to i8 +// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 +// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 +// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] +// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 +// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 + +// ... the rest is the same, but with i64 instead of i32. -- GitLab From 56d0ebe7c24815335ed50bfaf0eb76b211bbb6ba Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 6 Jun 2018 01:44:10 +0000 Subject: [PATCH 0022/1023] Fix std::tuple errors git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334060 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index f65230a0f2..5829396b0f 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -492,30 +492,30 @@ static std::tuple getBitTestActionSizeAndLocking(unsigned BuiltinID) { switch (BuiltinID) { case Builtin::BI_bittest: - return {'\0', 'l', false}; + return std::make_tuple('\0', 'l', false); case Builtin::BI_bittestandcomplement: - return {'c', 'l', false}; + return std::make_tuple('c', 'l', false); case Builtin::BI_bittestandreset: - return {'r', 'l', false}; + return std::make_tuple('r', 'l', false); case Builtin::BI_bittestandset: - return {'s', 'l', false}; + return std::make_tuple('s', 'l', false); case Builtin::BI_interlockedbittestandreset: - return {'r', 'l', /*Locked=*/true}; + return std::make_tuple('r', 'l', /*Locked=*/true); case Builtin::BI_interlockedbittestandset: - return {'s', 'l', /*Locked=*/true}; + return std::make_tuple('s', 'l', /*Locked=*/true); case Builtin::BI_bittest64: - return {'\0', 'q', false}; + return std::make_tuple('\0', 'q', false); case Builtin::BI_bittestandcomplement64: - return {'c', 'q', false}; + return std::make_tuple('c', 'q', false); case Builtin::BI_bittestandreset64: - return {'r', 'q', false}; + return std::make_tuple('r', 'q', false); case Builtin::BI_bittestandset64: - return {'s', 'q', false}; + return std::make_tuple('s', 'q', false); case Builtin::BI_interlockedbittestandreset64: - return {'r', 'q', /*Locked=*/true}; + return std::make_tuple('r', 'q', /*Locked=*/true); case Builtin::BI_interlockedbittestandset64: - return {'s', 'q', /*Locked=*/true}; + return std::make_tuple('s', 'q', /*Locked=*/true); } llvm_unreachable("expected only bittest builtins"); } -- GitLab From 061e488871f28e55b8b3da15c88617b7fa08a541 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 6 Jun 2018 04:51:52 +0000 Subject: [PATCH 0023/1023] [X86] Move the vec_set/vec_ext builtins for 64-bit elements to BuiltinsX86_64.def. The instructions these correspond to and the intrinsics that use them are only available in 64-bit mode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334061 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 4 ---- include/clang/Basic/BuiltinsX86_64.def | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 04646b8fd8..a164681b2e 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -272,7 +272,6 @@ TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "nc", "sse2") @@ -395,7 +394,6 @@ TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "nc", "sse4.1") // SSE 4.2 TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "nc", "sse4.2") @@ -531,11 +529,9 @@ TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "n", "avx") TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "nc", "avx") // AVX2 TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "nc", "avx2") diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def index 81632f275a..f3d4d1794c 100644 --- a/include/clang/Basic/BuiltinsX86_64.def +++ b/include/clang/Basic/BuiltinsX86_64.def @@ -49,7 +49,11 @@ TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "nc", "sse") TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "n", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "nc", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "n", "fsgsbase") TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "n", "fsgsbase") TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "n", "fsgsbase") -- GitLab From 86869aa106eeea261d088f20479c15939675e0c4 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Wed, 6 Jun 2018 05:16:34 +0000 Subject: [PATCH 0024/1023] [Sema] Fix parsing of anonymous union in language linkage specification C++17 [dcl.link]p4: A linkage specification does not establish a scope. C++17 [class.union.anon]p2: Namespace level anonymous unions shall be declared static. Differential Revision: https://reviews.llvm.org/D45884 rdar://problem/37545925 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334062 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 8 +++++--- test/SemaCXX/anonymous-union-export.cpp | 6 ++++++ test/SemaCXX/anonymous-union.cpp | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 test/SemaCXX/anonymous-union-export.cpp diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 862da62149..e1ee8ec079 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4642,12 +4642,14 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, unsigned DiagID; if (Record->isUnion()) { // C++ [class.union]p6: + // C++17 [class.union.anon]p2: // Anonymous unions declared in a named namespace or in the // global namespace shall be declared static. + DeclContext *OwnerScope = Owner->getRedeclContext(); if (DS.getStorageClassSpec() != DeclSpec::SCS_static && - (isa(Owner) || - (isa(Owner) && - cast(Owner)->getDeclName()))) { + (OwnerScope->isTranslationUnit() || + (OwnerScope->isNamespace() && + !cast(OwnerScope)->isAnonymousNamespace()))) { Diag(Record->getLocation(), diag::err_anonymous_union_not_static) << FixItHint::CreateInsertion(Record->getLocation(), "static "); diff --git a/test/SemaCXX/anonymous-union-export.cpp b/test/SemaCXX/anonymous-union-export.cpp new file mode 100644 index 0000000000..270c0c3ae9 --- /dev/null +++ b/test/SemaCXX/anonymous-union-export.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify %s + +export module M; +export { + union { bool a; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 0b654266f7..5538ea4703 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -80,6 +80,10 @@ union { // expected-error{{anonymous unions at namespace or global scope must be float float_val; }; +extern "C++" { +union { }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +} + static union { int int_val2; // expected-note{{previous definition is here}} float float_val2; -- GitLab From 444222b20fbc56be2632d7c1baf2241dbc557111 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 6 Jun 2018 05:18:39 +0000 Subject: [PATCH 0025/1023] [Fuchsia] Include install-distribution-stripped in bootstrap targets This enables the use of install-distribution-stripped target in the 2-stage builds. Differential Revision: https://reviews.llvm.org/D47758 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334063 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index 2a47ea0192..3055e8d5d3 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -38,6 +38,7 @@ set(CLANG_BOOTSTRAP_TARGETS clang-test-depends distribution install-distribution + install-distribution-stripped clang CACHE STRING "") get_cmake_property(variableNames VARIABLES) -- GitLab From 30d2ec366ebeee034d96c1cc2d7d21e5a2ba5ca4 Mon Sep 17 00:00:00 2001 From: Vlad Tsyrklevich Date: Wed, 6 Jun 2018 06:09:02 +0000 Subject: [PATCH 0026/1023] [Analyzer] Fix Z3ConstraintManager crash (PR37646) Summary: Fix another Z3ConstraintManager crash, use fixAPSInt() to extend a boolean APSInt. Reviewers: george.karpenkov, NoQ, ddcc Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D47617 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334065 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp | 6 ++++-- test/Analysis/apsint.c | 7 ------- test/Analysis/z3/apsint.c | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 9 deletions(-) delete mode 100644 test/Analysis/apsint.c create mode 100644 test/Analysis/z3/apsint.c diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index a9f67fc124..dccd158489 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -1231,8 +1231,10 @@ const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, if (!LHS || !RHS) return nullptr; - llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS; - QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS); + llvm::APSInt ConvertedLHS, ConvertedRHS; + QualType LTy, RTy; + std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); + std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); doIntTypeConversion( ConvertedLHS, LTy, ConvertedRHS, RTy); return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); diff --git a/test/Analysis/apsint.c b/test/Analysis/apsint.c deleted file mode 100644 index d37fce11dd..0000000000 --- a/test/Analysis/apsint.c +++ /dev/null @@ -1,7 +0,0 @@ -// REQUIRES: z3 -// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s -// expected-no-diagnostics - -_Bool a() { - return !({ a(); }); -} diff --git a/test/Analysis/z3/apsint.c b/test/Analysis/z3/apsint.c new file mode 100644 index 0000000000..670ef2be1c --- /dev/null +++ b/test/Analysis/z3/apsint.c @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s +// expected-no-diagnostics + +// https://bugs.llvm.org/show_bug.cgi?id=37622 +_Bool a() { + return !({ a(); }); +} + +// https://bugs.llvm.org/show_bug.cgi?id=37646 +_Bool b; +void c() { + _Bool a = b | 0; + for (;;) + if (a) + ; +} -- GitLab From c4bba57dc83b9a904715f281af1cf03488071640 Mon Sep 17 00:00:00 2001 From: Vlad Tsyrklevich Date: Wed, 6 Jun 2018 06:25:51 +0000 Subject: [PATCH 0027/1023] [Analyzer][Z3] Test fixes for Z3 constraint manager Summary: Since Z3 tests have been not been running [1] some tests needed to be updated. I also added a regression test for [1]. [1] https://reviews.llvm.org/D47722 Reviewers: george.karpenkov, NoQ, ddcc Reviewed By: george.karpenkov Subscribers: mikhail.ramalho, dcoughlin, xazax.hun, szepet, zzheng, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D47726 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334067 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/PR24184.cpp | 1 + test/Analysis/constant-folding.c | 4 ++++ test/Analysis/loop-unrolling.cpp | 4 ++++ test/Analysis/z3/enabled.c | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 test/Analysis/z3/enabled.c diff --git a/test/Analysis/PR24184.cpp b/test/Analysis/PR24184.cpp index 1280334d4d..bfc5ae6ea5 100644 --- a/test/Analysis/PR24184.cpp +++ b/test/Analysis/PR24184.cpp @@ -1,3 +1,4 @@ +// UNSUPPORTED: z3 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s // RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c index 8189868be2..e21d629e9a 100644 --- a/test/Analysis/constant-folding.c +++ b/test/Analysis/constant-folding.c @@ -108,7 +108,11 @@ void testBitwiseRules(unsigned int a, int b) { clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}} clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}} clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}} +#ifdef ANALYZER_CM_Z3 + clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}} +#else clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}} +#endif // Check that dynamically computed constants also work. int constant = 1 << 3; diff --git a/test/Analysis/loop-unrolling.cpp b/test/Analysis/loop-unrolling.cpp index ce7ada8bd7..b7375df38b 100644 --- a/test/Analysis/loop-unrolling.cpp +++ b/test/Analysis/loop-unrolling.cpp @@ -368,7 +368,11 @@ int nested_inlined_unroll1() { int nested_inlined_no_unroll1() { int k; for (int i = 0; i < 9; i++) { +#ifdef ANALYZER_CM_Z3 + clang_analyzer_numTimesReached(); // expected-warning {{13}} +#else clang_analyzer_numTimesReached(); // expected-warning {{15}} +#endif k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well } int a = 22 / k; // no-warning diff --git a/test/Analysis/z3/enabled.c b/test/Analysis/z3/enabled.c new file mode 100644 index 0000000000..9f44233b26 --- /dev/null +++ b/test/Analysis/z3/enabled.c @@ -0,0 +1,3 @@ +// REQUIRES: z3 +// RUN: echo %clang_analyze_cc1 | FileCheck %s +// CHECK: -analyzer-constraints=z3 -- GitLab From 52d10dc5c2eaad79a44e4f724173be9d4a9a4e04 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 6 Jun 2018 07:17:26 +0000 Subject: [PATCH 0028/1023] [Frontend] Honor UserFilesAreVolatile flag getting file buffer in ASTUnit Do not memory map the main file if the flag UserFilesAreVolatile is set to true in ASTUnit when calling FileSystem::getBufferForFile. Differential Revision: https://reviews.llvm.org/D47460 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334070 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/FileManager.h | 2 +- lib/Basic/FileManager.cpp | 6 +-- lib/Frontend/ASTUnit.cpp | 11 ++-- unittests/Frontend/ASTUnitTest.cpp | 81 ++++++++++++++++++++---------- 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index ea0ed39a8a..ab5dfca716 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -239,7 +239,7 @@ public: getBufferForFile(const FileEntry *Entry, bool isVolatile = false, bool ShouldCloseOpenFile = true); llvm::ErrorOr> - getBufferForFile(StringRef Filename); + getBufferForFile(StringRef Filename, bool isVolatile = false); /// Get the 'stat' information for the given \p Path. /// diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 5cbcdf4477..7e2d01c498 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -450,13 +450,13 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile, } llvm::ErrorOr> -FileManager::getBufferForFile(StringRef Filename) { +FileManager::getBufferForFile(StringRef Filename, bool isVolatile) { if (FileSystemOpts.WorkingDir.empty()) - return FS->getBufferForFile(Filename); + return FS->getBufferForFile(Filename, -1, true, isVolatile); SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); - return FS->getBufferForFile(FilePath.c_str()); + return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile); } /// getStatValue - Get the 'stat' information for the specified path, diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index e0e8e8b22a..d7bbf6fe4a 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -156,7 +156,8 @@ static bool moveOnNoError(llvm::ErrorOr Val, T &Output) { static std::unique_ptr getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, vfs::FileSystem *VFS, - StringRef FilePath) { + StringRef FilePath, + bool isVolatile) { const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); // Try to determine if the main file has been remapped, either from the @@ -176,7 +177,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); if (MainFileID == MID) { // We found a remapping. Try to load the resulting, remapped source. - BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second)); + BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile)); if (!BufferOwner) return nullptr; } @@ -201,7 +202,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, // If the main source file was not remapped, load it now. if (!Buffer && !BufferOwner) { - BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath)); + BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile)); if (!BufferOwner) return nullptr; } @@ -707,7 +708,7 @@ ASTDeserializationListener *ASTUnit::getDeserializationListener() { std::unique_ptr ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { assert(FileMgr); - auto Buffer = FileMgr->getBufferForFile(Filename); + auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile); if (Buffer) return std::move(*Buffer); if (ErrorStr) @@ -1278,7 +1279,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile(); std::unique_ptr MainFileBuffer = getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(), - MainFilePath); + MainFilePath, UserFilesAreVolatile); if (!MainFileBuffer) return nullptr; diff --git a/unittests/Frontend/ASTUnitTest.cpp b/unittests/Frontend/ASTUnitTest.cpp index 4f529cf55d..5296fc51f8 100644 --- a/unittests/Frontend/ASTUnitTest.cpp +++ b/unittests/Frontend/ASTUnitTest.cpp @@ -23,7 +23,41 @@ using namespace clang; namespace { -TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) { +class ASTUnitTest : public ::testing::Test { +protected: + int FD; + llvm::SmallString<256> InputFileName; + std::unique_ptr input_file; + IntrusiveRefCntPtr Diags; + std::shared_ptr CInvok; + std::shared_ptr PCHContainerOps; + + std::unique_ptr createASTUnit(bool isVolatile) { + EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD, + InputFileName)); + input_file = std::make_unique(InputFileName, FD); + input_file->os() << ""; + + const char *Args[] = {"clang", "-xc++", InputFileName.c_str()}; + + Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + + CInvok = createInvocationFromCommandLine(Args, Diags); + + if (!CInvok) + return nullptr; + + FileManager *FileMgr = + new FileManager(FileSystemOptions(), vfs::getRealFileSystem()); + PCHContainerOps = std::make_shared(); + + return ASTUnit::LoadFromCompilerInvocation( + CInvok, PCHContainerOps, Diags, FileMgr, false, false, 0, TU_Complete, + false, false, isVolatile); + } +}; + +TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) { // Check that the printing policy is restored with the correct language // options when loading an ASTUnit from a file. To this end, an ASTUnit // for a C++ translation unit is set up and written to a temporary file. @@ -38,29 +72,7 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) { EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams); } - int FD; - llvm::SmallString<256> InputFileName; - ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD, InputFileName)); - ToolOutputFile input_file(InputFileName, FD); - input_file.os() << ""; - - const char* Args[] = {"clang", "-xc++", InputFileName.c_str()}; - - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); - - std::shared_ptr CInvok = - createInvocationFromCommandLine(Args, Diags); - - if (!CInvok) - FAIL() << "could not create compiler invocation"; - - FileManager *FileMgr = - new FileManager(FileSystemOptions(), vfs::getRealFileSystem()); - auto PCHContainerOps = std::make_shared(); - - std::unique_ptr AST = ASTUnit::LoadFromCompilerInvocation( - CInvok, PCHContainerOps, Diags, FileMgr); + std::unique_ptr AST = createASTUnit(false); if (!AST) FAIL() << "failed to create ASTUnit"; @@ -68,15 +80,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) { EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams); llvm::SmallString<256> ASTFileName; - ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName)); + ASSERT_FALSE( + llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName)); ToolOutputFile ast_file(ASTFileName, FD); AST->Save(ASTFileName.str()); EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName)); std::unique_ptr AU = ASTUnit::LoadFromASTFile( - ASTFileName.str(), PCHContainerOps->getRawReader(), ASTUnit::LoadEverything, Diags, - FileSystemOptions(), /*UseDebugInfo=*/false); + ASTFileName.str(), PCHContainerOps->getRawReader(), + ASTUnit::LoadEverything, Diags, FileSystemOptions(), + /*UseDebugInfo=*/false); if (!AU) FAIL() << "failed to load ASTUnit"; @@ -84,4 +98,17 @@ TEST(ASTUnit, SaveLoadPreservesLangOptionsInPrintingPolicy) { EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams); } +TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) { + std::unique_ptr AST = createASTUnit(true); + + if (!AST) + FAIL() << "failed to create ASTUnit"; + + std::unique_ptr memoryBuffer = + AST->getBufferForFile(InputFileName); + + EXPECT_NE(memoryBuffer->getBufferKind(), + llvm::MemoryBuffer::MemoryBuffer_MMap); +} + } // anonymous namespace -- GitLab From 3cab9725c69c7c7771a4aed5f3e17954702309f3 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 6 Jun 2018 08:25:54 +0000 Subject: [PATCH 0029/1023] Fix build - use llvm::make_unique git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334072 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Frontend/ASTUnitTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/Frontend/ASTUnitTest.cpp b/unittests/Frontend/ASTUnitTest.cpp index 5296fc51f8..c60004e40b 100644 --- a/unittests/Frontend/ASTUnitTest.cpp +++ b/unittests/Frontend/ASTUnitTest.cpp @@ -35,7 +35,7 @@ protected: std::unique_ptr createASTUnit(bool isVolatile) { EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD, InputFileName)); - input_file = std::make_unique(InputFileName, FD); + input_file = llvm::make_unique(InputFileName, FD); input_file->os() << ""; const char *Args[] = {"clang", "-xc++", InputFileName.c_str()}; -- GitLab From 603b69a6644b3013c18619a171c4defffa9f3822 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 6 Jun 2018 08:50:12 +0000 Subject: [PATCH 0030/1023] Change test to output 'pcm' to the temp dir, not the source dir git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334073 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/anonymous-union-export.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SemaCXX/anonymous-union-export.cpp b/test/SemaCXX/anonymous-union-export.cpp index 270c0c3ae9..1d83d809f5 100644 --- a/test/SemaCXX/anonymous-union-export.cpp +++ b/test/SemaCXX/anonymous-union-export.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify %s +// RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify -o %t.pcm %s export module M; export { -- GitLab From 88a9296de1aff76228cf4b72eef815ac867a9b7c Mon Sep 17 00:00:00 2001 From: Pierre Gousseau Date: Wed, 6 Jun 2018 14:04:15 +0000 Subject: [PATCH 0031/1023] [Driver] Add flag "--dependent-lib=..." when enabling asan or ubsan on PS4. NFC for targets other than PS4. Simplify users' workflow when enabling asan or ubsan and calling the linker separately. Differential Revision: https://reviews.llvm.org/D47375 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334096 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 6 ++++-- lib/Driver/ToolChains/PS4CPU.cpp | 9 +++++++++ lib/Driver/ToolChains/PS4CPU.h | 2 ++ test/Driver/fsanitize.c | 2 ++ test/Driver/sanitizer-ld.c | 5 +++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index afcf45d9f8..3eee463bb1 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3687,9 +3687,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ)) ABICompatArg->render(Args, CmdArgs); - // Add runtime flag for PS4 when PGO or Coverage are enabled. - if (RawTriple.isPS4CPU()) + // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled. + if (RawTriple.isPS4CPU()) { PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs); + PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs); + } // Pass options for controlling the default header search paths. if (Args.hasArg(options::OPT_nostdinc)) { diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp index 16d9bc87d8..a4b74d4923 100644 --- a/lib/Driver/ToolChains/PS4CPU.cpp +++ b/lib/Driver/ToolChains/PS4CPU.cpp @@ -76,6 +76,15 @@ static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { } } +void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, + ArgStringList &CmdArgs) { + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + if (SanArgs.needsUbsanRt()) + CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a"); + if (SanArgs.needsAsanRt()) + CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a"); +} + static void ConstructPS4LinkJob(const Tool &T, Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/lib/Driver/ToolChains/PS4CPU.h b/lib/Driver/ToolChains/PS4CPU.h index 93752c4079..bd0a44352f 100644 --- a/lib/Driver/ToolChains/PS4CPU.h +++ b/lib/Driver/ToolChains/PS4CPU.h @@ -23,6 +23,8 @@ namespace PS4cpu { void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); +void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); + class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { public: Assemble(const ToolChain &TC) diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 5729f61550..5f66e24075 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -621,6 +621,8 @@ // RUN: %clang -target x86_64-scei-ps4 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-PS4 // Make sure there are no *.{o,bc} or -l passed before the ASan library. // CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}} +// CHECK-ASAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a +// CHECK-ASAN-PS4-NOT: {{(\.(o|bc)"? |-l).*-lSceDbgAddressSanitizer_stub_weak}} // CHECK-ASAN-PS4: -lSceDbgAddressSanitizer_stub_weak // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-MINIMAL diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index 3c55f5034d..93df586e30 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -646,6 +646,7 @@ // RUN: -target x86_64-scei-ps4 -fuse-ld=ld \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-PS4 %s +// CHECK-UBSAN-PS4: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a // CHECK-UBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}" // CHECK-UBSAN-PS4: -lSceDbgUBSanitizer_stub_weak @@ -653,6 +654,7 @@ // RUN: -target x86_64-scei-ps4 -fuse-ld=ld \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-PS4 %s +// CHECK-ASAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a // CHECK-ASAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}" // CHECK-ASAN-PS4: -lSceDbgAddressSanitizer_stub_weak @@ -660,6 +662,9 @@ // RUN: -target x86_64-scei-ps4 -fuse-ld=ld \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-AUBSAN-PS4 %s +// CHECK-AUBSAN-PS4-NOT: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a +// CHECK-AUBSAN-PS4: --dependent-lib=libSceDbgAddressSanitizer_stub_weak.a +// CHECK-AUBSAN-PS4-NOT: --dependent-lib=libSceDbgUBSanitizer_stub_weak.a // CHECK-AUBSAN-PS4: "{{.*}}ld{{(.gold)?(.exe)?}}" // CHECK-AUBSAN-PS4: -lSceDbgAddressSanitizer_stub_weak -- GitLab From 29aed5067f7fed62152613e217865e01b0ff8cff Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 6 Jun 2018 16:36:56 +0000 Subject: [PATCH 0032/1023] PR37680: fix faulty assertion condition. When looking up a template name, we can find an overload set containing a function template and an unresolved non-type using declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334106 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 1 + test/SemaTemplate/dependent-names.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c759c96be5..64f45af618 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -7292,6 +7292,7 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, for (UnresolvedSetIterator I = Begin; I != End; ++I) { NamedDecl *D = *I; assert(isa(D) || + isa(D) || (isa(D) && isa(D->getUnderlyingDecl()))); *Storage++ = D; diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp index 05ef33b535..67ef238083 100644 --- a/test/SemaTemplate/dependent-names.cpp +++ b/test/SemaTemplate/dependent-names.cpp @@ -447,3 +447,15 @@ namespace DependentUnresolvedUsingTemplate { xb.h(); // expected-note {{instantiation of}} } } + +namespace PR37680 { + template struct b : a { + using a::add; + template int add() { return this->template add(0); } + }; + struct a { + template int add(...); + void add(int); + }; + int f(b ba) { return ba.add<0>(); } +} -- GitLab From c0511c542a483e4dc6933fbab1e6477be16de2d0 Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Wed, 6 Jun 2018 17:52:55 +0000 Subject: [PATCH 0033/1023] [CUDA] Replace 'nv_weak' attributes in CUDA headers with 'weak'. Differential Revision: https://reviews.llvm.org/D47804 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334108 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/__clang_cuda_runtime_wrapper.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Headers/__clang_cuda_runtime_wrapper.h b/lib/Headers/__clang_cuda_runtime_wrapper.h index ed6cefb295..09705a273a 100644 --- a/lib/Headers/__clang_cuda_runtime_wrapper.h +++ b/lib/Headers/__clang_cuda_runtime_wrapper.h @@ -100,11 +100,17 @@ #include "host_config.h" #include "host_defines.h" +// Temporarily replace "nv_weak" with weak, so __attribute__((nv_weak)) in +// cuda_device_runtime_api.h ends up being __attribute__((weak)) which is the +// functional equivalent of what we need. +#pragma push_macro("nv_weak") +#define nv_weak weak #undef __CUDABE__ #undef __CUDA_LIBDEVICE__ #define __CUDACC__ #include "cuda_runtime.h" +#pragma pop_macro("nv_weak") #undef __CUDACC__ #define __CUDABE__ -- GitLab From 67a59f70404395fdb74d2944d099787ff44407bc Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 6 Jun 2018 18:39:47 +0000 Subject: [PATCH 0034/1023] [MS][ARM64]: Promote _setjmp to_setjmpex as there is no _setjmp in the ARM64 libvcruntime.lib Factor out the common setjmp call emission code. Based on a patch by Chris January Differential Revision: https://reviews.llvm.org/D47784 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334112 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 104 ++++++++++++++++++++------------------ test/CodeGen/ms-setjmp.c | 12 +++++ 2 files changed, 67 insertions(+), 49 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 5829396b0f..a09fa7aae5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -643,6 +643,52 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res")); } +namespace { +enum class MSVCSetJmpKind { + _setjmpex, + _setjmp3, + _setjmp +}; +} + +/// MSVC handles setjmp a bit differently on different platforms. On every +/// architecture except 32-bit x86, the frame address is passed. On x86, extra +/// parameters can be passed as variadic arguments, but we always pass none. +static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind, + const CallExpr *E) { + llvm::Value *Arg1 = nullptr; + llvm::Type *Arg1Ty = nullptr; + StringRef Name; + bool IsVarArg = false; + if (SJKind == MSVCSetJmpKind::_setjmp3) { + Name = "_setjmp3"; + Arg1Ty = CGF.Int32Ty; + Arg1 = llvm::ConstantInt::get(CGF.IntTy, 0); + IsVarArg = true; + } else { + Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex"; + Arg1Ty = CGF.Int8PtrTy; + Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress), + llvm::ConstantInt::get(CGF.Int32Ty, 0)); + } + + // Mark the call site and declaration with ReturnsTwice. + llvm::Type *ArgTypes[2] = {CGF.Int8PtrTy, Arg1Ty}; + llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( + CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, + llvm::Attribute::ReturnsTwice); + llvm::Constant *SetJmpFn = CGF.CGM.CreateRuntimeFunction( + llvm::FunctionType::get(CGF.IntTy, ArgTypes, IsVarArg), Name, + ReturnsTwiceAttr, /*Local=*/true); + + llvm::Value *Buf = CGF.Builder.CreateBitOrPointerCast( + CGF.EmitScalarExpr(E->getArg(0)), CGF.Int8PtrTy); + llvm::Value *Args[] = {Buf, Arg1}; + llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(SetJmpFn, Args); + CS.setAttributes(ReturnsTwiceAttr); + return RValue::get(CS.getInstruction()); +} + // Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we // handle them here. enum class CodeGenFunction::MSVCIntrin { @@ -2957,59 +3003,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__abnormal_termination: case Builtin::BI_abnormal_termination: return RValue::get(EmitSEHAbnormalTermination()); - case Builtin::BI_setjmpex: { - if (getTarget().getTriple().isOSMSVCRT()) { - llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy}; - llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReturnsTwice); - llvm::Constant *SetJmpEx = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false), - "_setjmpex", ReturnsTwiceAttr, /*Local=*/true); - llvm::Value *Buf = Builder.CreateBitOrPointerCast( - EmitScalarExpr(E->getArg(0)), Int8PtrTy); - llvm::Value *FrameAddr = - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), - ConstantInt::get(Int32Ty, 0)); - llvm::Value *Args[] = {Buf, FrameAddr}; - llvm::CallSite CS = EmitRuntimeCallOrInvoke(SetJmpEx, Args); - CS.setAttributes(ReturnsTwiceAttr); - return RValue::get(CS.getInstruction()); - } + case Builtin::BI_setjmpex: + if (getTarget().getTriple().isOSMSVCRT()) + return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); break; - } - case Builtin::BI_setjmp: { + case Builtin::BI_setjmp: if (getTarget().getTriple().isOSMSVCRT()) { - llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReturnsTwice); - llvm::Value *Buf = Builder.CreateBitOrPointerCast( - EmitScalarExpr(E->getArg(0)), Int8PtrTy); - llvm::CallSite CS; - if (getTarget().getTriple().getArch() == llvm::Triple::x86) { - llvm::Type *ArgTypes[] = {Int8PtrTy, IntTy}; - llvm::Constant *SetJmp3 = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/true), - "_setjmp3", ReturnsTwiceAttr, /*Local=*/true); - llvm::Value *Count = ConstantInt::get(IntTy, 0); - llvm::Value *Args[] = {Buf, Count}; - CS = EmitRuntimeCallOrInvoke(SetJmp3, Args); - } else { - llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy}; - llvm::Constant *SetJmp = CGM.CreateRuntimeFunction( - llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false), - "_setjmp", ReturnsTwiceAttr, /*Local=*/true); - llvm::Value *FrameAddr = - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), - ConstantInt::get(Int32Ty, 0)); - llvm::Value *Args[] = {Buf, FrameAddr}; - CS = EmitRuntimeCallOrInvoke(SetJmp, Args); - } - CS.setAttributes(ReturnsTwiceAttr); - return RValue::get(CS.getInstruction()); + if (getTarget().getTriple().getArch() == llvm::Triple::x86) + return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp3, E); + else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64) + return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); + return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp, E); } break; - } case Builtin::BI__GetExceptionInfo: { if (llvm::GlobalVariable *GV = diff --git a/test/CodeGen/ms-setjmp.c b/test/CodeGen/ms-setjmp.c index b9c67eb304..d92f4d00ff 100644 --- a/test/CodeGen/ms-setjmp.c +++ b/test/CodeGen/ms-setjmp.c @@ -1,7 +1,9 @@ // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s +// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s // RUN: %clang_cc1 -fms-extensions -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s // RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s +// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s typedef char jmp_buf[1]; #ifdef DECLARE_SETJMP @@ -21,6 +23,11 @@ int test_setjmp() { // X64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) // X64: %[[call:.*]] = call i32 @_setjmp(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) // X64-NEXT: ret i32 %[[call]] + + // AARCH64-LABEL: define dso_local i32 @test_setjmp + // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) + // AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) + // AARCH64-NEXT: ret i32 %[[call]] } int test_setjmpex() { @@ -29,4 +36,9 @@ int test_setjmpex() { // X64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) // X64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) // X64-NEXT: ret i32 %[[call]] + + // AARCH64-LABEL: define dso_local i32 @test_setjmpex + // AARCH64: %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) + // AARCH64: %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) + // AARCH64-NEXT: ret i32 %[[call]] } -- GitLab From 318f522d0cf2e6ddb5beee84886ed3792cdbbdda Mon Sep 17 00:00:00 2001 From: Evandro Menezes Date: Wed, 6 Jun 2018 18:58:01 +0000 Subject: [PATCH 0035/1023] [PATCH 2/2] [test] Add support for Samsung Exynos M4 (NFC) Add test cases for Exynos M4. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334116 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/arm-target-features.c | 1 + test/Driver/aarch64-cpus.c | 25 ++++++++++++++ test/Driver/arm-cortex-cpus.c | 36 ++++++++++++++------- test/Preprocessor/aarch64-target-features.c | 1 + test/Preprocessor/arm-target-features.c | 18 +++++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c index 42b08e23e3..6bc56be4f4 100644 --- a/test/CodeGen/arm-target-features.c +++ b/test/CodeGen/arm-target-features.c @@ -28,6 +28,7 @@ // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 +// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8 // CHECK-BASIC-V8: "target-features"="+armv8-a,+crc,+crypto,+dsp,+fp-armv8,+hwdiv,+hwdiv-arm,+neon,+thumb-mode" // RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM diff --git a/test/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c index 229484b257..8c7f06052f 100644 --- a/test/Driver/aarch64-cpus.c +++ b/test/Driver/aarch64-cpus.c @@ -155,6 +155,15 @@ // M3: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3" // M3-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" +// RUN: %clang -target aarch64_be -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s +// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s +// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4 %s +// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s +// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s +// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-TUNE %s +// M4: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4" +// M4-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" + // RUN: %clang -target arm64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s // RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s // RUN: %clang -target arm64 -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1-TUNE %s @@ -176,6 +185,13 @@ // ARM64-M3: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m3" // ARM64-M3-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" +// RUN: %clang -target arm64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4 %s +// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4 %s +// RUN: %clang -target arm64 -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s +// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M4-TUNE %s +// ARM64-M4: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m4" +// ARM64-M4-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" + // RUN: %clang -target aarch64 -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s // RUN: %clang -target aarch64 -mlittle-endian -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s // RUN: %clang -target aarch64 -mtune=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR-TUNE %s @@ -308,6 +324,15 @@ // M3-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3" // M3-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" +// RUN: %clang -target aarch64_be -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s +// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s +// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE %s +// RUN: %clang -target aarch64_be -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s +// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s +// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=M4-BE-TUNE %s +// M4-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m4" +// M4-BE-TUNE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" + // RUN: %clang -target aarch64_be -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s // RUN: %clang -target aarch64 -mbig-endian -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s // RUN: %clang -target aarch64_be -mbig-endian -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=THUNDERX2T99-BE %s diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c index 3c1eb2ea9a..90542326f3 100644 --- a/test/Driver/arm-cortex-cpus.c +++ b/test/Driver/arm-cortex-cpus.c @@ -493,18 +493,21 @@ // RUN: %clang -target arm -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s -// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s -// RUN: %clang -target arm -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s -// RUN: %clang -target arm -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a32 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a73 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// +// RUN: %clang -target arm -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A %s // CHECK-CPUV8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}} // RUN: %clang -target arm -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV82A %s @@ -519,18 +522,21 @@ // RUN: %clang -target armeb -mcpu=cortex-a57 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target armeb -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target armeb -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s -// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s -// RUN: %clang -target armeb -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s -// RUN: %clang -target armeb -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a32 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=cortex-a73 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// +// RUN: %clang -target armeb -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target armeb -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target armeb -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target armeb -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s +// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s // CHECK-BE-CPUV8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}} // RUN: %clang -target armeb -mcpu=cortex-a55 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A %s @@ -548,18 +554,21 @@ // RUN: %clang -target arm -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a73 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s -// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s -// RUN: %clang -target arm -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s -// RUN: %clang -target arm -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a32 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a35 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a53 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a57 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a73 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// +// RUN: %clang -target arm -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m1 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m2 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m3 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m4 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s // CHECK-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}} // RUN: %clang -target arm -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECKCPUV82A-THUMB %s @@ -574,18 +583,21 @@ // RUN: %clang -target armeb -mcpu=cortex-a57 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target armeb -mcpu=cortex-a72 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target armeb -mcpu=cortex-a73 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s -// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s -// RUN: %clang -target armeb -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s -// RUN: %clang -target armeb -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a32 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a35 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a53 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a57 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a72 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=cortex-a73 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// +// RUN: %clang -target armeb -mcpu=exynos-m1 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target armeb -mcpu=exynos-m2 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target armeb -mcpu=exynos-m3 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target armeb -mcpu=exynos-m4 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m1 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m2 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // RUN: %clang -target arm -mcpu=exynos-m3 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s +// RUN: %clang -target arm -mcpu=exynos-m4 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s // CHECK-BE-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}} // RUN: %clang -target armeb -mcpu=cortex-a55 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV82A-THUMB %s diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c index 80e5394592..92df0004e9 100644 --- a/test/Preprocessor/aarch64-target-features.c +++ b/test/Preprocessor/aarch64-target-features.c @@ -118,6 +118,7 @@ // RUN: %clang -target aarch64 -mcpu=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s // RUN: %clang -target aarch64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s // RUN: %clang -target aarch64 -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s +// RUN: %clang -target aarch64 -mcpu=exynos-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-M1 %s // RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-KRYO %s // RUN: %clang -target aarch64 -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-THUNDERX2T99 %s // CHECK-MCPU-CYCLONE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz" diff --git a/test/Preprocessor/arm-target-features.c b/test/Preprocessor/arm-target-features.c index 2301b21f32..a982d80850 100644 --- a/test/Preprocessor/arm-target-features.c +++ b/test/Preprocessor/arm-target-features.c @@ -485,6 +485,15 @@ // RUN: %clang -target armv8 -mthumb -mcpu=cortex-a72 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s // RUN: %clang -target armv8 -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s // RUN: %clang -target armv8 -mthumb -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// +// RUN: %clang -target armv8 -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s +// RUN: %clang -target armv8 -mthumb -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8 %s // ARMV8:#define __ARM_ARCH_EXT_IDIV__ 1 // ARMV8:#define __ARM_FEATURE_DSP 1 // ARMV8-NOT:#define __ARM_FP 0x @@ -502,6 +511,15 @@ // RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a72 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s // RUN: %clang -target armv8-eabi -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s // RUN: %clang -target armv8-eabi -mthumb -mcpu=cortex-a73 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// +// RUN: %clang -target armv8-eabi -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m1 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m2 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m3 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s +// RUN: %clang -target armv8-eabi -mthumb -mcpu=exynos-m4 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMV8-ALLOW-FP-INSTR %s // ARMV8-ALLOW-FP-INSTR:#define __ARM_ARCH_EXT_IDIV__ 1 // ARMV8-ALLOW-FP-INSTR:#define __ARM_FEATURE_DSP 1 // ARMV8-ALLOW-FP-INSTR:#define __ARM_FP 0xe -- GitLab From 7b0693d79162eca545845a8b2a82143ae955c1df Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Wed, 6 Jun 2018 19:44:10 +0000 Subject: [PATCH 0036/1023] [HIP] Fix unbundling HIP uses clang-offload-bundler to bundle intermediate files for host and different gpu archs together. When a file is unbundled, clang-offload-bundler should be called only once, and the objects for host and different gpu archs should be passed to the next jobs. This is because Driver maintains CachedResults which maps triple-arch string to output files for each job. This patch fixes a bug in Driver::BuildJobsForActionNoCache which uses incorrect key for CachedResults for HIP which causes clang-offload-bundler being called mutiple times and incorrect output files being used. It only affects HIP. Differential Revision: https://reviews.llvm.org/D47555 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334128 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Driver.cpp | 17 +++++++++++++---- test/Driver/hip-binding.hip | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 test/Driver/hip-binding.hip diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index c3ff9341a8..d0858764e7 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2808,7 +2808,7 @@ public: C.MakeAction(HostAction); UnbundlingHostAction->registerDependentActionInfo( C.getSingleOffloadToolChain(), - /*BoundArch=*/StringRef(), Action::OFK_Host); + /*BoundArch=*/"all", Action::OFK_Host); HostAction = UnbundlingHostAction; } @@ -3880,9 +3880,18 @@ InputInfo Driver::BuildJobsForActionNoCache( // Get the unique string identifier for this dependence and cache the // result. - CachedResults[{A, GetTriplePlusArchString( - UI.DependentToolChain, BoundArch, - UI.DependentOffloadKind)}] = CurI; + StringRef Arch; + if (TargetDeviceOffloadKind == Action::OFK_HIP) { + if (UI.DependentOffloadKind == Action::OFK_Host) + Arch = "all"; + else + Arch = UI.DependentBoundArch; + } else + Arch = BoundArch; + + CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch, + UI.DependentOffloadKind)}] = + CurI; } // Now that we have all the results generated, select the one that should be diff --git a/test/Driver/hip-binding.hip b/test/Driver/hip-binding.hip new file mode 100644 index 0000000000..c08cc67362 --- /dev/null +++ b/test/Driver/hip-binding.hip @@ -0,0 +1,15 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// RUN: touch %t.o +// RUN: %clang --hip-link -ccc-print-bindings -target x86_64-linux-gnu \ +// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o\ +// RUN: 2>&1 | FileCheck %s + +// CHECK: # "amdgcn-amd-amdhsa" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[OBJ1:.*o]]", "[[OBJ2:.*o]]", "[[OBJ3:.*o]]"] +// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ2]]"], output: "[[IMG2:.*out]]" +// CHECK-NOT: offload bundler +// CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ3]]"], output: "[[IMG3:.*out]]" +// CHECK-NOT: offload bundler +// CHECK: # "x86_64--linux-gnu" - "GNU::Linker", inputs: ["[[OBJ1]]", "[[IMG2]]", "[[IMG3]]"], output: "a.out" -- GitLab From 1fb14508226281332d180eacbbed286fb53162aa Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Wed, 6 Jun 2018 22:37:25 +0000 Subject: [PATCH 0037/1023] [CUDA] Check initializers of instantiated template variables. We were already performing checks on non-template variables, but the checks on templated ones were missing. Differential Revision: https://reviews.llvm.org/D45231 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334143 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 10 +++++ lib/Sema/SemaCUDA.cpp | 53 +++++++++++++++++++++++ lib/Sema/SemaDecl.cpp | 54 +----------------------- lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++ test/SemaCUDA/device-var-init.cu | 17 ++++++++ 5 files changed, 85 insertions(+), 52 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 06ecb57bc1..f42ce6d150 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -10166,6 +10166,16 @@ public: bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In + // case of error emits appropriate diagnostic and invalidates \p Var. + // + // \details CUDA allows only empty constructors as initializers for global + // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all + // __shared__ variables whether they are local or not (they all are implicitly + // static in CUDA). One exception is that CUDA allows constant initializers + // for __constant__ and __device__ variables. + void checkAllowedCUDAInitializer(VarDecl *Var); + /// Check whether NewFD is a valid overload for CUDA. Emits /// diagnostics and invalidates NewFD if not. void checkCUDATargetOverload(FunctionDecl *NewFD, diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp index c5deef8708..a44eeb47c1 100644 --- a/lib/Sema/SemaCUDA.cpp +++ b/lib/Sema/SemaCUDA.cpp @@ -472,6 +472,59 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { return true; } +void Sema::checkAllowedCUDAInitializer(VarDecl *VD) { + if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage()) + return; + const Expr *Init = VD->getInit(); + if (VD->hasAttr() || VD->hasAttr() || + VD->hasAttr()) { + assert(!VD->isStaticLocal() || VD->hasAttr()); + bool AllowedInit = false; + if (const CXXConstructExpr *CE = dyn_cast(Init)) + AllowedInit = + isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); + // We'll allow constant initializers even if it's a non-empty + // constructor according to CUDA rules. This deviates from NVCC, + // but allows us to handle things like constexpr constructors. + if (!AllowedInit && + (VD->hasAttr() || VD->hasAttr())) + AllowedInit = VD->getInit()->isConstantInitializer( + Context, VD->getType()->isReferenceType()); + + // Also make sure that destructor, if there is one, is empty. + if (AllowedInit) + if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl()) + AllowedInit = + isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); + + if (!AllowedInit) { + Diag(VD->getLocation(), VD->hasAttr() + ? diag::err_shared_var_init + : diag::err_dynamic_var_init) + << Init->getSourceRange(); + VD->setInvalidDecl(); + } + } else { + // This is a host-side global variable. Check that the initializer is + // callable from the host side. + const FunctionDecl *InitFn = nullptr; + if (const CXXConstructExpr *CE = dyn_cast(Init)) { + InitFn = CE->getConstructor(); + } else if (const CallExpr *CE = dyn_cast(Init)) { + InitFn = CE->getDirectCallee(); + } + if (InitFn) { + CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); + if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { + Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) + << InitFnTarget << InitFn; + Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; + VD->setInvalidDecl(); + } + } + } +} + // With -fcuda-host-device-constexpr, an unattributed constexpr function is // treated as implicitly __host__ __device__, unless: // * it is a variadic function (device-side variadic functions are not diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e1ee8ec079..f6faf38c95 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11675,58 +11675,8 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { // 7.5). We must also apply the same checks to all __shared__ // variables whether they are local or not. CUDA also allows // constant initializers for __constant__ and __device__ variables. - if (getLangOpts().CUDA) { - const Expr *Init = VD->getInit(); - if (Init && VD->hasGlobalStorage()) { - if (VD->hasAttr() || VD->hasAttr() || - VD->hasAttr()) { - assert(!VD->isStaticLocal() || VD->hasAttr()); - bool AllowedInit = false; - if (const CXXConstructExpr *CE = dyn_cast(Init)) - AllowedInit = - isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); - // We'll allow constant initializers even if it's a non-empty - // constructor according to CUDA rules. This deviates from NVCC, - // but allows us to handle things like constexpr constructors. - if (!AllowedInit && - (VD->hasAttr() || VD->hasAttr())) - AllowedInit = VD->getInit()->isConstantInitializer( - Context, VD->getType()->isReferenceType()); - - // Also make sure that destructor, if there is one, is empty. - if (AllowedInit) - if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl()) - AllowedInit = - isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); - - if (!AllowedInit) { - Diag(VD->getLocation(), VD->hasAttr() - ? diag::err_shared_var_init - : diag::err_dynamic_var_init) - << Init->getSourceRange(); - VD->setInvalidDecl(); - } - } else { - // This is a host-side global variable. Check that the initializer is - // callable from the host side. - const FunctionDecl *InitFn = nullptr; - if (const CXXConstructExpr *CE = dyn_cast(Init)) { - InitFn = CE->getConstructor(); - } else if (const CallExpr *CE = dyn_cast(Init)) { - InitFn = CE->getDirectCallee(); - } - if (InitFn) { - CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); - if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { - Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) - << InitFnTarget << InitFn; - Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; - VD->setInvalidDecl(); - } - } - } - } - } + if (getLangOpts().CUDA) + checkAllowedCUDAInitializer(VD); // Grab the dllimport or dllexport attribute off of the VarDecl. const InheritableAttr *DLLAttr = getDLLAttr(VD); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index dd62d4c98f..68857d972b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4224,6 +4224,9 @@ void Sema::InstantiateVariableInitializer( ActOnUninitializedDecl(Var); } + + if (getLangOpts().CUDA) + checkAllowedCUDAInitializer(Var); } /// Instantiate the definition of the given variable from its diff --git a/test/SemaCUDA/device-var-init.cu b/test/SemaCUDA/device-var-init.cu index 71f2352843..46cb90da2e 100644 --- a/test/SemaCUDA/device-var-init.cu +++ b/test/SemaCUDA/device-var-init.cu @@ -225,3 +225,20 @@ inline __host__ __device__ void hd_emitted_host_only() { static int x = 42; // no error on device because this is never codegen'ed there. } void call_hd_emitted_host_only() { hd_emitted_host_only(); } + +// Verify that we also check field initializers in instantiated structs. +struct NontrivialInitializer { + __host__ __device__ NontrivialInitializer() : x(43) {} + int x; +}; + +template +__global__ void bar() { + __shared__ T bad; +// expected-error@-1 {{initialization is not supported for __shared__ variables.}} +} + +void instantiate() { + bar<<<1, 1>>>(); +// expected-note@-1 {{in instantiation of function template specialization 'bar' requested here}} +} -- GitLab From f7a73f32af153d5dd46a071ac51a5cb65b6bdc06 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Wed, 6 Jun 2018 23:09:02 +0000 Subject: [PATCH 0038/1023] [Driver] Stop passing -fseh-exceptions for x86_64-windows-msvc -fseh-exceptions is only meaningful for MinGW targets, and that driver already has logic to pass either -fdwarf-exceptions or -fseh-exceptions as appropriate. -fseh-exceptions is just a no-op for MSVC triples, and passing it to cc1 causes unnecessary confusion. Differential Revision: https://reviews.llvm.org/D47850 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334145 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChain.cpp | 2 -- test/Driver/windows-exceptions.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 test/Driver/windows-exceptions.cpp diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index c12943c6c9..a3799ac613 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -471,8 +471,6 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { llvm::ExceptionHandling ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const { - if (Triple.isOSWindows() && Triple.getArch() != llvm::Triple::x86) - return llvm::ExceptionHandling::WinEH; return llvm::ExceptionHandling::None; } diff --git a/test/Driver/windows-exceptions.cpp b/test/Driver/windows-exceptions.cpp new file mode 100644 index 0000000000..8bce3b8dd8 --- /dev/null +++ b/test/Driver/windows-exceptions.cpp @@ -0,0 +1,9 @@ +// RUN: %clang -target i686-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s +// RUN: %clang -target x86_64-windows-msvc -c %s -### 2>&1 | FileCheck -check-prefix=MSVC %s +// RUN: %clang -target i686-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-DWARF %s +// RUN: %clang -target x86_64-windows-gnu -c %s -### 2>&1 | FileCheck -check-prefix=MINGW-SEH %s + +MSVC-NOT: -fdwarf-exceptions +MSVC-NOT: -fseh-exceptions +MINGW-DWARF: -fdwarf-exceptions +MINGW-SEH: -fseh-exceptions -- GitLab From 45021ac24d6325163e48b5e4451ec97330e7dd40 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Thu, 7 Jun 2018 00:20:58 +0000 Subject: [PATCH 0039/1023] [ODRHash] Adjust info stored for FunctionTemplateDecl. Avoid storing information for definitions since those can be out-of-line and vary between modules even when the declarations are the same. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334151 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ODRHash.cpp | 2 +- test/Modules/odr_hash.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 7a3a6964e5..126b6de25e 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -427,7 +427,7 @@ public: void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { Visit(D->getTemplatedDecl()); - ID.AddInteger(D->getTemplatedDecl()->getODRHash()); + AddDecl(D->getTemplatedDecl()); Inherited::VisitFunctionTemplateDecl(D); } }; diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index dd3952232b..9cb177fbfc 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -3617,6 +3617,20 @@ int I10 = F10(); #endif // expected-error@second.h:* {{'FunctionDecl::F10' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}} // expected-note@first.h:* {{but in 'FirstModule' found a different body}} + +#if defined(FIRST) +struct S11 { + template void foo(); +}; +#elif defined(SECOND) +struct S11 { + template void foo(); +}; +template void S11::foo() {} +#else +S11 s11; +#endif + } // namespace FunctionDecl namespace DeclTemplateArguments { -- GitLab From 0e636ed28eaa8d03e7141630f33ec11316163c57 Mon Sep 17 00:00:00 2001 From: Sunil Srivastava Date: Thu, 7 Jun 2018 00:42:59 +0000 Subject: [PATCH 0040/1023] Change the wording of RTTI errors to make them more generic. An attempt to use dynamic_cast while rtti is disabled, used to emit the error: cannot use dynamic_cast with -fno-rtti and a similar one for typeid. This patch changes that to: use of dynamic_cast requires -frtti Differential Revision: https://reviews.llvm.org/D47291 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334153 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- test/SemaCXX/no-rtti.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 16836b9861..e0050d6839 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6607,9 +6607,9 @@ def err_not_tag_in_scope : Error< "no %select{struct|interface|union|class|enum}0 named %1 in %2">; def err_no_typeid_with_fno_rtti : Error< - "cannot use typeid with -fno-rtti">; + "use of typeid requires -frtti">; def err_no_dynamic_cast_with_fno_rtti : Error< - "cannot use dynamic_cast with -fno-rtti">; + "use of dynamic_cast requires -frtti">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; diff --git a/test/SemaCXX/no-rtti.cpp b/test/SemaCXX/no-rtti.cpp index a171b3cde2..e0b57153c2 100644 --- a/test/SemaCXX/no-rtti.cpp +++ b/test/SemaCXX/no-rtti.cpp @@ -6,7 +6,7 @@ namespace std { void f() { - (void)typeid(int); // expected-error {{cannot use typeid with -fno-rtti}} + (void)typeid(int); // expected-error {{use of typeid requires -frtti}} } namespace { @@ -20,7 +20,7 @@ struct B : public A { } bool isa_B(A *a) { - return dynamic_cast(a) != 0; // expected-error {{cannot use dynamic_cast with -fno-rtti}} + return dynamic_cast(a) != 0; // expected-error {{use of dynamic_cast requires -frtti}} } void* getMostDerived(A* a) { -- GitLab From f9e757c085f864c96f76f4807e94f6bfb6146f49 Mon Sep 17 00:00:00 2001 From: Han Shen Date: Thu, 7 Jun 2018 00:55:54 +0000 Subject: [PATCH 0041/1023] ClangTidy fix - 'clang::Sema::checkAllowedCUDAInitializer' has a definition with different parameter names. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334155 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f42ce6d150..7641814319 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -10174,7 +10174,7 @@ public: // __shared__ variables whether they are local or not (they all are implicitly // static in CUDA). One exception is that CUDA allows constant initializers // for __constant__ and __device__ variables. - void checkAllowedCUDAInitializer(VarDecl *Var); + void checkAllowedCUDAInitializer(VarDecl *VD); /// Check whether NewFD is a valid overload for CUDA. Emits /// diagnostics and invalidates NewFD if not. -- GitLab From 57ebd133fb0101cd93bb97bd61275a9fc6a5c642 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 7 Jun 2018 02:46:02 +0000 Subject: [PATCH 0042/1023] [X86] Add back _mask, _maskz, and _mask3 builtins for some 512-bit fmadd/fmsub/fmaddsub/fmsubadd builtins. Summary: We recently switch to using a selects in the intrinsics header files for FMA instructions. But the 512-bit versions support flavors with rounding mode which must be an Integer Constant Expression. This has forced those intrinsics to be implemented as macros. As it stands now the mask and mask3 intrinsics evaluate one of their macro arguments twice. If that argument itself is another intrinsic macro, we can end up over expanding macros. Or if its something we can CSE later it would show up multiple times when it shouldn't. I tried adding __extension__ around the macro and making it an expression statement and declaring a local variable. But whatever name you choose for the local variable can never be used as the name of an input to the macro in user code. If that happens you would end up with the same name on the LHS and RHS of an assignment after expansion. We might be safe if we use __ in front of the variable names because those names are reserved and user code shouldn't use that, but I wasn't sure I wanted to make that claim. The other option which I've chosen here, is to add back _mask, _maskz, and _mask3 flavors of the builtin which we will expand in CGBuiltin.cpp to replicate the argument as needed and insert any fneg needed on the third operand to make a subtract. The _maskz isn't truly necessary if we have an unmasked version or if we use the masked version with a -1 mask and wrap a select around it. But I've chosen to make things more uniform. I separated out the scalar builtin handling to avoid too many things going on in EmitX86FMAExpr. It was different enough due to the extract and insert that the minor duplication of the CreateCall was probably worth it. Reviewers: tkrupa, RKSimon, spatel, GBuella Reviewed By: tkrupa Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47724 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334159 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 20 +- lib/CodeGen/CGBuiltin.cpp | 173 +++-- lib/Headers/avx512fintrin.h | 956 +++++++++++++--------------- lib/Sema/SemaChecking.cpp | 20 +- test/CodeGen/avx512f-builtins.c | 48 +- 5 files changed, 600 insertions(+), 617 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index a164681b2e..33dda55fe3 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -731,10 +731,22 @@ TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "nc", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "nc", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512, "V8dV8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512, "V16fV16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512, "V8dV8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512, "V16fV16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") // XOP TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "nc", "xop") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a09fa7aae5..a086b4d926 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8555,79 +8555,110 @@ static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred, // Lowers X86 FMA intrinsics to IR. static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef Ops, - unsigned BuiltinID) { + unsigned BuiltinID, bool IsAddSub) { - bool IsAddSub = false; - bool IsScalar = false; - - // 4 operands always means rounding mode without a mask here. - bool IsRound = Ops.size() == 4; - - Intrinsic::ID ID; + bool Subtract = false; + Intrinsic::ID IID = Intrinsic::not_intrinsic; switch (BuiltinID) { default: break; - case clang::X86::BI__builtin_ia32_vfmaddss3: IsScalar = true; break; - case clang::X86::BI__builtin_ia32_vfmaddsd3: IsScalar = true; break; - case clang::X86::BI__builtin_ia32_vfmaddps512: - ID = llvm::Intrinsic::x86_avx512_vfmadd_ps_512; break; - case clang::X86::BI__builtin_ia32_vfmaddpd512: - ID = llvm::Intrinsic::x86_avx512_vfmadd_pd_512; break; - case clang::X86::BI__builtin_ia32_vfmaddsubps: IsAddSub = true; break; - case clang::X86::BI__builtin_ia32_vfmaddsubpd: IsAddSub = true; break; - case clang::X86::BI__builtin_ia32_vfmaddsubps256: IsAddSub = true; break; - case clang::X86::BI__builtin_ia32_vfmaddsubpd256: IsAddSub = true; break; - case clang::X86::BI__builtin_ia32_vfmaddsubps512: { - ID = llvm::Intrinsic::x86_avx512_vfmaddsub_ps_512; - IsAddSub = true; + case clang::X86::BI__builtin_ia32_vfmsubps512_mask3: + Subtract = true; + LLVM_FALLTHROUGH; + case clang::X86::BI__builtin_ia32_vfmaddps512_mask: + case clang::X86::BI__builtin_ia32_vfmaddps512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddps512_mask3: + IID = llvm::Intrinsic::x86_avx512_vfmadd_ps_512; break; + case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3: + Subtract = true; + LLVM_FALLTHROUGH; + case clang::X86::BI__builtin_ia32_vfmaddpd512_mask: + case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3: + IID = llvm::Intrinsic::x86_avx512_vfmadd_pd_512; break; + case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3: + Subtract = true; + LLVM_FALLTHROUGH; + case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask: + case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3: + IID = llvm::Intrinsic::x86_avx512_vfmaddsub_ps_512; break; - } - case clang::X86::BI__builtin_ia32_vfmaddsubpd512: { - ID = llvm::Intrinsic::x86_avx512_vfmaddsub_pd_512; - IsAddSub = true; + case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3: + Subtract = true; + LLVM_FALLTHROUGH; + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask: + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3: + IID = llvm::Intrinsic::x86_avx512_vfmaddsub_pd_512; break; } - } - - // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding). - if (IsRound) { - Function *Intr = CGF.CGM.getIntrinsic(ID); - if (cast(Ops[3])->getZExtValue() != (uint64_t)4) - return CGF.Builder.CreateCall(Intr, Ops); - } Value *A = Ops[0]; Value *B = Ops[1]; Value *C = Ops[2]; - if (IsScalar) { - A = CGF.Builder.CreateExtractElement(A, (uint64_t)0); - B = CGF.Builder.CreateExtractElement(B, (uint64_t)0); - C = CGF.Builder.CreateExtractElement(C, (uint64_t)0); - } + if (Subtract) + C = CGF.Builder.CreateFNeg(C); - llvm::Type *Ty = A->getType(); - Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty); - Value *Res = CGF.Builder.CreateCall(FMA, {A, B, C} ); + Value *Res; - if (IsScalar) - return CGF.Builder.CreateInsertElement(Ops[0], Res, (uint64_t)0); + // Only handle in case of _MM_FROUND_CUR_DIRECTION/4 (no rounding). + if (IID != Intrinsic::not_intrinsic && + cast(Ops.back())->getZExtValue() != (uint64_t)4) { + Function *Intr = CGF.CGM.getIntrinsic(IID); + Res = CGF.Builder.CreateCall(Intr, {A, B, C, Ops.back() }); + } else { + llvm::Type *Ty = A->getType(); + Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty); + Res = CGF.Builder.CreateCall(FMA, {A, B, C} ); + + if (IsAddSub) { + // Negate even elts in C using a mask. + unsigned NumElts = Ty->getVectorNumElements(); + SmallVector NMask; + Constant *Zero = ConstantInt::get(CGF.Builder.getInt1Ty(), 0); + Constant *One = ConstantInt::get(CGF.Builder.getInt1Ty(), 1); + for (unsigned i = 0; i < NumElts; ++i) { + NMask.push_back(i % 2 == 0 ? One : Zero); + } + Value *NegMask = ConstantVector::get(NMask); - if (IsAddSub) { - // Negate even elts in C using a mask. - unsigned NumElts = Ty->getVectorNumElements(); - SmallVector NMask; - Constant *Zero = ConstantInt::get(CGF.Builder.getInt1Ty(), 0); - Constant *One = ConstantInt::get(CGF.Builder.getInt1Ty(), 1); - for (unsigned i = 0; i < NumElts; ++i) { - NMask.push_back(i % 2 == 0 ? One : Zero); + Value *NegC = CGF.Builder.CreateFNeg(C); + Value *FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} ); + Res = CGF.Builder.CreateSelect(NegMask, FMSub, Res); } - Value *NegMask = ConstantVector::get(NMask); + } - Value *NegC = CGF.Builder.CreateFNeg(C); - Value *FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} ); - Res = CGF.Builder.CreateSelect(NegMask, FMSub, Res); + // Handle any required masking. + Value *MaskFalseVal = nullptr; + switch (BuiltinID) { + case clang::X86::BI__builtin_ia32_vfmaddps512_mask: + case clang::X86::BI__builtin_ia32_vfmaddpd512_mask: + case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask: + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask: + MaskFalseVal = Ops[0]; + break; + case clang::X86::BI__builtin_ia32_vfmaddps512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddpd512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz: + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz: + MaskFalseVal = Constant::getNullValue(Ops[0]->getType()); + break; + case clang::X86::BI__builtin_ia32_vfmsubps512_mask3: + case clang::X86::BI__builtin_ia32_vfmaddps512_mask3: + case clang::X86::BI__builtin_ia32_vfmsubpd512_mask3: + case clang::X86::BI__builtin_ia32_vfmaddpd512_mask3: + case clang::X86::BI__builtin_ia32_vfmsubaddps512_mask3: + case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3: + case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3: + case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3: + MaskFalseVal = Ops[2]; + break; } + if (MaskFalseVal) + return EmitX86Select(CGF, Ops[3], Res, MaskFalseVal); + return Res; } @@ -9046,20 +9077,40 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return EmitX86ConvertToMask(*this, Ops[0]); case X86::BI__builtin_ia32_vfmaddss3: - case X86::BI__builtin_ia32_vfmaddsd3: + case X86::BI__builtin_ia32_vfmaddsd3: { + Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); + Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); + Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); + Function *FMA = CGM.getIntrinsic(Intrinsic::fma, A->getType()); + Value *Res = Builder.CreateCall(FMA, {A, B, C} ); + return Builder.CreateInsertElement(Ops[0], Res, (uint64_t)0); + } case X86::BI__builtin_ia32_vfmaddps: case X86::BI__builtin_ia32_vfmaddpd: case X86::BI__builtin_ia32_vfmaddps256: case X86::BI__builtin_ia32_vfmaddpd256: - case X86::BI__builtin_ia32_vfmaddps512: - case X86::BI__builtin_ia32_vfmaddpd512: + case X86::BI__builtin_ia32_vfmaddps512_mask: + case X86::BI__builtin_ia32_vfmaddps512_maskz: + case X86::BI__builtin_ia32_vfmaddps512_mask3: + case X86::BI__builtin_ia32_vfmsubps512_mask3: + case X86::BI__builtin_ia32_vfmaddpd512_mask: + case X86::BI__builtin_ia32_vfmaddpd512_maskz: + case X86::BI__builtin_ia32_vfmaddpd512_mask3: + case X86::BI__builtin_ia32_vfmsubpd512_mask3: + return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/false); case X86::BI__builtin_ia32_vfmaddsubps: case X86::BI__builtin_ia32_vfmaddsubpd: case X86::BI__builtin_ia32_vfmaddsubps256: case X86::BI__builtin_ia32_vfmaddsubpd256: - case X86::BI__builtin_ia32_vfmaddsubps512: - case X86::BI__builtin_ia32_vfmaddsubpd512: - return EmitX86FMAExpr(*this, Ops, BuiltinID); + case X86::BI__builtin_ia32_vfmaddsubps512_mask: + case X86::BI__builtin_ia32_vfmaddsubps512_maskz: + case X86::BI__builtin_ia32_vfmaddsubps512_mask3: + case X86::BI__builtin_ia32_vfmsubaddps512_mask3: + case X86::BI__builtin_ia32_vfmaddsubpd512_mask: + case X86::BI__builtin_ia32_vfmaddsubpd512_maskz: + case X86::BI__builtin_ia32_vfmaddsubpd512_mask3: + case X86::BI__builtin_ia32_vfmsubaddpd512_mask3: + return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/true); case X86::BI__builtin_ia32_movdqa32store128_mask: case X86::BI__builtin_ia32_movdqa64store128_mask: diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 2b3633e377..47a0c9d433 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -2578,910 +2578,818 @@ _mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__mmask8)-1, (int)(R)) #define _mm512_fmadd_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), (int)(R)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_mask_fmadd_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_mask3_fmadd_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmaddpd512_mask3((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_maskz_fmadd_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddpd512_maskz((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_fmsub_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_mask_fmsub_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_maskz_fmsub_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddpd512_maskz((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_fnmadd_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), (int)(R)) + (__m512d)__builtin_ia32_vfmaddpd512_mask(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_mask3_fnmadd_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmaddpd512_mask3(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_maskz_fnmadd_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddpd512_maskz(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_fnmsub_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)) + (__m512d)__builtin_ia32_vfmaddpd512_mask(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_maskz_fnmsub_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddpd512_maskz(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + -(__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d) __builtin_ia32_vfmaddpd512_mask3 (-(__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + -(__v8df) __B, + -(__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_fmadd_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), (int)(R)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_mask_fmadd_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_mask3_fmadd_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmaddps512_mask3((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_maskz_fmadd_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddps512_maskz((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_fmsub_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_mask_fmsub_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_maskz_fmsub_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddps512_maskz((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_fnmadd_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), (int)(R)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + -(__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_mask3_fnmadd_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmaddps512_mask3(-(__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_maskz_fnmadd_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddps512_maskz(-(__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_fnmsub_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + -(__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_maskz_fnmsub_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddps512_maskz(-(__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + -(__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512) __builtin_ia32_vfmaddps512_mask3 (-(__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + -(__v16sf) __B, + -(__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_fmaddsub_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)) + (__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_mask_fmaddsub_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_mask3_fmaddsub_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmaddsubpd512_mask3((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_maskz_fmaddsub_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddsubpd512_maskz((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_fmsubadd_round_pd(A, B, C, R) \ - (__m512d)__builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)) + (__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)-1, (int)(R)) #define _mm512_mask_fmsubadd_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddsubpd512_mask((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_maskz_fmsubadd_round_pd(U, A, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)_mm512_setzero_pd()) + (__m512d)__builtin_ia32_vfmaddsubpd512_maskz((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) _mm512_setzero_pd()); + return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, + (__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_fmaddsub_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)) + (__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_mask_fmaddsub_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_mask3_fmaddsub_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmaddsubps512_mask3((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_maskz_fmaddsub_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddsubps512_maskz((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_fmsubadd_round_ps(A, B, C, R) \ - (__m512)__builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)) + (__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)-1, (int)(R)) #define _mm512_mask_fmsubadd_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddsubps512_mask((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_maskz_fmsubadd_round_ps(U, A, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)_mm512_setzero_ps()) + (__m512)__builtin_ia32_vfmaddsubps512_maskz((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) -1, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) _mm512_setzero_ps()); + return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, + (__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask3_fmsub_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - (__m512d)__builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmsubpd512_mask3((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - (__m512d)__builtin_ia32_vfmaddpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d)__builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask3_fmsub_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - (__m512)__builtin_ia32_vfmaddps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmsubps512_mask3((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - (__m512)__builtin_ia32_vfmaddps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512)__builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask3_fmsubadd_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - (__m512d)__builtin_ia32_vfmaddsubpd512((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmsubaddpd512_mask3((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - (__m512d)__builtin_ia32_vfmaddsubpd512 ((__v8df) __A, - (__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d)__builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask3_fmsubadd_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - (__m512)__builtin_ia32_vfmaddsubps512((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmsubaddps512_mask3((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - (__m512)__builtin_ia32_vfmaddsubps512 ((__v16sf) __A, - (__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512)__builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask_fnmadd_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - __builtin_ia32_vfmaddpd512(-(__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + -(__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask8) __U, - __builtin_ia32_vfmaddpd512 (-(__v8df) __A, - (__v8df) __B, - (__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + -(__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask_fnmadd_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - __builtin_ia32_vfmaddps512(-(__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + -(__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - __builtin_ia32_vfmaddps512 (-(__v16sf) __A, - (__v16sf) __B, - (__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + -(__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask_fnmsub_round_pd(A, U, B, C, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - (__m512d)__builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - -(__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(A)) + (__m512d)__builtin_ia32_vfmaddpd512_mask((__v8df)(__m512d)(A), \ + -(__v8df)(__m512d)(B), \ + -(__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) #define _mm512_mask3_fnmsub_round_pd(A, B, C, U, R) \ - (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ - (__m512d)__builtin_ia32_vfmaddpd512((__v8df)(__m512d)(A), \ - -(__v8df)(__m512d)(B), \ - -(__v8df)(__m512d)(C), \ - (int)(R)), \ - (__v8df)(__m512d)(C)) + (__m512d)__builtin_ia32_vfmsubpd512_mask3(-(__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), \ + (__v8df)(__m512d)(C), \ + (__mmask8)(U), (int)(R)) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask16) __U, - (__m512d) __builtin_ia32_vfmaddpd512 ((__v8df) __A, - -(__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __A); + return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, + -(__v8df) __B, + -(__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { - return (__m512d) __builtin_ia32_selectpd_512((__mmask16) __U, - (__m512d) __builtin_ia32_vfmaddpd512 ((__v8df) __A, - -(__v8df) __B, - -(__v8df) __C, - _MM_FROUND_CUR_DIRECTION), - (__v8df) __C); + return (__m512d) __builtin_ia32_vfmsubpd512_mask3 (-(__v8df) __A, + (__v8df) __B, + (__v8df) __C, + (__mmask8) __U, + _MM_FROUND_CUR_DIRECTION); } #define _mm512_mask_fnmsub_round_ps(A, U, B, C, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - (__m512)__builtin_ia32_vfmaddps512 ((__v16sf)(__m512)(A), \ - -(__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(A)) + (__m512)__builtin_ia32_vfmaddps512_mask((__v16sf)(__m512)(A), \ + -(__v16sf)(__m512)(B), \ + -(__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) #define _mm512_mask3_fnmsub_round_ps(A, B, C, U, R) \ - (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ - (__m512)__builtin_ia32_vfmaddps512 ((__v16sf)(__m512)(A), \ - -(__v16sf)(__m512)(B), \ - -(__v16sf)(__m512)(C), \ - (int)(R)), \ - (__v16sf)(__m512)(C)) + (__m512)__builtin_ia32_vfmsubps512_mask3(-(__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + (__v16sf)(__m512)(C), \ + (__mmask16)(U), (int)(R)) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - (__m512) __builtin_ia32_vfmaddps512 ((__v16sf) __A, - -(__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __A); + return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, + -(__v16sf) __B, + -(__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { - return (__m512) __builtin_ia32_selectps_512((__mmask16) __U, - (__m512) __builtin_ia32_vfmaddps512 ((__v16sf) __A, - -(__v16sf) __B, - -(__v16sf) __C, - _MM_FROUND_CUR_DIRECTION), - (__v16sf) __C); + return (__m512) __builtin_ia32_vfmsubps512_mask3 (-(__v16sf) __A, + (__v16sf) __B, + (__v16sf) __C, + (__mmask16) __U, + _MM_FROUND_CUR_DIRECTION); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index b4fdcc0f7e..44c8731641 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2340,10 +2340,6 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_cvtuqq2ps512_mask: case X86::BI__builtin_ia32_sqrtpd512_mask: case X86::BI__builtin_ia32_sqrtps512_mask: - case X86::BI__builtin_ia32_vfmaddpd512: - case X86::BI__builtin_ia32_vfmaddps512: - case X86::BI__builtin_ia32_vfmaddsubpd512: - case X86::BI__builtin_ia32_vfmaddsubps512: ArgNum = 3; HasRC = true; break; @@ -2378,6 +2374,22 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vfmaddss3_mask: case X86::BI__builtin_ia32_vfmaddss3_maskz: case X86::BI__builtin_ia32_vfmaddss3_mask3: + case X86::BI__builtin_ia32_vfmaddpd512_mask: + case X86::BI__builtin_ia32_vfmaddpd512_maskz: + case X86::BI__builtin_ia32_vfmaddpd512_mask3: + case X86::BI__builtin_ia32_vfmsubpd512_mask3: + case X86::BI__builtin_ia32_vfmaddps512_mask: + case X86::BI__builtin_ia32_vfmaddps512_maskz: + case X86::BI__builtin_ia32_vfmaddps512_mask3: + case X86::BI__builtin_ia32_vfmsubps512_mask3: + case X86::BI__builtin_ia32_vfmaddsubpd512_mask: + case X86::BI__builtin_ia32_vfmaddsubpd512_maskz: + case X86::BI__builtin_ia32_vfmaddsubpd512_mask3: + case X86::BI__builtin_ia32_vfmsubaddpd512_mask3: + case X86::BI__builtin_ia32_vfmaddsubps512_mask: + case X86::BI__builtin_ia32_vfmaddsubps512_maskz: + case X86::BI__builtin_ia32_vfmaddsubps512_mask3: + case X86::BI__builtin_ia32_vfmsubaddps512_mask3: ArgNum = 4; HasRC = true; break; diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index cd773791a2..a6f7e17aa6 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -461,7 +461,7 @@ __m512d test_mm512_maskz_fmadd_round_pd(__mmask8 __U, __m512d __A, __m512d __B, // CHECK-LABEL: @test_mm512_maskz_fmadd_round_pd // CHECK: @llvm.x86.avx512.vfmadd.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fmsub_round_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -483,7 +483,7 @@ __m512d test_mm512_maskz_fmsub_round_pd(__mmask8 __U, __m512d __A, __m512d __B, // CHECK: fsub <8 x double> // CHECK: @llvm.x86.avx512.vfmadd.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fnmadd_round_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -505,7 +505,7 @@ __m512d test_mm512_maskz_fnmadd_round_pd(__mmask8 __U, __m512d __A, __m512d __B, // CHECK: fsub <8 x double> // CHECK: @llvm.x86.avx512.vfmadd.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fnmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fnmsub_round_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -521,7 +521,7 @@ __m512d test_mm512_maskz_fnmsub_round_pd(__mmask8 __U, __m512d __A, __m512d __B, // CHECK: fsub <8 x double> // CHECK: @llvm.x86.avx512.vfmadd.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fnmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -547,7 +547,7 @@ __m512d test_mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512 // CHECK-LABEL: @test_mm512_maskz_fmadd_pd // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmadd_pd(__U, __A, __B, __C); } __m512d test_mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -569,7 +569,7 @@ __m512d test_mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512 // CHECK: fsub <8 x double> , %{{.*}} // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsub_pd(__U, __A, __B, __C); } __m512d test_mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -591,7 +591,7 @@ __m512d test_mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m51 // CHECK: fsub <8 x double> , %{{.*}} // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fnmadd_pd(__U, __A, __B, __C); } __m512d test_mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -607,7 +607,7 @@ __m512d test_mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m51 // CHECK: fsub <8 x double> , %{{.*}} // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fnmsub_pd(__U, __A, __B, __C); } __m512 test_mm512_fmadd_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -633,7 +633,7 @@ __m512 test_mm512_maskz_fmadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __ // CHECK-LABEL: @test_mm512_maskz_fmadd_round_ps // CHECK: @llvm.x86.avx512.vfmadd.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fmsub_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -655,7 +655,7 @@ __m512 test_mm512_maskz_fmsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, __ // CHECK: fsub <16 x float> , %{{.*}} // CHECK: @llvm.x86.avx512.vfmadd.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fnmadd_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -677,7 +677,7 @@ __m512 test_mm512_maskz_fnmadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, _ // CHECK: fsub <16 x float> , %{{.*}} // CHECK: @llvm.x86.avx512.vfmadd.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fnmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fnmsub_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -693,7 +693,7 @@ __m512 test_mm512_maskz_fnmsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, _ // CHECK: fsub <16 x float> , %{{.*}} // CHECK: @llvm.x86.avx512.vfmadd.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fnmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -717,7 +717,7 @@ __m512 test_mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 _ // CHECK-LABEL: @test_mm512_maskz_fmadd_ps // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmadd_ps(__U, __A, __B, __C); } __m512 test_mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -739,7 +739,7 @@ __m512 test_mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 _ // CHECK: fsub <16 x float> , %{{.*}} // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsub_ps(__U, __A, __B, __C); } __m512 test_mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -761,7 +761,7 @@ __m512 test_mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 // CHECK: fsub <16 x float> , %{{.*}} // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fnmadd_ps(__U, __A, __B, __C); } __m512 test_mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -777,7 +777,7 @@ __m512 test_mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 // CHECK: fsub <16 x float> , %{{.*}} // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fnmsub_ps(__U, __A, __B, __C); } __m512d test_mm512_fmaddsub_round_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -803,7 +803,7 @@ __m512d test_mm512_maskz_fmaddsub_round_pd(__mmask8 __U, __m512d __A, __m512d __ // CHECK-LABEL: @test_mm512_maskz_fmaddsub_round_pd // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmaddsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fmsubadd_round_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -825,7 +825,7 @@ __m512d test_mm512_maskz_fmsubadd_round_pd(__mmask8 __U, __m512d __A, __m512d __ // CHECK: fsub <8 x double> , %{{.*}} // CHECK: @llvm.x86.avx512.vfmaddsub.pd.512 // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsubadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -863,7 +863,7 @@ __m512d test_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m // check: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // check: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmaddsub_pd(__U, __A, __B, __C); } __m512d test_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) { @@ -891,7 +891,7 @@ __m512d test_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsubadd_pd(__U, __A, __B, __C); } __m512 test_mm512_fmaddsub_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -917,7 +917,7 @@ __m512 test_mm512_maskz_fmaddsub_round_ps(__mmask16 __U, __m512 __A, __m512 __B, // CHECK-LABEL: @test_mm512_maskz_fmaddsub_round_ps // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmaddsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fmsubadd_round_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -939,7 +939,7 @@ __m512 test_mm512_maskz_fmsubadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, // CHECK: fsub <16 x float> , %{{.*}} // CHECK: @llvm.x86.avx512.vfmaddsub.ps.512 // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsubadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -977,7 +977,7 @@ __m512 test_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m51 // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmaddsub_ps(__U, __A, __B, __C); } __m512 test_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) { @@ -1005,7 +1005,7 @@ __m512 test_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m51 // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} // CHECK: bitcast i16 %{{.*}} to <16 x i1> - // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsubadd_ps(__U, __A, __B, __C); } __m512d test_mm512_mask3_fmsub_round_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { -- GitLab From 91851548aaf19adfa1702aaa739676097ea53cea Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Thu, 7 Jun 2018 03:20:30 +0000 Subject: [PATCH 0043/1023] Change return value of trivial visibility check. Previous, if no Decl's were checked, visibility was set to false. Switch it so that in cases of no Decl's, return true. These are the Decl's after being filtered. Also remove an unreachable return statement since it is directly after another return statement. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334160 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaLookup.cpp | 12 +++++++++--- test/Modules/local-visibility.cpp | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/Modules/local-visibility.cpp diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index d2d4171c93..984247bacc 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1452,6 +1452,8 @@ template static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, llvm::SmallVectorImpl *Modules, Filter F) { + bool HasFilteredRedecls = false; + for (auto *Redecl : D->redecls()) { auto *R = cast(Redecl); if (!F(R)) @@ -1460,6 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, if (S.isVisible(R)) return true; + HasFilteredRedecls = true; + if (Modules) { Modules->push_back(R->getOwningModule()); const auto &Merged = S.Context.getModulesWithMergedDefinition(R); @@ -1467,7 +1471,11 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D, } } - return false; + // Only return false if there is at least one redecl that is not filtered out. + if (HasFilteredRedecls) + return false; + + return true; } bool Sema::hasVisibleExplicitSpecialization( @@ -1497,8 +1505,6 @@ bool Sema::hasVisibleMemberSpecialization( // class definition? return D->getLexicalDeclContext()->isFileContext(); }); - - return false; } /// Determine whether a declaration is visible to name lookup. diff --git a/test/Modules/local-visibility.cpp b/test/Modules/local-visibility.cpp new file mode 100644 index 0000000000..fa2d20c433 --- /dev/null +++ b/test/Modules/local-visibility.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -fmodules %s -verify +// RUN: %clang_cc1 -fsyntax-only %s -verify + +// expected-no-diagnostics +template +struct S { + template + struct Inner { }; + + template <> + struct Inner<0> { }; +}; + +S::Inner<1> I1; +S::Inner<0> I0; -- GitLab From c307b5069c8049c0c033d8e2a28a731ac68b9802 Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Thu, 7 Jun 2018 08:48:36 +0000 Subject: [PATCH 0044/1023] [CodeGen] Improve diagnostics related to target attributes Summary: When requirement imposed by __target__ attributes on functions are not satisfied, prefer printing those requirements, which are explicitly mentioned in the attributes. This makes such messages more useful, e.g. printing avx512f instead of avx2 in the following scenario: ``` $ cat foo.c static inline void __attribute__((__always_inline__, __target__("avx512f"))) x(void) { } int main(void) { x(); } $ clang foo.c foo.c:7:2: error: always_inline function 'x' requires target feature 'avx2', but would be inlined into function 'main' that is compiled without support for 'avx2' x(); ^ 1 error generated. ``` bugzilla: https://bugs.llvm.org/show_bug.cgi?id=37338 Reviewers: craig.topper, echristo, dblaikie Reviewed By: craig.topper, echristo Differential Revision: https://reviews.llvm.org/D46541 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334174 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 10 +++++++ lib/CodeGen/CodeGenModule.cpp | 26 ++++++++++++------- lib/CodeGen/CodeGenModule.h | 4 +++ test/CodeGen/target-features-error-2.c | 36 ++++++++++++++++---------- test/CodeGen/target-features-error.c | 3 +-- 5 files changed, 53 insertions(+), 26 deletions(-) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 6c73a8cebd..916051556a 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -2330,9 +2330,19 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E, } else if (TargetDecl->hasAttr()) { // Get the required features for the callee. + + const TargetAttr *TD = TargetDecl->getAttr(); + TargetAttr::ParsedTargetAttr ParsedAttr = CGM.filterFunctionTargetAttrs(TD); + SmallVector ReqFeatures; llvm::StringMap CalleeFeatureMap; CGM.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl); + + for (const auto &F : ParsedAttr.Features) { + if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1))) + ReqFeatures.push_back(StringRef(F).substr(1)); + } + for (const auto &F : CalleeFeatureMap) { // Only positive features are "required". if (F.getValue()) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b57004f7e1..19cfffd81c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -5033,22 +5033,28 @@ void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable, } } +TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const TargetAttr *TD) { + assert(TD != nullptr); + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + + ParsedAttr.Features.erase( + llvm::remove_if(ParsedAttr.Features, + [&](const std::string &Feat) { + return !Target.isValidFeatureName( + StringRef{Feat}.substr(1)); + }), + ParsedAttr.Features.end()); + return ParsedAttr; +} + + // Fills in the supplied string map with the set of target features for the // passed in function. void CodeGenModule::getFunctionFeatureMap(llvm::StringMap &FeatureMap, const FunctionDecl *FD) { StringRef TargetCPU = Target.getTargetOpts().CPU; if (const auto *TD = FD->getAttr()) { - // If we have a TargetAttr build up the feature map based on that. - TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - - ParsedAttr.Features.erase( - llvm::remove_if(ParsedAttr.Features, - [&](const std::string &Feat) { - return !Target.isValidFeatureName( - StringRef{Feat}.substr(1)); - }), - ParsedAttr.Features.end()); + TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 961bae324d..89823982ac 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -1089,6 +1089,10 @@ public: /// It's up to you to ensure that this is safe. void AddDefaultFnAttrs(llvm::Function &F); + /// Parses the target attributes passed in, and returns only the ones that are + /// valid feature names. + TargetAttr::ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD); + // Fills in the supplied string map with the set of target features for the // passed in function. void getFunctionFeatureMap(llvm::StringMap &FeatureMap, diff --git a/test/CodeGen/target-features-error-2.c b/test/CodeGen/target-features-error-2.c index 40279fb6de..60586fb57f 100644 --- a/test/CodeGen/target-features-error-2.c +++ b/test/CodeGen/target-features-error-2.c @@ -1,38 +1,46 @@ -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_SSE42 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_1 // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_2 -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_3 -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX_4 +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - -D NEED_AVX512f +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +movdir64b -S -verify -o - -D NEED_MOVDIRI +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512vnni -target-feature +movdiri -S -verify -o - -D NEED_CLWB #define __MM_MALLOC_H #include -#if NEED_SSE42 +#if NEED_AVX_1 int baz(__m256i a) { return _mm256_extract_epi32(a, 3); // expected-error {{'__builtin_ia32_vec_ext_v8si' needs target feature avx}} } #endif -#if NEED_AVX_1 +#if NEED_AVX_2 __m128 need_avx(__m128 a, __m128 b) { return _mm_cmp_ps(a, b, 0); // expected-error {{'__builtin_ia32_cmpps' needs target feature avx}} } #endif -#if NEED_AVX_2 -__m128 need_avx(__m128 a, __m128 b) { - return _mm_cmp_ss(a, b, 0); // expected-error {{'__builtin_ia32_cmpss' needs target feature avx}} +#if NEED_AVX512f +unsigned short need_avx512f(unsigned short a, unsigned short b) { + return __builtin_ia32_korhi(a, b); // expected-error {{'__builtin_ia32_korhi' needs target feature avx512f}} } #endif -#if NEED_AVX_3 -__m128d need_avx(__m128d a, __m128d b) { - return _mm_cmp_pd(a, b, 0); // expected-error {{'__builtin_ia32_cmppd' needs target feature avx}} +#if NEED_MOVDIRI +void need_movdiri(unsigned int *a, unsigned int b) { + __builtin_ia32_directstore_u32(a, b); // expected-error {{'__builtin_ia32_directstore_u32' needs target feature movdiri}} } #endif -#if NEED_AVX_4 -__m128d need_avx(__m128d a, __m128d b) { - return _mm_cmp_sd(a, b, 0); // expected-error {{'__builtin_ia32_cmpsd' needs target feature avx}} +#if NEED_CLWB +static __inline__ void + __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni,clwb,movdiri,movdir64b"))) + func(unsigned int *a, unsigned int b) +{ + __builtin_ia32_directstore_u32(a, b); +} + +void need_clwb(unsigned int *a, unsigned int b) { + func(a, b); // expected-error {{always_inline function 'func' requires target feature 'clwb', but would be inlined into function 'need_clwb' that is compiled without support for 'clwb'}} + } #endif diff --git a/test/CodeGen/target-features-error.c b/test/CodeGen/target-features-error.c index 518f6e6189..a55163a95d 100644 --- a/test/CodeGen/target-features-error.c +++ b/test/CodeGen/target-features-error.c @@ -3,6 +3,5 @@ int __attribute__((target("avx"), always_inline)) foo(int a) { return a + 4; } int bar() { - return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'sse4.2', but would be inlined into function 'bar' that is compiled without support for 'sse4.2'}} + return foo(4); // expected-error {{always_inline function 'foo' requires target feature 'avx', but would be inlined into function 'bar' that is compiled without support for 'avx'}} } - -- GitLab From e63bbc3a5282f86265da104a9f8b9a74c41fdf37 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 7 Jun 2018 09:46:24 +0000 Subject: [PATCH 0045/1023] [clang-format] Consider tok::hashhash in python-style comments Summary: We were missing the case when python-style comments in text protos start with `##`. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47870 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334179 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/BreakableToken.cpp | 3 ++- lib/Format/FormatTokenLexer.cpp | 2 +- unittests/Format/FormatTestTextProto.cpp | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp index 933dce3540..f727f8ddf8 100644 --- a/lib/Format/BreakableToken.cpp +++ b/lib/Format/BreakableToken.cpp @@ -44,7 +44,8 @@ static StringRef getLineCommentIndentPrefix(StringRef Comment, const FormatStyle &Style) { static const char *const KnownCStylePrefixes[] = {"///<", "//!<", "///", "//", "//!"}; - static const char *const KnownTextProtoPrefixes[] = {"//", "#"}; + static const char *const KnownTextProtoPrefixes[] = {"//", "#", "##", "###", + "####"}; ArrayRef KnownPrefixes(KnownCStylePrefixes); if (Style.Language == FormatStyle::LK_TextProto) KnownPrefixes = KnownTextProtoPrefixes; diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp index fbd26965a6..c7f720a443 100644 --- a/lib/Format/FormatTokenLexer.cpp +++ b/lib/Format/FormatTokenLexer.cpp @@ -334,7 +334,7 @@ void FormatTokenLexer::handleTemplateStrings() { void FormatTokenLexer::tryParsePythonComment() { FormatToken *HashToken = Tokens.back(); - if (HashToken->isNot(tok::hash)) + if (!HashToken->isOneOf(tok::hash, tok::hashhash)) return; // Turn the remainder of this line into a comment. const char *CommentBegin = diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index 050c319e4f..fcf118eee8 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -347,6 +347,28 @@ TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) { "cccccccccccccccccccccccc: 3849"); } +TEST_F(FormatTestTextProto, UnderstandsHashHashComments) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; // To make writing tests easier. + EXPECT_EQ("aaa: 100\n" + "##this is a double-hash comment.\n" + "bb: 100\n" + "## another double-hash comment.\n" + "### a triple-hash comment\n" + "cc: 200\n" + "#### a quadriple-hash comment\n" + "dd: 100\n", + format("aaa: 100\n" + "##this is a double-hash comment.\n" + "bb: 100\n" + "## another double-hash comment.\n" + "### a triple-hash comment\n" + "cc: 200\n" + "#### a quadriple-hash comment\n" + "dd: 100\n", + Style)); +} + TEST_F(FormatTestTextProto, FormatsExtensions) { verifyFormat("[type] { key: value }"); verifyFormat("[type] {\n" -- GitLab From 3b4ec91916b5e5ea297fab01be9ebc3d5dcf32f6 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 7 Jun 2018 17:28:03 +0000 Subject: [PATCH 0046/1023] [X86] Add back builtins for _mm_slli_si128/_mm_srli_si128 and similar intrinsics. We still lower them to native shuffle IR, but we do it in CGBuiltin.cpp now. This allows us to check the target feature and ensure the immediate fits in 8 bits. This also improves our -O0 codegen slightly because we're able to see the zeroinitializer in the shuffle. It looks like it got lost behind a store+load previously. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334208 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 6 ++ lib/CodeGen/CGBuiltin.cpp | 62 +++++++++++++ lib/Headers/avx2intrin.h | 82 ++--------------- lib/Headers/avx512bwintrin.h | 136 +--------------------------- lib/Headers/emmintrin.h | 44 +-------- lib/Sema/SemaChecking.cpp | 8 ++ test/CodeGen/avx2-builtins.c | 8 +- test/CodeGen/avx512bw-builtins.c | 4 +- test/CodeGen/sse2-builtins.c | 12 +-- 9 files changed, 102 insertions(+), 260 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 33dda55fe3..fb284d3de5 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -358,6 +358,8 @@ TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLiIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLiIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "n", "sse3") TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "n", "sse3") @@ -585,6 +587,7 @@ TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslldqi256, "V4LLiV4LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "nc", "avx2") @@ -593,6 +596,7 @@ TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrldqi256, "V4LLiV4LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "nc", "avx2") @@ -1352,6 +1356,8 @@ TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pslldqi512, "V8LLiV8LLiIi", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrldqi512, "V8LLiV8LLiIi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "n", "avx512vl") TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "n", "avx512vl") TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "n", "avx512f") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a086b4d926..a126e75b19 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9262,6 +9262,68 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, "vperm"); } + case X86::BI__builtin_ia32_pslldqi128: + case X86::BI__builtin_ia32_pslldqi256: + case X86::BI__builtin_ia32_pslldqi512: { + // Shift value is in bits so divide by 8. + unsigned ShiftVal = cast(Ops[1])->getZExtValue() >> 3; + llvm::Type *ResultType = Ops[0]->getType(); + // Builtin type is vXi64 so multiply by 8 to get bytes. + unsigned NumElts = ResultType->getVectorNumElements() * 8; + + // If pslldq is shifting the vector more than 15 bytes, emit zero. + if (ShiftVal >= 16) + return llvm::Constant::getNullValue(ResultType); + + uint32_t Indices[64]; + // 256/512-bit pslldq operates on 128-bit lanes so we need to handle that + for (unsigned l = 0; l != NumElts; l += 16) { + for (unsigned i = 0; i != 16; ++i) { + unsigned Idx = NumElts + i - ShiftVal; + if (Idx < NumElts) Idx -= NumElts - 16; // end of lane, switch operand. + Indices[l + i] = Idx + l; + } + } + + llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts); + Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast"); + Value *Zero = llvm::Constant::getNullValue(VecTy); + Value *SV = Builder.CreateShuffleVector(Zero, Cast, + makeArrayRef(Indices, NumElts), + "pslldq"); + return Builder.CreateBitCast(SV, Ops[0]->getType(), "cast"); + } + case X86::BI__builtin_ia32_psrldqi128: + case X86::BI__builtin_ia32_psrldqi256: + case X86::BI__builtin_ia32_psrldqi512: { + // Shift value is in bits so divide by 8. + unsigned ShiftVal = cast(Ops[1])->getZExtValue() >> 3; + llvm::Type *ResultType = Ops[0]->getType(); + // Builtin type is vXi64 so multiply by 8 to get bytes. + unsigned NumElts = ResultType->getVectorNumElements() * 8; + + // If psrldq is shifting the vector more than 15 bytes, emit zero. + if (ShiftVal >= 16) + return llvm::Constant::getNullValue(ResultType); + + uint32_t Indices[64]; + // 256/512-bit psrldq operates on 128-bit lanes so we need to handle that + for (unsigned l = 0; l != NumElts; l += 16) { + for (unsigned i = 0; i != 16; ++i) { + unsigned Idx = i + ShiftVal; + if (Idx >= 16) Idx += NumElts - 16; // end of lane, switch operand. + Indices[l + i] = Idx + l; + } + } + + llvm::Type *VecTy = llvm::VectorType::get(Int8Ty, NumElts); + Value *Cast = Builder.CreateBitCast(Ops[0], VecTy, "cast"); + Value *Zero = llvm::Constant::getNullValue(VecTy); + Value *SV = Builder.CreateShuffleVector(Cast, Zero, + makeArrayRef(Indices, NumElts), + "psrldq"); + return Builder.CreateBitCast(SV, ResultType, "cast"); + } case X86::BI__builtin_ia32_movnti: case X86::BI__builtin_ia32_movnti64: case X86::BI__builtin_ia32_movntsd: diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 57c4dfada8..9371fcb949 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -562,43 +562,10 @@ _mm256_sign_epi32(__m256i __a, __m256i __b) } #define _mm256_slli_si256(a, imm) \ - (__m256i)__builtin_shufflevector( \ - (__v32qi)_mm256_setzero_si256(), \ - (__v32qi)(__m256i)(a), \ - ((char)(imm)&0xF0) ? 0 : ((char)(imm)>0x0 ? 16 : 32) - (char)(imm), \ - ((char)(imm)&0xF0) ? 1 : ((char)(imm)>0x1 ? 17 : 33) - (char)(imm), \ - ((char)(imm)&0xF0) ? 2 : ((char)(imm)>0x2 ? 18 : 34) - (char)(imm), \ - ((char)(imm)&0xF0) ? 3 : ((char)(imm)>0x3 ? 19 : 35) - (char)(imm), \ - ((char)(imm)&0xF0) ? 4 : ((char)(imm)>0x4 ? 20 : 36) - (char)(imm), \ - ((char)(imm)&0xF0) ? 5 : ((char)(imm)>0x5 ? 21 : 37) - (char)(imm), \ - ((char)(imm)&0xF0) ? 6 : ((char)(imm)>0x6 ? 22 : 38) - (char)(imm), \ - ((char)(imm)&0xF0) ? 7 : ((char)(imm)>0x7 ? 23 : 39) - (char)(imm), \ - ((char)(imm)&0xF0) ? 8 : ((char)(imm)>0x8 ? 24 : 40) - (char)(imm), \ - ((char)(imm)&0xF0) ? 9 : ((char)(imm)>0x9 ? 25 : 41) - (char)(imm), \ - ((char)(imm)&0xF0) ? 10 : ((char)(imm)>0xA ? 26 : 42) - (char)(imm), \ - ((char)(imm)&0xF0) ? 11 : ((char)(imm)>0xB ? 27 : 43) - (char)(imm), \ - ((char)(imm)&0xF0) ? 12 : ((char)(imm)>0xC ? 28 : 44) - (char)(imm), \ - ((char)(imm)&0xF0) ? 13 : ((char)(imm)>0xD ? 29 : 45) - (char)(imm), \ - ((char)(imm)&0xF0) ? 14 : ((char)(imm)>0xE ? 30 : 46) - (char)(imm), \ - ((char)(imm)&0xF0) ? 15 : ((char)(imm)>0xF ? 31 : 47) - (char)(imm), \ - ((char)(imm)&0xF0) ? 16 : ((char)(imm)>0x0 ? 32 : 48) - (char)(imm), \ - ((char)(imm)&0xF0) ? 17 : ((char)(imm)>0x1 ? 33 : 49) - (char)(imm), \ - ((char)(imm)&0xF0) ? 18 : ((char)(imm)>0x2 ? 34 : 50) - (char)(imm), \ - ((char)(imm)&0xF0) ? 19 : ((char)(imm)>0x3 ? 35 : 51) - (char)(imm), \ - ((char)(imm)&0xF0) ? 20 : ((char)(imm)>0x4 ? 36 : 52) - (char)(imm), \ - ((char)(imm)&0xF0) ? 21 : ((char)(imm)>0x5 ? 37 : 53) - (char)(imm), \ - ((char)(imm)&0xF0) ? 22 : ((char)(imm)>0x6 ? 38 : 54) - (char)(imm), \ - ((char)(imm)&0xF0) ? 23 : ((char)(imm)>0x7 ? 39 : 55) - (char)(imm), \ - ((char)(imm)&0xF0) ? 24 : ((char)(imm)>0x8 ? 40 : 56) - (char)(imm), \ - ((char)(imm)&0xF0) ? 25 : ((char)(imm)>0x9 ? 41 : 57) - (char)(imm), \ - ((char)(imm)&0xF0) ? 26 : ((char)(imm)>0xA ? 42 : 58) - (char)(imm), \ - ((char)(imm)&0xF0) ? 27 : ((char)(imm)>0xB ? 43 : 59) - (char)(imm), \ - ((char)(imm)&0xF0) ? 28 : ((char)(imm)>0xC ? 44 : 60) - (char)(imm), \ - ((char)(imm)&0xF0) ? 29 : ((char)(imm)>0xD ? 45 : 61) - (char)(imm), \ - ((char)(imm)&0xF0) ? 30 : ((char)(imm)>0xE ? 46 : 62) - (char)(imm), \ - ((char)(imm)&0xF0) ? 31 : ((char)(imm)>0xF ? 47 : 63) - (char)(imm)) - -#define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count)) + (__m256i)__builtin_ia32_pslldqi256((__v4di)(__m256i)(a), (int)(imm) * 8) + +#define _mm256_bslli_epi128(a, imm) \ + (__m256i)__builtin_ia32_pslldqi256((__v4di)(__m256i)(a), (int)(imm) * 8) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_slli_epi16(__m256i __a, int __count) @@ -661,43 +628,10 @@ _mm256_sra_epi32(__m256i __a, __m128i __count) } #define _mm256_srli_si256(a, imm) \ - (__m256i)__builtin_shufflevector( \ - (__v32qi)(__m256i)(a), \ - (__v32qi)_mm256_setzero_si256(), \ - ((char)(imm)&0xF0) ? 32 : (char)(imm) + ((char)(imm)>0xF ? 16 : 0), \ - ((char)(imm)&0xF0) ? 33 : (char)(imm) + ((char)(imm)>0xE ? 17 : 1), \ - ((char)(imm)&0xF0) ? 34 : (char)(imm) + ((char)(imm)>0xD ? 18 : 2), \ - ((char)(imm)&0xF0) ? 35 : (char)(imm) + ((char)(imm)>0xC ? 19 : 3), \ - ((char)(imm)&0xF0) ? 36 : (char)(imm) + ((char)(imm)>0xB ? 20 : 4), \ - ((char)(imm)&0xF0) ? 37 : (char)(imm) + ((char)(imm)>0xA ? 21 : 5), \ - ((char)(imm)&0xF0) ? 38 : (char)(imm) + ((char)(imm)>0x9 ? 22 : 6), \ - ((char)(imm)&0xF0) ? 39 : (char)(imm) + ((char)(imm)>0x8 ? 23 : 7), \ - ((char)(imm)&0xF0) ? 40 : (char)(imm) + ((char)(imm)>0x7 ? 24 : 8), \ - ((char)(imm)&0xF0) ? 41 : (char)(imm) + ((char)(imm)>0x6 ? 25 : 9), \ - ((char)(imm)&0xF0) ? 42 : (char)(imm) + ((char)(imm)>0x5 ? 26 : 10), \ - ((char)(imm)&0xF0) ? 43 : (char)(imm) + ((char)(imm)>0x4 ? 27 : 11), \ - ((char)(imm)&0xF0) ? 44 : (char)(imm) + ((char)(imm)>0x3 ? 28 : 12), \ - ((char)(imm)&0xF0) ? 45 : (char)(imm) + ((char)(imm)>0x2 ? 29 : 13), \ - ((char)(imm)&0xF0) ? 46 : (char)(imm) + ((char)(imm)>0x1 ? 30 : 14), \ - ((char)(imm)&0xF0) ? 47 : (char)(imm) + ((char)(imm)>0x0 ? 31 : 15), \ - ((char)(imm)&0xF0) ? 48 : (char)(imm) + ((char)(imm)>0xF ? 32 : 16), \ - ((char)(imm)&0xF0) ? 49 : (char)(imm) + ((char)(imm)>0xE ? 33 : 17), \ - ((char)(imm)&0xF0) ? 50 : (char)(imm) + ((char)(imm)>0xD ? 34 : 18), \ - ((char)(imm)&0xF0) ? 51 : (char)(imm) + ((char)(imm)>0xC ? 35 : 19), \ - ((char)(imm)&0xF0) ? 52 : (char)(imm) + ((char)(imm)>0xB ? 36 : 20), \ - ((char)(imm)&0xF0) ? 53 : (char)(imm) + ((char)(imm)>0xA ? 37 : 21), \ - ((char)(imm)&0xF0) ? 54 : (char)(imm) + ((char)(imm)>0x9 ? 38 : 22), \ - ((char)(imm)&0xF0) ? 55 : (char)(imm) + ((char)(imm)>0x8 ? 39 : 23), \ - ((char)(imm)&0xF0) ? 56 : (char)(imm) + ((char)(imm)>0x7 ? 40 : 24), \ - ((char)(imm)&0xF0) ? 57 : (char)(imm) + ((char)(imm)>0x6 ? 41 : 25), \ - ((char)(imm)&0xF0) ? 58 : (char)(imm) + ((char)(imm)>0x5 ? 42 : 26), \ - ((char)(imm)&0xF0) ? 59 : (char)(imm) + ((char)(imm)>0x4 ? 43 : 27), \ - ((char)(imm)&0xF0) ? 60 : (char)(imm) + ((char)(imm)>0x3 ? 44 : 28), \ - ((char)(imm)&0xF0) ? 61 : (char)(imm) + ((char)(imm)>0x2 ? 45 : 29), \ - ((char)(imm)&0xF0) ? 62 : (char)(imm) + ((char)(imm)>0x1 ? 46 : 30), \ - ((char)(imm)&0xF0) ? 63 : (char)(imm) + ((char)(imm)>0x0 ? 47 : 31)) - -#define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count)) + (__m256i)__builtin_ia32_psrldqi256((__m256i)(a), (int)(imm) * 8) + +#define _mm256_bsrli_epi128(a, imm) \ + (__m256i)__builtin_ia32_psrldqi256((__m256i)(a), (int)(imm) * 8) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_srli_epi16(__m256i __a, int __count) diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index f392b250b7..aabaabd648 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -1427,73 +1427,7 @@ _mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A, int __B) } #define _mm512_bslli_epi128(a, imm) \ - (__m512i)__builtin_shufflevector( \ - (__v64qi)_mm512_setzero_si512(), \ - (__v64qi)(__m512i)(a), \ - ((char)(imm)&0xF0) ? 0 : ((char)(imm)>0x0 ? 16 : 64) - (char)(imm), \ - ((char)(imm)&0xF0) ? 1 : ((char)(imm)>0x1 ? 17 : 65) - (char)(imm), \ - ((char)(imm)&0xF0) ? 2 : ((char)(imm)>0x2 ? 18 : 66) - (char)(imm), \ - ((char)(imm)&0xF0) ? 3 : ((char)(imm)>0x3 ? 19 : 67) - (char)(imm), \ - ((char)(imm)&0xF0) ? 4 : ((char)(imm)>0x4 ? 20 : 68) - (char)(imm), \ - ((char)(imm)&0xF0) ? 5 : ((char)(imm)>0x5 ? 21 : 69) - (char)(imm), \ - ((char)(imm)&0xF0) ? 6 : ((char)(imm)>0x6 ? 22 : 70) - (char)(imm), \ - ((char)(imm)&0xF0) ? 7 : ((char)(imm)>0x7 ? 23 : 71) - (char)(imm), \ - ((char)(imm)&0xF0) ? 8 : ((char)(imm)>0x8 ? 24 : 72) - (char)(imm), \ - ((char)(imm)&0xF0) ? 9 : ((char)(imm)>0x9 ? 25 : 73) - (char)(imm), \ - ((char)(imm)&0xF0) ? 10 : ((char)(imm)>0xA ? 26 : 74) - (char)(imm), \ - ((char)(imm)&0xF0) ? 11 : ((char)(imm)>0xB ? 27 : 75) - (char)(imm), \ - ((char)(imm)&0xF0) ? 12 : ((char)(imm)>0xC ? 28 : 76) - (char)(imm), \ - ((char)(imm)&0xF0) ? 13 : ((char)(imm)>0xD ? 29 : 77) - (char)(imm), \ - ((char)(imm)&0xF0) ? 14 : ((char)(imm)>0xE ? 30 : 78) - (char)(imm), \ - ((char)(imm)&0xF0) ? 15 : ((char)(imm)>0xF ? 31 : 79) - (char)(imm), \ - ((char)(imm)&0xF0) ? 16 : ((char)(imm)>0x0 ? 32 : 80) - (char)(imm), \ - ((char)(imm)&0xF0) ? 17 : ((char)(imm)>0x1 ? 33 : 81) - (char)(imm), \ - ((char)(imm)&0xF0) ? 18 : ((char)(imm)>0x2 ? 34 : 82) - (char)(imm), \ - ((char)(imm)&0xF0) ? 19 : ((char)(imm)>0x3 ? 35 : 83) - (char)(imm), \ - ((char)(imm)&0xF0) ? 20 : ((char)(imm)>0x4 ? 36 : 84) - (char)(imm), \ - ((char)(imm)&0xF0) ? 21 : ((char)(imm)>0x5 ? 37 : 85) - (char)(imm), \ - ((char)(imm)&0xF0) ? 22 : ((char)(imm)>0x6 ? 38 : 86) - (char)(imm), \ - ((char)(imm)&0xF0) ? 23 : ((char)(imm)>0x7 ? 39 : 87) - (char)(imm), \ - ((char)(imm)&0xF0) ? 24 : ((char)(imm)>0x8 ? 40 : 88) - (char)(imm), \ - ((char)(imm)&0xF0) ? 25 : ((char)(imm)>0x9 ? 41 : 89) - (char)(imm), \ - ((char)(imm)&0xF0) ? 26 : ((char)(imm)>0xA ? 42 : 90) - (char)(imm), \ - ((char)(imm)&0xF0) ? 27 : ((char)(imm)>0xB ? 43 : 91) - (char)(imm), \ - ((char)(imm)&0xF0) ? 28 : ((char)(imm)>0xC ? 44 : 92) - (char)(imm), \ - ((char)(imm)&0xF0) ? 29 : ((char)(imm)>0xD ? 45 : 93) - (char)(imm), \ - ((char)(imm)&0xF0) ? 30 : ((char)(imm)>0xE ? 46 : 94) - (char)(imm), \ - ((char)(imm)&0xF0) ? 31 : ((char)(imm)>0xF ? 47 : 95) - (char)(imm), \ - ((char)(imm)&0xF0) ? 32 : ((char)(imm)>0x0 ? 48 : 96) - (char)(imm), \ - ((char)(imm)&0xF0) ? 33 : ((char)(imm)>0x1 ? 49 : 97) - (char)(imm), \ - ((char)(imm)&0xF0) ? 34 : ((char)(imm)>0x2 ? 50 : 98) - (char)(imm), \ - ((char)(imm)&0xF0) ? 35 : ((char)(imm)>0x3 ? 51 : 99) - (char)(imm), \ - ((char)(imm)&0xF0) ? 36 : ((char)(imm)>0x4 ? 52 : 100) - (char)(imm), \ - ((char)(imm)&0xF0) ? 37 : ((char)(imm)>0x5 ? 53 : 101) - (char)(imm), \ - ((char)(imm)&0xF0) ? 38 : ((char)(imm)>0x6 ? 54 : 102) - (char)(imm), \ - ((char)(imm)&0xF0) ? 39 : ((char)(imm)>0x7 ? 55 : 103) - (char)(imm), \ - ((char)(imm)&0xF0) ? 40 : ((char)(imm)>0x8 ? 56 : 104) - (char)(imm), \ - ((char)(imm)&0xF0) ? 41 : ((char)(imm)>0x9 ? 57 : 105) - (char)(imm), \ - ((char)(imm)&0xF0) ? 42 : ((char)(imm)>0xA ? 58 : 106) - (char)(imm), \ - ((char)(imm)&0xF0) ? 43 : ((char)(imm)>0xB ? 59 : 107) - (char)(imm), \ - ((char)(imm)&0xF0) ? 44 : ((char)(imm)>0xC ? 60 : 108) - (char)(imm), \ - ((char)(imm)&0xF0) ? 45 : ((char)(imm)>0xD ? 61 : 109) - (char)(imm), \ - ((char)(imm)&0xF0) ? 46 : ((char)(imm)>0xE ? 62 : 110) - (char)(imm), \ - ((char)(imm)&0xF0) ? 47 : ((char)(imm)>0xF ? 63 : 111) - (char)(imm), \ - ((char)(imm)&0xF0) ? 48 : ((char)(imm)>0x0 ? 64 : 112) - (char)(imm), \ - ((char)(imm)&0xF0) ? 49 : ((char)(imm)>0x1 ? 65 : 113) - (char)(imm), \ - ((char)(imm)&0xF0) ? 50 : ((char)(imm)>0x2 ? 66 : 114) - (char)(imm), \ - ((char)(imm)&0xF0) ? 51 : ((char)(imm)>0x3 ? 67 : 115) - (char)(imm), \ - ((char)(imm)&0xF0) ? 52 : ((char)(imm)>0x4 ? 68 : 116) - (char)(imm), \ - ((char)(imm)&0xF0) ? 53 : ((char)(imm)>0x5 ? 69 : 117) - (char)(imm), \ - ((char)(imm)&0xF0) ? 54 : ((char)(imm)>0x6 ? 70 : 118) - (char)(imm), \ - ((char)(imm)&0xF0) ? 55 : ((char)(imm)>0x7 ? 71 : 119) - (char)(imm), \ - ((char)(imm)&0xF0) ? 56 : ((char)(imm)>0x8 ? 72 : 120) - (char)(imm), \ - ((char)(imm)&0xF0) ? 57 : ((char)(imm)>0x9 ? 73 : 121) - (char)(imm), \ - ((char)(imm)&0xF0) ? 58 : ((char)(imm)>0xA ? 74 : 122) - (char)(imm), \ - ((char)(imm)&0xF0) ? 59 : ((char)(imm)>0xB ? 75 : 123) - (char)(imm), \ - ((char)(imm)&0xF0) ? 60 : ((char)(imm)>0xC ? 76 : 124) - (char)(imm), \ - ((char)(imm)&0xF0) ? 61 : ((char)(imm)>0xD ? 77 : 125) - (char)(imm), \ - ((char)(imm)&0xF0) ? 62 : ((char)(imm)>0xE ? 78 : 126) - (char)(imm), \ - ((char)(imm)&0xF0) ? 63 : ((char)(imm)>0xF ? 79 : 127) - (char)(imm)) + (__m512i)__builtin_ia32_pslldqi512((__v8di)(__m512i)(a), (int)(imm) * 8) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_srlv_epi16(__m512i __A, __m512i __B) @@ -1628,73 +1562,7 @@ _mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A, int __B) } #define _mm512_bsrli_epi128(a, imm) \ - (__m512i)__builtin_shufflevector( \ - (__v64qi)(__m512i)(a), \ - (__v64qi)_mm512_setzero_si512(), \ - ((char)(imm)&0xF0) ? 64 : (char)(imm) + ((char)(imm)>0xF ? 48 : 0), \ - ((char)(imm)&0xF0) ? 65 : (char)(imm) + ((char)(imm)>0xE ? 49 : 1), \ - ((char)(imm)&0xF0) ? 66 : (char)(imm) + ((char)(imm)>0xD ? 50 : 2), \ - ((char)(imm)&0xF0) ? 67 : (char)(imm) + ((char)(imm)>0xC ? 51 : 3), \ - ((char)(imm)&0xF0) ? 68 : (char)(imm) + ((char)(imm)>0xB ? 52 : 4), \ - ((char)(imm)&0xF0) ? 69 : (char)(imm) + ((char)(imm)>0xA ? 53 : 5), \ - ((char)(imm)&0xF0) ? 70 : (char)(imm) + ((char)(imm)>0x9 ? 54 : 6), \ - ((char)(imm)&0xF0) ? 71 : (char)(imm) + ((char)(imm)>0x8 ? 55 : 7), \ - ((char)(imm)&0xF0) ? 72 : (char)(imm) + ((char)(imm)>0x7 ? 56 : 8), \ - ((char)(imm)&0xF0) ? 73 : (char)(imm) + ((char)(imm)>0x6 ? 57 : 9), \ - ((char)(imm)&0xF0) ? 74 : (char)(imm) + ((char)(imm)>0x5 ? 58 : 10), \ - ((char)(imm)&0xF0) ? 75 : (char)(imm) + ((char)(imm)>0x4 ? 59 : 11), \ - ((char)(imm)&0xF0) ? 76 : (char)(imm) + ((char)(imm)>0x3 ? 60 : 12), \ - ((char)(imm)&0xF0) ? 77 : (char)(imm) + ((char)(imm)>0x2 ? 61 : 13), \ - ((char)(imm)&0xF0) ? 78 : (char)(imm) + ((char)(imm)>0x1 ? 62 : 14), \ - ((char)(imm)&0xF0) ? 79 : (char)(imm) + ((char)(imm)>0x0 ? 63 : 15), \ - ((char)(imm)&0xF0) ? 80 : (char)(imm) + ((char)(imm)>0xF ? 64 : 16), \ - ((char)(imm)&0xF0) ? 81 : (char)(imm) + ((char)(imm)>0xE ? 65 : 17), \ - ((char)(imm)&0xF0) ? 82 : (char)(imm) + ((char)(imm)>0xD ? 66 : 18), \ - ((char)(imm)&0xF0) ? 83 : (char)(imm) + ((char)(imm)>0xC ? 67 : 19), \ - ((char)(imm)&0xF0) ? 84 : (char)(imm) + ((char)(imm)>0xB ? 68 : 20), \ - ((char)(imm)&0xF0) ? 85 : (char)(imm) + ((char)(imm)>0xA ? 69 : 21), \ - ((char)(imm)&0xF0) ? 86 : (char)(imm) + ((char)(imm)>0x9 ? 70 : 22), \ - ((char)(imm)&0xF0) ? 87 : (char)(imm) + ((char)(imm)>0x8 ? 71 : 23), \ - ((char)(imm)&0xF0) ? 88 : (char)(imm) + ((char)(imm)>0x7 ? 72 : 24), \ - ((char)(imm)&0xF0) ? 89 : (char)(imm) + ((char)(imm)>0x6 ? 73 : 25), \ - ((char)(imm)&0xF0) ? 90 : (char)(imm) + ((char)(imm)>0x5 ? 74 : 26), \ - ((char)(imm)&0xF0) ? 91 : (char)(imm) + ((char)(imm)>0x4 ? 75 : 27), \ - ((char)(imm)&0xF0) ? 92 : (char)(imm) + ((char)(imm)>0x3 ? 76 : 28), \ - ((char)(imm)&0xF0) ? 93 : (char)(imm) + ((char)(imm)>0x2 ? 77 : 29), \ - ((char)(imm)&0xF0) ? 94 : (char)(imm) + ((char)(imm)>0x1 ? 78 : 30), \ - ((char)(imm)&0xF0) ? 95 : (char)(imm) + ((char)(imm)>0x0 ? 79 : 31), \ - ((char)(imm)&0xF0) ? 96 : (char)(imm) + ((char)(imm)>0xF ? 80 : 32), \ - ((char)(imm)&0xF0) ? 97 : (char)(imm) + ((char)(imm)>0xE ? 81 : 33), \ - ((char)(imm)&0xF0) ? 98 : (char)(imm) + ((char)(imm)>0xD ? 82 : 34), \ - ((char)(imm)&0xF0) ? 99 : (char)(imm) + ((char)(imm)>0xC ? 83 : 35), \ - ((char)(imm)&0xF0) ? 100 : (char)(imm) + ((char)(imm)>0xB ? 84 : 36), \ - ((char)(imm)&0xF0) ? 101 : (char)(imm) + ((char)(imm)>0xA ? 85 : 37), \ - ((char)(imm)&0xF0) ? 102 : (char)(imm) + ((char)(imm)>0x9 ? 86 : 38), \ - ((char)(imm)&0xF0) ? 103 : (char)(imm) + ((char)(imm)>0x8 ? 87 : 39), \ - ((char)(imm)&0xF0) ? 104 : (char)(imm) + ((char)(imm)>0x7 ? 88 : 40), \ - ((char)(imm)&0xF0) ? 105 : (char)(imm) + ((char)(imm)>0x6 ? 89 : 41), \ - ((char)(imm)&0xF0) ? 106 : (char)(imm) + ((char)(imm)>0x5 ? 90 : 42), \ - ((char)(imm)&0xF0) ? 107 : (char)(imm) + ((char)(imm)>0x4 ? 91 : 43), \ - ((char)(imm)&0xF0) ? 108 : (char)(imm) + ((char)(imm)>0x3 ? 92 : 44), \ - ((char)(imm)&0xF0) ? 109 : (char)(imm) + ((char)(imm)>0x2 ? 93 : 45), \ - ((char)(imm)&0xF0) ? 110 : (char)(imm) + ((char)(imm)>0x1 ? 94 : 46), \ - ((char)(imm)&0xF0) ? 111 : (char)(imm) + ((char)(imm)>0x0 ? 95 : 47), \ - ((char)(imm)&0xF0) ? 112 : (char)(imm) + ((char)(imm)>0xF ? 96 : 48), \ - ((char)(imm)&0xF0) ? 113 : (char)(imm) + ((char)(imm)>0xE ? 97 : 49), \ - ((char)(imm)&0xF0) ? 114 : (char)(imm) + ((char)(imm)>0xD ? 98 : 50), \ - ((char)(imm)&0xF0) ? 115 : (char)(imm) + ((char)(imm)>0xC ? 99 : 51), \ - ((char)(imm)&0xF0) ? 116 : (char)(imm) + ((char)(imm)>0xB ? 100 : 52), \ - ((char)(imm)&0xF0) ? 117 : (char)(imm) + ((char)(imm)>0xA ? 101 : 53), \ - ((char)(imm)&0xF0) ? 118 : (char)(imm) + ((char)(imm)>0x9 ? 102 : 54), \ - ((char)(imm)&0xF0) ? 119 : (char)(imm) + ((char)(imm)>0x8 ? 103 : 55), \ - ((char)(imm)&0xF0) ? 120 : (char)(imm) + ((char)(imm)>0x7 ? 104 : 56), \ - ((char)(imm)&0xF0) ? 121 : (char)(imm) + ((char)(imm)>0x6 ? 105 : 57), \ - ((char)(imm)&0xF0) ? 122 : (char)(imm) + ((char)(imm)>0x5 ? 106 : 58), \ - ((char)(imm)&0xF0) ? 123 : (char)(imm) + ((char)(imm)>0x4 ? 107 : 59), \ - ((char)(imm)&0xF0) ? 124 : (char)(imm) + ((char)(imm)>0x3 ? 108 : 60), \ - ((char)(imm)&0xF0) ? 125 : (char)(imm) + ((char)(imm)>0x2 ? 109 : 61), \ - ((char)(imm)&0xF0) ? 126 : (char)(imm) + ((char)(imm)>0x1 ? 110 : 62), \ - ((char)(imm)&0xF0) ? 127 : (char)(imm) + ((char)(imm)>0x0 ? 111 : 63)) + (__m512i)__builtin_ia32_psrldqi512((__v8di)(__m512i)(a), (int)(imm) * 8) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_mov_epi16 (__m512i __W, __mmask32 __U, __m512i __A) diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index 605fb7993f..ad836b1e63 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -2794,28 +2794,10 @@ _mm_xor_si128(__m128i __a, __m128i __b) /// \a a. /// \returns A 128-bit integer vector containing the left-shifted value. #define _mm_slli_si128(a, imm) \ - (__m128i)__builtin_shufflevector( \ - (__v16qi)_mm_setzero_si128(), \ - (__v16qi)(__m128i)(a), \ - ((char)(imm)&0xF0) ? 0 : 16 - (char)(imm), \ - ((char)(imm)&0xF0) ? 1 : 17 - (char)(imm), \ - ((char)(imm)&0xF0) ? 2 : 18 - (char)(imm), \ - ((char)(imm)&0xF0) ? 3 : 19 - (char)(imm), \ - ((char)(imm)&0xF0) ? 4 : 20 - (char)(imm), \ - ((char)(imm)&0xF0) ? 5 : 21 - (char)(imm), \ - ((char)(imm)&0xF0) ? 6 : 22 - (char)(imm), \ - ((char)(imm)&0xF0) ? 7 : 23 - (char)(imm), \ - ((char)(imm)&0xF0) ? 8 : 24 - (char)(imm), \ - ((char)(imm)&0xF0) ? 9 : 25 - (char)(imm), \ - ((char)(imm)&0xF0) ? 10 : 26 - (char)(imm), \ - ((char)(imm)&0xF0) ? 11 : 27 - (char)(imm), \ - ((char)(imm)&0xF0) ? 12 : 28 - (char)(imm), \ - ((char)(imm)&0xF0) ? 13 : 29 - (char)(imm), \ - ((char)(imm)&0xF0) ? 14 : 30 - (char)(imm), \ - ((char)(imm)&0xF0) ? 15 : 31 - (char)(imm)) + (__m128i)__builtin_ia32_pslldqi128((__v2di)(__m128i)(a), (int)(imm) * 8) #define _mm_bslli_si128(a, imm) \ - _mm_slli_si128((a), (imm)) + (__m128i)__builtin_ia32_pslldqi128((__v2di)(__m128i)(a), (int)(imm) * 8) /// Left-shifts each 16-bit value in the 128-bit integer vector operand /// by the specified number of bits. Low-order bits are cleared. @@ -3029,28 +3011,10 @@ _mm_sra_epi32(__m128i __a, __m128i __count) /// \a a. /// \returns A 128-bit integer vector containing the right-shifted value. #define _mm_srli_si128(a, imm) \ - (__m128i)__builtin_shufflevector( \ - (__v16qi)(__m128i)(a), \ - (__v16qi)_mm_setzero_si128(), \ - ((char)(imm)&0xF0) ? 16 : (char)(imm) + 0, \ - ((char)(imm)&0xF0) ? 17 : (char)(imm) + 1, \ - ((char)(imm)&0xF0) ? 18 : (char)(imm) + 2, \ - ((char)(imm)&0xF0) ? 19 : (char)(imm) + 3, \ - ((char)(imm)&0xF0) ? 20 : (char)(imm) + 4, \ - ((char)(imm)&0xF0) ? 21 : (char)(imm) + 5, \ - ((char)(imm)&0xF0) ? 22 : (char)(imm) + 6, \ - ((char)(imm)&0xF0) ? 23 : (char)(imm) + 7, \ - ((char)(imm)&0xF0) ? 24 : (char)(imm) + 8, \ - ((char)(imm)&0xF0) ? 25 : (char)(imm) + 9, \ - ((char)(imm)&0xF0) ? 26 : (char)(imm) + 10, \ - ((char)(imm)&0xF0) ? 27 : (char)(imm) + 11, \ - ((char)(imm)&0xF0) ? 28 : (char)(imm) + 12, \ - ((char)(imm)&0xF0) ? 29 : (char)(imm) + 13, \ - ((char)(imm)&0xF0) ? 30 : (char)(imm) + 14, \ - ((char)(imm)&0xF0) ? 31 : (char)(imm) + 15) + (__m128i)__builtin_ia32_psrldqi128((__v2di)(__m128i)(a), (int)(imm) * 8) #define _mm_bsrli_si128(a, imm) \ - _mm_srli_si128((a), (imm)) + (__m128i)__builtin_ia32_psrldqi128((__v2di)(__m128i)(a), (int)(imm) * 8) /// Right-shifts each of 16-bit values in the 128-bit integer vector /// operand by the specified number of bits. High-order bits are cleared. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 44c8731641..0c5be0506e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2781,6 +2781,14 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_rndscaless_round_mask: i = 4; l = 0; u = 255; break; + case X86::BI__builtin_ia32_pslldqi128: + case X86::BI__builtin_ia32_pslldqi256: + case X86::BI__builtin_ia32_pslldqi512: + case X86::BI__builtin_ia32_psrldqi128: + case X86::BI__builtin_ia32_psrldqi256: + case X86::BI__builtin_ia32_psrldqi512: + i = 1; l = 0; u = 1023; + break; } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index 02ddb4d5fc..b647ca595b 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -248,13 +248,13 @@ __m256i test_mm256_broadcastw_epi16(__m128i a) { __m256i test_mm256_bslli_epi128(__m256i a) { // CHECK-LABEL: test_mm256_bslli_epi128 - // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i8> zeroinitializer, <32 x i8> %{{.*}}, <32 x i32> return _mm256_bslli_epi128(a, 3); } __m256i test_mm256_bsrli_epi128(__m256i a) { // CHECK-LABEL: test_mm256_bsrli_epi128 - // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> zeroinitializer, <32 x i32> return _mm256_bsrli_epi128(a, 3); } @@ -1009,7 +1009,7 @@ __m256i test_mm256_slli_epi64(__m256i a) { __m256i test_mm256_slli_si256(__m256i a) { // CHECK-LABEL: test_mm256_slli_si256 - // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i8> zeroinitializer, <32 x i8> %{{.*}}, <32 x i32> return _mm256_slli_si256(a, 3); } @@ -1111,7 +1111,7 @@ __m256i test_mm256_srli_epi64(__m256i a) { __m256i test_mm256_srli_si256(__m256i a) { // CHECK-LABEL: test_mm256_srli_si256 - // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i8> %{{.*}}, <32 x i8> zeroinitializer, <32 x i32> return _mm256_srli_si256(a, 3); } diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c index 600eccd914..07569f53c7 100644 --- a/test/CodeGen/avx512bw-builtins.c +++ b/test/CodeGen/avx512bw-builtins.c @@ -1350,7 +1350,7 @@ __m512i test_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A) { __m512i test_mm512_bslli_epi128(__m512i __A) { // CHECK-LABEL: @test_mm512_bslli_epi128 - // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> %{{.*}}, <64 x i32> + // CHECK: shufflevector <64 x i8> zeroinitializer, <64 x i8> %{{.*}}, <64 x i32> return _mm512_bslli_epi128(__A, 5); } @@ -1476,7 +1476,7 @@ __m512i test_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A) { __m512i test_mm512_bsrli_epi128(__m512i __A) { // CHECK-LABEL: @test_mm512_bsrli_epi128 - // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> %{{.*}}, <64 x i32> + // CHECK: shufflevector <64 x i8> %{{.*}}, <64 x i8> zeroinitializer, <64 x i32> return _mm512_bsrli_epi128(__A, 5); } __m512i test_mm512_mask_mov_epi16(__m512i __W, __mmask32 __U, __m512i __A) { diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index c0a44795bf..0031215f7c 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -121,13 +121,13 @@ __m128i test_mm_avg_epu16(__m128i A, __m128i B) { __m128i test_mm_bslli_si128(__m128i A) { // CHECK-LABEL: test_mm_bslli_si128 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i8> zeroinitializer, <16 x i8> %{{.*}}, <16 x i32> return _mm_bslli_si128(A, 5); } __m128i test_mm_bsrli_si128(__m128i A) { // CHECK-LABEL: test_mm_bsrli_si128 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <16 x i32> return _mm_bsrli_si128(A, 5); } @@ -1176,13 +1176,13 @@ __m128i test_mm_slli_epi64(__m128i A) { __m128i test_mm_slli_si128(__m128i A) { // CHECK-LABEL: test_mm_slli_si128 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i8> zeroinitializer, <16 x i8> %{{.*}}, <16 x i32> return _mm_slli_si128(A, 5); } __m128i test_mm_slli_si128_2(__m128i A) { // CHECK-LABEL: test_mm_slli_si128_2 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // CHECK: ret <2 x i64> zeroinitializer return _mm_slli_si128(A, 17); } @@ -1264,13 +1264,13 @@ __m128i test_mm_srli_epi64(__m128i A) { __m128i test_mm_srli_si128(__m128i A) { // CHECK-LABEL: test_mm_srli_si128 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> zeroinitializer, <16 x i32> return _mm_srli_si128(A, 5); } __m128i test_mm_srli_si128_2(__m128i A) { // CHECK-LABEL: test_mm_srli_si128_2 - // CHECK: shufflevector <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i32> + // ret <2 x i64> zeroinitializer return _mm_srli_si128(A, 17); } -- GitLab From 6a02bc74723d0b902caff15ae176e6725922c5f4 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 7 Jun 2018 19:17:46 +0000 Subject: [PATCH 0047/1023] Introducing single for loop into clang_proto_fuzzer Summary: Created a new protobuf and protobuf-to-C++ "converter" that wraps the entire C++ code in a single for loop. - Slightly changed cxx_proto.proto -> cxx_loop_proto.proto - Made some changes to proto_to_cxx files to handle the new kind of protobuf - Created ExampleClangLoopProtoFuzzer to test new protobuf and "converter" Patch by Emmett Neyman Reviewers: kcc, vitalybuka, morehouse Reviewed By: vitalybuka, morehouse Subscribers: mgorny, llvm-commits, cfe-commits Differential Revision: https://reviews.llvm.org/D47843 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334216 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/CMakeLists.txt | 34 +++- .../ExampleClangLoopProtoFuzzer.cpp | 30 ++++ tools/clang-fuzzer/cxx_loop_proto.proto | 97 ++++++++++++ .../clang-fuzzer/proto-to-cxx/CMakeLists.txt | 11 +- .../proto-to-cxx/loop_proto_to_cxx.cpp | 148 ++++++++++++++++++ .../proto-to-cxx/loop_proto_to_cxx_main.cpp | 32 ++++ .../clang-fuzzer/proto-to-cxx/proto_to_cxx.h | 4 + 7 files changed, 351 insertions(+), 5 deletions(-) create mode 100644 tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp create mode 100644 tools/clang-fuzzer/cxx_loop_proto.proto create mode 100644 tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp create mode 100644 tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp diff --git a/tools/clang-fuzzer/CMakeLists.txt b/tools/clang-fuzzer/CMakeLists.txt index cc9266c4db..039449aca6 100644 --- a/tools/clang-fuzzer/CMakeLists.txt +++ b/tools/clang-fuzzer/CMakeLists.txt @@ -14,6 +14,7 @@ set(LLVM_OPTIONAL_SOURCES ClangFuzzer.cpp DummyClangFuzzer.cpp ExampleClangProtoFuzzer.cpp + ExampleClangLoopProtoFuzzer.cpp ) if(CLANG_ENABLE_PROTO_FUZZER) @@ -24,6 +25,7 @@ if(CLANG_ENABLE_PROTO_FUZZER) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS cxx_proto.proto) + protobuf_generate_cpp(LOOP_PROTO_SRCS LOOP_PROTO_HDRS cxx_loop_proto.proto) set(LLVM_OPTIONAL_SOURCES ${LLVM_OPTIONAL_SOURCES} ${PROTO_SRCS}) add_clang_library(clangCXXProto ${PROTO_SRCS} @@ -33,13 +35,21 @@ if(CLANG_ENABLE_PROTO_FUZZER) ${PROTOBUF_LIBRARIES} ) + add_clang_library(clangCXXLoopProto + ${LOOP_PROTO_SRCS} + ${LOOP_PROTO_HDRS} + + LINK_LIBS + ${PROTOBUF_LIBRARIES} + ) + # Build and include libprotobuf-mutator include(ProtobufMutator) include_directories(${ProtobufMutator_INCLUDE_DIRS}) # Build the protobuf->C++ translation library and driver. add_clang_subdirectory(proto-to-cxx) - + # Build the fuzzer initialization library. add_clang_subdirectory(fuzzer-initialize) @@ -49,16 +59,32 @@ if(CLANG_ENABLE_PROTO_FUZZER) ExampleClangProtoFuzzer.cpp ) - target_link_libraries(clang-proto-fuzzer - PRIVATE + # Build the loop protobuf fuzzer + add_clang_executable(clang-loop-proto-fuzzer + ${DUMMY_MAIN} + ExampleClangLoopProtoFuzzer.cpp + ) + + set(COMMON_PROTO_FUZZ_LIBRARIES ${ProtobufMutator_LIBRARIES} ${PROTOBUF_LIBRARIES} ${LLVM_LIB_FUZZING_ENGINE} - clangCXXProto clangFuzzerInitialize clangHandleCXX + ) + + target_link_libraries(clang-proto-fuzzer + PRIVATE + ${COMMON_PROTO_FUZZ_LIBRARIES} + clangCXXProto clangProtoToCXX ) + target_link_libraries(clang-loop-proto-fuzzer + PRIVATE + ${COMMON_PROTO_FUZZ_LIBRARIES} + clangCXXLoopProto + clangLoopProtoToCXX + ) endif() add_clang_subdirectory(handle-cxx) diff --git a/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp new file mode 100644 index 0000000000..69fa31f170 --- /dev/null +++ b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp @@ -0,0 +1,30 @@ +//===-- ExampleClangLoopProtoFuzzer.cpp - Fuzz Clang ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a function that runs Clang on a single +/// input and uses libprotobuf-mutator to find new inputs. This function is +/// then linked into the Fuzzer library. This file differs from +/// ExampleClangProtoFuzzer in that it uses the new protobuf that includes +/// C++ code with a single for loop. +/// +//===----------------------------------------------------------------------===// + +#include "cxx_loop_proto.pb.h" +#include "fuzzer-initialize/fuzzer_initialize.h" +#include "handle-cxx/handle_cxx.h" +#include "proto-to-cxx/proto_to_cxx.h" +#include "src/libfuzzer/libfuzzer_macro.h" + +using namespace clang_fuzzer; + +DEFINE_BINARY_PROTO_FUZZER(const LoopFunction &input) { + auto S = LoopFunctionToString(input); + HandleCXX(S, GetCLArgs()); +} diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto new file mode 100644 index 0000000000..5dae576940 --- /dev/null +++ b/tools/clang-fuzzer/cxx_loop_proto.proto @@ -0,0 +1,97 @@ +//===-- cxx_loop_proto.proto - Protobuf description of C++ with for loops -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file describes a subset of C++ as a protobuf. It is used to +/// more easily find interesting inputs for fuzzing Clang. This subset +/// extends the one defined in cxx_proto.proto by adding the option that +/// a VarRef can use the for loop's counter variable. +/// +//===----------------------------------------------------------------------===// + + +syntax = "proto2"; + +message VarRef { + required int32 varnum = 1; + required bool is_loop_var = 2; +} + +message Lvalue { + required VarRef varref = 1; +} + +message Const { + required int32 val = 1; +} + +message BinaryOp { + enum Op { + PLUS = 0; + MINUS = 1; + MUL = 2; + DIV = 3; + MOD = 4; + XOR = 5; + AND = 6; + OR = 7; + EQ = 8; + NE = 9; + LE = 10; + GE = 11; + LT = 12; + GT = 13; + }; + required Op op = 1; + required Rvalue left = 2; + required Rvalue right = 3; +} + +message Rvalue { + oneof rvalue_oneof { + VarRef varref = 1; + Const cons = 2; + BinaryOp binop = 3; + } +} + +message AssignmentStatement { + required Lvalue lvalue = 1; + required Rvalue rvalue = 2; +} + + +message IfElse { + required Rvalue cond = 1; + required StatementSeq if_body = 2; + required StatementSeq else_body = 3; +} + +message While { + required Rvalue cond = 1; + required StatementSeq body = 2; +} + +message Statement { + oneof stmt_oneof { + AssignmentStatement assignment = 1; + IfElse ifelse = 2; + While while_loop = 3; + } +} + +message StatementSeq { + repeated Statement statements = 1; +} + +message LoopFunction { + required StatementSeq statements = 1; +} + +package clang_fuzzer; diff --git a/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt b/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt index 9337092fa4..339959b81a 100644 --- a/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt +++ b/tools/clang-fuzzer/proto-to-cxx/CMakeLists.txt @@ -2,12 +2,21 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ}) # Needed by LLVM's CMake checks because this file defines multiple targets. -set(LLVM_OPTIONAL_SOURCES proto_to_cxx.cpp proto_to_cxx_main.cpp) +set(LLVM_OPTIONAL_SOURCES proto_to_cxx.cpp proto_to_cxx_main.cpp + loop_proto_to_cxx.cpp loop_proto_to_cxx_main.cpp) add_clang_library(clangProtoToCXX proto_to_cxx.cpp DEPENDS clangCXXProto LINK_LIBS clangCXXProto ${PROTOBUF_LIBRARIES} ) +add_clang_library(clangLoopProtoToCXX loop_proto_to_cxx.cpp + DEPENDS clangCXXLoopProto + LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES} + ) + add_clang_executable(clang-proto-to-cxx proto_to_cxx_main.cpp) +add_clang_executable(clang-loop-proto-to-cxx loop_proto_to_cxx_main.cpp) + target_link_libraries(clang-proto-to-cxx PRIVATE clangProtoToCXX) +target_link_libraries(clang-loop-proto-to-cxx PRIVATE clangLoopProtoToCXX) diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp new file mode 100644 index 0000000000..a0007fb6f9 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp @@ -0,0 +1,148 @@ +//==-- loop_proto_to_cxx.cpp - Protobuf-C++ conversion ---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements functions for converting between protobufs and C++. Extends +// proto_to_cxx.cpp by wrapping all the generated C++ code in a single for +// loop. Also coutputs a different function signature that includes a +// size_t parameter for the loop to use. +// +//===----------------------------------------------------------------------===// + +#include "cxx_loop_proto.pb.h" +#include "proto_to_cxx.h" + +// The following is needed to convert protos in human-readable form +#include + +#include +#include + +namespace clang_fuzzer { + +// Forward decls. +std::ostream &operator<<(std::ostream &os, const BinaryOp &x); +std::ostream &operator<<(std::ostream &os, const StatementSeq &x); + +// Proto to C++. +std::ostream &operator<<(std::ostream &os, const Const &x) { + return os << "(" << x.val() << ")"; +} +std::ostream &operator<<(std::ostream &os, const VarRef &x) { + if (x.is_loop_var()) { + return os << "a[loop_ctr]"; + } else { + return os << "a[" << static_cast(x.varnum()) << " % s]"; + } +} +std::ostream &operator<<(std::ostream &os, const Lvalue &x) { + return os << x.varref(); +} +std::ostream &operator<<(std::ostream &os, const Rvalue &x) { + if (x.has_varref()) + return os << x.varref(); + if (x.has_cons()) + return os << x.cons(); + if (x.has_binop()) + return os << x.binop(); + return os << "1"; +} +std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { + os << "(" << x.left(); + switch (x.op()) { + case BinaryOp::PLUS: + os << "+"; + break; + case BinaryOp::MINUS: + os << "-"; + break; + case BinaryOp::MUL: + os << "*"; + break; + case BinaryOp::DIV: + os << "/"; + break; + case BinaryOp::MOD: + os << "%"; + break; + case BinaryOp::XOR: + os << "^"; + break; + case BinaryOp::AND: + os << "&"; + break; + case BinaryOp::OR: + os << "|"; + break; + case BinaryOp::EQ: + os << "=="; + break; + case BinaryOp::NE: + os << "!="; + break; + case BinaryOp::LE: + os << "<="; + break; + case BinaryOp::GE: + os << ">="; + break; + case BinaryOp::LT: + os << "<"; + break; + case BinaryOp::GT: + os << ">"; + break; + } + return os << x.right() << ")"; +} +std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { + return os << x.lvalue() << "=" << x.rvalue(); +} +std::ostream &operator<<(std::ostream &os, const IfElse &x) { + return os << "if (" << x.cond() << "){\n" + << x.if_body() << "} else { \n" + << x.else_body() << "}\n"; +} +std::ostream &operator<<(std::ostream &os, const While &x) { + return os << "while (" << x.cond() << "){\n" << x.body() << "}\n"; +} +std::ostream &operator<<(std::ostream &os, const Statement &x) { + if (x.has_assignment()) + return os << x.assignment() << ";\n"; + if (x.has_ifelse()) + return os << x.ifelse(); + if (x.has_while_loop()) + return os << x.while_loop(); + return os << "(void)0;\n"; +} +std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { + for (auto &st : x.statements()) + os << st; + return os; +} +std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { + return os << "void foo(int *a, size_t s) {\n" + << "for (int loop_ctr = 0; loop_ctr < s; loop_ctr++){\n" + << x.statements() << "}\n}\n"; +} + +// --------------------------------- + +std::string LoopFunctionToString(const LoopFunction &input) { + std::ostringstream os; + os << input; + return os.str(); +} +std::string LoopProtoToCxx(const uint8_t *data, size_t size) { + LoopFunction message; + if (!message.ParsePartialFromArray(data, size)) + return "#error invalid proto, may not be binary encoded\n"; + return LoopFunctionToString(message); +} + +} // namespace clang_fuzzer diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp new file mode 100644 index 0000000000..e4b1414c63 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp @@ -0,0 +1,32 @@ +//==-- loop_proto_to_cxx_main.cpp - Driver for protobuf-C++ conversion -----==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements a simple driver to print a C++ program from a protobuf with loops. +// +//===----------------------------------------------------------------------===// + +// This is a copy and will be updated later to introduce changes + +#include +#include +#include +#include + +#include "proto_to_cxx.h" + +int main(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + std::fstream in(argv[i]); + std::string str((std::istreambuf_iterator(in)), + std::istreambuf_iterator()); + std::cout << "// " << argv[i] << std::endl; + std::cout << clang_fuzzer::LoopProtoToCxx( + reinterpret_cast(str.data()), str.size()); + } +} diff --git a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h index 1985e91ba2..8d2e2e6f00 100644 --- a/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h +++ b/tools/clang-fuzzer/proto-to-cxx/proto_to_cxx.h @@ -17,6 +17,10 @@ namespace clang_fuzzer { class Function; +class LoopFunction; + std::string FunctionToString(const Function &input); std::string ProtoToCxx(const uint8_t *data, size_t size); +std::string LoopFunctionToString(const LoopFunction &input); +std::string LoopProtoToCxx(const uint8_t *data, size_t size); } -- GitLab From 63624e51bdbda6731b3b4ce87ecc1789c9b85b5e Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Thu, 7 Jun 2018 19:58:58 +0000 Subject: [PATCH 0048/1023] [FileSystem] Split up the OpenFlags enumeration. This breaks the OpenFlags enumeration into two separate enumerations: OpenFlags and CreationDisposition. The first controls the behavior of the API depending on whether or not the target file already exists, and is not a flags-based enum. The second controls more flags-like values. This yields a more easy to understand API, while also allowing flags to be passed to the openForRead api, where most of the values didn't make sense before. This also makes the apis more testable as it becomes easy to enumerate all the configurations which make sense, so I've added many new tests to exercise all the different values. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334221 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/VirtualFileSystem.cpp | 3 ++- lib/Driver/Driver.cpp | 2 +- lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 6 ++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index 234adcd9aa..bcfcbdbb90 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -258,7 +258,8 @@ ErrorOr> RealFileSystem::openFileForRead(const Twine &Name) { int FD; SmallString<256> RealName; - if (std::error_code EC = sys::fs::openFileForRead(Name, FD, &RealName)) + if (std::error_code EC = + sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName)) return EC; return std::unique_ptr(new RealFile(FD, Name.str(), RealName.str())); } diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index d0858764e7..b006eb3521 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1293,7 +1293,7 @@ void Driver::generateCompilationDiagnostics( std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; std::error_code EC; - llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::F_Excl); + llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew); if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + EC.message(); diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 1cb122a536..d5e5f96dee 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -238,10 +238,8 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D, << "-" << i << ".html"; llvm::sys::path::append(Model, Directory, filename.str()); - EC = llvm::sys::fs::openFileForWrite(Model, - FD, - llvm::sys::fs::F_RW | - llvm::sys::fs::F_Excl); + EC = llvm::sys::fs::openFileForReadWrite( + Model, FD, llvm::sys::fs::CD_CreateNew, llvm::sys::fs::OF_None); if (EC && EC != llvm::errc::file_exists) { llvm::errs() << "warning: could not create file '" << Model << "': " << EC.message() << '\n'; -- GitLab From 3a20c380550f154c20faa251963d136d0cf55cd3 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Thu, 7 Jun 2018 20:07:52 +0000 Subject: [PATCH 0049/1023] [Parse] Use CapturedStmt for @finally on MSVC The body of a `@finally` needs to be executed on both exceptional and non-exceptional paths. On landingpad platforms, this is straightforward: the `@finally` body is emitted as a normal (non-exceptional) cleanup, and then a catch-all is emitted which branches to that cleanup (the cleanup has code to conditionally re-throw based on a flag which is set by the catch-all). Unfortunately, we can't use the same approach for MSVC exceptions, where the catch-all will be emitted as a catchpad. We can't just branch to the cleanup from within the catchpad, since we can only exit it via a catchret, at which point the exception is destroyed and we can't rethrow. We could potentially emit the finally body inside the catchpad and have the normal cleanup path somehow branch into it, but that would require some new IR construct that could branch into a catchpad. Instead, after discussing it with Reid Kleckner, we decided that frontend outlining was the best approach, similar to how SEH `__finally` works today. We decided to use CapturedStmt (which was also suggested by Reid) rather than CaptureFinder (which is what `__finally` uses) since the latter doesn't handle a lot of cases we care about, e.g. self accesses, property accesses, block captures, etc. Extending CaptureFinder to handle those additional cases proved unwieldy, whereas CapturedStmt already took care of all of those. In theory `__finally` could also be moved over to CapturedStmt, which would remove some existing limitations (e.g. the inability to capture this), although CaptureFinder would still be needed for SEH filters. The one case supported by `@finally` but not CapturedStmt (or CaptureFinder for that matter) is arbitrary control flow out of the `@finally`, e.g. having a return statement inside a `@finally`. We can add that support as a follow-up, but in practice we've found it to be used very rarely anyway. Differential Revision: https://reviews.llvm.org/D47564 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334224 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Stmt.h | 2 +- include/clang/Basic/CapturedStmt.h | 1 + include/clang/Sema/ScopeInfo.h | 2 ++ lib/Parse/ParseObjc.cpp | 15 ++++++++++++++- test/SemaObjC/finally-msvc.m | 14 ++++++++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 test/SemaObjC/finally-msvc.m diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 03c808d394..3b678dcc75 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -2133,7 +2133,7 @@ private: /// The pointer part is the implicit the outlined function and the /// int part is the captured region kind, 'CR_Default' etc. - llvm::PointerIntPair CapDeclAndKind; + llvm::PointerIntPair CapDeclAndKind; /// The record for captured variables, a RecordDecl or CXXRecordDecl. RecordDecl *TheRecordDecl = nullptr; diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h index 6c8d6edab0..324e1b1d3d 100644 --- a/include/clang/Basic/CapturedStmt.h +++ b/include/clang/Basic/CapturedStmt.h @@ -16,6 +16,7 @@ namespace clang { /// The different kinds of captured statement. enum CapturedRegionKind { CR_Default, + CR_ObjCAtFinally, CR_OpenMP }; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b0f6bac994..fa1b1037a2 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -748,6 +748,8 @@ public: switch (CapRegionKind) { case CR_Default: return "default captured statement"; + case CR_ObjCAtFinally: + return "Objective-C @finally statement"; case CR_OpenMP: return "OpenMP region"; } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 6ca0ad855f..ff33d5fb96 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2585,13 +2585,26 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ParseScope FinallyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + bool ShouldCapture = + getTargetInfo().getTriple().isWindowsMSVCEnvironment(); + if (ShouldCapture) + Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), + CR_ObjCAtFinally, 1); + StmtResult FinallyBody(true); if (Tok.is(tok::l_brace)) FinallyBody = ParseCompoundStatementBody(); else Diag(Tok, diag::err_expected) << tok::l_brace; - if (FinallyBody.isInvalid()) + + if (FinallyBody.isInvalid()) { FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); + if (ShouldCapture) + Actions.ActOnCapturedRegionError(); + } else if (ShouldCapture) { + FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); + } + FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, FinallyBody.get()); catch_or_finally_seen = true; diff --git a/test/SemaObjC/finally-msvc.m b/test/SemaObjC/finally-msvc.m new file mode 100644 index 0000000000..5db08a7f71 --- /dev/null +++ b/test/SemaObjC/finally-msvc.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple i686--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s + +void f() { + @try { + } @finally { + } +} + +// CHECK: ObjCAtFinallyStmt +// CHECK-NEXT: CapturedStmt +// CHECK-NEXT: CapturedDecl +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ImplicitParamDecl -- GitLab From 2dbbac4dddd5ec3c3bfeaf681336831fca254e28 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 7 Jun 2018 21:27:41 +0000 Subject: [PATCH 0050/1023] [X86] Add builtins for VALIGNQ/VALIGND to enable proper target feature checking. We still emit shufflevector instructions we just do it from CGBuiltin.cpp now. This ensures the intrinsics that use this are only available on CPUs that support the feature. I also added range checking to the immediate, but only checked it is 8 bits or smaller. We should maybe be stricter since we never use all 8 bits, but gcc doesn't seem to do that. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334237 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 6 +++++ lib/CodeGen/CGBuiltin.cpp | 20 +++++++++++++++++ lib/Headers/avx512fintrin.h | 32 ++++----------------------- lib/Headers/avx512vlintrin.h | 34 +++++++---------------------- lib/Sema/SemaChecking.cpp | 6 +++++ 5 files changed, 44 insertions(+), 54 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index fb284d3de5..e3a0e4e1ab 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -909,6 +909,12 @@ TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "n", "avx512f") TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "n", "avx512f") TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "n", "avx512f") TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "n", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd512, "V16iV16iV16iIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a126e75b19..c911ab9fc5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9222,6 +9222,26 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "palignr"); } + case X86::BI__builtin_ia32_alignd128: + case X86::BI__builtin_ia32_alignd256: + case X86::BI__builtin_ia32_alignd512: + case X86::BI__builtin_ia32_alignq128: + case X86::BI__builtin_ia32_alignq256: + case X86::BI__builtin_ia32_alignq512: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + unsigned ShiftVal = cast(Ops[2])->getZExtValue(); + + // Mask the shift amount to width of two vectors. + ShiftVal &= (2 * NumElts) - 1; + + uint32_t Indices[16]; + for (unsigned i = 0; i != NumElts; ++i) + Indices[i] = i + ShiftVal; + + return Builder.CreateShuffleVector(Ops[1], Ops[0], + makeArrayRef(Indices, NumElts), + "valign"); + } case X86::BI__builtin_ia32_vperm2f128_pd256: case X86::BI__builtin_ia32_vperm2f128_ps256: diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 47a0c9d433..5132edde65 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -3465,16 +3465,8 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, } #define _mm512_alignr_epi64(A, B, I) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(B), \ - (__v8di)(__m512i)(A), \ - ((int)(I) & 0x7) + 0, \ - ((int)(I) & 0x7) + 1, \ - ((int)(I) & 0x7) + 2, \ - ((int)(I) & 0x7) + 3, \ - ((int)(I) & 0x7) + 4, \ - ((int)(I) & 0x7) + 5, \ - ((int)(I) & 0x7) + 6, \ - ((int)(I) & 0x7) + 7) + (__m512i)__builtin_ia32_alignq512((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(I)) #define _mm512_mask_alignr_epi64(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ @@ -3487,24 +3479,8 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, (__v8di)_mm512_setzero_si512()) #define _mm512_alignr_epi32(A, B, I) \ - (__m512i)__builtin_shufflevector((__v16si)(__m512i)(B), \ - (__v16si)(__m512i)(A), \ - ((int)(I) & 0xf) + 0, \ - ((int)(I) & 0xf) + 1, \ - ((int)(I) & 0xf) + 2, \ - ((int)(I) & 0xf) + 3, \ - ((int)(I) & 0xf) + 4, \ - ((int)(I) & 0xf) + 5, \ - ((int)(I) & 0xf) + 6, \ - ((int)(I) & 0xf) + 7, \ - ((int)(I) & 0xf) + 8, \ - ((int)(I) & 0xf) + 9, \ - ((int)(I) & 0xf) + 10, \ - ((int)(I) & 0xf) + 11, \ - ((int)(I) & 0xf) + 12, \ - ((int)(I) & 0xf) + 13, \ - ((int)(I) & 0xf) + 14, \ - ((int)(I) & 0xf) + 15) + (__m512i)__builtin_ia32_alignd512((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B), (int)(I)) #define _mm512_mask_alignr_epi32(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index 2b9f14b99f..e5963720fe 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -8082,12 +8082,8 @@ _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) } #define _mm_alignr_epi32(A, B, imm) \ - (__m128i)__builtin_shufflevector((__v4si)(__m128i)(B), \ - (__v4si)(__m128i)(A), \ - ((int)(imm) & 0x3) + 0, \ - ((int)(imm) & 0x3) + 1, \ - ((int)(imm) & 0x3) + 2, \ - ((int)(imm) & 0x3) + 3) + (__m128i)__builtin_ia32_alignd128((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B), (int)(imm)) #define _mm_mask_alignr_epi32(W, U, A, B, imm) \ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ @@ -8100,16 +8096,8 @@ _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) (__v4si)_mm_setzero_si128()) #define _mm256_alignr_epi32(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v8si)(__m256i)(B), \ - (__v8si)(__m256i)(A), \ - ((int)(imm) & 0x7) + 0, \ - ((int)(imm) & 0x7) + 1, \ - ((int)(imm) & 0x7) + 2, \ - ((int)(imm) & 0x7) + 3, \ - ((int)(imm) & 0x7) + 4, \ - ((int)(imm) & 0x7) + 5, \ - ((int)(imm) & 0x7) + 6, \ - ((int)(imm) & 0x7) + 7) + (__m256i)__builtin_ia32_alignd256((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B), (int)(imm)) #define _mm256_mask_alignr_epi32(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ @@ -8122,10 +8110,8 @@ _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) (__v8si)_mm256_setzero_si256()) #define _mm_alignr_epi64(A, B, imm) \ - (__m128i)__builtin_shufflevector((__v2di)(__m128i)(B), \ - (__v2di)(__m128i)(A), \ - ((int)(imm) & 0x1) + 0, \ - ((int)(imm) & 0x1) + 1) + (__m128i)__builtin_ia32_alignq128((__v2di)(__m128i)(A), \ + (__v2di)(__m128i)(B), (int)(imm)) #define _mm_mask_alignr_epi64(W, U, A, B, imm) \ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ @@ -8138,12 +8124,8 @@ _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) (__v2di)_mm_setzero_si128()) #define _mm256_alignr_epi64(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(B), \ - (__v4di)(__m256i)(A), \ - ((int)(imm) & 0x3) + 0, \ - ((int)(imm) & 0x3) + 1, \ - ((int)(imm) & 0x3) + 2, \ - ((int)(imm) & 0x3) + 3) + (__m256i)__builtin_ia32_alignq256((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), (int)(imm)) #define _mm256_mask_alignr_epi64(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 0c5be0506e..419ac47b9b 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2712,6 +2712,12 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: + case X86::BI__builtin_ia32_alignq512: + case X86::BI__builtin_ia32_alignd512: + case X86::BI__builtin_ia32_alignd128: + case X86::BI__builtin_ia32_alignd256: + case X86::BI__builtin_ia32_alignq128: + case X86::BI__builtin_ia32_alignq256: case X86::BI__builtin_ia32_vcomisd: case X86::BI__builtin_ia32_vcomiss: case X86::BI__builtin_ia32_dbpsadbw128_mask: -- GitLab From c1c07cca8cae5f924cedaac7b202b0f3c167111d Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 7 Jun 2018 21:39:04 +0000 Subject: [PATCH 0051/1023] [MS] Re-add support for the ARM interlocked bittest intrinscs Adds support for these intrinsics, which are ARM and ARM64 only: _interlockedbittestandreset_acq _interlockedbittestandreset_rel _interlockedbittestandreset_nf _interlockedbittestandset_acq _interlockedbittestandset_rel _interlockedbittestandset_nf Refactor the bittest intrinsic handling to decompose each intrinsic into its action, its width, and its atomicity. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334239 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 14 +- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/CodeGen/CGBuiltin.cpp | 185 +++++++++++++-------- lib/Headers/intrin.h | 17 ++ lib/Sema/SemaChecking.cpp | 41 +++++ test/CodeGen/bittest-intrin.c | 33 ++-- test/Sema/bittest-intrinsics.c | 84 ++++++++++ 7 files changed, 293 insertions(+), 83 deletions(-) create mode 100644 test/Sema/bittest-intrinsics.c diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index ed2190dac4..6f39c16302 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -791,10 +791,16 @@ LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e0050d6839..f0ea769f91 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8154,6 +8154,8 @@ def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; def err_x86_builtin_invalid_scale : Error< "scale argument must be 1, 2, 4, or 8">; +def err_builtin_target_unsupported : Error< + "builtin is not supported on this target">; def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index c911ab9fc5..0a410da4b9 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -484,58 +484,99 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown}); } -// Get properties of an X86 BT* assembly instruction. The first returned value -// is the action character code, which can be for complement, reset, or set. The -// second is the size suffix which our assembler needs. The last is whether to -// add the lock prefix. -static std::tuple -getBitTestActionSizeAndLocking(unsigned BuiltinID) { +namespace { +/// A struct to generically desribe a bit test intrinsic. +struct BitTest { + enum ActionKind : uint8_t { TestOnly, Complement, Reset, Set }; + enum InterlockingKind : uint8_t { + Unlocked, + Sequential, + Acquire, + Release, + NoFence + }; + + ActionKind Action; + InterlockingKind Interlocking; + bool Is64Bit; + + static BitTest decodeBitTestBuiltin(unsigned BuiltinID); +}; +} // namespace + +BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { switch (BuiltinID) { + // Main portable variants. case Builtin::BI_bittest: - return std::make_tuple('\0', 'l', false); + return {TestOnly, Unlocked, false}; case Builtin::BI_bittestandcomplement: - return std::make_tuple('c', 'l', false); + return {Complement, Unlocked, false}; case Builtin::BI_bittestandreset: - return std::make_tuple('r', 'l', false); + return {Reset, Unlocked, false}; case Builtin::BI_bittestandset: - return std::make_tuple('s', 'l', false); + return {Set, Unlocked, false}; case Builtin::BI_interlockedbittestandreset: - return std::make_tuple('r', 'l', /*Locked=*/true); + return {Reset, Sequential, false}; case Builtin::BI_interlockedbittestandset: - return std::make_tuple('s', 'l', /*Locked=*/true); + return {Set, Sequential, false}; + // X86-specific 64-bit variants. case Builtin::BI_bittest64: - return std::make_tuple('\0', 'q', false); + return {TestOnly, Unlocked, true}; case Builtin::BI_bittestandcomplement64: - return std::make_tuple('c', 'q', false); + return {Complement, Unlocked, true}; case Builtin::BI_bittestandreset64: - return std::make_tuple('r', 'q', false); + return {Reset, Unlocked, true}; case Builtin::BI_bittestandset64: - return std::make_tuple('s', 'q', false); + return {Set, Unlocked, true}; case Builtin::BI_interlockedbittestandreset64: - return std::make_tuple('r', 'q', /*Locked=*/true); + return {Reset, Sequential, true}; case Builtin::BI_interlockedbittestandset64: - return std::make_tuple('s', 'q', /*Locked=*/true); + return {Set, Sequential, true}; + + // ARM/AArch64-specific ordering variants. + case Builtin::BI_interlockedbittestandset_acq: + return {Set, Acquire, false}; + case Builtin::BI_interlockedbittestandset_rel: + return {Set, Release, false}; + case Builtin::BI_interlockedbittestandset_nf: + return {Set, NoFence, false}; + case Builtin::BI_interlockedbittestandreset_acq: + return {Reset, Acquire, false}; + case Builtin::BI_interlockedbittestandreset_rel: + return {Reset, Release, false}; + case Builtin::BI_interlockedbittestandreset_nf: + return {Reset, NoFence, false}; + } + llvm_unreachable("expected only bittest intrinsics"); +} + +static char bitActionToX86BTCode(BitTest::ActionKind A) { + switch (A) { + case BitTest::TestOnly: return '\0'; + case BitTest::Complement: return 'c'; + case BitTest::Reset: return 'r'; + case BitTest::Set: return 's'; } - llvm_unreachable("expected only bittest builtins"); + llvm_unreachable("invalid action"); } -static RValue EmitX86BitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, - const CallExpr *E, Value *BitBase, - Value *BitPos) { - char Action, Size; - bool Locked; - std::tie(Action, Size, Locked) = getBitTestActionSizeAndLocking(BuiltinID); +static llvm::Value *EmitX86BitTestIntrinsic(CodeGenFunction &CGF, + BitTest BT, + const CallExpr *E, Value *BitBase, + Value *BitPos) { + char Action = bitActionToX86BTCode(BT.Action); + char SizeSuffix = BT.Is64Bit ? 'q' : 'l'; // Build the assembly. SmallString<64> Asm; raw_svector_ostream AsmOS(Asm); - if (Locked) + if (BT.Interlocking != BitTest::Unlocked) AsmOS << "lock "; AsmOS << "bt"; if (Action) AsmOS << Action; - AsmOS << Size << " $2, ($1)\n\tsetc ${0:b}"; + AsmOS << SizeSuffix << " $2, ($1)\n\tsetc ${0:b}"; // Build the constraints. FIXME: We should support immediates when possible. std::string Constraints = "=r,r,r,~{cc},~{flags},~{fpsr}"; @@ -548,24 +589,38 @@ static RValue EmitX86BitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, llvm::InlineAsm *IA = llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); - CallSite CS = CGF.Builder.CreateCall(IA, {BitBase, BitPos}); - return RValue::get(CS.getInstruction()); + return CGF.Builder.CreateCall(IA, {BitBase, BitPos}); +} + +static llvm::AtomicOrdering +getBitTestAtomicOrdering(BitTest::InterlockingKind I) { + switch (I) { + case BitTest::Unlocked: return llvm::AtomicOrdering::NotAtomic; + case BitTest::Sequential: return llvm::AtomicOrdering::SequentiallyConsistent; + case BitTest::Acquire: return llvm::AtomicOrdering::Acquire; + case BitTest::Release: return llvm::AtomicOrdering::Release; + case BitTest::NoFence: return llvm::AtomicOrdering::Monotonic; + } + llvm_unreachable("invalid interlocking"); } /// Emit a _bittest* intrinsic. These intrinsics take a pointer to an array of /// bits and a bit position and read and optionally modify the bit at that /// position. The position index can be arbitrarily large, i.e. it can be larger /// than 31 or 63, so we need an indexed load in the general case. -static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, - const CallExpr *E) { +static llvm::Value *EmitBitTestIntrinsic(CodeGenFunction &CGF, + unsigned BuiltinID, + const CallExpr *E) { Value *BitBase = CGF.EmitScalarExpr(E->getArg(0)); Value *BitPos = CGF.EmitScalarExpr(E->getArg(1)); + BitTest BT = BitTest::decodeBitTestBuiltin(BuiltinID); + // X86 has special BT, BTC, BTR, and BTS instructions that handle the array // indexing operation internally. Use them if possible. llvm::Triple::ArchType Arch = CGF.getTarget().getTriple().getArch(); if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) - return EmitX86BitTestIntrinsic(CGF, BuiltinID, E, BitBase, BitPos); + return EmitX86BitTestIntrinsic(CGF, BT, E, BitBase, BitPos); // Otherwise, use generic code to load one byte and test the bit. Use all but // the bottom three bits as the array index, and the bottom three bits to form @@ -583,54 +638,42 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, // The updating instructions will need a mask. Value *Mask = nullptr; - if (BuiltinID != Builtin::BI_bittest && BuiltinID != Builtin::BI_bittest64) { + if (BT.Action != BitTest::TestOnly) { Mask = CGF.Builder.CreateShl(llvm::ConstantInt::get(CGF.Int8Ty, 1), PosLow, "bittest.mask"); } - // Emit a combined atomicrmw load/store operation for the interlocked - // intrinsics. - Value *OldByte = nullptr; - switch (BuiltinID) { - case Builtin::BI_interlockedbittestandreset: - case Builtin::BI_interlockedbittestandreset64: - OldByte = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::And, ByteAddr.getPointer(), CGF.Builder.CreateNot(Mask), - llvm::AtomicOrdering::SequentiallyConsistent); - break; - case Builtin::BI_interlockedbittestandset: - case Builtin::BI_interlockedbittestandset64: - OldByte = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::Or, ByteAddr.getPointer(), Mask, - llvm::AtomicOrdering::SequentiallyConsistent); - break; - default: - break; - } + // Check the action and ordering of the interlocked intrinsics. + llvm::AtomicOrdering Ordering = getBitTestAtomicOrdering(BT.Interlocking); - // Emit a plain load for the non-interlocked intrinsics. - if (!OldByte) { + Value *OldByte = nullptr; + if (Ordering != llvm::AtomicOrdering::NotAtomic) { + // Emit a combined atomicrmw load/store operation for the interlocked + // intrinsics. + llvm::AtomicRMWInst::BinOp RMWOp = llvm::AtomicRMWInst::Or; + if (BT.Action == BitTest::Reset) { + Mask = CGF.Builder.CreateNot(Mask); + RMWOp = llvm::AtomicRMWInst::And; + } + OldByte = CGF.Builder.CreateAtomicRMW(RMWOp, ByteAddr.getPointer(), Mask, + Ordering); + } else { + // Emit a plain load for the non-interlocked intrinsics. OldByte = CGF.Builder.CreateLoad(ByteAddr, "bittest.byte"); Value *NewByte = nullptr; - switch (BuiltinID) { - case Builtin::BI_bittest: - case Builtin::BI_bittest64: + switch (BT.Action) { + case BitTest::TestOnly: // Don't store anything. break; - case Builtin::BI_bittestandcomplement: - case Builtin::BI_bittestandcomplement64: + case BitTest::Complement: NewByte = CGF.Builder.CreateXor(OldByte, Mask); break; - case Builtin::BI_bittestandreset: - case Builtin::BI_bittestandreset64: + case BitTest::Reset: NewByte = CGF.Builder.CreateAnd(OldByte, CGF.Builder.CreateNot(Mask)); break; - case Builtin::BI_bittestandset: - case Builtin::BI_bittestandset64: + case BitTest::Set: NewByte = CGF.Builder.CreateOr(OldByte, Mask); break; - default: - llvm_unreachable("non bittest family builtin"); } if (NewByte) CGF.Builder.CreateStore(NewByte, ByteAddr); @@ -639,8 +682,8 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID, // However we loaded the old byte, either by plain load or atomicrmw, shift // the bit into the low position and mask it to 0 or 1. Value *ShiftedByte = CGF.Builder.CreateLShr(OldByte, PosLow, "bittest.shr"); - return RValue::get(CGF.Builder.CreateAnd( - ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res")); + return CGF.Builder.CreateAnd( + ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res"); } namespace { @@ -2992,7 +3035,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI_interlockedbittestandreset64: case Builtin::BI_interlockedbittestandset64: case Builtin::BI_interlockedbittestandset: - return EmitBitTestIntrinsic(*this, BuiltinID, E); + case Builtin::BI_interlockedbittestandset_acq: + case Builtin::BI_interlockedbittestandset_rel: + case Builtin::BI_interlockedbittestandset_nf: + case Builtin::BI_interlockedbittestandreset_acq: + case Builtin::BI_interlockedbittestandreset_rel: + case Builtin::BI_interlockedbittestandreset_nf: + return RValue::get(EmitBitTestIntrinsic(*this, BuiltinID, E)); case Builtin::BI__exception_code: case Builtin::BI_exception_code: diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index 4600942016..4118fb7d8f 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -521,6 +521,23 @@ _InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask) { } #endif /*----------------------------------------------------------------------------*\ +|* Bit Counting and Testing +\*----------------------------------------------------------------------------*/ +#if defined(__arm__) || defined(__aarch64__) +unsigned char _interlockedbittestandset_acq(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandset_nf(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandset_rel(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_acq(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_nf(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_rel(long volatile *_BitBase, + long _BitPos); +#endif +/*----------------------------------------------------------------------------*\ |* Interlocked Or \*----------------------------------------------------------------------------*/ #if defined(__arm__) || defined(__aarch64__) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 419ac47b9b..11164df173 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -851,6 +851,20 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, return false; } +// Emit an error and return true if the current architecture is not in the list +// of supported architectures. +static bool +CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, + ArrayRef SupportedArchs) { + llvm::Triple::ArchType CurArch = + S.getASTContext().getTargetInfo().getTriple().getArch(); + if (llvm::is_contained(SupportedArchs, CurArch)) + return false; + S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) + << TheCall->getSourceRange(); + return true; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -901,6 +915,33 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } + + // The acquire, release, and no fence variants are ARM and AArch64 only. + case Builtin::BI_interlockedbittestandset_acq: + case Builtin::BI_interlockedbittestandset_rel: + case Builtin::BI_interlockedbittestandset_nf: + case Builtin::BI_interlockedbittestandreset_acq: + case Builtin::BI_interlockedbittestandreset_rel: + case Builtin::BI_interlockedbittestandreset_nf: + if (CheckBuiltinTargetSupport( + *this, BuiltinID, TheCall, + {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + + // The 64-bit bittest variants are x64, ARM, and AArch64 only. + case Builtin::BI_bittest64: + case Builtin::BI_bittestandcomplement64: + case Builtin::BI_bittestandreset64: + case Builtin::BI_bittestandset64: + case Builtin::BI_interlockedbittestandreset64: + case Builtin::BI_interlockedbittestandset64: + if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, + {llvm::Triple::x86_64, llvm::Triple::arm, + llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + case Builtin::BI__builtin_isgreater: case Builtin::BI__builtin_isgreaterequal: case Builtin::BI__builtin_isless: diff --git a/test/CodeGen/bittest-intrin.c b/test/CodeGen/bittest-intrin.c index 21a26efa10..f89a8267b0 100644 --- a/test/CodeGen/bittest-intrin.c +++ b/test/CodeGen/bittest-intrin.c @@ -10,7 +10,9 @@ void test32(long *base, long idx) { sink = _bittestandset(base, idx); sink = _interlockedbittestandreset(base, idx); sink = _interlockedbittestandset(base, idx); + sink = _interlockedbittestandset(base, idx); } + void test64(__int64 *base, __int64 idx) { sink = _bittest64(base, idx); sink = _bittestandcomplement64(base, idx); @@ -20,6 +22,17 @@ void test64(__int64 *base, __int64 idx) { sink = _interlockedbittestandset64(base, idx); } +#if defined(_M_ARM) || defined(_M_ARM64) +void test_arm(long *base, long idx) { + sink = _interlockedbittestandreset_acq(base, idx); + sink = _interlockedbittestandreset_rel(base, idx); + sink = _interlockedbittestandreset_nf(base, idx); + sink = _interlockedbittestandset_acq(base, idx); + sink = _interlockedbittestandset_rel(base, idx); + sink = _interlockedbittestandset_nf(base, idx); +} +#endif + // X64-LABEL: define dso_local void @test32(i32* %base, i32 %idx) // X64: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) // X64: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}}) @@ -110,15 +123,13 @@ void test64(__int64 *base, __int64 idx) { // ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 // ARM: store volatile i8 %[[RES]], i8* @sink, align 1 -// ARM-LABEL: define dso_local {{.*}}void @test64(i64* %base, i64 %idx) -// ARM: %[[IDXHI:[^ ]*]] = ashr i64 %{{.*}}, 3 -// ARM: %[[BASE:[^ ]*]] = bitcast i64* %{{.*}} to i8* -// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i64 %[[IDXHI]] -// ARM: %[[IDX8:[^ ]*]] = trunc i64 %{{.*}} to i8 -// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7 -// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1 -// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]] -// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1 -// ARM: store volatile i8 %[[RES]], i8* @sink, align 1 -// ... the rest is the same, but with i64 instead of i32. +// Just look for the atomicrmw instructions. + +// ARM-LABEL: define dso_local {{.*}}void @test_arm(i32* %base, i32 %idx) +// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} acquire +// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} release +// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} monotonic +// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} acquire +// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} release +// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} monotonic diff --git a/test/Sema/bittest-intrinsics.c b/test/Sema/bittest-intrinsics.c new file mode 100644 index 0000000000..536c1eb066 --- /dev/null +++ b/test/Sema/bittest-intrinsics.c @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple i686-windows-msvc -fms-extensions -DTEST_X86 +// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple x86_64-windows-msvc -fms-extensions -DTEST_X64 +// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple arm-windows-msvc -fms-extensions -DTEST_ARM +// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple thumbv7-windows-msvc -fms-extensions -DTEST_ARM +// RUN: %clang_cc1 -ffreestanding -fms-compatibility -fms-compatibility-version=19 -verify %s -triple aarch64-windows-msvc -fms-extensions -DTEST_ARM + +#include +extern unsigned char sink; + +#ifdef TEST_X86 +void x86(long *bits, __int64 *bits64, long bitidx) { + sink = _bittest(bits, bitidx); + sink = _bittestandcomplement(bits, bitidx); + sink = _bittestandreset(bits, bitidx); + sink = _bittestandset(bits, bitidx); + sink = _interlockedbittestandreset(bits, bitidx); + sink = _interlockedbittestandset(bits, bitidx); + + sink = _bittest64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _bittestandcomplement64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _bittestandreset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _bittestandset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandreset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset64(bits64, bitidx); // expected-error {{builtin is not supported on this target}} + + sink = _interlockedbittestandreset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandreset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandreset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}} +} +#endif + +#ifdef TEST_X64 +void x64(long *bits, __int64 *bits64, long bitidx) { + sink = _bittest(bits, bitidx); + sink = _bittestandcomplement(bits, bitidx); + sink = _bittestandreset(bits, bitidx); + sink = _bittestandset(bits, bitidx); + sink = _interlockedbittestandreset(bits, bitidx); + sink = _interlockedbittestandset(bits, bitidx); + + sink = _bittest64(bits64, bitidx); + sink = _bittestandcomplement64(bits64, bitidx); + sink = _bittestandreset64(bits64, bitidx); + sink = _bittestandset64(bits64, bitidx); + sink = _interlockedbittestandreset64(bits64, bitidx); + sink = _interlockedbittestandset64(bits64, bitidx); + + sink = _interlockedbittestandreset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandreset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandreset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_acq(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_rel(bits, bitidx); // expected-error {{builtin is not supported on this target}} + sink = _interlockedbittestandset_nf(bits, bitidx); // expected-error {{builtin is not supported on this target}} +} +#endif + +#ifdef TEST_ARM +// expected-no-diagnostics +void arm(long *bits, __int64 *bits64, long bitidx) { + sink = _bittest(bits, bitidx); + sink = _bittestandcomplement(bits, bitidx); + sink = _bittestandreset(bits, bitidx); + sink = _bittestandset(bits, bitidx); + sink = _interlockedbittestandreset(bits, bitidx); + sink = _interlockedbittestandset(bits, bitidx); + + sink = _bittest64(bits64, bitidx); + sink = _bittestandcomplement64(bits64, bitidx); + sink = _bittestandreset64(bits64, bitidx); + sink = _bittestandset64(bits64, bitidx); + sink = _interlockedbittestandreset64(bits64, bitidx); + sink = _interlockedbittestandset64(bits64, bitidx); + + sink = _interlockedbittestandreset_acq(bits, bitidx); + sink = _interlockedbittestandreset_rel(bits, bitidx); + sink = _interlockedbittestandreset_nf(bits, bitidx); + sink = _interlockedbittestandset_acq(bits, bitidx); + sink = _interlockedbittestandset_rel(bits, bitidx); + sink = _interlockedbittestandset_nf(bits, bitidx); +} +#endif -- GitLab From 02655f4bc1895e79729373c6be525b2140d133d3 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Thu, 7 Jun 2018 22:24:20 +0000 Subject: [PATCH 0052/1023] Revert "[Parse] Use CapturedStmt for @finally on MSVC" This reverts commit r334224. This is causing buildbot failures on Windows, presumably because some tests don't specify a triple. I'll test this on Windows locally and recommit with the tests fixed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334240 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Stmt.h | 2 +- include/clang/Basic/CapturedStmt.h | 1 - include/clang/Sema/ScopeInfo.h | 2 -- lib/Parse/ParseObjc.cpp | 15 +-------------- test/SemaObjC/finally-msvc.m | 14 -------------- 5 files changed, 2 insertions(+), 32 deletions(-) delete mode 100644 test/SemaObjC/finally-msvc.m diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 3b678dcc75..03c808d394 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -2133,7 +2133,7 @@ private: /// The pointer part is the implicit the outlined function and the /// int part is the captured region kind, 'CR_Default' etc. - llvm::PointerIntPair CapDeclAndKind; + llvm::PointerIntPair CapDeclAndKind; /// The record for captured variables, a RecordDecl or CXXRecordDecl. RecordDecl *TheRecordDecl = nullptr; diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h index 324e1b1d3d..6c8d6edab0 100644 --- a/include/clang/Basic/CapturedStmt.h +++ b/include/clang/Basic/CapturedStmt.h @@ -16,7 +16,6 @@ namespace clang { /// The different kinds of captured statement. enum CapturedRegionKind { CR_Default, - CR_ObjCAtFinally, CR_OpenMP }; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index fa1b1037a2..b0f6bac994 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -748,8 +748,6 @@ public: switch (CapRegionKind) { case CR_Default: return "default captured statement"; - case CR_ObjCAtFinally: - return "Objective-C @finally statement"; case CR_OpenMP: return "OpenMP region"; } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ff33d5fb96..6ca0ad855f 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2585,26 +2585,13 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ParseScope FinallyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); - bool ShouldCapture = - getTargetInfo().getTriple().isWindowsMSVCEnvironment(); - if (ShouldCapture) - Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), - CR_ObjCAtFinally, 1); - StmtResult FinallyBody(true); if (Tok.is(tok::l_brace)) FinallyBody = ParseCompoundStatementBody(); else Diag(Tok, diag::err_expected) << tok::l_brace; - - if (FinallyBody.isInvalid()) { + if (FinallyBody.isInvalid()) FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); - if (ShouldCapture) - Actions.ActOnCapturedRegionError(); - } else if (ShouldCapture) { - FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); - } - FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, FinallyBody.get()); catch_or_finally_seen = true; diff --git a/test/SemaObjC/finally-msvc.m b/test/SemaObjC/finally-msvc.m deleted file mode 100644 index 5db08a7f71..0000000000 --- a/test/SemaObjC/finally-msvc.m +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -triple i686--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s -// RUN: %clang_cc1 -triple x86_64--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s - -void f() { - @try { - } @finally { - } -} - -// CHECK: ObjCAtFinallyStmt -// CHECK-NEXT: CapturedStmt -// CHECK-NEXT: CapturedDecl -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: ImplicitParamDecl -- GitLab From 92651da517c38e2425712bf6152557f3bfae5b96 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Thu, 7 Jun 2018 22:54:54 +0000 Subject: [PATCH 0053/1023] [Frontend] Disallow non-MSVC exception models for windows-msvc targets The windows-msvc target is used for MSVC ABI compatibility, including the exceptions model. It doesn't make sense to pair a windows-msvc target with a non-MSVC exception model. This would previously cause an assertion failure; explicitly error out for it in the frontend instead. This also allows us to reduce the matrix of target/exception models a bit (see the modified tests), and we can possibly simplify some of the personality code in a follow-up. Differential Revision: https://reviews.llvm.org/D47853 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334243 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 2 ++ lib/Frontend/CompilerInvocation.cpp | 5 ++++ test/CodeGen/personality.c | 15 +++++------ test/CodeGenCXX/ms-eh-personality.cpp | 20 -------------- test/CodeGenCXX/personality.cpp | 12 +++------ test/CodeGenObjC/personality.m | 10 ------- test/CodeGenObjCXX/personality.mm | 23 ---------------- test/Frontend/windows-exceptions.cpp | 27 +++++++++++++++++++ 8 files changed, 43 insertions(+), 71 deletions(-) delete mode 100644 test/CodeGenCXX/ms-eh-personality.cpp create mode 100644 test/Frontend/windows-exceptions.cpp diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b25181f256..2211a92574 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -118,6 +118,8 @@ def err_fe_invalid_alignment : Error< "invalid value '%1' in '%0'; alignment must be a power of 2">; def err_fe_invalid_wchar_type : Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">; +def err_fe_invalid_exception_model + : Error<"invalid exception model '%0' for target '%1'">; def warn_fe_serialized_diag_merge_failure : Warning< "unable to merge a subprocess's serialized diagnostics">, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 46f8c9f235..b10155da96 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2344,6 +2344,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, options::OPT_fdwarf_exceptions); if (A) { const Option &Opt = A->getOption(); + llvm::Triple T(TargetOpts.Triple); + if (T.isWindowsMSVCEnvironment()) + Diags.Report(diag::err_fe_invalid_exception_model) + << Opt.getName() << T.str(); + Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); diff --git a/test/CodeGen/personality.c b/test/CodeGen/personality.c index 283fccd428..1c533ce786 100644 --- a/test/CodeGen/personality.c +++ b/test/CodeGen/personality.c @@ -4,13 +4,13 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH -check-prefix CHECK-WIN-SEH-X86 -// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH -check-prefix CHECK-WIN-SEH-X64 -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fblocks -fsjlj-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SJLJ +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86 +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64 -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MINGW-SEH -check-prefix CHECK-WIN-SEH-X86 -// RUN: %clang_cc1 -triple x86_64-unknown-windows-gnu -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fblocks -fseh-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MINGW-SEH -check-prefix CHECK-WIN-SEH-X64 +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-DWARF +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SEH +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fblocks -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-SJLJ extern void g(void (^)(void)); @@ -22,10 +22,7 @@ extern void i(void); // CHECK-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) // CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) -// CHECK-WIN-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*) -// CHECK-WIN-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) void f(void) { __block int i; diff --git a/test/CodeGenCXX/ms-eh-personality.cpp b/test/CodeGenCXX/ms-eh-personality.cpp deleted file mode 100644 index 36661b7270..0000000000 --- a/test/CodeGenCXX/ms-eh-personality.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fsjlj-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=SJLJ -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fseh-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=MSVC -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fdwarf-exceptions %s -emit-llvm -o - | FileCheck %s --check-prefix=DWARF - -// MSVC: define dso_local void @f(){{.*}}@__CxxFrameHandler3 -// SJLJ: define dso_local void @f(){{.*}}@__gxx_personality_sj0 -// DWARF: define dso_local void @f(){{.*}}@__gxx_personality_v0 - -struct Cleanup { - Cleanup(); - ~Cleanup(); - int x = 0; -}; - -void g(); -extern "C" void f() { - Cleanup c; - g(); -} diff --git a/test/CodeGenCXX/personality.cpp b/test/CodeGenCXX/personality.cpp index dc6222906f..ce4bad370d 100644 --- a/test/CodeGenCXX/personality.cpp +++ b/test/CodeGenCXX/personality.cpp @@ -4,14 +4,11 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN -// %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH -// %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SJLJ -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86 -// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64 +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X86 +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -D __SEH_EXCEPTIONS__ -fms-extensions -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-SEH-X64 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-DWARF +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-DWARF // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ @@ -23,9 +20,6 @@ extern void g(); // CHECK-GNU-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) // CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) -// CHECK-WIN-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) void f() { try { diff --git a/test/CodeGenObjC/personality.m b/test/CodeGenObjC/personality.m index 4176394954..66b489b172 100644 --- a/test/CodeGenObjC/personality.m +++ b/test/CodeGenObjC/personality.m @@ -12,20 +12,13 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-DWARF @@ -57,9 +50,6 @@ void g(void); // CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*) // CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) // CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) diff --git a/test/CodeGenObjCXX/personality.mm b/test/CodeGenObjCXX/personality.mm index c2b4789c2e..d64ce2944a 100644 --- a/test/CodeGenObjCXX/personality.mm +++ b/test/CodeGenObjCXX/personality.mm @@ -26,31 +26,13 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-DWARF -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE @@ -99,12 +81,7 @@ void g(void); // CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*) // CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-SEH: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-MACOSX-FRAGILE-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) // CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-NS-DWARF: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) -// CHECK-WIN-NS-SJLJ: personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) void f(void) { @try { diff --git a/test/Frontend/windows-exceptions.cpp b/test/Frontend/windows-exceptions.cpp new file mode 100644 index 0000000000..56316872be --- /dev/null +++ b/test/Frontend/windows-exceptions.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple i686--windows-msvc -fsyntax-only %s +// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fdwarf-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-DWARF %s +// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fseh-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-SEH %s +// RUN: not %clang_cc1 -triple i686--windows-msvc -fsyntax-only -fsjlj-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X86-SJLJ %s + +// RUN: %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only %s +// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fdwarf-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-DWARF %s +// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fseh-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-SEH %s +// RUN: not %clang_cc1 -triple x86_64--windows-msvc -fsyntax-only -fsjlj-exceptions %s 2>&1 | FileCheck -check-prefix=MSVC-X64-SJLJ %s + +// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only %s +// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fdwarf-exceptions %s +// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fseh-exceptions %s +// RUN: %clang_cc1 -triple i686--windows-gnu -fsyntax-only -fsjlj-exceptions %s + +// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only %s +// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fdwarf-exceptions %s +// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fseh-exceptions %s +// RUN: %clang_cc1 -triple x86_64--windows-gnu -fsyntax-only -fsjlj-exceptions %s + +// MSVC-X86-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'i686--windows-msvc' +// MSVC-X86-SEH: error: invalid exception model 'fseh-exceptions' for target 'i686--windows-msvc' +// MSVC-X86-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'i686--windows-msvc' + +// MSVC-X64-DWARF: error: invalid exception model 'fdwarf-exceptions' for target 'x86_64--windows-msvc' +// MSVC-X64-SEH: error: invalid exception model 'fseh-exceptions' for target 'x86_64--windows-msvc' +// MSVC-X64-SJLJ: error: invalid exception model 'fsjlj-exceptions' for target 'x86_64--windows-msvc' -- GitLab From 93994679596d37b178ddf735521adbacd8b5faac Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 7 Jun 2018 23:03:08 +0000 Subject: [PATCH 0054/1023] [X86] Add builtins for shuff32x4/shuff64x2/shufi32x4/shuff64x2 to enable target feature checking and immediate range checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334244 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 8 +++++ lib/CodeGen/CGBuiltin.cpp | 29 +++++++++++++++ lib/Headers/avx512fintrin.h | 56 +++++------------------------ lib/Headers/avx512vlintrin.h | 36 +++++-------------- lib/Sema/SemaChecking.cpp | 8 +++++ test/CodeGen/avx512f-builtins.c | 6 ++-- test/CodeGen/avx512vl-builtins.c | 6 ++-- 7 files changed, 67 insertions(+), 82 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index e3a0e4e1ab..9e56028281 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1500,6 +1500,14 @@ TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc", "nc TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc", "nc", "avx512vl") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 0a410da4b9..69f7d91b38 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9291,6 +9291,35 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "valign"); } + case X86::BI__builtin_ia32_shuf_f32x4_256: + case X86::BI__builtin_ia32_shuf_f64x2_256: + case X86::BI__builtin_ia32_shuf_i32x4_256: + case X86::BI__builtin_ia32_shuf_i64x2_256: + case X86::BI__builtin_ia32_shuf_f32x4: + case X86::BI__builtin_ia32_shuf_f64x2: + case X86::BI__builtin_ia32_shuf_i32x4: + case X86::BI__builtin_ia32_shuf_i64x2: { + unsigned Imm = cast(Ops[2])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + unsigned NumLanes = Ty->getPrimitiveSizeInBits() == 512 ? 4 : 2; + unsigned NumLaneElts = NumElts / NumLanes; + + uint32_t Indices[16]; + for (unsigned l = 0; l != NumElts; l += NumLaneElts) { + unsigned Index = (Imm % NumLanes) * NumLaneElts; + Imm /= NumLanes; // Discard the bits we just used. + if (l >= (NumElts / 2)) + Index += NumElts; // Switch to other source. + for (unsigned i = 0; i != NumLaneElts; ++i) { + Indices[l + i] = Index + i; + } + } + + return Builder.CreateShuffleVector(Ops[0], Ops[1], + makeArrayRef(Indices, NumElts), + "shuf"); + } case X86::BI__builtin_ia32_vperm2f128_pd256: case X86::BI__builtin_ia32_vperm2f128_ps256: diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 5132edde65..074bf61c7b 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -6829,24 +6829,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) } #define _mm512_shuffle_f32x4(A, B, imm) \ - (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - 0 + ((((imm) >> 0) & 0x3) * 4), \ - 1 + ((((imm) >> 0) & 0x3) * 4), \ - 2 + ((((imm) >> 0) & 0x3) * 4), \ - 3 + ((((imm) >> 0) & 0x3) * 4), \ - 0 + ((((imm) >> 2) & 0x3) * 4), \ - 1 + ((((imm) >> 2) & 0x3) * 4), \ - 2 + ((((imm) >> 2) & 0x3) * 4), \ - 3 + ((((imm) >> 2) & 0x3) * 4), \ - 16 + ((((imm) >> 4) & 0x3) * 4), \ - 17 + ((((imm) >> 4) & 0x3) * 4), \ - 18 + ((((imm) >> 4) & 0x3) * 4), \ - 19 + ((((imm) >> 4) & 0x3) * 4), \ - 16 + ((((imm) >> 6) & 0x3) * 4), \ - 17 + ((((imm) >> 6) & 0x3) * 4), \ - 18 + ((((imm) >> 6) & 0x3) * 4), \ - 19 + ((((imm) >> 6) & 0x3) * 4)) + (__m512)__builtin_ia32_shuf_f32x4((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(imm)) #define _mm512_mask_shuffle_f32x4(W, U, A, B, imm) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ @@ -6859,16 +6843,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v16sf)_mm512_setzero_ps()) #define _mm512_shuffle_f64x2(A, B, imm) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - 0 + ((((imm) >> 0) & 0x3) * 2), \ - 1 + ((((imm) >> 0) & 0x3) * 2), \ - 0 + ((((imm) >> 2) & 0x3) * 2), \ - 1 + ((((imm) >> 2) & 0x3) * 2), \ - 8 + ((((imm) >> 4) & 0x3) * 2), \ - 9 + ((((imm) >> 4) & 0x3) * 2), \ - 8 + ((((imm) >> 6) & 0x3) * 2), \ - 9 + ((((imm) >> 6) & 0x3) * 2)) + (__m512d)__builtin_ia32_shuf_f64x2((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(imm)) #define _mm512_mask_shuffle_f64x2(W, U, A, B, imm) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -6881,16 +6857,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v8df)_mm512_setzero_pd()) #define _mm512_shuffle_i32x4(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - 0 + ((((imm) >> 0) & 0x3) * 2), \ - 1 + ((((imm) >> 0) & 0x3) * 2), \ - 0 + ((((imm) >> 2) & 0x3) * 2), \ - 1 + ((((imm) >> 2) & 0x3) * 2), \ - 8 + ((((imm) >> 4) & 0x3) * 2), \ - 9 + ((((imm) >> 4) & 0x3) * 2), \ - 8 + ((((imm) >> 6) & 0x3) * 2), \ - 9 + ((((imm) >> 6) & 0x3) * 2)) + (__m512i)__builtin_ia32_shuf_i32x4((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B), (int)(imm)) #define _mm512_mask_shuffle_i32x4(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ @@ -6903,16 +6871,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v16si)_mm512_setzero_si512()) #define _mm512_shuffle_i64x2(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - 0 + ((((imm) >> 0) & 0x3) * 2), \ - 1 + ((((imm) >> 0) & 0x3) * 2), \ - 0 + ((((imm) >> 2) & 0x3) * 2), \ - 1 + ((((imm) >> 2) & 0x3) * 2), \ - 8 + ((((imm) >> 4) & 0x3) * 2), \ - 9 + ((((imm) >> 4) & 0x3) * 2), \ - 8 + ((((imm) >> 6) & 0x3) * 2), \ - 9 + ((((imm) >> 6) & 0x3) * 2)) + (__m512i)__builtin_ia32_shuf_i64x2((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(imm)) #define _mm512_mask_shuffle_i64x2(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index e5963720fe..49198ec533 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -6465,16 +6465,8 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) #define _mm256_shuffle_f32x4(A, B, imm) \ - (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \ - (__v8sf)(__m256)(B), \ - 0 + ((((imm) >> 0) & 0x1) * 4), \ - 1 + ((((imm) >> 0) & 0x1) * 4), \ - 2 + ((((imm) >> 0) & 0x1) * 4), \ - 3 + ((((imm) >> 0) & 0x1) * 4), \ - 8 + ((((imm) >> 1) & 0x1) * 4), \ - 9 + ((((imm) >> 1) & 0x1) * 4), \ - 10 + ((((imm) >> 1) & 0x1) * 4), \ - 11 + ((((imm) >> 1) & 0x1) * 4)) + (__m256)__builtin_ia32_shuf_f32x4_256((__v8sf)(__m256)(A), \ + (__v8sf)(__m256)(B), (int)(imm)) #define _mm256_mask_shuffle_f32x4(W, U, A, B, imm) \ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \ @@ -6487,12 +6479,8 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) (__v8sf)_mm256_setzero_ps()) #define _mm256_shuffle_f64x2(A, B, imm) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \ - (__v4df)(__m256d)(B), \ - 0 + ((((imm) >> 0) & 0x1) * 2), \ - 1 + ((((imm) >> 0) & 0x1) * 2), \ - 4 + ((((imm) >> 1) & 0x1) * 2), \ - 5 + ((((imm) >> 1) & 0x1) * 2)) + (__m256d)__builtin_ia32_shuf_f64x2_256((__v4df)(__m256d)(A), \ + (__v4df)(__m256d)(B), (int)(imm)) #define _mm256_mask_shuffle_f64x2(W, U, A, B, imm) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ @@ -6505,12 +6493,8 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) (__v4df)_mm256_setzero_pd()) #define _mm256_shuffle_i32x4(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - 0 + ((((imm) >> 0) & 0x1) * 2), \ - 1 + ((((imm) >> 0) & 0x1) * 2), \ - 4 + ((((imm) >> 1) & 0x1) * 2), \ - 5 + ((((imm) >> 1) & 0x1) * 2)) + (__m256i)__builtin_ia32_shuf_i32x4_256((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B), (int)(imm)) #define _mm256_mask_shuffle_i32x4(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ @@ -6523,12 +6507,8 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) (__v8si)_mm256_setzero_si256()) #define _mm256_shuffle_i64x2(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - 0 + ((((imm) >> 0) & 0x1) * 2), \ - 1 + ((((imm) >> 0) & 0x1) * 2), \ - 4 + ((((imm) >> 1) & 0x1) * 2), \ - 5 + ((((imm) >> 1) & 0x1) * 2)) + (__m256i)__builtin_ia32_shuf_i64x2_256((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), (int)(imm)) #define _mm256_mask_shuffle_i64x2(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 11164df173..03a117f435 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2627,6 +2627,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_set_v4hi: case X86::BI__builtin_ia32_vec_set_v4si: case X86::BI__builtin_ia32_vec_set_v4di: + case X86::BI__builtin_ia32_shuf_f32x4_256: + case X86::BI__builtin_ia32_shuf_f64x2_256: + case X86::BI__builtin_ia32_shuf_i32x4_256: + case X86::BI__builtin_ia32_shuf_i64x2_256: i = 2; l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: @@ -2761,6 +2765,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_alignq256: case X86::BI__builtin_ia32_vcomisd: case X86::BI__builtin_ia32_vcomiss: + case X86::BI__builtin_ia32_shuf_f32x4: + case X86::BI__builtin_ia32_shuf_f64x2: + case X86::BI__builtin_ia32_shuf_i32x4: + case X86::BI__builtin_ia32_shuf_i64x2: case X86::BI__builtin_ia32_dbpsadbw128_mask: case X86::BI__builtin_ia32_dbpsadbw256_mask: case X86::BI__builtin_ia32_dbpsadbw512_mask: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index a6f7e17aa6..ce324d7b8d 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -4860,20 +4860,20 @@ __m512d test_mm512_maskz_shuffle_f64x2(__mmask8 __U, __m512d __A, __m512d __B) { __m512i test_mm512_shuffle_i32x4(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shuffle_i32x4 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> return _mm512_shuffle_i32x4(__A, __B, 4); } __m512i test_mm512_mask_shuffle_i32x4(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shuffle_i32x4 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_shuffle_i32x4(__W, __U, __A, __B, 4); } __m512i test_mm512_maskz_shuffle_i32x4(__mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shuffle_i32x4 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_shuffle_i32x4(__U, __A, __B, 4); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 58af2b43b9..9e09096692 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -6071,20 +6071,20 @@ __m256d test_mm256_maskz_shuffle_f64x2(__mmask8 __U, __m256d __A, __m256d __B) { __m256i test_mm256_shuffle_i32x4(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shuffle_i32x4 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> return _mm256_shuffle_i32x4(__A, __B, 3); } __m256i test_mm256_mask_shuffle_i32x4(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shuffle_i32x4 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_shuffle_i32x4(__W, __U, __A, __B, 3); } __m256i test_mm256_maskz_shuffle_i32x4(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shuffle_i32x4 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_shuffle_i32x4(__U, __A, __B, 3); } -- GitLab From 1efc61399759e092c2fea20d27d6da707a0db1b9 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 00:00:21 +0000 Subject: [PATCH 0055/1023] [X86] Add builtins for blend with immediate control to enforce target feature requirements and check immediate range. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334249 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 8 ++++++ lib/CodeGen/CGBuiltin.cpp | 21 +++++++++++++++ lib/Headers/avx2intrin.h | 40 +++++------------------------ lib/Headers/avxintrin.h | 20 +++------------ lib/Headers/smmintrin.h | 25 +++++------------- lib/Sema/SemaChecking.cpp | 8 ++++++ test/CodeGen/avx-builtins.c | 2 +- test/CodeGen/avx2-builtins.c | 2 +- 8 files changed, 55 insertions(+), 71 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 9e56028281..6f952bc061 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -369,6 +369,9 @@ TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "nc", "ssse3") TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "nc", "sse4.1") TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "nc", "sse4.1") @@ -477,6 +480,8 @@ TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "nc", "avx") @@ -554,6 +559,7 @@ TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "nc", "avx2") @@ -603,6 +609,8 @@ TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "nc", "avx2") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 69f7d91b38..0002058495 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9235,6 +9235,27 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); } + case X86::BI__builtin_ia32_pblendw128: + case X86::BI__builtin_ia32_blendpd: + case X86::BI__builtin_ia32_blendps: + case X86::BI__builtin_ia32_blendpd256: + case X86::BI__builtin_ia32_blendps256: + case X86::BI__builtin_ia32_pblendw256: + case X86::BI__builtin_ia32_pblendd128: + case X86::BI__builtin_ia32_pblendd256: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + unsigned Imm = cast(Ops[2])->getZExtValue(); + + uint32_t Indices[16]; + // If there are more than 8 elements, the immediate is used twice so make + // sure we handle that. + for (unsigned i = 0; i != NumElts; ++i) + Indices[i] = ((Imm >> (i % 8)) & 0x1) ? NumElts + i : i; + + return Builder.CreateShuffleVector(Ops[1], Ops[0], + makeArrayRef(Indices, NumElts), + "blend"); + } case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: { diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 9371fcb949..d1c530693b 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -170,24 +170,8 @@ _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M) } #define _mm256_blend_epi16(V1, V2, M) \ - (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(V1), \ - (__v16hi)(__m256i)(V2), \ - (((M) & 0x01) ? 16 : 0), \ - (((M) & 0x02) ? 17 : 1), \ - (((M) & 0x04) ? 18 : 2), \ - (((M) & 0x08) ? 19 : 3), \ - (((M) & 0x10) ? 20 : 4), \ - (((M) & 0x20) ? 21 : 5), \ - (((M) & 0x40) ? 22 : 6), \ - (((M) & 0x80) ? 23 : 7), \ - (((M) & 0x01) ? 24 : 8), \ - (((M) & 0x02) ? 25 : 9), \ - (((M) & 0x04) ? 26 : 10), \ - (((M) & 0x08) ? 27 : 11), \ - (((M) & 0x10) ? 28 : 12), \ - (((M) & 0x20) ? 29 : 13), \ - (((M) & 0x40) ? 30 : 14), \ - (((M) & 0x80) ? 31 : 15)) + (__m256i)__builtin_ia32_pblendw256((__v16hi)(__m256i)(V1), \ + (__v16hi)(__m256i)(V2), (int)(M)) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_cmpeq_epi8(__m256i __a, __m256i __b) @@ -809,24 +793,12 @@ _mm256_broadcastsi128_si256(__m128i __X) } #define _mm_blend_epi32(V1, V2, M) \ - (__m128i)__builtin_shufflevector((__v4si)(__m128i)(V1), \ - (__v4si)(__m128i)(V2), \ - (((M) & 0x01) ? 4 : 0), \ - (((M) & 0x02) ? 5 : 1), \ - (((M) & 0x04) ? 6 : 2), \ - (((M) & 0x08) ? 7 : 3)) + (__m128i)__builtin_ia32_pblendd128((__v4si)(__m128i)(V1), \ + (__v4si)(__m128i)(V2), (int)(M)) #define _mm256_blend_epi32(V1, V2, M) \ - (__m256i)__builtin_shufflevector((__v8si)(__m256i)(V1), \ - (__v8si)(__m256i)(V2), \ - (((M) & 0x01) ? 8 : 0), \ - (((M) & 0x02) ? 9 : 1), \ - (((M) & 0x04) ? 10 : 2), \ - (((M) & 0x08) ? 11 : 3), \ - (((M) & 0x10) ? 12 : 4), \ - (((M) & 0x20) ? 13 : 5), \ - (((M) & 0x40) ? 14 : 6), \ - (((M) & 0x80) ? 15 : 7)) + (__m256i)__builtin_ia32_pblendd256((__v8si)(__m256i)(V1), \ + (__v8si)(__m256i)(V2), (int)(M)) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_broadcastb_epi8(__m128i __X) diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 883b2e350d..7e3c51ffb6 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -1355,12 +1355,8 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// operand \a V2 is copied to the same position in the destination. /// \returns A 256-bit vector of [4 x double] containing the copied values. #define _mm256_blend_pd(V1, V2, M) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V1), \ - (__v4df)(__m256d)(V2), \ - (((M) & 0x01) ? 4 : 0), \ - (((M) & 0x02) ? 5 : 1), \ - (((M) & 0x04) ? 6 : 2), \ - (((M) & 0x08) ? 7 : 3)) + (__m256d)__builtin_ia32_blendpd256((__v4df)(__m256d)(V1), \ + (__v4df)(__m256d)(V2), (int)(M)) /// Merges 32-bit single-precision data values stored in either of the /// two 256-bit vectors of [8 x float], as specified by the immediate @@ -1387,16 +1383,8 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// operand \a V2 is copied to the same position in the destination. /// \returns A 256-bit vector of [8 x float] containing the copied values. #define _mm256_blend_ps(V1, V2, M) \ - (__m256)__builtin_shufflevector((__v8sf)(__m256)(V1), \ - (__v8sf)(__m256)(V2), \ - (((M) & 0x01) ? 8 : 0), \ - (((M) & 0x02) ? 9 : 1), \ - (((M) & 0x04) ? 10 : 2), \ - (((M) & 0x08) ? 11 : 3), \ - (((M) & 0x10) ? 12 : 4), \ - (((M) & 0x20) ? 13 : 5), \ - (((M) & 0x40) ? 14 : 6), \ - (((M) & 0x80) ? 15 : 7)) + (__m256)__builtin_ia32_blendps256((__v8sf)(__m256)(V1), \ + (__v8sf)(__m256)(V2), (int)(M)) /// Merges 64-bit double-precision data values stored in either of the /// two 256-bit vectors of [4 x double], as specified by the 256-bit vector diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h index b3084562a0..7ccb1a37f5 100644 --- a/lib/Headers/smmintrin.h +++ b/lib/Headers/smmintrin.h @@ -390,10 +390,8 @@ /// is copied to the same position in the result. /// \returns A 128-bit vector of [2 x double] containing the copied values. #define _mm_blend_pd(V1, V2, M) \ - (__m128d)__builtin_shufflevector((__v2df)(__m128d)(V1), \ - (__v2df)(__m128d)(V2), \ - (((M) & 0x01) ? 2 : 0), \ - (((M) & 0x02) ? 3 : 1)) + (__m128d) __builtin_ia32_blendpd ((__v2df)(__m128d)(V1), \ + (__v2df)(__m128d)(V2), (int)(M)) /// Returns a 128-bit vector of [4 x float] where the values are selected /// from either the first or second operand as specified by the third @@ -420,11 +418,8 @@ /// is copied to the same position in the result. /// \returns A 128-bit vector of [4 x float] containing the copied values. #define _mm_blend_ps(V1, V2, M) \ - (__m128)__builtin_shufflevector((__v4sf)(__m128)(V1), (__v4sf)(__m128)(V2), \ - (((M) & 0x01) ? 4 : 0), \ - (((M) & 0x02) ? 5 : 1), \ - (((M) & 0x04) ? 6 : 2), \ - (((M) & 0x08) ? 7 : 3)) + (__m128) __builtin_ia32_blendps ((__v4sf)(__m128)(V1), \ + (__v4sf)(__m128)(V2), (int)(M)) /// Returns a 128-bit vector of [2 x double] where the values are /// selected from either the first or second operand as specified by the @@ -532,16 +527,8 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M) /// is copied to the same position in the result. /// \returns A 128-bit vector of [8 x i16] containing the copied values. #define _mm_blend_epi16(V1, V2, M) \ - (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(V1), \ - (__v8hi)(__m128i)(V2), \ - (((M) & 0x01) ? 8 : 0), \ - (((M) & 0x02) ? 9 : 1), \ - (((M) & 0x04) ? 10 : 2), \ - (((M) & 0x08) ? 11 : 3), \ - (((M) & 0x10) ? 12 : 4), \ - (((M) & 0x20) ? 13 : 5), \ - (((M) & 0x40) ? 14 : 6), \ - (((M) & 0x80) ? 15 : 7)) + (__m128i) __builtin_ia32_pblendw128 ((__v8hi)(__m128i)(V1), \ + (__v8hi)(__m128i)(V2), (int)(M)) /* SSE4 Dword Multiply Instructions. */ /// Multiples corresponding elements of two 128-bit vectors of [4 x i32] diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 03a117f435..db004607cc 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2624,6 +2624,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { i = 1; l = 0; u = 7; break; case X86::BI__builtin_ia32_sha1rnds4: + case X86::BI__builtin_ia32_blendpd: case X86::BI__builtin_ia32_vec_set_v4hi: case X86::BI__builtin_ia32_vec_set_v4si: case X86::BI__builtin_ia32_vec_set_v4di: @@ -2683,6 +2684,9 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_ext_v16hi: i = 1; l = 0; u = 15; break; + case X86::BI__builtin_ia32_pblendd128: + case X86::BI__builtin_ia32_blendps: + case X86::BI__builtin_ia32_blendpd256: case X86::BI__builtin_ia32_roundss: case X86::BI__builtin_ia32_roundsd: case X86::BI__builtin_ia32_rangepd128_mask: @@ -2754,6 +2758,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_fpclassss_mask: i = 1; l = 0; u = 255; break; + case X86::BI__builtin_ia32_pblendw128: + case X86::BI__builtin_ia32_pblendw256: + case X86::BI__builtin_ia32_blendps256: + case X86::BI__builtin_ia32_pblendd256: case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index 43c502f47f..e40a03d8cf 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -59,7 +59,7 @@ __m256 test_mm256_andnot_ps(__m256 A, __m256 B) { __m256d test_mm256_blend_pd(__m256d A, __m256d B) { // CHECK-LABEL: test_mm256_blend_pd // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> - return _mm256_blend_pd(A, B, 0x35); + return _mm256_blend_pd(A, B, 0x05); } __m256 test_mm256_blend_ps(__m256 A, __m256 B) { diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index b647ca595b..bd7e3a9596 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -141,7 +141,7 @@ __m128i test_mm_blend_epi32(__m128i a, __m128i b) { // CHECK-LABEL: test_mm_blend_epi32 // CHECK-NOT: @llvm.x86.avx2.pblendd.128 // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> - return _mm_blend_epi32(a, b, 0x35); + return _mm_blend_epi32(a, b, 0x05); } __m256i test_mm256_blend_epi32(__m256i a, __m256i b) { -- GitLab From e8805d277d9619804fc65f9c5ac69b2e7f8002ed Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Fri, 8 Jun 2018 00:30:00 +0000 Subject: [PATCH 0056/1023] Reapply "[Parse] Use CapturedStmt for @finally on MSVC" This reapplies r334224 and adds explicit triples to some tests to fix them on Windows (where otherwise they would have run with the default windows-msvc triple, which I'm changing the behavior for). Original commit message: The body of a `@finally` needs to be executed on both exceptional and non-exceptional paths. On landingpad platforms, this is straightforward: the `@finally` body is emitted as a normal (non-exceptional) cleanup, and then a catch-all is emitted which branches to that cleanup (the cleanup has code to conditionally re-throw based on a flag which is set by the catch-all). Unfortunately, we can't use the same approach for MSVC exceptions, where the catch-all will be emitted as a catchpad. We can't just branch to the cleanup from within the catchpad, since we can only exit it via a catchret, at which point the exception is destroyed and we can't rethrow. We could potentially emit the finally body inside the catchpad and have the normal cleanup path somehow branch into it, but that would require some new IR construct that could branch into a catchpad. Instead, after discussing it with Reid Kleckner, we decided that frontend outlining was the best approach, similar to how SEH `__finally` works today. We decided to use CapturedStmt (which was also suggested by Reid) rather than CaptureFinder (which is what `__finally` uses) since the latter doesn't handle a lot of cases we care about, e.g. self accesses, property accesses, block captures, etc. Extending CaptureFinder to handle those additional cases proved unwieldy, whereas CapturedStmt already took care of all of those. In theory `__finally` could also be moved over to CapturedStmt, which would remove some existing limitations (e.g. the inability to capture this), although CaptureFinder would still be needed for SEH filters. The one case supported by `@finally` but not CapturedStmt (or CaptureFinder for that matter) is arbitrary control flow out of the `@finally`, e.g. having a return statement inside a `@finally`. We can add that support as a follow-up, but in practice we've found it to be used very rarely anyway. Differential Revision: https://reviews.llvm.org/D47564 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334251 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Stmt.h | 2 +- include/clang/Basic/CapturedStmt.h | 1 + include/clang/Sema/ScopeInfo.h | 2 ++ lib/Parse/ParseObjc.cpp | 15 ++++++++++++++- test/Coverage/ast-printing.m | 6 +++--- test/PCH/objc_stmts.m | 10 +++++----- test/Parser/objc-try-catch-1.m | 4 ++-- test/Rewriter/rewrite-modern-try-finally.m | 4 ++-- test/SemaObjC/finally-msvc.m | 14 ++++++++++++++ test/SemaObjC/scope-check.m | 2 +- 10 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 test/SemaObjC/finally-msvc.m diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 03c808d394..3b678dcc75 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -2133,7 +2133,7 @@ private: /// The pointer part is the implicit the outlined function and the /// int part is the captured region kind, 'CR_Default' etc. - llvm::PointerIntPair CapDeclAndKind; + llvm::PointerIntPair CapDeclAndKind; /// The record for captured variables, a RecordDecl or CXXRecordDecl. RecordDecl *TheRecordDecl = nullptr; diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h index 6c8d6edab0..324e1b1d3d 100644 --- a/include/clang/Basic/CapturedStmt.h +++ b/include/clang/Basic/CapturedStmt.h @@ -16,6 +16,7 @@ namespace clang { /// The different kinds of captured statement. enum CapturedRegionKind { CR_Default, + CR_ObjCAtFinally, CR_OpenMP }; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index b0f6bac994..fa1b1037a2 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -748,6 +748,8 @@ public: switch (CapRegionKind) { case CR_Default: return "default captured statement"; + case CR_ObjCAtFinally: + return "Objective-C @finally statement"; case CR_OpenMP: return "OpenMP region"; } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 6ca0ad855f..ff33d5fb96 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2585,13 +2585,26 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ParseScope FinallyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + bool ShouldCapture = + getTargetInfo().getTriple().isWindowsMSVCEnvironment(); + if (ShouldCapture) + Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), + CR_ObjCAtFinally, 1); + StmtResult FinallyBody(true); if (Tok.is(tok::l_brace)) FinallyBody = ParseCompoundStatementBody(); else Diag(Tok, diag::err_expected) << tok::l_brace; - if (FinallyBody.isInvalid()) + + if (FinallyBody.isInvalid()) { FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); + if (ShouldCapture) + Actions.ActOnCapturedRegionError(); + } else if (ShouldCapture) { + FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); + } + FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, FinallyBody.get()); catch_or_finally_seen = true; diff --git a/test/Coverage/ast-printing.m b/test/Coverage/ast-printing.m index 81c3a6b0ba..d9909b2859 100644 --- a/test/Coverage/ast-printing.m +++ b/test/Coverage/ast-printing.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -fobjc-exceptions %s -// RUN: %clang_cc1 -ast-print -fobjc-exceptions %s -// RUN: %clang_cc1 -ast-dump -fobjc-exceptions %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -fobjc-exceptions %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -ast-print -fobjc-exceptions %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -ast-dump -fobjc-exceptions %s #include "objc-language-features.inc" diff --git a/test/PCH/objc_stmts.m b/test/PCH/objc_stmts.m index 8deb14a815..ee7b780731 100644 --- a/test/PCH/objc_stmts.m +++ b/test/PCH/objc_stmts.m @@ -1,11 +1,11 @@ // Test this without pch. -// RUN: %clang_cc1 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s -// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-print -fobjc-exceptions -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include %S/objc_stmts.h -ast-print -fobjc-exceptions -o - %s | FileCheck %s // Test with pch. -// RUN: %clang_cc1 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h -// RUN: %clang_cc1 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s -// RUN: %clang_cc1 -include-pch %t -ast-print -fobjc-exceptions -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -include-pch %t -ast-print -fobjc-exceptions -o - %s | FileCheck %s // CHECK: @catch(A *a) // CHECK: @catch(B *b) diff --git a/test/Parser/objc-try-catch-1.m b/test/Parser/objc-try-catch-1.m index a3220ebc64..3a60148c8b 100644 --- a/test/Parser/objc-try-catch-1.m +++ b/test/Parser/objc-try-catch-1.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions %s -// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -x objective-c++ %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions -x objective-c++ %s void * proc(); @interface NSConstantString diff --git a/test/Rewriter/rewrite-modern-try-finally.m b/test/Rewriter/rewrite-modern-try-finally.m index 500133b861..41737e95f0 100644 --- a/test/Rewriter/rewrite-modern-try-finally.m +++ b/test/Rewriter/rewrite-modern-try-finally.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -fcxx-exceptions -fexceptions -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp typedef struct objc_class *Class; typedef struct objc_object { diff --git a/test/SemaObjC/finally-msvc.m b/test/SemaObjC/finally-msvc.m new file mode 100644 index 0000000000..5db08a7f71 --- /dev/null +++ b/test/SemaObjC/finally-msvc.m @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple i686--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64--windows-msvc -fexceptions -fobjc-exceptions -ast-dump %s 2>&1 | FileCheck %s + +void f() { + @try { + } @finally { + } +} + +// CHECK: ObjCAtFinallyStmt +// CHECK-NEXT: CapturedStmt +// CHECK-NEXT: CapturedDecl +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ImplicitParamDecl diff --git a/test/SemaObjC/scope-check.m b/test/SemaObjC/scope-check.m index b52e7a06ff..b23edd1240 100644 --- a/test/SemaObjC/scope-check.m +++ b/test/SemaObjC/scope-check.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-exceptions -Wno-objc-root-class %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -fsyntax-only -verify -fobjc-exceptions -Wno-objc-root-class %s @class A, B, C; -- GitLab From 823b8b1afba83604564779a568062eb3d51675e0 Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Fri, 8 Jun 2018 00:33:35 +0000 Subject: [PATCH 0057/1023] [clang-fuzzer] Made loop_proto more "vectorizable". Edited loop_proto and its converter to make more "vectorizable" code according to kcc's comment in D47666 - Removed all while loops - Can only index into array with induction variable Patch By: emmettneyman Differential Revision: https://reviews.llvm.org/D47920 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334252 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/cxx_loop_proto.proto | 28 ++++------------- .../proto-to-cxx/loop_proto_to_cxx.cpp | 30 +++++-------------- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto index 5dae576940..98b9bbf2a0 100644 --- a/tools/clang-fuzzer/cxx_loop_proto.proto +++ b/tools/clang-fuzzer/cxx_loop_proto.proto @@ -10,23 +10,14 @@ /// \file /// This file describes a subset of C++ as a protobuf. It is used to /// more easily find interesting inputs for fuzzing Clang. This subset -/// extends the one defined in cxx_proto.proto by adding the option that -/// a VarRef can use the for loop's counter variable. +/// differs from the one defined in cxx_proto.proto by eliminating while +/// loops and Lvalues. The goal is that the C++ code generated will be +/// more likely to stress the LLVM loop vectorizer. /// //===----------------------------------------------------------------------===// - syntax = "proto2"; -message VarRef { - required int32 varnum = 1; - required bool is_loop_var = 2; -} - -message Lvalue { - required VarRef varref = 1; -} - message Const { required int32 val = 1; } @@ -55,34 +46,25 @@ message BinaryOp { message Rvalue { oneof rvalue_oneof { - VarRef varref = 1; - Const cons = 2; - BinaryOp binop = 3; + Const cons = 1; + BinaryOp binop = 2; } } message AssignmentStatement { - required Lvalue lvalue = 1; required Rvalue rvalue = 2; } - message IfElse { required Rvalue cond = 1; required StatementSeq if_body = 2; required StatementSeq else_body = 3; } -message While { - required Rvalue cond = 1; - required StatementSeq body = 2; -} - message Statement { oneof stmt_oneof { AssignmentStatement assignment = 1; IfElse ifelse = 2; - While while_loop = 3; } } diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp index a0007fb6f9..fa6ba307ac 100644 --- a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp @@ -7,10 +7,13 @@ // //===----------------------------------------------------------------------===// // -// Implements functions for converting between protobufs and C++. Extends +// Implements functions for converting between protobufs and C++. Differs from // proto_to_cxx.cpp by wrapping all the generated C++ code in a single for // loop. Also coutputs a different function signature that includes a -// size_t parameter for the loop to use. +// size_t parameter for the loop to use. The C++ code generated is meant to +// stress the LLVM loop vectorizer. +// +// Still a work in progress. // //===----------------------------------------------------------------------===// @@ -33,19 +36,7 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x); std::ostream &operator<<(std::ostream &os, const Const &x) { return os << "(" << x.val() << ")"; } -std::ostream &operator<<(std::ostream &os, const VarRef &x) { - if (x.is_loop_var()) { - return os << "a[loop_ctr]"; - } else { - return os << "a[" << static_cast(x.varnum()) << " % s]"; - } -} -std::ostream &operator<<(std::ostream &os, const Lvalue &x) { - return os << x.varref(); -} std::ostream &operator<<(std::ostream &os, const Rvalue &x) { - if (x.has_varref()) - return os << x.varref(); if (x.has_cons()) return os << x.cons(); if (x.has_binop()) @@ -101,23 +92,18 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { return os << x.right() << ")"; } std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { - return os << x.lvalue() << "=" << x.rvalue(); + return os << "a[i]=" << x.rvalue(); } std::ostream &operator<<(std::ostream &os, const IfElse &x) { return os << "if (" << x.cond() << "){\n" << x.if_body() << "} else { \n" << x.else_body() << "}\n"; } -std::ostream &operator<<(std::ostream &os, const While &x) { - return os << "while (" << x.cond() << "){\n" << x.body() << "}\n"; -} std::ostream &operator<<(std::ostream &os, const Statement &x) { if (x.has_assignment()) return os << x.assignment() << ";\n"; if (x.has_ifelse()) return os << x.ifelse(); - if (x.has_while_loop()) - return os << x.while_loop(); return os << "(void)0;\n"; } std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { @@ -127,7 +113,7 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { } std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { return os << "void foo(int *a, size_t s) {\n" - << "for (int loop_ctr = 0; loop_ctr < s; loop_ctr++){\n" + << "for (int i=0; i Date: Fri, 8 Jun 2018 00:41:01 +0000 Subject: [PATCH 0058/1023] [CodeGen] Always use MSVC personality for windows-msvc targets The windows-msvc target is meant to be ABI compatible with MSVC, including the exception handling. Ensure that a windows-msvc triple always equates to the MSVC personality being used. This mostly affects the GNUStep and ObjFW Obj-C runtimes. To the best of my knowledge, those are normally not used with windows-msvc triples. I believe WinObjC is based on GNUStep (or it at least uses libobjc2), but that also takes the approach of wrapping Obj-C exceptions in C++ exceptions, so the MSVC personality function is the right one to use there as well. Differential Revision: https://reviews.llvm.org/D47862 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334253 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGException.cpp | 16 ++++++++++------ test/CodeGenObjC/personality.m | 19 +++++++++---------- test/CodeGenObjCXX/personality.mm | 19 +++++++++---------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 27f7eb8d30..c9820c2425 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -117,12 +117,12 @@ EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr }; static const EHPersonality &getCPersonality(const TargetInfo &Target, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); + if (T.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; if (L.SjLjExceptions) return EHPersonality::GNU_C_SJLJ; if (L.DWARFExceptions) return EHPersonality::GNU_C; - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; if (L.SEHExceptions) return EHPersonality::GNU_C_SEH; return EHPersonality::GNU_C; @@ -131,14 +131,15 @@ static const EHPersonality &getCPersonality(const TargetInfo &Target, static const EHPersonality &getObjCPersonality(const TargetInfo &Target, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); + if (T.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + switch (L.ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: return getCPersonality(Target, L); case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; return EHPersonality::NeXT_ObjC; case ObjCRuntime::GNUstep: if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) @@ -158,12 +159,12 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, static const EHPersonality &getCXXPersonality(const TargetInfo &Target, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); + if (T.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; if (L.DWARFExceptions) return EHPersonality::GNU_CPlusPlus; - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; if (L.SEHExceptions) return EHPersonality::GNU_CPlusPlus_SEH; // Wasm EH is a non-MVP feature for now. @@ -178,6 +179,9 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target, /// and Objective-C exceptions are being caught. static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, const LangOptions &L) { + if (Target.getTriple().isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + switch (L.ObjCRuntime.getKind()) { // In the fragile ABI, just use C++ exception handling and hope // they're not doing crazy exception mixing. diff --git a/test/CodeGenObjC/personality.m b/test/CodeGenObjC/personality.m index 66b489b172..0db0803c45 100644 --- a/test/CodeGenObjC/personality.m +++ b/test/CodeGenObjC/personality.m @@ -11,14 +11,14 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE-MINGW-DWARF @@ -49,8 +49,7 @@ void g(void); // CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*) // CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*) -// CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) +// CHECK-WIN-MSVC: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) // CHECK-MACOSX-FRAGILE-MINGW-SEH: personality i8* bitcast (i32 (...)* @__gcc_personality_seh0 to i8*) diff --git a/test/CodeGenObjCXX/personality.mm b/test/CodeGenObjCXX/personality.mm index d64ce2944a..22cfc2c45b 100644 --- a/test/CodeGenObjCXX/personality.mm +++ b/test/CodeGenObjCXX/personality.mm @@ -25,14 +25,14 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fseh-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SEH // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -fsjlj-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW-SJLJ -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MACOSX-FRAGILE -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC -// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-OBJFW +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=objfw -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-MSVC // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fdwarf-exceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=macosx-fragile -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACOSX-FRAGILE @@ -80,8 +80,7 @@ void g(void); // CHECK-OBJFW-SEH: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_seh0 to i8*) // CHECK-OBJFW-SJLJ: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*) -// CHECK-WIN-MACOSX-FRAGILE: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CHECK-WIN-NS: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) +// CHECK-WIN-MSVC: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) void f(void) { @try { -- GitLab From 3abc7713293f9e2b62eea6f9c350ca8c68bd54f6 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 00:59:27 +0000 Subject: [PATCH 0059/1023] [X86] Add builtins for vpermilps/pd instructions to enable target feature checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334256 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 6 ++++++ lib/CodeGen/CGBuiltin.cpp | 27 ++++++++++++++++++++++++++ lib/Headers/avx512fintrin.h | 30 ++--------------------------- lib/Headers/avxintrin.h | 27 ++++---------------------- lib/Sema/SemaChecking.cpp | 6 ++++++ test/CodeGen/avx-builtins.c | 10 +++++----- test/CodeGen/avx512f-builtins.c | 12 ++++++------ test/CodeGen/avx512vl-builtins.c | 16 +++++++-------- 8 files changed, 64 insertions(+), 70 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 6f952bc061..7cc5e6060a 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -499,6 +499,10 @@ TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "nc", "avx") @@ -1470,6 +1474,8 @@ TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilpd512, "V8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilps512, "V16fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi", "nc", "avx512f") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 0002058495..4331005cb3 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9256,6 +9256,33 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "blend"); } + case X86::BI__builtin_ia32_vpermilpd: + case X86::BI__builtin_ia32_vpermilps: + case X86::BI__builtin_ia32_vpermilpd256: + case X86::BI__builtin_ia32_vpermilps256: + case X86::BI__builtin_ia32_vpermilpd512: + case X86::BI__builtin_ia32_vpermilps512: { + uint32_t Imm = cast(Ops[1])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128; + unsigned NumLaneElts = NumElts / NumLanes; + + // Splat the 8-bits of immediate 4 times to help the loop wrap around. + Imm = (Imm & 0xff) * 0x01010101; + + uint32_t Indices[16]; + for (unsigned l = 0; l != NumElts; l += NumLaneElts) { + for (unsigned i = 0; i != NumLaneElts; ++i) { + Indices[i + l] = (Imm % NumLaneElts) + l; + Imm /= NumLaneElts; + } + } + + return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), + makeArrayRef(Indices, NumElts), + "permil"); + } case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: { diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 074bf61c7b..ccc445a6ac 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -6302,16 +6302,7 @@ _mm_cvttss_u64 (__m128 __A) #endif #define _mm512_permute_pd(X, C) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(X), \ - (__v8df)_mm512_undefined_pd(), \ - 0 + (((C) >> 0) & 0x1), \ - 0 + (((C) >> 1) & 0x1), \ - 2 + (((C) >> 2) & 0x1), \ - 2 + (((C) >> 3) & 0x1), \ - 4 + (((C) >> 4) & 0x1), \ - 4 + (((C) >> 5) & 0x1), \ - 6 + (((C) >> 6) & 0x1), \ - 6 + (((C) >> 7) & 0x1)) + (__m512d)__builtin_ia32_vpermilpd512((__v8df)(__m512d)(X), (int)(C)) #define _mm512_mask_permute_pd(W, U, X, C) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -6324,24 +6315,7 @@ _mm_cvttss_u64 (__m128 __A) (__v8df)_mm512_setzero_pd()) #define _mm512_permute_ps(X, C) \ - (__m512)__builtin_shufflevector((__v16sf)(__m512)(X), \ - (__v16sf)_mm512_undefined_ps(), \ - 0 + (((C) >> 0) & 0x3), \ - 0 + (((C) >> 2) & 0x3), \ - 0 + (((C) >> 4) & 0x3), \ - 0 + (((C) >> 6) & 0x3), \ - 4 + (((C) >> 0) & 0x3), \ - 4 + (((C) >> 2) & 0x3), \ - 4 + (((C) >> 4) & 0x3), \ - 4 + (((C) >> 6) & 0x3), \ - 8 + (((C) >> 0) & 0x3), \ - 8 + (((C) >> 2) & 0x3), \ - 8 + (((C) >> 4) & 0x3), \ - 8 + (((C) >> 6) & 0x3), \ - 12 + (((C) >> 0) & 0x3), \ - 12 + (((C) >> 2) & 0x3), \ - 12 + (((C) >> 4) & 0x3), \ - 12 + (((C) >> 6) & 0x3)) + (__m512)__builtin_ia32_vpermilps512((__v16sf)(__m512)(X), (int)(C)) #define _mm512_mask_permute_ps(W, U, X, C) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 7e3c51ffb6..7c85893ba1 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -998,9 +998,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// returned vector. /// \returns A 128-bit vector of [2 x double] containing the copied values. #define _mm_permute_pd(A, C) \ - (__m128d)__builtin_shufflevector((__v2df)(__m128d)(A), \ - (__v2df)_mm_undefined_pd(), \ - ((C) >> 0) & 0x1, ((C) >> 1) & 0x1) + (__m128d)__builtin_ia32_vpermilpd((__v2df)(__m128d)(A), (int)(C)) /// Copies the values in a 256-bit vector of [4 x double] as specified by /// the immediate integer operand. @@ -1040,12 +1038,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// returned vector. /// \returns A 256-bit vector of [4 x double] containing the copied values. #define _mm256_permute_pd(A, C) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \ - (__v4df)_mm256_undefined_pd(), \ - 0 + (((C) >> 0) & 0x1), \ - 0 + (((C) >> 1) & 0x1), \ - 2 + (((C) >> 2) & 0x1), \ - 2 + (((C) >> 3) & 0x1)) + (__m256d)__builtin_ia32_vpermilpd256((__v4df)(__m256d)(A), (int)(C)) /// Copies the values in a 128-bit vector of [4 x float] as specified by /// the immediate integer operand. @@ -1101,10 +1094,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// returned vector. /// \returns A 128-bit vector of [4 x float] containing the copied values. #define _mm_permute_ps(A, C) \ - (__m128)__builtin_shufflevector((__v4sf)(__m128)(A), \ - (__v4sf)_mm_undefined_ps(), \ - ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \ - ((C) >> 4) & 0x3, ((C) >> 6) & 0x3) + (__m128)__builtin_ia32_vpermilps((__v4sf)(__m128)(A), (int)(C)) /// Copies the values in a 256-bit vector of [8 x float] as specified by /// the immediate integer operand. @@ -1196,16 +1186,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// returned vector. /// \returns A 256-bit vector of [8 x float] containing the copied values. #define _mm256_permute_ps(A, C) \ - (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \ - (__v8sf)_mm256_undefined_ps(), \ - 0 + (((C) >> 0) & 0x3), \ - 0 + (((C) >> 2) & 0x3), \ - 0 + (((C) >> 4) & 0x3), \ - 0 + (((C) >> 6) & 0x3), \ - 4 + (((C) >> 0) & 0x3), \ - 4 + (((C) >> 2) & 0x3), \ - 4 + (((C) >> 4) & 0x3), \ - 4 + (((C) >> 6) & 0x3)) + (__m256)__builtin_ia32_vpermilps256((__v8sf)(__m256)(A), (int)(C)) /// Permutes 128-bit data values stored in two 256-bit vectors of /// [4 x double], as specified by the immediate integer operand. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index db004607cc..d16921c6c7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2612,6 +2612,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_set_v2di: i = 2; l = 0; u = 1; break; + case X86::BI__builtin_ia32_vpermilpd: case X86::BI__builtin_ia32_vec_ext_v4hi: case X86::BI__builtin_ia32_vec_ext_v4si: case X86::BI__builtin_ia32_vec_ext_v4sf: @@ -2676,6 +2677,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_set_v8si: i = 2; l = 0; u = 7; break; + case X86::BI__builtin_ia32_vpermilpd256: case X86::BI__builtin_ia32_roundps: case X86::BI__builtin_ia32_roundpd: case X86::BI__builtin_ia32_roundps256: @@ -2721,6 +2723,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_set_v32qi: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_vpermilps: + case X86::BI__builtin_ia32_vpermilps256: + case X86::BI__builtin_ia32_vpermilpd512: + case X86::BI__builtin_ia32_vpermilps512: case X86::BI__builtin_ia32_vcvtps2ph: case X86::BI__builtin_ia32_vcvtps2ph_mask: case X86::BI__builtin_ia32_vcvtps2ph256: diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index e40a03d8cf..cb4b103f46 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -639,32 +639,32 @@ __m256 test_mm256_or_ps(__m256 A, __m256 B) { __m128d test_mm_permute_pd(__m128d A) { // CHECK-LABEL: test_mm_permute_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> return _mm_permute_pd(A, 1); } __m256d test_mm256_permute_pd(__m256d A) { // CHECK-LABEL: test_mm256_permute_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> return _mm256_permute_pd(A, 5); } __m128 test_mm_permute_ps(__m128 A) { // CHECK-LABEL: test_mm_permute_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> return _mm_permute_ps(A, 0x1b); } // Test case for PR12401 __m128 test2_mm_permute_ps(__m128 a) { // CHECK-LABEL: test2_mm_permute_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> return _mm_permute_ps(a, 0xe6); } __m256 test_mm256_permute_ps(__m256 A) { // CHECK-LABEL: test_mm256_permute_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> return _mm256_permute_ps(A, 0x1b); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index ce324d7b8d..0ed5b7b952 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -4016,40 +4016,40 @@ __m512i test_mm512_mask2_permutex2var_epi64(__m512i __A, __m512i __I, __mmask8 _ __m512d test_mm512_permute_pd(__m512d __X) { // CHECK-LABEL: @test_mm512_permute_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> return _mm512_permute_pd(__X, 2); } __m512d test_mm512_mask_permute_pd(__m512d __W, __mmask8 __U, __m512d __X) { // CHECK-LABEL: @test_mm512_mask_permute_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_permute_pd(__W, __U, __X, 2); } __m512d test_mm512_maskz_permute_pd(__mmask8 __U, __m512d __X) { // CHECK-LABEL: @test_mm512_maskz_permute_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_permute_pd(__U, __X, 2); } __m512 test_mm512_permute_ps(__m512 __X) { // CHECK-LABEL: @test_mm512_permute_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> return _mm512_permute_ps(__X, 2); } __m512 test_mm512_mask_permute_ps(__m512 __W, __mmask16 __U, __m512 __X) { // CHECK-LABEL: @test_mm512_mask_permute_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_permute_ps(__W, __U, __X, 2); } __m512 test_mm512_maskz_permute_ps(__mmask16 __U, __m512 __X) { // CHECK-LABEL: @test_mm512_maskz_permute_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <16 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_permute_ps(__U, __X, 2); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 9e09096692..27dca971d8 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -5470,56 +5470,56 @@ __m256 test_mm256_maskz_rcp14_ps(__mmask8 __U, __m256 __A) { __m128d test_mm_mask_permute_pd(__m128d __W, __mmask8 __U, __m128d __X) { // CHECK-LABEL: @test_mm_mask_permute_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm_mask_permute_pd(__W, __U, __X, 1); } __m128d test_mm_maskz_permute_pd(__mmask8 __U, __m128d __X) { // CHECK-LABEL: @test_mm_maskz_permute_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm_maskz_permute_pd(__U, __X, 1); } __m256d test_mm256_mask_permute_pd(__m256d __W, __mmask8 __U, __m256d __X) { // CHECK-LABEL: @test_mm256_mask_permute_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm256_mask_permute_pd(__W, __U, __X, 5); } __m256d test_mm256_maskz_permute_pd(__mmask8 __U, __m256d __X) { // CHECK-LABEL: @test_mm256_maskz_permute_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm256_maskz_permute_pd(__U, __X, 5); } __m128 test_mm_mask_permute_ps(__m128 __W, __mmask8 __U, __m128 __X) { // CHECK-LABEL: @test_mm_mask_permute_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm_mask_permute_ps(__W, __U, __X, 0x1b); } __m128 test_mm_maskz_permute_ps(__mmask8 __U, __m128 __X) { // CHECK-LABEL: @test_mm_maskz_permute_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm_maskz_permute_ps(__U, __X, 0x1b); } __m256 test_mm256_mask_permute_ps(__m256 __W, __mmask8 __U, __m256 __X) { // CHECK-LABEL: @test_mm256_mask_permute_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_permute_ps(__W, __U, __X, 0x1b); } __m256 test_mm256_maskz_permute_ps(__mmask8 __U, __m256 __X) { // CHECK-LABEL: @test_mm256_maskz_permute_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_permute_ps(__U, __X, 0x1b); } -- GitLab From c38646b3325bacec867358444a9a0fa9e5dca8ba Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 03:24:47 +0000 Subject: [PATCH 0060/1023] [X86] Add subvector insert and extract builtins to enable target feature checking and immediate range checking. Test changes are due to differences in how we generate undef elements now. We also changed the types used for extractf128_si256/insertf128_si256 to match the signature of the builtin that previously existed which this patch resurrects. This also matches gcc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334261 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 32 ++++++++++ lib/CodeGen/CGBuiltin.cpp | 69 +++++++++++++++++++++ lib/Headers/avx2intrin.h | 13 +--- lib/Headers/avx512dqintrin.h | 96 ++++------------------------- lib/Headers/avx512fintrin.h | 92 ++++----------------------- lib/Headers/avx512vldqintrin.h | 26 ++------ lib/Headers/avx512vlintrin.h | 38 ++---------- lib/Headers/avxintrin.h | 51 +++------------ lib/Sema/SemaChecking.cpp | 32 ++++++++++ test/CodeGen/avx-builtins.c | 28 ++++----- test/CodeGen/avx-shuffle-builtins.c | 8 +-- test/CodeGen/avx2-builtins.c | 16 ++--- test/CodeGen/avx512dq-builtins.c | 24 ++++---- test/CodeGen/avx512f-builtins.c | 24 ++++---- test/CodeGen/avx512vl-builtins.c | 12 ++-- test/CodeGen/avx512vldq-builtins.c | 12 ++-- 16 files changed, 243 insertions(+), 330 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 7cc5e6060a..c63289e25d 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -491,6 +491,9 @@ TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "nc", "avx") @@ -503,6 +506,9 @@ TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "nc", "avx") @@ -618,6 +624,8 @@ TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIc", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIc", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "n", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "n", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "n", "avx2") @@ -927,6 +935,8 @@ TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf64x4, "V4dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf32x4, "V4fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") @@ -1646,6 +1656,28 @@ TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "n", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "n", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x8, "V8fV16fIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_512, "V2dV8dIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x8, "V8iV16iIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_512, "V2LLiV8LLiIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x4, "V4iV16iIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extracti64x4, "V4LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_256, "V2dV4dIi", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_256, "V2LLiV4LLiIi", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_256, "V4fV8fIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_256, "V4iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_512, "V8LLiV8LLiV2LLiIi", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x4, "V8dV8dV4dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti64x4, "V8LLiV8LLiV4LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_256, "V4dV4dV2dIi", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_256, "V4LLiV4LLiV2LLiIi", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4_256, "V8fV8fV4fIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti32x4_256, "V8iV8iV4iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4, "V16fV16fV4fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti32x4, "V16iV16iV4iIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2diV2dUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4diV4dUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fiV4fUc", "nc", "avx512vl") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 4331005cb3..025b34e809 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9235,6 +9235,75 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); } + case X86::BI__builtin_ia32_vextractf128_pd256: + case X86::BI__builtin_ia32_vextractf128_ps256: + case X86::BI__builtin_ia32_vextractf128_si256: + case X86::BI__builtin_ia32_extract128i256: + case X86::BI__builtin_ia32_extractf64x4: + case X86::BI__builtin_ia32_extractf32x4: + case X86::BI__builtin_ia32_extracti64x4: + case X86::BI__builtin_ia32_extracti32x4: + case X86::BI__builtin_ia32_extractf32x8: + case X86::BI__builtin_ia32_extracti32x8: + case X86::BI__builtin_ia32_extractf32x4_256: + case X86::BI__builtin_ia32_extracti32x4_256: + case X86::BI__builtin_ia32_extractf64x2_256: + case X86::BI__builtin_ia32_extracti64x2_256: + case X86::BI__builtin_ia32_extractf64x2_512: + case X86::BI__builtin_ia32_extracti64x2_512: { + llvm::Type *DstTy = ConvertType(E->getType()); + unsigned NumElts = DstTy->getVectorNumElements(); + unsigned Index = cast(Ops[1])->getZExtValue() * NumElts; + + uint32_t Indices[16]; + for (unsigned i = 0; i != NumElts; ++i) + Indices[i] = i + Index; + + return Builder.CreateShuffleVector(Ops[0], + UndefValue::get(Ops[0]->getType()), + makeArrayRef(Indices, NumElts), + "extract"); + } + case X86::BI__builtin_ia32_vinsertf128_pd256: + case X86::BI__builtin_ia32_vinsertf128_ps256: + case X86::BI__builtin_ia32_vinsertf128_si256: + case X86::BI__builtin_ia32_insert128i256: + case X86::BI__builtin_ia32_insertf64x4: + case X86::BI__builtin_ia32_insertf32x4: + case X86::BI__builtin_ia32_inserti64x4: + case X86::BI__builtin_ia32_inserti32x4: + case X86::BI__builtin_ia32_insertf32x8: + case X86::BI__builtin_ia32_inserti32x8: + case X86::BI__builtin_ia32_insertf32x4_256: + case X86::BI__builtin_ia32_inserti32x4_256: + case X86::BI__builtin_ia32_insertf64x2_256: + case X86::BI__builtin_ia32_inserti64x2_256: + case X86::BI__builtin_ia32_insertf64x2_512: + case X86::BI__builtin_ia32_inserti64x2_512: { + unsigned DstNumElts = Ops[0]->getType()->getVectorNumElements(); + unsigned SrcNumElts = Ops[1]->getType()->getVectorNumElements(); + unsigned Index = cast(Ops[2])->getZExtValue() * SrcNumElts; + + uint32_t Indices[16]; + for (unsigned i = 0; i != DstNumElts; ++i) + Indices[i] = (i >= SrcNumElts) ? SrcNumElts + (i % SrcNumElts) : i; + + Value *Op1 = Builder.CreateShuffleVector(Ops[1], + UndefValue::get(Ops[1]->getType()), + makeArrayRef(Indices, DstNumElts), + "widen"); + + for (unsigned i = 0; i != DstNumElts; ++i) { + if (i >= Index && i < (Index + SrcNumElts)) + Indices[i] = (i - Index) + DstNumElts; + else + Indices[i] = i; + } + + return Builder.CreateShuffleVector(Ops[0], Op1, + makeArrayRef(Indices, DstNumElts), + "insert"); + } case X86::BI__builtin_ia32_pblendw128: case X86::BI__builtin_ia32_blendpd: case X86::BI__builtin_ia32_blendps: diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index d1c530693b..3867af08cc 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -881,18 +881,11 @@ _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (M)) #define _mm256_extracti128_si256(V, M) \ - (__m128i)__builtin_shufflevector((__v4di)(__m256i)(V), \ - (__v4di)_mm256_undefined_si256(), \ - (((M) & 1) ? 2 : 0), \ - (((M) & 1) ? 3 : 1) ) + (__m128i)__builtin_ia32_extract128i256((__v4di)(__m256i)(V), (int)(M)) #define _mm256_inserti128_si256(V1, V2, M) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V1), \ - (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \ - (((M) & 1) ? 0 : 4), \ - (((M) & 1) ? 1 : 5), \ - (((M) & 1) ? 4 : 2), \ - (((M) & 1) ? 5 : 3) ) + (__m256i)__builtin_ia32_insert128i256((__v4di)(__m256i)(V1), \ + (__v2di)(__m128i)(V2), (int)(M)) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskload_epi32(int const *__X, __m256i __M) diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h index 9ef78041d1..fbb4bbce8d 100644 --- a/lib/Headers/avx512dqintrin.h +++ b/lib/Headers/avx512dqintrin.h @@ -1103,16 +1103,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) } #define _mm512_extractf32x8_ps(A, imm) \ - (__m256)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_undefined_ps(), \ - ((imm) & 1) ? 8 : 0, \ - ((imm) & 1) ? 9 : 1, \ - ((imm) & 1) ? 10 : 2, \ - ((imm) & 1) ? 11 : 3, \ - ((imm) & 1) ? 12 : 4, \ - ((imm) & 1) ? 13 : 5, \ - ((imm) & 1) ? 14 : 6, \ - ((imm) & 1) ? 15 : 7) + (__m256)__builtin_ia32_extractf32x8((__v16sf)(__m512)(A), (int)(imm)) #define _mm512_mask_extractf32x8_ps(W, U, A, imm) \ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \ @@ -1125,10 +1116,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v8sf)_mm256_setzero_ps()) #define _mm512_extractf64x2_pd(A, imm) \ - (__m128d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)_mm512_undefined_pd(), \ - 0 + ((imm) & 0x3) * 2, \ - 1 + ((imm) & 0x3) * 2) + (__m128d)__builtin_ia32_extractf64x2_512((__v8df)(__m512d)(A), (int)(imm)) #define _mm512_mask_extractf64x2_pd(W, U, A, imm) \ (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ @@ -1141,16 +1129,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v2df)_mm_setzero_pd()) #define _mm512_extracti32x8_epi32(A, imm) \ - (__m256i)__builtin_shufflevector((__v16si)(__m512i)(A), \ - (__v16si)_mm512_undefined_epi32(), \ - ((imm) & 1) ? 8 : 0, \ - ((imm) & 1) ? 9 : 1, \ - ((imm) & 1) ? 10 : 2, \ - ((imm) & 1) ? 11 : 3, \ - ((imm) & 1) ? 12 : 4, \ - ((imm) & 1) ? 13 : 5, \ - ((imm) & 1) ? 14 : 6, \ - ((imm) & 1) ? 15 : 7) + (__m256i)__builtin_ia32_extracti32x8((__v16si)(__m512i)(A), (int)(imm)) #define _mm512_mask_extracti32x8_epi32(W, U, A, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ @@ -1163,10 +1142,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v8si)_mm256_setzero_si256()) #define _mm512_extracti64x2_epi64(A, imm) \ - (__m128i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)_mm512_undefined_epi32(), \ - 0 + ((imm) & 0x3) * 2, \ - 1 + ((imm) & 0x3) * 2) + (__m128i)__builtin_ia32_extracti64x2_512((__v8di)(__m512i)(A), (int)(imm)) #define _mm512_mask_extracti64x2_epi64(W, U, A, imm) \ (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \ @@ -1179,24 +1155,8 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v2di)_mm_setzero_si128()) #define _mm512_insertf32x8(A, B, imm) \ - (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_castps256_ps512((__m256)(B)),\ - ((imm) & 0x1) ? 0 : 16, \ - ((imm) & 0x1) ? 1 : 17, \ - ((imm) & 0x1) ? 2 : 18, \ - ((imm) & 0x1) ? 3 : 19, \ - ((imm) & 0x1) ? 4 : 20, \ - ((imm) & 0x1) ? 5 : 21, \ - ((imm) & 0x1) ? 6 : 22, \ - ((imm) & 0x1) ? 7 : 23, \ - ((imm) & 0x1) ? 16 : 8, \ - ((imm) & 0x1) ? 17 : 9, \ - ((imm) & 0x1) ? 18 : 10, \ - ((imm) & 0x1) ? 19 : 11, \ - ((imm) & 0x1) ? 20 : 12, \ - ((imm) & 0x1) ? 21 : 13, \ - ((imm) & 0x1) ? 22 : 14, \ - ((imm) & 0x1) ? 23 : 15) + (__m512)__builtin_ia32_insertf32x8((__v16sf)(__m512)(A), \ + (__v8sf)(__m256)(B), (int)(imm)) #define _mm512_mask_insertf32x8(W, U, A, B, imm) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ @@ -1209,16 +1169,8 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v16sf)_mm512_setzero_ps()) #define _mm512_insertf64x2(A, B, imm) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)_mm512_castpd128_pd512((__m128d)(B)),\ - (((imm) & 0x3) == 0) ? 8 : 0, \ - (((imm) & 0x3) == 0) ? 9 : 1, \ - (((imm) & 0x3) == 1) ? 8 : 2, \ - (((imm) & 0x3) == 1) ? 9 : 3, \ - (((imm) & 0x3) == 2) ? 8 : 4, \ - (((imm) & 0x3) == 2) ? 9 : 5, \ - (((imm) & 0x3) == 3) ? 8 : 6, \ - (((imm) & 0x3) == 3) ? 9 : 7) + (__m512d)__builtin_ia32_insertf64x2_512((__v8df)(__m512d)(A), \ + (__v2df)(__m128d)(B), (int)(imm)) #define _mm512_mask_insertf64x2(W, U, A, B, imm) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -1231,24 +1183,8 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v8df)_mm512_setzero_pd()) #define _mm512_inserti32x8(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \ - (__v16si)_mm512_castsi256_si512((__m256i)(B)),\ - ((imm) & 0x1) ? 0 : 16, \ - ((imm) & 0x1) ? 1 : 17, \ - ((imm) & 0x1) ? 2 : 18, \ - ((imm) & 0x1) ? 3 : 19, \ - ((imm) & 0x1) ? 4 : 20, \ - ((imm) & 0x1) ? 5 : 21, \ - ((imm) & 0x1) ? 6 : 22, \ - ((imm) & 0x1) ? 7 : 23, \ - ((imm) & 0x1) ? 16 : 8, \ - ((imm) & 0x1) ? 17 : 9, \ - ((imm) & 0x1) ? 18 : 10, \ - ((imm) & 0x1) ? 19 : 11, \ - ((imm) & 0x1) ? 20 : 12, \ - ((imm) & 0x1) ? 21 : 13, \ - ((imm) & 0x1) ? 22 : 14, \ - ((imm) & 0x1) ? 23 : 15) + (__m512i)__builtin_ia32_inserti32x8((__v16si)(__m512i)(A), \ + (__v8si)(__m256i)(B), (int)(imm)) #define _mm512_mask_inserti32x8(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ @@ -1261,16 +1197,8 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) (__v16si)_mm512_setzero_si512()) #define _mm512_inserti64x2(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)_mm512_castsi128_si512((__m128i)(B)),\ - (((imm) & 0x3) == 0) ? 8 : 0, \ - (((imm) & 0x3) == 0) ? 9 : 1, \ - (((imm) & 0x3) == 1) ? 8 : 2, \ - (((imm) & 0x3) == 1) ? 9 : 3, \ - (((imm) & 0x3) == 2) ? 8 : 4, \ - (((imm) & 0x3) == 2) ? 9 : 5, \ - (((imm) & 0x3) == 3) ? 8 : 6, \ - (((imm) & 0x3) == 3) ? 9 : 7) + (__m512i)__builtin_ia32_inserti64x2_512((__v8di)(__m512i)(A), \ + (__v2di)(__m128i)(B), (int)(imm)) #define _mm512_mask_inserti64x2(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index ccc445a6ac..4ae235e633 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -3494,12 +3494,7 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, /* Vector Extract */ #define _mm512_extractf64x4_pd(A, I) \ - (__m256d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)_mm512_undefined_pd(), \ - ((I) & 1) ? 4 : 0, \ - ((I) & 1) ? 5 : 1, \ - ((I) & 1) ? 6 : 2, \ - ((I) & 1) ? 7 : 3) + (__m256d)__builtin_ia32_extractf64x4((__v8df)(__m512d)(A), (int)(I)) #define _mm512_mask_extractf64x4_pd(W, U, A, imm) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ @@ -3512,12 +3507,7 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, (__v4df)_mm256_setzero_pd()) #define _mm512_extractf32x4_ps(A, I) \ - (__m128)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_undefined_ps(), \ - 0 + ((I) & 0x3) * 4, \ - 1 + ((I) & 0x3) * 4, \ - 2 + ((I) & 0x3) * 4, \ - 3 + ((I) & 0x3) * 4) + (__m128)__builtin_ia32_extractf32x4((__v16sf)(__m512)(A), (int)(I)) #define _mm512_mask_extractf32x4_ps(W, U, A, imm) \ (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ @@ -7544,12 +7534,7 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) } #define _mm512_extracti32x4_epi32(A, imm) \ - (__m128i)__builtin_shufflevector((__v16si)(__m512i)(A), \ - (__v16si)_mm512_undefined_epi32(), \ - 0 + ((imm) & 0x3) * 4, \ - 1 + ((imm) & 0x3) * 4, \ - 2 + ((imm) & 0x3) * 4, \ - 3 + ((imm) & 0x3) * 4) + (__m128i)__builtin_ia32_extracti32x4((__v16si)(__m512i)(A), (int)(imm)) #define _mm512_mask_extracti32x4_epi32(W, U, A, imm) \ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ @@ -7562,12 +7547,7 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v4si)_mm_setzero_si128()) #define _mm512_extracti64x4_epi64(A, imm) \ - (__m256i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)_mm512_undefined_epi32(), \ - ((imm) & 1) ? 4 : 0, \ - ((imm) & 1) ? 5 : 1, \ - ((imm) & 1) ? 6 : 2, \ - ((imm) & 1) ? 7 : 3) + (__m256i)__builtin_ia32_extracti64x4((__v8di)(__m512i)(A), (int)(imm)) #define _mm512_mask_extracti64x4_epi64(W, U, A, imm) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ @@ -7580,16 +7560,8 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v4di)_mm256_setzero_si256()) #define _mm512_insertf64x4(A, B, imm) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)_mm512_castpd256_pd512((__m256d)(B)), \ - ((imm) & 0x1) ? 0 : 8, \ - ((imm) & 0x1) ? 1 : 9, \ - ((imm) & 0x1) ? 2 : 10, \ - ((imm) & 0x1) ? 3 : 11, \ - ((imm) & 0x1) ? 8 : 4, \ - ((imm) & 0x1) ? 9 : 5, \ - ((imm) & 0x1) ? 10 : 6, \ - ((imm) & 0x1) ? 11 : 7) + (__m512d)__builtin_ia32_insertf64x4((__v8df)(__m512d)(A), \ + (__v4df)(__m256d)(B), (int)(imm)) #define _mm512_mask_insertf64x4(W, U, A, B, imm) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -7602,16 +7574,8 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v8df)_mm512_setzero_pd()) #define _mm512_inserti64x4(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(A), \ - (__v8di)_mm512_castsi256_si512((__m256i)(B)), \ - ((imm) & 0x1) ? 0 : 8, \ - ((imm) & 0x1) ? 1 : 9, \ - ((imm) & 0x1) ? 2 : 10, \ - ((imm) & 0x1) ? 3 : 11, \ - ((imm) & 0x1) ? 8 : 4, \ - ((imm) & 0x1) ? 9 : 5, \ - ((imm) & 0x1) ? 10 : 6, \ - ((imm) & 0x1) ? 11 : 7) + (__m512i)__builtin_ia32_inserti64x4((__v8di)(__m512i)(A), \ + (__v4di)(__m256i)(B), (int)(imm)) #define _mm512_mask_inserti64x4(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ @@ -7624,24 +7588,8 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v8di)_mm512_setzero_si512()) #define _mm512_insertf32x4(A, B, imm) \ - (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_castps128_ps512((__m128)(B)),\ - (((imm) & 0x3) == 0) ? 16 : 0, \ - (((imm) & 0x3) == 0) ? 17 : 1, \ - (((imm) & 0x3) == 0) ? 18 : 2, \ - (((imm) & 0x3) == 0) ? 19 : 3, \ - (((imm) & 0x3) == 1) ? 16 : 4, \ - (((imm) & 0x3) == 1) ? 17 : 5, \ - (((imm) & 0x3) == 1) ? 18 : 6, \ - (((imm) & 0x3) == 1) ? 19 : 7, \ - (((imm) & 0x3) == 2) ? 16 : 8, \ - (((imm) & 0x3) == 2) ? 17 : 9, \ - (((imm) & 0x3) == 2) ? 18 : 10, \ - (((imm) & 0x3) == 2) ? 19 : 11, \ - (((imm) & 0x3) == 3) ? 16 : 12, \ - (((imm) & 0x3) == 3) ? 17 : 13, \ - (((imm) & 0x3) == 3) ? 18 : 14, \ - (((imm) & 0x3) == 3) ? 19 : 15) + (__m512)__builtin_ia32_insertf32x4((__v16sf)(__m512)(A), \ + (__v4sf)(__m128)(B), (int)(imm)) #define _mm512_mask_insertf32x4(W, U, A, B, imm) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ @@ -7654,24 +7602,8 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v16sf)_mm512_setzero_ps()) #define _mm512_inserti32x4(A, B, imm) \ - (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \ - (__v16si)_mm512_castsi128_si512((__m128i)(B)),\ - (((imm) & 0x3) == 0) ? 16 : 0, \ - (((imm) & 0x3) == 0) ? 17 : 1, \ - (((imm) & 0x3) == 0) ? 18 : 2, \ - (((imm) & 0x3) == 0) ? 19 : 3, \ - (((imm) & 0x3) == 1) ? 16 : 4, \ - (((imm) & 0x3) == 1) ? 17 : 5, \ - (((imm) & 0x3) == 1) ? 18 : 6, \ - (((imm) & 0x3) == 1) ? 19 : 7, \ - (((imm) & 0x3) == 2) ? 16 : 8, \ - (((imm) & 0x3) == 2) ? 17 : 9, \ - (((imm) & 0x3) == 2) ? 18 : 10, \ - (((imm) & 0x3) == 2) ? 19 : 11, \ - (((imm) & 0x3) == 3) ? 16 : 12, \ - (((imm) & 0x3) == 3) ? 17 : 13, \ - (((imm) & 0x3) == 3) ? 18 : 14, \ - (((imm) & 0x3) == 3) ? 19 : 15) + (__m512i)__builtin_ia32_inserti32x4((__v16si)(__m512i)(A), \ + (__v4si)(__m128i)(B), (int)(imm)) #define _mm512_mask_inserti32x4(W, U, A, B, imm) \ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ diff --git a/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h index 60571adb5e..8d6ff3ec8d 100644 --- a/lib/Headers/avx512vldqintrin.h +++ b/lib/Headers/avx512vldqintrin.h @@ -1083,10 +1083,7 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) } #define _mm256_extractf64x2_pd(A, imm) \ - (__m128d)__builtin_shufflevector((__v4df)(__m256d)(A), \ - (__v4df)_mm256_undefined_pd(), \ - ((imm) & 1) ? 2 : 0, \ - ((imm) & 1) ? 3 : 1) + (__m128d)__builtin_ia32_extractf64x2_256((__v4df)(__m256d)(A), (int)(imm)) #define _mm256_mask_extractf64x2_pd(W, U, A, imm) \ (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ @@ -1099,10 +1096,7 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) (__v2df)_mm_setzero_pd()) #define _mm256_extracti64x2_epi64(A, imm) \ - (__m128i)__builtin_shufflevector((__v4di)(__m256i)(A), \ - (__v4di)_mm256_undefined_si256(), \ - ((imm) & 1) ? 2 : 0, \ - ((imm) & 1) ? 3 : 1) + (__m128i)__builtin_ia32_extracti64x2_256((__v4di)(__m256i)(A), (int)(imm)) #define _mm256_mask_extracti64x2_epi64(W, U, A, imm) \ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ @@ -1115,12 +1109,8 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) (__v2di)_mm_setzero_si128()) #define _mm256_insertf64x2(A, B, imm) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \ - (__v4df)_mm256_castpd128_pd256((__m128d)(B)), \ - ((imm) & 0x1) ? 0 : 4, \ - ((imm) & 0x1) ? 1 : 5, \ - ((imm) & 0x1) ? 4 : 2, \ - ((imm) & 0x1) ? 5 : 3) + (__m256d)__builtin_ia32_insertf64x2_256((__v4df)(__m256d)(A), \ + (__v2df)(__m128d)(B), (int)(imm)) #define _mm256_mask_insertf64x2(W, U, A, B, imm) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ @@ -1133,12 +1123,8 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) (__v4df)_mm256_setzero_pd()) #define _mm256_inserti64x2(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(A), \ - (__v4di)_mm256_castsi128_si256((__m128i)(B)), \ - ((imm) & 0x1) ? 0 : 4, \ - ((imm) & 0x1) ? 1 : 5, \ - ((imm) & 0x1) ? 4 : 2, \ - ((imm) & 0x1) ? 5 : 3) + (__m256i)__builtin_ia32_inserti64x2_256((__v4di)(__m256i)(A), \ + (__v2di)(__m128i)(B), (int)(imm)) #define _mm256_mask_inserti64x2(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index 49198ec533..d1e81528cd 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -7699,12 +7699,7 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) } #define _mm256_extractf32x4_ps(A, imm) \ - (__m128)__builtin_shufflevector((__v8sf)(__m256)(A), \ - (__v8sf)_mm256_undefined_ps(), \ - ((imm) & 1) ? 4 : 0, \ - ((imm) & 1) ? 5 : 1, \ - ((imm) & 1) ? 6 : 2, \ - ((imm) & 1) ? 7 : 3) + (__m128)__builtin_ia32_extractf32x4_256((__v8sf)(__m256)(A), (int)(imm)) #define _mm256_mask_extractf32x4_ps(W, U, A, imm) \ (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ @@ -7717,12 +7712,7 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v4sf)_mm_setzero_ps()) #define _mm256_extracti32x4_epi32(A, imm) \ - (__m128i)__builtin_shufflevector((__v8si)(__m256)(A), \ - (__v8si)_mm256_undefined_si256(), \ - ((imm) & 1) ? 4 : 0, \ - ((imm) & 1) ? 5 : 1, \ - ((imm) & 1) ? 6 : 2, \ - ((imm) & 1) ? 7 : 3) + (__m128i)__builtin_ia32_extracti32x4_256((__v8si)(__m256i)(A), (int)(imm)) #define _mm256_mask_extracti32x4_epi32(W, U, A, imm) \ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ @@ -7735,16 +7725,8 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v4si)_mm_setzero_si128()) #define _mm256_insertf32x4(A, B, imm) \ - (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \ - (__v8sf)_mm256_castps128_ps256((__m128)(B)), \ - ((imm) & 0x1) ? 0 : 8, \ - ((imm) & 0x1) ? 1 : 9, \ - ((imm) & 0x1) ? 2 : 10, \ - ((imm) & 0x1) ? 3 : 11, \ - ((imm) & 0x1) ? 8 : 4, \ - ((imm) & 0x1) ? 9 : 5, \ - ((imm) & 0x1) ? 10 : 6, \ - ((imm) & 0x1) ? 11 : 7) + (__m256)__builtin_ia32_insertf32x4_256((__v8sf)(__m256)(A), \ + (__v4sf)(__m128)(B), (int)(imm)) #define _mm256_mask_insertf32x4(W, U, A, B, imm) \ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \ @@ -7757,16 +7739,8 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v8sf)_mm256_setzero_ps()) #define _mm256_inserti32x4(A, B, imm) \ - (__m256i)__builtin_shufflevector((__v8si)(__m256i)(A), \ - (__v8si)_mm256_castsi128_si256((__m128i)(B)), \ - ((imm) & 0x1) ? 0 : 8, \ - ((imm) & 0x1) ? 1 : 9, \ - ((imm) & 0x1) ? 2 : 10, \ - ((imm) & 0x1) ? 3 : 11, \ - ((imm) & 0x1) ? 8 : 4, \ - ((imm) & 0x1) ? 9 : 5, \ - ((imm) & 0x1) ? 10 : 6, \ - ((imm) & 0x1) ? 11 : 7) + (__m256i)__builtin_ia32_inserti32x4_256((__v8si)(__m256i)(A), \ + (__v4si)(__m128i)(B), (int)(imm)) #define _mm256_mask_inserti32x4(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 7c85893ba1..6c42132cf4 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -4613,17 +4613,8 @@ _mm256_zextsi128_si256(__m128i __a) /// result. /// \returns A 256-bit vector of [8 x float] containing the interleaved values. #define _mm256_insertf128_ps(V1, V2, M) \ - (__m256)__builtin_shufflevector( \ - (__v8sf)(__m256)(V1), \ - (__v8sf)_mm256_castps128_ps256((__m128)(V2)), \ - (((M) & 1) ? 0 : 8), \ - (((M) & 1) ? 1 : 9), \ - (((M) & 1) ? 2 : 10), \ - (((M) & 1) ? 3 : 11), \ - (((M) & 1) ? 8 : 4), \ - (((M) & 1) ? 9 : 5), \ - (((M) & 1) ? 10 : 6), \ - (((M) & 1) ? 11 : 7) ) + (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)(__m256)(V1), \ + (__v4sf)(__m128)(V2), (int)(M)) /// Constructs a new 256-bit vector of [4 x double] by first duplicating /// a 256-bit vector of [4 x double] given in the first parameter, and then @@ -4660,13 +4651,8 @@ _mm256_zextsi128_si256(__m128i __a) /// result. /// \returns A 256-bit vector of [4 x double] containing the interleaved values. #define _mm256_insertf128_pd(V1, V2, M) \ - (__m256d)__builtin_shufflevector( \ - (__v4df)(__m256d)(V1), \ - (__v4df)_mm256_castpd128_pd256((__m128d)(V2)), \ - (((M) & 1) ? 0 : 4), \ - (((M) & 1) ? 1 : 5), \ - (((M) & 1) ? 4 : 2), \ - (((M) & 1) ? 5 : 3) ) + (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)(__m256d)(V1), \ + (__v2df)(__m128d)(V2), (int)(M)) /// Constructs a new 256-bit integer vector by first duplicating a /// 256-bit integer vector given in the first parameter, and then replacing @@ -4703,13 +4689,8 @@ _mm256_zextsi128_si256(__m128i __a) /// result. /// \returns A 256-bit integer vector containing the interleaved values. #define _mm256_insertf128_si256(V1, V2, M) \ - (__m256i)__builtin_shufflevector( \ - (__v4di)(__m256i)(V1), \ - (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \ - (((M) & 1) ? 0 : 4), \ - (((M) & 1) ? 1 : 5), \ - (((M) & 1) ? 4 : 2), \ - (((M) & 1) ? 5 : 3) ) + (__m256i)__builtin_ia32_vinsertf128_si256((__v4di)(__m256i)(V1), \ + (__v2di)(__m128i)(V2), (int)(M)) /* Vector extract. @@ -4738,13 +4719,7 @@ _mm256_zextsi128_si256(__m128i __a) /// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result. /// \returns A 128-bit vector of [4 x float] containing the extracted bits. #define _mm256_extractf128_ps(V, M) \ - (__m128)__builtin_shufflevector( \ - (__v8sf)(__m256)(V), \ - (__v8sf)(_mm256_undefined_ps()), \ - (((M) & 1) ? 4 : 0), \ - (((M) & 1) ? 5 : 1), \ - (((M) & 1) ? 6 : 2), \ - (((M) & 1) ? 7 : 3) ) + (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)(__m256)(V), (int)(M)) /// Extracts either the upper or the lower 128 bits from a 256-bit vector /// of [4 x double], as determined by the immediate integer parameter, and @@ -4768,11 +4743,7 @@ _mm256_zextsi128_si256(__m128i __a) /// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result. /// \returns A 128-bit vector of [2 x double] containing the extracted bits. #define _mm256_extractf128_pd(V, M) \ - (__m128d)__builtin_shufflevector( \ - (__v4df)(__m256d)(V), \ - (__v4df)(_mm256_undefined_pd()), \ - (((M) & 1) ? 2 : 0), \ - (((M) & 1) ? 3 : 1) ) + (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)(__m256d)(V), (int)(M)) /// Extracts either the upper or the lower 128 bits from a 256-bit /// integer vector, as determined by the immediate integer parameter, and @@ -4796,11 +4767,7 @@ _mm256_zextsi128_si256(__m128i __a) /// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result. /// \returns A 128-bit integer vector containing the extracted bits. #define _mm256_extractf128_si256(V, M) \ - (__m128i)__builtin_shufflevector( \ - (__v4di)(__m256i)(V), \ - (__v4di)(_mm256_undefined_si256()), \ - (((M) & 1) ? 2 : 0), \ - (((M) & 1) ? 3 : 1) ) + (__m128i)__builtin_ia32_vextractf128_si256((__v4di)(__m256i)(V), (int)(M)) /* SIMD load ops (unaligned) */ /// Loads two 128-bit floating-point vectors of [4 x float] from diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index d16921c6c7..4f5405935e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2607,9 +2607,33 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return false; case X86::BI__builtin_ia32_vec_ext_v2si: case X86::BI__builtin_ia32_vec_ext_v2di: + case X86::BI__builtin_ia32_vextractf128_pd256: + case X86::BI__builtin_ia32_vextractf128_ps256: + case X86::BI__builtin_ia32_vextractf128_si256: + case X86::BI__builtin_ia32_extract128i256: + case X86::BI__builtin_ia32_extractf64x4: + case X86::BI__builtin_ia32_extracti64x4: + case X86::BI__builtin_ia32_extractf32x8: + case X86::BI__builtin_ia32_extracti32x8: + case X86::BI__builtin_ia32_extractf64x2_256: + case X86::BI__builtin_ia32_extracti64x2_256: + case X86::BI__builtin_ia32_extractf32x4_256: + case X86::BI__builtin_ia32_extracti32x4_256: i = 1; l = 0; u = 1; break; case X86::BI__builtin_ia32_vec_set_v2di: + case X86::BI__builtin_ia32_vinsertf128_pd256: + case X86::BI__builtin_ia32_vinsertf128_ps256: + case X86::BI__builtin_ia32_vinsertf128_si256: + case X86::BI__builtin_ia32_insert128i256: + case X86::BI__builtin_ia32_insertf32x8: + case X86::BI__builtin_ia32_inserti32x8: + case X86::BI__builtin_ia32_insertf64x4: + case X86::BI__builtin_ia32_inserti64x4: + case X86::BI__builtin_ia32_insertf64x2_256: + case X86::BI__builtin_ia32_inserti64x2_256: + case X86::BI__builtin_ia32_insertf32x4_256: + case X86::BI__builtin_ia32_inserti32x4_256: i = 2; l = 0; u = 1; break; case X86::BI__builtin_ia32_vpermilpd: @@ -2617,6 +2641,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_ext_v4si: case X86::BI__builtin_ia32_vec_ext_v4sf: case X86::BI__builtin_ia32_vec_ext_v4di: + case X86::BI__builtin_ia32_extractf32x4: + case X86::BI__builtin_ia32_extracti32x4: + case X86::BI__builtin_ia32_extractf64x2_512: + case X86::BI__builtin_ia32_extracti64x2_512: i = 1; l = 0; u = 3; break; case X86::BI_mm_prefetch: @@ -2633,6 +2661,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_shuf_f64x2_256: case X86::BI__builtin_ia32_shuf_i32x4_256: case X86::BI__builtin_ia32_shuf_i64x2_256: + case X86::BI__builtin_ia32_insertf64x2_512: + case X86::BI__builtin_ia32_inserti64x2_512: + case X86::BI__builtin_ia32_insertf32x4: + case X86::BI__builtin_ia32_inserti32x4: i = 2; l = 0; u = 3; break; case X86::BI__builtin_ia32_vpermil2pd: diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index cb4b103f46..5743e36c1d 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -342,19 +342,19 @@ long long test_mm256_extract_epi64(__m256i A) { __m128d test_mm256_extractf128_pd(__m256d A) { // CHECK-LABEL: test_mm256_extractf128_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> return _mm256_extractf128_pd(A, 1); } __m128 test_mm256_extractf128_ps(__m256 A) { // CHECK-LABEL: test_mm256_extractf128_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> return _mm256_extractf128_ps(A, 1); } __m128i test_mm256_extractf128_si256(__m256i A) { // CHECK-LABEL: test_mm256_extractf128_si256 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> return _mm256_extractf128_si256(A, 1); } @@ -420,22 +420,22 @@ __m256i test_mm256_insert_epi64(__m256i x, long long b) { __m256d test_mm256_insertf128_pd(__m256d A, __m128d B) { // CHECK-LABEL: test_mm256_insertf128_pd - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <4 x i32> // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> return _mm256_insertf128_pd(A, B, 0); } __m256 test_mm256_insertf128_ps(__m256 A, __m128 B) { // CHECK-LABEL: test_mm256_insertf128_ps - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <8 x i32> // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> return _mm256_insertf128_ps(A, B, 1); } __m256i test_mm256_insertf128_si256(__m256i A, __m128i B) { // CHECK-LABEL: test_mm256_insertf128_si256 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <8 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> return _mm256_insertf128_si256(A, B, 0); } @@ -486,7 +486,7 @@ __m256 test_mm256_loadu2_m128(float* A, float* B) { // CHECK: load <4 x float>, <4 x float>* %{{.*}}, align 1{{$}} // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> // CHECK: load <4 x float>, <4 x float>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> undef, <8 x i32> // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> return _mm256_loadu2_m128(A, B); } @@ -496,7 +496,7 @@ __m256d test_mm256_loadu2_m128d(double* A, double* B) { // CHECK: load <2 x double>, <2 x double>* %{{.*}}, align 1{{$}} // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> // CHECK: load <2 x double>, <2 x double>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> undef, <4 x i32> // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> return _mm256_loadu2_m128d(A, B); } @@ -506,8 +506,8 @@ __m256i test_mm256_loadu2_m128i(__m128i* A, __m128i* B) { // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}} // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> // CHECK: load <2 x i64>, <2 x i64>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <8 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> return _mm256_loadu2_m128i(A, B); } @@ -1169,7 +1169,7 @@ void test_mm256_storeu2_m128(float* A, float* B, __m256 C) { // CHECK-LABEL: test_mm256_storeu2_m128 // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <4 x i32> // CHECK: store <4 x float> %{{.*}}, <4 x float>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> // CHECK: store <4 x float> %{{.*}}, <4 x float>* %{{.*}}, align 1{{$}} _mm256_storeu2_m128(A, B, C); } @@ -1178,7 +1178,7 @@ void test_mm256_storeu2_m128d(double* A, double* B, __m256d C) { // CHECK-LABEL: test_mm256_storeu2_m128d // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <2 x i32> // CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> // CHECK: store <2 x double> %{{.*}}, <2 x double>* %{{.*}}, align 1{{$}} _mm256_storeu2_m128d(A, B, C); } @@ -1187,7 +1187,7 @@ void test_mm256_storeu2_m128i(__m128i* A, __m128i* B, __m256i C) { // CHECK-LABEL: test_mm256_storeu2_m128i // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <2 x i32> // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}} - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> // CHECK: store <2 x i64> %{{.*}}, <2 x i64>* %{{.*}}, align 1{{$}} _mm256_storeu2_m128i(A, B, C); } diff --git a/test/CodeGen/avx-shuffle-builtins.c b/test/CodeGen/avx-shuffle-builtins.c index b5bac89bd1..0830015961 100644 --- a/test/CodeGen/avx-shuffle-builtins.c +++ b/test/CodeGen/avx-shuffle-builtins.c @@ -103,7 +103,7 @@ __m256d test_mm256_insertf128_pd_0(__m256d a, __m128d b) { __m256i test_mm256_insertf128_si256_0(__m256i a, __m128i b) { // CHECK-LABEL: @test_mm256_insertf128_si256_0 - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_insertf128_si256(a, b, 0); } @@ -121,7 +121,7 @@ __m256d test_mm256_insertf128_pd_1(__m256d a, __m128d b) { __m256i test_mm256_insertf128_si256_1(__m256i a, __m128i b) { // CHECK-LABEL: @test_mm256_insertf128_si256_1 - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_insertf128_si256(a, b, 1); } @@ -141,7 +141,7 @@ __m128d test_mm256_extractf128_pd_0(__m256d a) { __m128i test_mm256_extractf128_si256_0(__m256i a) { // CHECK-LABEL: @test_mm256_extractf128_si256_0 - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_extractf128_si256(a, 0); } @@ -159,7 +159,7 @@ __m128d test_mm256_extractf128_pd_1(__m256d a) { __m128i test_mm256_extractf128_si256_1(__m256i a) { // CHECK-LABEL: @test_mm256_extractf128_si256_1 - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_extractf128_si256(a, 1); } diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index bd7e3a9596..72b4349f6e 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -386,21 +386,21 @@ __m256i test_mm256_cvtepu32_epi64(__m128i a) { __m128i test0_mm256_extracti128_si256_0(__m256i a) { // CHECK-LABEL: test0_mm256_extracti128_si256 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> return _mm256_extracti128_si256(a, 0); } __m128i test1_mm256_extracti128_si256_1(__m256i a) { // CHECK-LABEL: test1_mm256_extracti128_si256 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> return _mm256_extracti128_si256(a, 1); } // Immediate should be truncated to one bit. __m128i test2_mm256_extracti128_si256(__m256i a) { // CHECK-LABEL: test2_mm256_extracti128_si256 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> - return _mm256_extracti128_si256(a, 2); + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> + return _mm256_extracti128_si256(a, 0); } __m256i test_mm256_hadd_epi16(__m256i a, __m256i b) { @@ -657,14 +657,14 @@ __m128 test_mm256_mask_i64gather_ps(__m128 a, float const *b, __m256i c, __m128 __m256i test0_mm256_inserti128_si256(__m256i a, __m128i b) { // CHECK-LABEL: test0_mm256_inserti128_si256 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> return _mm256_inserti128_si256(a, b, 0); } __m256i test1_mm256_inserti128_si256(__m256i a, __m128i b) { // CHECK-LABEL: test1_mm256_inserti128_si256 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> return _mm256_inserti128_si256(a, b, 1); } @@ -672,9 +672,9 @@ __m256i test1_mm256_inserti128_si256(__m256i a, __m128i b) { // Immediate should be truncated to one bit. __m256i test2_mm256_inserti128_si256(__m256i a, __m128i b) { // CHECK-LABEL: test2_mm256_inserti128_si256 - // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> undef, <4 x i32> // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> - return _mm256_inserti128_si256(a, b, 2); + return _mm256_inserti128_si256(a, b, 0); } __m256i test_mm256_madd_epi16(__m256i a, __m256i b) { diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c index 756ecf3e6c..f5c4b2633b 100644 --- a/test/CodeGen/avx512dq-builtins.c +++ b/test/CodeGen/avx512dq-builtins.c @@ -1075,80 +1075,80 @@ __m512i test_mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i const* __A) { __m256 test_mm512_extractf32x8_ps(__m512 __A) { // CHECK-LABEL: @test_mm512_extractf32x8_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> return _mm512_extractf32x8_ps(__A, 1); } __m256 test_mm512_mask_extractf32x8_ps(__m256 __W, __mmask8 __U, __m512 __A) { // CHECK-LABEL: @test_mm512_mask_extractf32x8_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm512_mask_extractf32x8_ps(__W, __U, __A, 1); } __m256 test_mm512_maskz_extractf32x8_ps(__mmask8 __U, __m512 __A) { // CHECK-LABEL: @test_mm512_maskz_extractf32x8_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <8 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm512_maskz_extractf32x8_ps(__U, __A, 1); } __m128d test_mm512_extractf64x2_pd(__m512d __A) { // CHECK-LABEL: @test_mm512_extractf64x2_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> return _mm512_extractf64x2_pd(__A, 3); } __m128d test_mm512_mask_extractf64x2_pd(__m128d __W, __mmask8 __U, __m512d __A) { // CHECK-LABEL: @test_mm512_mask_extractf64x2_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm512_mask_extractf64x2_pd(__W, __U, __A, 3); } __m128d test_mm512_maskz_extractf64x2_pd(__mmask8 __U, __m512d __A) { // CHECK-LABEL: @test_mm512_maskz_extractf64x2_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm512_maskz_extractf64x2_pd(__U, __A, 3); } __m256i test_mm512_extracti32x8_epi32(__m512i __A) { // CHECK-LABEL: @test_mm512_extracti32x8_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> return _mm512_extracti32x8_epi32(__A, 1); } __m256i test_mm512_mask_extracti32x8_epi32(__m256i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_extracti32x8_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm512_mask_extracti32x8_epi32(__W, __U, __A, 1); } __m256i test_mm512_maskz_extracti32x8_epi32(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_extracti32x8_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm512_maskz_extracti32x8_epi32(__U, __A, 1); } __m128i test_mm512_extracti64x2_epi64(__m512i __A) { // CHECK-LABEL: @test_mm512_extracti64x2_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> return _mm512_extracti64x2_epi64(__A, 3); } __m128i test_mm512_mask_extracti64x2_epi64(__m128i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_extracti64x2_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm512_mask_extracti64x2_epi64(__W, __U, __A, 3); } __m128i test_mm512_maskz_extracti64x2_epi64(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_extracti64x2_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm512_maskz_extracti64x2_epi64(__U, __A, 3); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 0ed5b7b952..52554ba183 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1508,20 +1508,20 @@ __mmask8 test_mm512_mask_cmpunord_ps_mask(__mmask8 k, __m512 a, __m512 b) { __m256d test_mm512_extractf64x4_pd(__m512d a) { // CHECK-LABEL: @test_mm512_extractf64x4_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> return _mm512_extractf64x4_pd(a, 1); } __m256d test_mm512_mask_extractf64x4_pd(__m256d __W,__mmask8 __U,__m512d __A){ // CHECK-LABEL:@test_mm512_mask_extractf64x4_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm512_mask_extractf64x4_pd( __W, __U, __A, 1); } __m256d test_mm512_maskz_extractf64x4_pd(__mmask8 __U,__m512d __A){ // CHECK-LABEL:@test_mm512_maskz_extractf64x4_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm512_maskz_extractf64x4_pd( __U, __A, 1); } @@ -1529,20 +1529,20 @@ __m256d test_mm512_maskz_extractf64x4_pd(__mmask8 __U,__m512d __A){ __m128 test_mm512_extractf32x4_ps(__m512 a) { // CHECK-LABEL: @test_mm512_extractf32x4_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> return _mm512_extractf32x4_ps(a, 1); } __m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512d __A){ // CHECK-LABEL:@test_mm512_mask_extractf32x4_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm512_mask_extractf32x4_ps( __W, __U, __A, 1); } __m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512d __A){ // CHECK-LABEL:@test_mm512_maskz_extractf32x4_ps - // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm512_maskz_extractf32x4_ps( __U, __A, 1); } @@ -5514,40 +5514,40 @@ void test_mm512_mask_cvtepi64_storeu_epi16(void *__P, __mmask8 __M, __m512i __A) __m128i test_mm512_extracti32x4_epi32(__m512i __A) { // CHECK-LABEL: @test_mm512_extracti32x4_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> return _mm512_extracti32x4_epi32(__A, 3); } __m128i test_mm512_mask_extracti32x4_epi32(__m128i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_extracti32x4_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm512_mask_extracti32x4_epi32(__W, __U, __A, 3); } __m128i test_mm512_maskz_extracti32x4_epi32(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_extracti32x4_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm512_maskz_extracti32x4_epi32(__U, __A, 3); } __m256i test_mm512_extracti64x4_epi64(__m512i __A) { // CHECK-LABEL: @test_mm512_extracti64x4_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> return _mm512_extracti64x4_epi64(__A, 1); } __m256i test_mm512_mask_extracti64x4_epi64(__m256i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_extracti64x4_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm512_mask_extracti64x4_epi64(__W, __U, __A, 1); } __m256i test_mm512_maskz_extracti64x4_epi64(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_extracti64x4_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm512_maskz_extracti64x4_epi64(__U, __A, 1); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 27dca971d8..1edc25d849 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -7101,40 +7101,40 @@ void test_mm256_mask_cvtepi64_storeu_epi16(void * __P, __mmask8 __M, __m256i __A __m128 test_mm256_extractf32x4_ps(__m256 __A) { // CHECK-LABEL: @test_mm256_extractf32x4_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> return _mm256_extractf32x4_ps(__A, 1); } __m128 test_mm256_mask_extractf32x4_ps(__m128 __W, __mmask8 __U, __m256 __A) { // CHECK-LABEL: @test_mm256_mask_extractf32x4_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm256_mask_extractf32x4_ps(__W, __U, __A, 1); } __m128 test_mm256_maskz_extractf32x4_ps(__mmask8 __U, __m256 __A) { // CHECK-LABEL: @test_mm256_maskz_extractf32x4_ps - // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> zeroinitializer, <4 x i32> + // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm256_maskz_extractf32x4_ps(__U, __A, 1); } __m128i test_mm256_extracti32x4_epi32(__m256i __A) { // CHECK-LABEL: @test_mm256_extracti32x4_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> return _mm256_extracti32x4_epi32(__A, 1); } __m128i test_mm256_mask_extracti32x4_epi32(__m128i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_extracti32x4_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm256_mask_extracti32x4_epi32(__W, __U, __A, 1); } __m128i test_mm256_maskz_extracti32x4_epi32(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_extracti32x4_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm256_maskz_extracti32x4_epi32(__U, __A, 1); } diff --git a/test/CodeGen/avx512vldq-builtins.c b/test/CodeGen/avx512vldq-builtins.c index ea9db6ecc8..31ae623fee 100644 --- a/test/CodeGen/avx512vldq-builtins.c +++ b/test/CodeGen/avx512vldq-builtins.c @@ -1024,40 +1024,40 @@ __m256i test_mm256_maskz_broadcast_i64x2(__mmask8 __M, __m128i const* __A) { __m128d test_mm256_extractf64x2_pd(__m256d __A) { // CHECK-LABEL: @test_mm256_extractf64x2_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> return _mm256_extractf64x2_pd(__A, 1); } __m128d test_mm256_mask_extractf64x2_pd(__m128d __W, __mmask8 __U, __m256d __A) { // CHECK-LABEL: @test_mm256_mask_extractf64x2_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm256_mask_extractf64x2_pd(__W, __U, __A, 1); } __m128d test_mm256_maskz_extractf64x2_pd(__mmask8 __U, __m256d __A) { // CHECK-LABEL: @test_mm256_maskz_extractf64x2_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} return _mm256_maskz_extractf64x2_pd(__U, __A, 1); } __m128i test_mm256_extracti64x2_epi64(__m256i __A) { // CHECK-LABEL: @test_mm256_extracti64x2_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> return _mm256_extracti64x2_epi64(__A, 1); } __m128i test_mm256_mask_extracti64x2_epi64(__m128i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_extracti64x2_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm256_mask_extracti64x2_epi64(__W, __U, __A, 1); } __m128i test_mm256_maskz_extracti64x2_epi64(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_extracti64x2_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <2 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm256_maskz_extracti64x2_epi64(__U, __A, 1); } -- GitLab From 62687137ae2b6f4c243e018671c25f8697e900c1 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 04:09:14 +0000 Subject: [PATCH 0061/1023] [X86] Fix some typecasts in intrinsic headers that I messed up in r334261. This was caught by the Header tests, but not the CodeGen tests. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334264 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avxintrin.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 6c42132cf4..0b7813526e 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -4689,8 +4689,8 @@ _mm256_zextsi128_si256(__m128i __a) /// result. /// \returns A 256-bit integer vector containing the interleaved values. #define _mm256_insertf128_si256(V1, V2, M) \ - (__m256i)__builtin_ia32_vinsertf128_si256((__v4di)(__m256i)(V1), \ - (__v2di)(__m128i)(V2), (int)(M)) + (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)(__m256i)(V1), \ + (__v4si)(__m128i)(V2), (int)(M)) /* Vector extract. @@ -4767,7 +4767,7 @@ _mm256_zextsi128_si256(__m128i __a) /// If bit [0] of \a M is 1, bits [255:128] of \a V are copied to the result. /// \returns A 128-bit integer vector containing the extracted bits. #define _mm256_extractf128_si256(V, M) \ - (__m128i)__builtin_ia32_vextractf128_si256((__v4di)(__m256i)(V), (int)(M)) + (__m128i)__builtin_ia32_vextractf128_si256((__v8si)(__m256i)(V), (int)(M)) /* SIMD load ops (unaligned) */ /// Loads two 128-bit floating-point vectors of [4 x float] from -- GitLab From ff71c0ecccdd75cbb164c6fdfcda954e75c7ed8b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 06:13:16 +0000 Subject: [PATCH 0062/1023] [X86] Add builtins for pshufd, pshuflw, and pshufhw to enable target feature and immediate range checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334265 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 9 +++++ lib/CodeGen/CGBuiltin.cpp | 51 +++++++++++++++++++++++++++++ lib/Headers/avx2intrin.h | 37 ++------------------- lib/Headers/avx512bwintrin.h | 46 ++------------------------ lib/Headers/avx512fintrin.h | 19 +---------- lib/Headers/emmintrin.h | 19 ++--------- lib/Sema/SemaChecking.cpp | 9 +++++ test/CodeGen/avx2-builtins.c | 6 ++-- test/CodeGen/avx512bw-builtins.c | 12 +++---- test/CodeGen/avx512f-builtins.c | 6 ++-- test/CodeGen/avx512vl-builtins.c | 8 ++--- test/CodeGen/avx512vlbw-builtins.c | 16 ++++----- test/CodeGen/sse2-builtins.c | 6 ++-- 13 files changed, 105 insertions(+), 139 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index c63289e25d..3466e9b035 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -321,6 +321,9 @@ TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "n", "sse2") TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "n", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufd, "V4iV4iIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshuflw, "V8sV8sIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "nc", "sse2") @@ -598,6 +601,9 @@ TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufd256, "V8iV8iIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshuflw256, "V16sV16sIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufhw256, "V16sV16sIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "nc", "avx2") @@ -1363,6 +1369,8 @@ TARGET_BUILTIN(__builtin_ia32_prorvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl" TARGET_BUILTIN(__builtin_ia32_prorvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_prorvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_prorvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "nc ", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "nc ", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si", "nc", "avx512bw") @@ -1737,6 +1745,7 @@ TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs", "nc", "avx51 TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pshufd512, "V16iV16iIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi", "nc", "avx512vbmi2") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 025b34e809..741f36b095 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9325,6 +9325,57 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "blend"); } + case X86::BI__builtin_ia32_pshuflw: + case X86::BI__builtin_ia32_pshuflw256: + case X86::BI__builtin_ia32_pshuflw512: { + uint32_t Imm = cast(Ops[1])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + + // Splat the 8-bits of immediate 4 times to help the loop wrap around. + Imm = (Imm & 0xff) * 0x01010101; + + uint32_t Indices[32]; + for (unsigned l = 0; l != NumElts; l += 8) { + for (unsigned i = 0; i != 4; ++i) { + Indices[l + i] = l + (Imm & 3); + Imm >>= 2; + } + for (unsigned i = 4; i != 8; ++i) + Indices[l + i] = l + i; + } + + return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), + makeArrayRef(Indices, NumElts), + "pshuflw"); + } + case X86::BI__builtin_ia32_pshufhw: + case X86::BI__builtin_ia32_pshufhw256: + case X86::BI__builtin_ia32_pshufhw512: { + uint32_t Imm = cast(Ops[1])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + + // Splat the 8-bits of immediate 4 times to help the loop wrap around. + Imm = (Imm & 0xff) * 0x01010101; + + uint32_t Indices[32]; + for (unsigned l = 0; l != NumElts; l += 8) { + for (unsigned i = 0; i != 4; ++i) + Indices[l + i] = l + i; + for (unsigned i = 4; i != 8; ++i) { + Indices[l + i] = l + 4 + (Imm & 3); + Imm >>= 2; + } + } + + return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), + makeArrayRef(Indices, NumElts), + "pshufhw"); + } + case X86::BI__builtin_ia32_pshufd: + case X86::BI__builtin_ia32_pshufd256: + case X86::BI__builtin_ia32_pshufd512: case X86::BI__builtin_ia32_vpermilpd: case X86::BI__builtin_ia32_vpermilps: case X86::BI__builtin_ia32_vpermilpd256: diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 3867af08cc..e7fdd2b1e5 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -488,44 +488,13 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b) } #define _mm256_shuffle_epi32(a, imm) \ - (__m256i)__builtin_shufflevector((__v8si)(__m256i)(a), \ - (__v8si)_mm256_undefined_si256(), \ - 0 + (((imm) >> 0) & 0x3), \ - 0 + (((imm) >> 2) & 0x3), \ - 0 + (((imm) >> 4) & 0x3), \ - 0 + (((imm) >> 6) & 0x3), \ - 4 + (((imm) >> 0) & 0x3), \ - 4 + (((imm) >> 2) & 0x3), \ - 4 + (((imm) >> 4) & 0x3), \ - 4 + (((imm) >> 6) & 0x3)) + (__m256i)__builtin_ia32_pshufd256((__v8si)(__m256i)(a), (int)(imm)) #define _mm256_shufflehi_epi16(a, imm) \ - (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \ - (__v16hi)_mm256_undefined_si256(), \ - 0, 1, 2, 3, \ - 4 + (((imm) >> 0) & 0x3), \ - 4 + (((imm) >> 2) & 0x3), \ - 4 + (((imm) >> 4) & 0x3), \ - 4 + (((imm) >> 6) & 0x3), \ - 8, 9, 10, 11, \ - 12 + (((imm) >> 0) & 0x3), \ - 12 + (((imm) >> 2) & 0x3), \ - 12 + (((imm) >> 4) & 0x3), \ - 12 + (((imm) >> 6) & 0x3)) + (__m256i)__builtin_ia32_pshufhw256((__v16hi)(__m256i)(a), (int)(imm)) #define _mm256_shufflelo_epi16(a, imm) \ - (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \ - (__v16hi)_mm256_undefined_si256(), \ - 0 + (((imm) >> 0) & 0x3), \ - 0 + (((imm) >> 2) & 0x3), \ - 0 + (((imm) >> 4) & 0x3), \ - 0 + (((imm) >> 6) & 0x3), \ - 4, 5, 6, 7, \ - 8 + (((imm) >> 0) & 0x3), \ - 8 + (((imm) >> 2) & 0x3), \ - 8 + (((imm) >> 4) & 0x3), \ - 8 + (((imm) >> 6) & 0x3), \ - 12, 13, 14, 15) + (__m256i)__builtin_ia32_pshuflw256((__v16hi)(__m256i)(a), (int)(imm)) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_sign_epi8(__m256i __a, __m256i __b) diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index aabaabd648..0e21a57f31 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -1287,28 +1287,7 @@ _mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A) #define _mm512_shufflehi_epi16(A, imm) \ - (__m512i)__builtin_shufflevector((__v32hi)(__m512i)(A), \ - (__v32hi)_mm512_undefined_epi32(), \ - 0, 1, 2, 3, \ - 4 + (((imm) >> 0) & 0x3), \ - 4 + (((imm) >> 2) & 0x3), \ - 4 + (((imm) >> 4) & 0x3), \ - 4 + (((imm) >> 6) & 0x3), \ - 8, 9, 10, 11, \ - 12 + (((imm) >> 0) & 0x3), \ - 12 + (((imm) >> 2) & 0x3), \ - 12 + (((imm) >> 4) & 0x3), \ - 12 + (((imm) >> 6) & 0x3), \ - 16, 17, 18, 19, \ - 20 + (((imm) >> 0) & 0x3), \ - 20 + (((imm) >> 2) & 0x3), \ - 20 + (((imm) >> 4) & 0x3), \ - 20 + (((imm) >> 6) & 0x3), \ - 24, 25, 26, 27, \ - 28 + (((imm) >> 0) & 0x3), \ - 28 + (((imm) >> 2) & 0x3), \ - 28 + (((imm) >> 4) & 0x3), \ - 28 + (((imm) >> 6) & 0x3)) + (__m512i)__builtin_ia32_pshufhw512((__v32hi)(__m512i)(A), (int)(imm)) #define _mm512_mask_shufflehi_epi16(W, U, A, imm) \ (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ @@ -1323,28 +1302,7 @@ _mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A) (__v32hi)_mm512_setzero_si512()) #define _mm512_shufflelo_epi16(A, imm) \ - (__m512i)__builtin_shufflevector((__v32hi)(__m512i)(A), \ - (__v32hi)_mm512_undefined_epi32(), \ - 0 + (((imm) >> 0) & 0x3), \ - 0 + (((imm) >> 2) & 0x3), \ - 0 + (((imm) >> 4) & 0x3), \ - 0 + (((imm) >> 6) & 0x3), \ - 4, 5, 6, 7, \ - 8 + (((imm) >> 0) & 0x3), \ - 8 + (((imm) >> 2) & 0x3), \ - 8 + (((imm) >> 4) & 0x3), \ - 8 + (((imm) >> 6) & 0x3), \ - 12, 13, 14, 15, \ - 16 + (((imm) >> 0) & 0x3), \ - 16 + (((imm) >> 2) & 0x3), \ - 16 + (((imm) >> 4) & 0x3), \ - 16 + (((imm) >> 6) & 0x3), \ - 20, 21, 22, 23, \ - 24 + (((imm) >> 0) & 0x3), \ - 24 + (((imm) >> 2) & 0x3), \ - 24 + (((imm) >> 4) & 0x3), \ - 24 + (((imm) >> 6) & 0x3), \ - 28, 29, 30, 31) + (__m512i)__builtin_ia32_pshuflw512((__v32hi)(__m512i)(A), (int)(imm)) #define _mm512_mask_shufflelo_epi16(W, U, A, imm) \ diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 4ae235e633..fe730ac27f 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -8849,24 +8849,7 @@ _mm_maskz_load_sd (__mmask8 __U, const double* __A) } #define _mm512_shuffle_epi32(A, I) \ - (__m512i)__builtin_shufflevector((__v16si)(__m512i)(A), \ - (__v16si)_mm512_undefined_epi32(), \ - 0 + (((I) >> 0) & 0x3), \ - 0 + (((I) >> 2) & 0x3), \ - 0 + (((I) >> 4) & 0x3), \ - 0 + (((I) >> 6) & 0x3), \ - 4 + (((I) >> 0) & 0x3), \ - 4 + (((I) >> 2) & 0x3), \ - 4 + (((I) >> 4) & 0x3), \ - 4 + (((I) >> 6) & 0x3), \ - 8 + (((I) >> 0) & 0x3), \ - 8 + (((I) >> 2) & 0x3), \ - 8 + (((I) >> 4) & 0x3), \ - 8 + (((I) >> 6) & 0x3), \ - 12 + (((I) >> 0) & 0x3), \ - 12 + (((I) >> 2) & 0x3), \ - 12 + (((I) >> 4) & 0x3), \ - 12 + (((I) >> 6) & 0x3)) + (__m512i)__builtin_ia32_pshufd512((__v16si)(__m512i)(A), (int)(I)) #define _mm512_mask_shuffle_epi32(W, U, A, I) \ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index ad836b1e63..8942790d5c 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -4343,10 +4343,7 @@ _mm_movemask_epi8(__m128i __a) /// 11: assign values from bits [127:96] of \a a. /// \returns A 128-bit integer vector containing the shuffled values. #define _mm_shuffle_epi32(a, imm) \ - (__m128i)__builtin_shufflevector((__v4si)(__m128i)(a), \ - (__v4si)_mm_undefined_si128(), \ - ((imm) >> 0) & 0x3, ((imm) >> 2) & 0x3, \ - ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3) + (__m128i)__builtin_ia32_pshufd((__v4si)(__m128i)(a), (int)(imm)) /// Constructs a 128-bit integer vector by shuffling four lower 16-bit /// elements of a 128-bit integer vector of [8 x i16], using the immediate @@ -4376,11 +4373,7 @@ _mm_movemask_epi8(__m128i __a) /// 11: assign values from bits [63:48] of \a a. \n /// \returns A 128-bit integer vector containing the shuffled values. #define _mm_shufflelo_epi16(a, imm) \ - (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \ - (__v8hi)_mm_undefined_si128(), \ - ((imm) >> 0) & 0x3, ((imm) >> 2) & 0x3, \ - ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3, \ - 4, 5, 6, 7) + (__m128i)__builtin_ia32_pshuflw((__v8hi)(__m128i)(a), (int)(imm)) /// Constructs a 128-bit integer vector by shuffling four upper 16-bit /// elements of a 128-bit integer vector of [8 x i16], using the immediate @@ -4410,13 +4403,7 @@ _mm_movemask_epi8(__m128i __a) /// 11: assign values from bits [127:112] of \a a. \n /// \returns A 128-bit integer vector containing the shuffled values. #define _mm_shufflehi_epi16(a, imm) \ - (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \ - (__v8hi)_mm_undefined_si128(), \ - 0, 1, 2, 3, \ - 4 + (((imm) >> 0) & 0x3), \ - 4 + (((imm) >> 2) & 0x3), \ - 4 + (((imm) >> 4) & 0x3), \ - 4 + (((imm) >> 6) & 0x3)) + (__m128i)__builtin_ia32_pshufhw((__v8hi)(__m128i)(a), (int)(imm)) /// Unpacks the high-order (index 8-15) values from two 128-bit vectors /// of [16 x i8] and interleaves them into a 128-bit vector of [16 x i8]. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 4f5405935e..020d82edf7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2759,6 +2759,15 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vpermilps256: case X86::BI__builtin_ia32_vpermilpd512: case X86::BI__builtin_ia32_vpermilps512: + case X86::BI__builtin_ia32_pshufd: + case X86::BI__builtin_ia32_pshufd256: + case X86::BI__builtin_ia32_pshufd512: + case X86::BI__builtin_ia32_pshufhw: + case X86::BI__builtin_ia32_pshufhw256: + case X86::BI__builtin_ia32_pshufhw512: + case X86::BI__builtin_ia32_pshuflw: + case X86::BI__builtin_ia32_pshuflw256: + case X86::BI__builtin_ia32_pshuflw512: case X86::BI__builtin_ia32_vcvtps2ph: case X86::BI__builtin_ia32_vcvtps2ph_mask: case X86::BI__builtin_ia32_vcvtps2ph256: diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index 72b4349f6e..99c304109c 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -955,19 +955,19 @@ __m256i test_mm256_shuffle_epi8(__m256i a, __m256i b) { __m256i test_mm256_shuffle_epi32(__m256i a) { // CHECK-LABEL: test_mm256_shuffle_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> return _mm256_shuffle_epi32(a, 15); } __m256i test_mm256_shufflehi_epi16(__m256i a) { // CHECK-LABEL: test_mm256_shufflehi_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> return _mm256_shufflehi_epi16(a, 107); } __m256i test_mm256_shufflelo_epi16(__m256i a) { // CHECK-LABEL: test_mm256_shufflelo_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> return _mm256_shufflelo_epi16(a, 83); } diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c index 07569f53c7..6803652a79 100644 --- a/test/CodeGen/avx512bw-builtins.c +++ b/test/CodeGen/avx512bw-builtins.c @@ -1250,40 +1250,40 @@ __m512i test_mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A) { __m512i test_mm512_shufflehi_epi16(__m512i __A) { // CHECK-LABEL: @test_mm512_shufflehi_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> return _mm512_shufflehi_epi16(__A, 5); } __m512i test_mm512_mask_shufflehi_epi16(__m512i __W, __mmask32 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_shufflehi_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_shufflehi_epi16(__W, __U, __A, 5); } __m512i test_mm512_maskz_shufflehi_epi16(__mmask32 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_shufflehi_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_shufflehi_epi16(__U, __A, 5); } __m512i test_mm512_shufflelo_epi16(__m512i __A) { // CHECK-LABEL: @test_mm512_shufflelo_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> return _mm512_shufflelo_epi16(__A, 5); } __m512i test_mm512_mask_shufflelo_epi16(__m512i __W, __mmask32 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_shufflelo_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_shufflelo_epi16(__W, __U, __A, 5); } __m512i test_mm512_maskz_shufflelo_epi16(__mmask32 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_shufflelo_epi16 - // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> %{{.*}}, <32 x i32> + // CHECK: shufflevector <32 x i16> %{{.*}}, <32 x i16> undef, <32 x i32> // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_shufflelo_epi16(__U, __A, 5); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 52554ba183..dd55c43940 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -7234,20 +7234,20 @@ __m512 test_mm512_maskz_moveldup_ps(__mmask16 __U, __m512 __A) { __m512i test_mm512_shuffle_epi32(__m512i __A) { // CHECK-LABEL: @test_mm512_shuffle_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> return _mm512_shuffle_epi32(__A, 1); } __m512i test_mm512_mask_shuffle_epi32(__m512i __W, __mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_shuffle_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_shuffle_epi32(__W, __U, __A, 1); } __m512i test_mm512_maskz_shuffle_epi32(__mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_shuffle_epi32 - // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_shuffle_epi32(__U, __A, 1); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 1edc25d849..c234e3b94d 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -7598,28 +7598,28 @@ __m256 test_mm256_maskz_moveldup_ps(__mmask8 __U, __m256 __A) { __m128i test_mm_mask_shuffle_epi32(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_shuffle_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_shuffle_epi32(__W, __U, __A, 1); } __m128i test_mm_maskz_shuffle_epi32(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_shuffle_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_shuffle_epi32(__U, __A, 2); } __m256i test_mm256_mask_shuffle_epi32(__m256i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_shuffle_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_shuffle_epi32(__W, __U, __A, 2); } __m256i test_mm256_maskz_shuffle_epi32(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_shuffle_epi32 - // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_shuffle_epi32(__U, __A, 2); } diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c index da16abd2a8..9cc58b6505 100644 --- a/test/CodeGen/avx512vlbw-builtins.c +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -3013,56 +3013,56 @@ __mmask16 test_mm256_movepi16_mask(__m256i __A) { __m128i test_mm_mask_shufflehi_epi16(__m128i __W, __mmask32 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_shufflehi_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shufflehi_epi16(__W, __U, __A, 5); } __m128i test_mm_maskz_shufflehi_epi16(__mmask32 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_shufflehi_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shufflehi_epi16(__U, __A, 5); } __m128i test_mm_mask_shufflelo_epi16(__m128i __W, __mmask32 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_shufflelo_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shufflelo_epi16(__W, __U, __A, 5); } __m128i test_mm_maskz_shufflelo_epi16(__mmask32 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_shufflelo_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shufflelo_epi16(__U, __A, 5); } __m256i test_mm256_mask_shufflehi_epi16(__m256i __W, __mmask32 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_shufflehi_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shufflehi_epi16(__W, __U, __A, 5); } __m256i test_mm256_maskz_shufflehi_epi16(__mmask32 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_shufflehi_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_shufflehi_epi16(__U, __A, 5); } __m256i test_mm256_mask_shufflelo_epi16(__m256i __W, __mmask32 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_shufflelo_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shufflelo_epi16(__W, __U, __A, 5); } __m256i test_mm256_maskz_shufflelo_epi16(__mmask32 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_shufflelo_epi16 - // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> %{{.*}}, <16 x i32> + // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_shufflelo_epi16(__U, __A, 5); } diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index 0031215f7c..0d79aabbaf 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -1116,7 +1116,7 @@ __m128i test_mm_setzero_si128() { __m128i test_mm_shuffle_epi32(__m128i A) { // CHECK-LABEL: test_mm_shuffle_epi32 - // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> zeroinitializer + // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> undef, <4 x i32> zeroinitializer return _mm_shuffle_epi32(A, 0); } @@ -1128,13 +1128,13 @@ __m128d test_mm_shuffle_pd(__m128d A, __m128d B) { __m128i test_mm_shufflehi_epi16(__m128i A) { // CHECK-LABEL: test_mm_shufflehi_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> return _mm_shufflehi_epi16(A, 0); } __m128i test_mm_shufflelo_epi16(__m128i A) { // CHECK-LABEL: test_mm_shufflelo_epi16 - // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> + // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> return _mm_shufflelo_epi16(A, 0); } -- GitLab From a90c85acaf28b8a2003f0d0358ee56ce92836571 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 07:18:33 +0000 Subject: [PATCH 0063/1023] [X86] Add builtins for shufps and shufpd to enable target feature and immediate range checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334266 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 6 ++++++ lib/CodeGen/CGBuiltin.cpp | 30 +++++++++++++++++++++++++++++ lib/Headers/avxintrin.h | 20 ++++--------------- lib/Headers/emmintrin.h | 5 ++--- lib/Headers/xmmintrin.h | 7 ++----- lib/Sema/SemaChecking.cpp | 6 ++++++ 6 files changed, 50 insertions(+), 24 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 3466e9b035..0354945d98 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -316,6 +316,7 @@ TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "nc", "sse") TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "nc", "sse") TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "nc", "sse") TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "nc", "sse") +TARGET_BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fIi", "nc", "sse") TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "n", "sse2") TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "nc", "sse2") @@ -327,6 +328,7 @@ TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2di", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "nc", "sse2") TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "nc", "sse2") @@ -487,6 +489,8 @@ TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "nc", "avx") @@ -1536,6 +1540,8 @@ TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufps512, "V16fV16fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "nc", "avx512vl") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 741f36b095..9d9a9427ed 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9403,6 +9403,36 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "permil"); } + case X86::BI__builtin_ia32_shufpd: + case X86::BI__builtin_ia32_shufpd256: + case X86::BI__builtin_ia32_shufpd512: + case X86::BI__builtin_ia32_shufps: + case X86::BI__builtin_ia32_shufps256: + case X86::BI__builtin_ia32_shufps512: { + uint32_t Imm = cast(Ops[2])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + unsigned NumLanes = Ty->getPrimitiveSizeInBits() / 128; + unsigned NumLaneElts = NumElts / NumLanes; + + // Splat the 8-bits of immediate 4 times to help the loop wrap around. + Imm = (Imm & 0xff) * 0x01010101; + + uint32_t Indices[16]; + for (unsigned l = 0; l != NumElts; l += NumLaneElts) { + for (unsigned i = 0; i != NumLaneElts; ++i) { + unsigned Index = Imm % NumLaneElts; + Imm /= NumLaneElts; + if (i >= (NumLaneElts / 2)) + Index += NumElts; + Indices[l + i] = l + Index; + } + } + + return Builder.CreateShuffleVector(Ops[0], Ops[1], + makeArrayRef(Indices, NumElts), + "shufp"); + } case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: { diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 0b7813526e..2aa3f5f6d6 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -1516,16 +1516,8 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// 11: Bits [127:96] and [255:224] are copied from the selected operand. /// \returns A 256-bit vector of [8 x float] containing the shuffled values. #define _mm256_shuffle_ps(a, b, mask) \ - (__m256)__builtin_shufflevector((__v8sf)(__m256)(a), \ - (__v8sf)(__m256)(b), \ - 0 + (((mask) >> 0) & 0x3), \ - 0 + (((mask) >> 2) & 0x3), \ - 8 + (((mask) >> 4) & 0x3), \ - 8 + (((mask) >> 6) & 0x3), \ - 4 + (((mask) >> 0) & 0x3), \ - 4 + (((mask) >> 2) & 0x3), \ - 12 + (((mask) >> 4) & 0x3), \ - 12 + (((mask) >> 6) & 0x3)) + (__m256)__builtin_ia32_shufps256((__v8sf)(__m256)(a), \ + (__v8sf)(__m256)(b), (int)(mask)) /// Selects four double-precision values from the 256-bit operands of /// [4 x double], as specified by the immediate value operand. @@ -1570,12 +1562,8 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// destination. /// \returns A 256-bit vector of [4 x double] containing the shuffled values. #define _mm256_shuffle_pd(a, b, mask) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(a), \ - (__v4df)(__m256d)(b), \ - 0 + (((mask) >> 0) & 0x1), \ - 4 + (((mask) >> 1) & 0x1), \ - 2 + (((mask) >> 2) & 0x1), \ - 6 + (((mask) >> 3) & 0x1)) + (__m256d)__builtin_ia32_shufpd256((__v4df)(__m256d)(a), \ + (__v4df)(__m256d)(b), (int)(mask)) /* Compare */ #define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */ diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index 8942790d5c..6c64d41517 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -4757,9 +4757,8 @@ _mm_movemask_pd(__m128d __a) /// Bit[1] = 1: upper element of \a b copied to upper element of result. \n /// \returns A 128-bit vector of [2 x double] containing the shuffled values. #define _mm_shuffle_pd(a, b, i) \ - (__m128d)__builtin_shufflevector((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \ - 0 + (((i) >> 0) & 0x1), \ - 2 + (((i) >> 1) & 0x1)) + (__m128d)__builtin_ia32_shufpd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \ + (int)(i)) /// Casts a 128-bit floating-point vector of [2 x double] into a 128-bit /// floating-point vector of [4 x float]. diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 92db4779be..8d82da3ce5 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -2605,11 +2605,8 @@ void _mm_setcsr(unsigned int __i); /// 11: Bits [127:96] copied from the specified operand. /// \returns A 128-bit vector of [4 x float] containing the shuffled values. #define _mm_shuffle_ps(a, b, mask) \ - (__m128)__builtin_shufflevector((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), \ - 0 + (((mask) >> 0) & 0x3), \ - 0 + (((mask) >> 2) & 0x3), \ - 4 + (((mask) >> 4) & 0x3), \ - 4 + (((mask) >> 6) & 0x3)) + (__m128)__builtin_ia32_shufps((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), \ + (int)(mask)) /// Unpacks the high-order (index 2,3) values from two 128-bit vectors of /// [4 x float] and interleaves them into a 128-bit vector of [4 x float]. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 020d82edf7..48671b4432 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2654,6 +2654,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; case X86::BI__builtin_ia32_sha1rnds4: case X86::BI__builtin_ia32_blendpd: + case X86::BI__builtin_ia32_shufpd: case X86::BI__builtin_ia32_vec_set_v4hi: case X86::BI__builtin_ia32_vec_set_v4si: case X86::BI__builtin_ia32_vec_set_v4di: @@ -2721,6 +2722,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_pblendd128: case X86::BI__builtin_ia32_blendps: case X86::BI__builtin_ia32_blendpd256: + case X86::BI__builtin_ia32_shufpd256: case X86::BI__builtin_ia32_roundss: case X86::BI__builtin_ia32_roundsd: case X86::BI__builtin_ia32_rangepd128_mask: @@ -2824,6 +2826,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_shuf_f64x2: case X86::BI__builtin_ia32_shuf_i32x4: case X86::BI__builtin_ia32_shuf_i64x2: + case X86::BI__builtin_ia32_shufpd512: + case X86::BI__builtin_ia32_shufps: + case X86::BI__builtin_ia32_shufps256: + case X86::BI__builtin_ia32_shufps512: case X86::BI__builtin_ia32_dbpsadbw128_mask: case X86::BI__builtin_ia32_dbpsadbw256_mask: case X86::BI__builtin_ia32_dbpsadbw512_mask: -- GitLab From dcdd53793ea9fb2c806fd7b02c9fc56d9fa8bb2d Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Fri, 8 Jun 2018 11:17:08 +0000 Subject: [PATCH 0064/1023] [CUDA] Fix emission of constant strings in sections CGM.GetAddrOfConstantCString() sets the adress of the created GlobalValue to unnamed. When emitting the object file LLVM will mark the surrounding section as SHF_MERGE iff the string is nul-terminated and contains no other nuls (see IsNullTerminatedString). This results in problems when saving temporaries because LLVM doesn't set an EntrySize, so reading in the serialized assembly file fails. This never happened for the GPU binaries because they usually contain a nul-character somewhere. Instead this only affected the module ID when compiling relocatable device code. However, this points to a potentially larger problem: If we put a constant string into a named section, we really want the data to end up in that section in the object file. To avoid LLVM merging sections this patch unmarks the GlobalVariable's address as unnamed which also fixes the problem of invalid serialized assembly files when saving temporaries. Differential Revision: https://reviews.llvm.org/D47902 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334281 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCUDANV.cpp | 6 +++++- test/CodeGenCUDA/device-stub.cu | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index 4c2e10b65c..7322095594 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -75,8 +75,12 @@ private: auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); llvm::GlobalVariable *GV = cast(ConstStr.getPointer()); - if (!SectionName.empty()) + if (!SectionName.empty()) { GV->setSection(SectionName); + // Mark the address as used which make sure that this section isn't + // merged and we will really have it in the object file. + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); + } if (Alignment) GV->setAlignment(Alignment); diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu index 894b7205c3..3798b8cf73 100644 --- a/test/CodeGenCUDA/device-stub.cu +++ b/test/CodeGenCUDA/device-stub.cu @@ -65,7 +65,7 @@ void use_pointers() { // ALL: private unnamed_addr constant{{.*}}kernelfunc{{.*}}\00" // * constant unnamed string with GPU binary // HIP: @[[FATBIN:__hip_fatbin]] = external constant i8, section ".hip_fatbin" -// CUDA: @[[FATBIN:.*]] = private unnamed_addr constant{{.*GPU binary would be here.*}}\00", +// CUDA: @[[FATBIN:.*]] = private constant{{.*GPU binary would be here.*}}\00", // CUDANORDC-SAME: section ".nv_fatbin", align 8 // CUDARDC-SAME: section "__nv_relfatbin", align 8 // * constant struct that wraps GPU binary @@ -81,7 +81,7 @@ void use_pointers() { // * variable to save GPU binary handle after initialization // NORDC: @__[[PREFIX]]_gpubin_handle = internal global i8** null // * constant unnamed string with NVModuleID -// RDC: [[MODULE_ID_GLOBAL:@.*]] = private unnamed_addr constant +// RDC: [[MODULE_ID_GLOBAL:@.*]] = private constant // CUDARDC-SAME: c"[[MODULE_ID:.+]]\00", section "__nv_module_id", align 32 // HIPRDC-SAME: c"[[MODULE_ID:.+]]\00", section "__hip_module_id", align 32 // * Make sure our constructor was added to global ctor list. @@ -141,7 +141,7 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); } // There should be no __[[PREFIX]]_register_globals if we have no // device-side globals, but we still need to register GPU binary. // Skip GPU binary string first. -// CUDANOGLOBALS: @{{.*}} = private unnamed_addr constant{{.*}} +// CUDANOGLOBALS: @{{.*}} = private constant{{.*}} // HIPNOGLOBALS: @{{.*}} = external constant{{.*}} // NOGLOBALS-NOT: define internal void @__{{.*}}_register_globals // NOGLOBALS: define internal void @__[[PREFIX:cuda|hip]]_module_ctor -- GitLab From a344be6ba4fe35d41cd19fb56bf822efeb1d6af4 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 18:00:22 +0000 Subject: [PATCH 0065/1023] [X86] Change immediate type for some builtins from char to int. These builtins are all handled by CGBuiltin.cpp so it doesn't much matter what the immediate type is, but int matches the intrinsic spec. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334310 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 24 ++++++++++++------------ lib/Headers/avx2intrin.h | 2 +- lib/Headers/avxintrin.h | 6 +++--- lib/Sema/SemaChecking.cpp | 4 ++++ 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 0354945d98..b0f07279c0 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -498,24 +498,24 @@ TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIc", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIi", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "nc", "avx") TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "nc", "avx") @@ -633,9 +633,9 @@ TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIc", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIc", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "n", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "n", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "n", "avx2") diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index e7fdd2b1e5..984ae9f64d 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -847,7 +847,7 @@ _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) ((M) >> 6) & 0x3) #define _mm256_permute2x128_si256(V1, V2, M) \ - (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (M)) + (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (int)(M)) #define _mm256_extracti128_si256(V, M) \ (__m128i)__builtin_ia32_extract128i256((__v4di)(__m256i)(V), (int)(M)) diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 2aa3f5f6d6..3bf7783db3 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -1227,7 +1227,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// \returns A 256-bit vector of [4 x double] containing the copied values. #define _mm256_permute2f128_pd(V1, V2, M) \ (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)(__m256d)(V1), \ - (__v4df)(__m256d)(V2), (M)) + (__v4df)(__m256d)(V2), (int)(M)) /// Permutes 128-bit data values stored in two 256-bit vectors of /// [8 x float], as specified by the immediate integer operand. @@ -1268,7 +1268,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// \returns A 256-bit vector of [8 x float] containing the copied values. #define _mm256_permute2f128_ps(V1, V2, M) \ (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)(__m256)(V1), \ - (__v8sf)(__m256)(V2), (M)) + (__v8sf)(__m256)(V2), (int)(M)) /// Permutes 128-bit data values stored in two 256-bit integer vectors, /// as specified by the immediate integer operand. @@ -1308,7 +1308,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c) /// \returns A 256-bit integer vector containing the copied values. #define _mm256_permute2f128_si256(V1, V2, M) \ (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)(__m256i)(V1), \ - (__v8si)(__m256i)(V2), (M)) + (__v8si)(__m256i)(V2), (int)(M)) /* Vector Blend */ /// Merges 64-bit double-precision data values stored in either of the diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 48671b4432..417422d2b4 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2807,6 +2807,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_fpclassss_mask: i = 1; l = 0; u = 255; break; + case X86::BI__builtin_ia32_vperm2f128_pd256: + case X86::BI__builtin_ia32_vperm2f128_ps256: + case X86::BI__builtin_ia32_vperm2f128_si256: + case X86::BI__builtin_ia32_permti256: case X86::BI__builtin_ia32_pblendw128: case X86::BI__builtin_ia32_pblendw256: case X86::BI__builtin_ia32_blendps256: -- GitLab From 8c873daccce7ee5339b9fd82c81fe02b73543b65 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 18:00:25 +0000 Subject: [PATCH 0066/1023] [X86] Add builtins for vpermq/vpermpd instructions to enable target feature checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334311 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 4 ++++ lib/CodeGen/CGBuiltin.cpp | 18 ++++++++++++++++++ lib/Headers/avx2intrin.h | 14 ++------------ lib/Headers/avx512fintrin.h | 22 ++-------------------- lib/Headers/avx512vlintrin.h | 10 ++-------- lib/Sema/SemaChecking.cpp | 4 ++++ test/CodeGen/avx2-builtins.c | 4 ++-- test/CodeGen/avx512f-builtins.c | 12 ++++++------ test/CodeGen/avx512vl-builtins.c | 12 ++++++------ 9 files changed, 46 insertions(+), 54 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index b0f07279c0..c920b47af0 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -632,8 +632,10 @@ TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdf256, "V4dV4dIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "nc", "avx2") TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "n", "avx2") @@ -1710,6 +1712,8 @@ TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512 TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vfnmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vfnmsubss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_permvardf512, "V8dV8dV8LLi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_permvardi512, "V8LLiV8LLiV8LLi", "nc", "avx512f") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 9d9a9427ed..ac9f46cb44 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9433,6 +9433,24 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, NumElts), "shufp"); } + case X86::BI__builtin_ia32_permdi256: + case X86::BI__builtin_ia32_permdf256: + case X86::BI__builtin_ia32_permdi512: + case X86::BI__builtin_ia32_permdf512: { + unsigned Imm = cast(Ops[1])->getZExtValue(); + llvm::Type *Ty = Ops[0]->getType(); + unsigned NumElts = Ty->getVectorNumElements(); + + // These intrinsics operate on 256-bit lanes of four 64-bit elements. + uint32_t Indices[8]; + for (unsigned l = 0; l != NumElts; l += 4) + for (unsigned i = 0; i != 4; ++i) + Indices[l + i] = l + ((Imm >> (2 * i)) & 0x3); + + return Builder.CreateShuffleVector(Ops[0], UndefValue::get(Ty), + makeArrayRef(Indices, NumElts), + "perm"); + } case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: { diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 984ae9f64d..7af494a0ab 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -825,12 +825,7 @@ _mm256_permutevar8x32_epi32(__m256i __a, __m256i __b) } #define _mm256_permute4x64_pd(V, M) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V), \ - (__v4df)_mm256_undefined_pd(), \ - ((M) >> 0) & 0x3, \ - ((M) >> 2) & 0x3, \ - ((M) >> 4) & 0x3, \ - ((M) >> 6) & 0x3) + (__m256d)__builtin_ia32_permdf256((__v4df)(__m256d)(V), (int)(M)) static __inline__ __m256 __DEFAULT_FN_ATTRS _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) @@ -839,12 +834,7 @@ _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) } #define _mm256_permute4x64_epi64(V, M) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V), \ - (__v4di)_mm256_undefined_si256(), \ - ((M) >> 0) & 0x3, \ - ((M) >> 2) & 0x3, \ - ((M) >> 4) & 0x3, \ - ((M) >> 6) & 0x3) + (__m256i)__builtin_ia32_permdi256((__v4di)(__m256i)(V), (int)(M)) #define _mm256_permute2x128_si256(V1, V2, M) \ (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (int)(M)) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index fe730ac27f..381011ed39 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -8339,16 +8339,7 @@ _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__mmask8)(U), (int)(R)) #define _mm512_permutex_pd(X, C) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(X), \ - (__v8df)_mm512_undefined_pd(), \ - 0 + (((C) >> 0) & 0x3), \ - 0 + (((C) >> 2) & 0x3), \ - 0 + (((C) >> 4) & 0x3), \ - 0 + (((C) >> 6) & 0x3), \ - 4 + (((C) >> 0) & 0x3), \ - 4 + (((C) >> 2) & 0x3), \ - 4 + (((C) >> 4) & 0x3), \ - 4 + (((C) >> 6) & 0x3)) + (__m512d)__builtin_ia32_permdf512((__v8df)(__m512d)(X), (int)(C)) #define _mm512_mask_permutex_pd(W, U, X, C) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -8361,16 +8352,7 @@ _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__v8df)_mm512_setzero_pd()) #define _mm512_permutex_epi64(X, C) \ - (__m512i)__builtin_shufflevector((__v8di)(__m512i)(X), \ - (__v8di)_mm512_undefined_epi32(), \ - 0 + (((C) >> 0) & 0x3), \ - 0 + (((C) >> 2) & 0x3), \ - 0 + (((C) >> 4) & 0x3), \ - 0 + (((C) >> 6) & 0x3), \ - 4 + (((C) >> 0) & 0x3), \ - 4 + (((C) >> 2) & 0x3), \ - 4 + (((C) >> 4) & 0x3), \ - 4 + (((C) >> 6) & 0x3)) + (__m512i)__builtin_ia32_permdi512((__v8di)(__m512i)(X), (int)(C)) #define _mm512_mask_permutex_epi64(W, U, X, C) \ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index d1e81528cd..22a1fcb41e 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -7921,10 +7921,7 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__mmask8)(mask), (int)(scale)) #define _mm256_permutex_pd(X, C) \ - (__m256d)__builtin_shufflevector((__v4df)(__m256d)(X), \ - (__v4df)_mm256_undefined_pd(), \ - ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \ - ((C) >> 4) & 0x3, ((C) >> 6) & 0x3) + (__m256d)__builtin_ia32_permdf256((__v4df)(__m256d)(X), (int)(C)) #define _mm256_mask_permutex_pd(W, U, X, C) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ @@ -7937,10 +7934,7 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v4df)_mm256_setzero_pd()) #define _mm256_permutex_epi64(X, C) \ - (__m256i)__builtin_shufflevector((__v4di)(__m256i)(X), \ - (__v4di)_mm256_undefined_si256(), \ - ((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \ - ((C) >> 4) & 0x3, ((C) >> 6) & 0x3) + (__m256d)__builtin_ia32_permdi256((__v4di)(__m256i)(X), (int)(C)) #define _mm256_mask_permutex_epi64(W, U, X, C) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 417422d2b4..3e0d36b384 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2757,6 +2757,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_set_v32qi: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_permdf256: + case X86::BI__builtin_ia32_permdi256: + case X86::BI__builtin_ia32_permdf512: + case X86::BI__builtin_ia32_permdi512: case X86::BI__builtin_ia32_vpermilps: case X86::BI__builtin_ia32_vpermilps256: case X86::BI__builtin_ia32_vpermilpd512: diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index 99c304109c..73b18c2e60 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -919,13 +919,13 @@ __m256i test_mm256_permute2x128_si256(__m256i a, __m256i b) { __m256i test_mm256_permute4x64_epi64(__m256i a) { // CHECK-LABEL: test_mm256_permute4x64_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> return _mm256_permute4x64_epi64(a, 35); } __m256d test_mm256_permute4x64_pd(__m256d a) { // CHECK-LABEL: test_mm256_permute4x64_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> return _mm256_permute4x64_pd(a, 25); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index dd55c43940..dab1c41912 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -6854,40 +6854,40 @@ __m128d test_mm_mask3_fnmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __m __m512d test_mm512_permutex_pd(__m512d __X) { // CHECK-LABEL: @test_mm512_permutex_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> return _mm512_permutex_pd(__X, 0); } __m512d test_mm512_mask_permutex_pd(__m512d __W, __mmask8 __U, __m512d __X) { // CHECK-LABEL: @test_mm512_mask_permutex_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_permutex_pd(__W, __U, __X, 0); } __m512d test_mm512_maskz_permutex_pd(__mmask8 __U, __m512d __X) { // CHECK-LABEL: @test_mm512_maskz_permutex_pd - // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_permutex_pd(__U, __X, 0); } __m512i test_mm512_permutex_epi64(__m512i __X) { // CHECK-LABEL: @test_mm512_permutex_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> return _mm512_permutex_epi64(__X, 0); } __m512i test_mm512_mask_permutex_epi64(__m512i __W, __mmask8 __M, __m512i __X) { // CHECK-LABEL: @test_mm512_mask_permutex_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_permutex_epi64(__W, __M, __X, 0); } __m512i test_mm512_maskz_permutex_epi64(__mmask8 __M, __m512i __X) { // CHECK-LABEL: @test_mm512_maskz_permutex_epi64 - // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> zeroinitializer, <8 x i32> + // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_permutex_epi64(__M, __X, 0); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index c234e3b94d..31dd0ec7b2 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -7349,40 +7349,40 @@ __m256i test_mm256_mask_i32gather_epi32(__m256i __v1_old, __mmask8 __mask, __m25 __m256d test_mm256_permutex_pd(__m256d __X) { // CHECK-LABEL: @test_mm256_permutex_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> return _mm256_permutex_pd(__X, 3); } __m256d test_mm256_mask_permutex_pd(__m256d __W, __mmask8 __U, __m256d __X) { // CHECK-LABEL: @test_mm256_mask_permutex_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm256_mask_permutex_pd(__W, __U, __X, 1); } __m256d test_mm256_maskz_permutex_pd(__mmask8 __U, __m256d __X) { // CHECK-LABEL: @test_mm256_maskz_permutex_pd - // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} return _mm256_maskz_permutex_pd(__U, __X, 1); } __m256i test_mm256_permutex_epi64(__m256i __X) { // CHECK-LABEL: @test_mm256_permutex_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> return _mm256_permutex_epi64(__X, 3); } __m256i test_mm256_mask_permutex_epi64(__m256i __W, __mmask8 __M, __m256i __X) { // CHECK-LABEL: @test_mm256_mask_permutex_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_permutex_epi64(__W, __M, __X, 3); } __m256i test_mm256_maskz_permutex_epi64(__mmask8 __M, __m256i __X) { // CHECK-LABEL: @test_mm256_maskz_permutex_epi64 - // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> zeroinitializer, <4 x i32> + // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_permutex_epi64(__M, __X, 3); } -- GitLab From 3cef3a6363ad17ab52f3e41d8de9511bbd07a26f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 21:50:07 +0000 Subject: [PATCH 0067/1023] [X86] Fold masking into subvector extract builtins. I'm looking into making the select builtins require avx512f, avx512bw, or avx512vl since masking operations generally require those features. The extract builtins are funny because the 512-bit versions return a 128 or 256 bit vector with masking even when avx512vl is not supported. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334330 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 24 +++++----- lib/CodeGen/CGBuiltin.cpp | 37 ++++++++------- lib/Headers/avx512dqintrin.h | 70 +++++++++++++++++------------ lib/Headers/avx512fintrin.h | 64 ++++++++++++++------------ lib/Headers/avx512vldqintrin.h | 38 ++++++++++------ lib/Headers/avx512vlintrin.h | 38 ++++++++++------ lib/Sema/SemaChecking.cpp | 24 +++++----- 7 files changed, 171 insertions(+), 124 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index c920b47af0..b694059adc 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -947,8 +947,8 @@ TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf64x4, "V4dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extractf32x4, "V4fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") @@ -1672,16 +1672,16 @@ TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "n", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf32x8, "V8fV16fIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extractf64x2_512, "V2dV8dIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti32x8, "V8iV16iIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti64x2_512, "V2LLiV8LLiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti32x4, "V4iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extracti64x4, "V4LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extractf64x2_256, "V2dV4dIi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_extracti64x2_256, "V2LLiV4LLiIi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf32x4_256, "V4fV8fIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extracti32x4_256, "V4iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x8_mask, "V8fV16fIiV8fUc", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc", "nc", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "nc", "avx512dq") TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "nc", "avx512dq") TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "nc", "avx512dq") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index ac9f46cb44..012428dbb2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9239,18 +9239,18 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_vextractf128_ps256: case X86::BI__builtin_ia32_vextractf128_si256: case X86::BI__builtin_ia32_extract128i256: - case X86::BI__builtin_ia32_extractf64x4: - case X86::BI__builtin_ia32_extractf32x4: - case X86::BI__builtin_ia32_extracti64x4: - case X86::BI__builtin_ia32_extracti32x4: - case X86::BI__builtin_ia32_extractf32x8: - case X86::BI__builtin_ia32_extracti32x8: - case X86::BI__builtin_ia32_extractf32x4_256: - case X86::BI__builtin_ia32_extracti32x4_256: - case X86::BI__builtin_ia32_extractf64x2_256: - case X86::BI__builtin_ia32_extracti64x2_256: - case X86::BI__builtin_ia32_extractf64x2_512: - case X86::BI__builtin_ia32_extracti64x2_512: { + case X86::BI__builtin_ia32_extractf64x4_mask: + case X86::BI__builtin_ia32_extractf32x4_mask: + case X86::BI__builtin_ia32_extracti64x4_mask: + case X86::BI__builtin_ia32_extracti32x4_mask: + case X86::BI__builtin_ia32_extractf32x8_mask: + case X86::BI__builtin_ia32_extracti32x8_mask: + case X86::BI__builtin_ia32_extractf32x4_256_mask: + case X86::BI__builtin_ia32_extracti32x4_256_mask: + case X86::BI__builtin_ia32_extractf64x2_256_mask: + case X86::BI__builtin_ia32_extracti64x2_256_mask: + case X86::BI__builtin_ia32_extractf64x2_512_mask: + case X86::BI__builtin_ia32_extracti64x2_512_mask: { llvm::Type *DstTy = ConvertType(E->getType()); unsigned NumElts = DstTy->getVectorNumElements(); unsigned Index = cast(Ops[1])->getZExtValue() * NumElts; @@ -9259,10 +9259,15 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i != NumElts; ++i) Indices[i] = i + Index; - return Builder.CreateShuffleVector(Ops[0], - UndefValue::get(Ops[0]->getType()), - makeArrayRef(Indices, NumElts), - "extract"); + Value *Res = Builder.CreateShuffleVector(Ops[0], + UndefValue::get(Ops[0]->getType()), + makeArrayRef(Indices, NumElts), + "extract"); + + if (Ops.size() == 4) + Res = EmitX86Select(*this, Ops[3], Res, Ops[2]); + + return Res; } case X86::BI__builtin_ia32_vinsertf128_pd256: case X86::BI__builtin_ia32_vinsertf128_ps256: diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h index fbb4bbce8d..76ce32f086 100644 --- a/lib/Headers/avx512dqintrin.h +++ b/lib/Headers/avx512dqintrin.h @@ -1103,56 +1103,70 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) } #define _mm512_extractf32x8_ps(A, imm) \ - (__m256)__builtin_ia32_extractf32x8((__v16sf)(__m512)(A), (int)(imm)) + (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \ + (__v8sf)_mm256_undefined_ps(), \ + (__mmask8)-1); #define _mm512_mask_extractf32x8_ps(W, U, A, imm) \ - (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \ - (__v8sf)_mm512_extractf32x8_ps((A), (imm)), \ - (__v8sf)(__m256)(W)) + (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \ + (__v8sf)(__m256)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extractf32x8_ps(U, A, imm) \ - (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \ - (__v8sf)_mm512_extractf32x8_ps((A), (imm)), \ - (__v8sf)_mm256_setzero_ps()) + (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \ + (__v8sf)_mm256_setzero_ps(), \ + (__mmask8)(U)) #define _mm512_extractf64x2_pd(A, imm) \ - (__m128d)__builtin_ia32_extractf64x2_512((__v8df)(__m512d)(A), (int)(imm)) + (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \ + (int)(imm), \ + (__v2df)_mm_undefined_pd(), \ + (__mmask8)-1) #define _mm512_mask_extractf64x2_pd(W, U, A, imm) \ - (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ - (__v2df)_mm512_extractf64x2_pd((A), (imm)), \ - (__v2df)(__m128d)(W)) + (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \ + (int)(imm), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extractf64x2_pd(U, A, imm) \ - (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ - (__v2df)_mm512_extractf64x2_pd((A), (imm)), \ - (__v2df)_mm_setzero_pd()) + (__m128d)__builtin_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \ + (int)(imm), \ + (__v2df)_mm_setzero_pd(), \ + (__mmask8)(U)) #define _mm512_extracti32x8_epi32(A, imm) \ - (__m256i)__builtin_ia32_extracti32x8((__v16si)(__m512i)(A), (int)(imm)) + (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v8si)_mm256_undefined_si256(), \ + (__mmask8)-1) #define _mm512_mask_extracti32x8_epi32(W, U, A, imm) \ - (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ - (__v8si)_mm512_extracti32x8_epi32((A), (imm)), \ - (__v8si)(__m256i)(W)) + (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v8si)(__m256i)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extracti32x8_epi32(U, A, imm) \ - (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ - (__v8si)_mm512_extracti32x8_epi32((A), (imm)), \ - (__v8si)_mm256_setzero_si256()) + (__m256i)__builtin_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v8si)_mm256_setzero_si256(), \ + (__mmask8)(U)) #define _mm512_extracti64x2_epi64(A, imm) \ - (__m128i)__builtin_ia32_extracti64x2_512((__v8di)(__m512i)(A), (int)(imm)) + (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \ + (int)(imm), \ + (__v2di)_mm_undefined_si128(), \ + (__mmask8)-1) #define _mm512_mask_extracti64x2_epi64(W, U, A, imm) \ - (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \ - (__v2di)_mm512_extracti64x2_epi64((A), (imm)), \ - (__v2di)(__m128i)(W)) + (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \ + (int)(imm), \ + (__v2di)(__m128i)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extracti64x2_epi64(U, A, imm) \ - (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \ - (__v2di)_mm512_extracti64x2_epi64((A), (imm)), \ - (__v2di)_mm_setzero_si128()) + (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \ + (int)(imm), \ + (__v2di)_mm_setzero_si128(), \ + (__mmask8)(U)) #define _mm512_insertf32x8(A, B, imm) \ (__m512)__builtin_ia32_insertf32x8((__v16sf)(__m512)(A), \ diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 381011ed39..dbac414fff 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -3494,30 +3494,34 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, /* Vector Extract */ #define _mm512_extractf64x4_pd(A, I) \ - (__m256d)__builtin_ia32_extractf64x4((__v8df)(__m512d)(A), (int)(I)) + (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(I), \ + (__v4df)_mm256_undefined_si256(), \ + (__mmask8)-1) #define _mm512_mask_extractf64x4_pd(W, U, A, imm) \ - (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ - (__v4df)_mm512_extractf64x4_pd((A), (imm)), \ - (__v4df)(__m256d)(W)) + (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \ + (__v4df)(__m256d)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extractf64x4_pd(U, A, imm) \ - (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ - (__v4df)_mm512_extractf64x4_pd((A), (imm)), \ - (__v4df)_mm256_setzero_pd()) + (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \ + (__v4df)_mm256_setzero_pd(), \ + (__mmask8)(U)) #define _mm512_extractf32x4_ps(A, I) \ - (__m128)__builtin_ia32_extractf32x4((__v16sf)(__m512)(A), (int)(I)) + (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(I), \ + (__v4sf)_mm_undefined_ps(), \ + (__mmask8)-1) #define _mm512_mask_extractf32x4_ps(W, U, A, imm) \ - (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ - (__v4sf)_mm512_extractf32x4_ps((A), (imm)), \ - (__v4sf)(__m128)(W)) + (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extractf32x4_ps(U, A, imm) \ - (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ - (__v4sf)_mm512_extractf32x4_ps((A), (imm)), \ - (__v4sf)_mm_setzero_ps()) + (__m128)__builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \ + (__v4sf)_mm_setzero_ps(), \ + (__mmask8)(U)) /* Vector Blend */ @@ -7534,30 +7538,34 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) } #define _mm512_extracti32x4_epi32(A, imm) \ - (__m128i)__builtin_ia32_extracti32x4((__v16si)(__m512i)(A), (int)(imm)) + (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v4si)_mm_undefined_si128(), \ + (__mmask8)-1) #define _mm512_mask_extracti32x4_epi32(W, U, A, imm) \ - (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ - (__v4si)_mm512_extracti32x4_epi32((A), (imm)), \ - (__v4si)(__m128i)(W)) + (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extracti32x4_epi32(U, A, imm) \ - (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ - (__v4si)_mm512_extracti32x4_epi32((A), (imm)), \ - (__v4si)_mm_setzero_si128()) + (__m128i)__builtin_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \ + (__v4si)_mm_setzero_si128(), \ + (__mmask8)(U)) #define _mm512_extracti64x4_epi64(A, imm) \ - (__m256i)__builtin_ia32_extracti64x4((__v8di)(__m512i)(A), (int)(imm)) + (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \ + (__v4di)_mm256_undefined_si256(), \ + (__mmask8)-1) #define _mm512_mask_extracti64x4_epi64(W, U, A, imm) \ - (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ - (__v4di)_mm512_extracti64x4_epi64((A), (imm)), \ - (__v4di)(__m256i)(W)) + (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \ + (__v4di)(__m256i)(W), \ + (__mmask8)(U)) #define _mm512_maskz_extracti64x4_epi64(U, A, imm) \ - (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ - (__v4di)_mm512_extracti64x4_epi64((A), (imm)), \ - (__v4di)_mm256_setzero_si256()) + (__m256i)__builtin_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \ + (__v4di)_mm256_setzero_si256(), \ + (__mmask8)(U)) #define _mm512_insertf64x4(A, B, imm) \ (__m512d)__builtin_ia32_insertf64x4((__v8df)(__m512d)(A), \ diff --git a/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h index 8d6ff3ec8d..62c0fd7bd1 100644 --- a/lib/Headers/avx512vldqintrin.h +++ b/lib/Headers/avx512vldqintrin.h @@ -1083,30 +1083,40 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) } #define _mm256_extractf64x2_pd(A, imm) \ - (__m128d)__builtin_ia32_extractf64x2_256((__v4df)(__m256d)(A), (int)(imm)) + (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \ + (int)(imm), \ + (__v2df)_mm_undefined_pd(), \ + (__mmask8)-1) #define _mm256_mask_extractf64x2_pd(W, U, A, imm) \ - (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ - (__v2df)_mm256_extractf64x2_pd((A), (imm)), \ - (__v2df)(__m128d)(W)) + (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \ + (int)(imm), \ + (__v2df)(__m128d)(W), \ + (__mmask8)(U)) #define _mm256_maskz_extractf64x2_pd(U, A, imm) \ - (__m128d)__builtin_ia32_selectpd_128((__mmask8)(U), \ - (__v2df)_mm256_extractf64x2_pd((A), (imm)), \ - (__v2df)_mm_setzero_pd()) + (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \ + (int)(imm), \ + (__v2df)_mm_setzero_pd(), \ + (__mmask8)(U)) #define _mm256_extracti64x2_epi64(A, imm) \ - (__m128i)__builtin_ia32_extracti64x2_256((__v4di)(__m256i)(A), (int)(imm)) + (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \ + (int)(imm), \ + (__v2di)_mm_undefined_si128(), \ + (__mmask8)-1) #define _mm256_mask_extracti64x2_epi64(W, U, A, imm) \ - (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ - (__v2di)_mm256_extracti64x2_epi64((A), (imm)), \ - (__v2di)(__m128i)(W)) + (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \ + (int)(imm), \ + (__v2di)(__m128i)(W), \ + (__mmask8)(U)) #define _mm256_maskz_extracti64x2_epi64(U, A, imm) \ - (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ - (__v2di)_mm256_extracti64x2_epi64((A), (imm)), \ - (__v2di)_mm_setzero_si128()) + (__m128i)__builtin_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \ + (int)(imm), \ + (__v2di)_mm_setzero_si128(), \ + (__mmask8)(U)) #define _mm256_insertf64x2(A, B, imm) \ (__m256d)__builtin_ia32_insertf64x2_256((__v4df)(__m256d)(A), \ diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index 22a1fcb41e..fea88e27c8 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -7699,30 +7699,40 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) } #define _mm256_extractf32x4_ps(A, imm) \ - (__m128)__builtin_ia32_extractf32x4_256((__v8sf)(__m256)(A), (int)(imm)) + (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \ + (int)(imm), \ + (__v4sf)_mm_undefined_ps(), \ + (__mmask8)-1) #define _mm256_mask_extractf32x4_ps(W, U, A, imm) \ - (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ - (__v4sf)_mm256_extractf32x4_ps((A), (imm)), \ - (__v4sf)(__m128)(W)) + (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \ + (int)(imm), \ + (__v4sf)(__m128)(W), \ + (__mmask8)(U)) #define _mm256_maskz_extractf32x4_ps(U, A, imm) \ - (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \ - (__v4sf)_mm256_extractf32x4_ps((A), (imm)), \ - (__v4sf)_mm_setzero_ps()) + (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \ + (int)(imm), \ + (__v4sf)_mm_setzero_ps(), \ + (__mmask8)(U)) #define _mm256_extracti32x4_epi32(A, imm) \ - (__m128i)__builtin_ia32_extracti32x4_256((__v8si)(__m256i)(A), (int)(imm)) + (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \ + (int)(imm), \ + (__v4si)_mm_undefined_si128(), \ + (__mmask8)-1) #define _mm256_mask_extracti32x4_epi32(W, U, A, imm) \ - (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ - (__v4si)_mm256_extracti32x4_epi32((A), (imm)), \ - (__v4si)(__m128i)(W)) + (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \ + (int)(imm), \ + (__v4si)(__m128i)(W), \ + (__mmask8)(U)) #define _mm256_maskz_extracti32x4_epi32(U, A, imm) \ - (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ - (__v4si)_mm256_extracti32x4_epi32((A), (imm)), \ - (__v4si)_mm_setzero_si128()) + (__m128i)__builtin_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \ + (int)(imm), \ + (__v4si)_mm_setzero_si128(), \ + (__mmask8)(U)) #define _mm256_insertf32x4(A, B, imm) \ (__m256)__builtin_ia32_insertf32x4_256((__v8sf)(__m256)(A), \ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 3e0d36b384..ae9c2f021f 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2611,14 +2611,14 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vextractf128_ps256: case X86::BI__builtin_ia32_vextractf128_si256: case X86::BI__builtin_ia32_extract128i256: - case X86::BI__builtin_ia32_extractf64x4: - case X86::BI__builtin_ia32_extracti64x4: - case X86::BI__builtin_ia32_extractf32x8: - case X86::BI__builtin_ia32_extracti32x8: - case X86::BI__builtin_ia32_extractf64x2_256: - case X86::BI__builtin_ia32_extracti64x2_256: - case X86::BI__builtin_ia32_extractf32x4_256: - case X86::BI__builtin_ia32_extracti32x4_256: + case X86::BI__builtin_ia32_extractf64x4_mask: + case X86::BI__builtin_ia32_extracti64x4_mask: + case X86::BI__builtin_ia32_extractf32x8_mask: + case X86::BI__builtin_ia32_extracti32x8_mask: + case X86::BI__builtin_ia32_extractf64x2_256_mask: + case X86::BI__builtin_ia32_extracti64x2_256_mask: + case X86::BI__builtin_ia32_extractf32x4_256_mask: + case X86::BI__builtin_ia32_extracti32x4_256_mask: i = 1; l = 0; u = 1; break; case X86::BI__builtin_ia32_vec_set_v2di: @@ -2641,10 +2641,10 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vec_ext_v4si: case X86::BI__builtin_ia32_vec_ext_v4sf: case X86::BI__builtin_ia32_vec_ext_v4di: - case X86::BI__builtin_ia32_extractf32x4: - case X86::BI__builtin_ia32_extracti32x4: - case X86::BI__builtin_ia32_extractf64x2_512: - case X86::BI__builtin_ia32_extracti64x2_512: + case X86::BI__builtin_ia32_extractf32x4_mask: + case X86::BI__builtin_ia32_extracti32x4_mask: + case X86::BI__builtin_ia32_extractf64x2_512_mask: + case X86::BI__builtin_ia32_extracti64x2_512_mask: i = 1; l = 0; u = 3; break; case X86::BI_mm_prefetch: -- GitLab From ceac5045d938b3c96f736a4f1cbc5299c23c3837 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 21:50:08 +0000 Subject: [PATCH 0068/1023] [X86] Add back some masked vector truncate builtins. Custom IRgen a a few others. I'd like to make the select builtins require an avx512f, avx512bw, or avx512vl fature to match what is normally required to get masking. Truncate is special in that there are instructions with a 128/256-bit masked result even without avx512vl. By using special buitlins we can emit a select without using the 128/256-bit select builtins. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334331 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 2 ++ lib/CodeGen/CGBuiltin.cpp | 29 +++++++++++++++++++++++++++++ lib/Headers/avx512bwintrin.h | 16 +++++++++------- lib/Headers/avx512fintrin.h | 27 +++++++++++++++++---------- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index b694059adc..24c1553004 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1298,6 +1298,7 @@ TARGET_BUILTIN(__builtin_ia32_vpshrdw512_mask, "V32sV32sV32sIiV32sUi", "nc", "av TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "nc", "avx512vl,avx512dq") TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") @@ -1648,6 +1649,7 @@ TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs", "n", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc", "n", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc", "n", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc", "n", "avx512f") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 012428dbb2..9106df0f1c 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9309,6 +9309,35 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, makeArrayRef(Indices, DstNumElts), "insert"); } + case X86::BI__builtin_ia32_pmovqd512_mask: + case X86::BI__builtin_ia32_pmovwb512_mask: { + Value *Res = Builder.CreateTrunc(Ops[0], Ops[1]->getType()); + return EmitX86Select(*this, Ops[2], Res, Ops[1]); + } + case X86::BI__builtin_ia32_pmovdb512_mask: + case X86::BI__builtin_ia32_pmovdw512_mask: + case X86::BI__builtin_ia32_pmovqw512_mask: { + if (const auto *C = dyn_cast(Ops[2])) + if (C->isAllOnesValue()) + return Builder.CreateTrunc(Ops[0], Ops[1]->getType()); + + Intrinsic::ID IID; + switch (BuiltinID) { + default: llvm_unreachable("Unsupported intrinsic!"); + case X86::BI__builtin_ia32_pmovdb512_mask: + IID = Intrinsic::x86_avx512_mask_pmov_db_512; + break; + case X86::BI__builtin_ia32_pmovdw512_mask: + IID = Intrinsic::x86_avx512_mask_pmov_dw_512; + break; + case X86::BI__builtin_ia32_pmovqw512_mask: + IID = Intrinsic::x86_avx512_mask_pmov_qw_512; + break; + } + + Function *Intr = CGM.getIntrinsic(IID); + return Builder.CreateCall(Intr, Ops); + } case X86::BI__builtin_ia32_pblendw128: case X86::BI__builtin_ia32_blendpd: case X86::BI__builtin_ia32_blendps: diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index 0e21a57f31..2590ec7154 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -1080,21 +1080,23 @@ _mm512_maskz_cvtusepi16_epi8 (__mmask32 __M, __m512i __A) { static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_cvtepi16_epi8 (__m512i __A) { - return (__m256i)__builtin_convertvector((__v32hi)__A, __v32qi); + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) _mm256_undefined_si256(), + (__mmask32) -1); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_mask_cvtepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) { - return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, - (__v32qi)_mm512_cvtepi16_epi8(__A), - (__v32qi)__O); + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) __O, + __M); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_maskz_cvtepi16_epi8 (__mmask32 __M, __m512i __A) { - return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, - (__v32qi)_mm512_cvtepi16_epi8(__A), - (__v32qi)_mm256_setzero_si256()); + return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A, + (__v32qi) _mm256_setzero_si256(), + __M); } static __inline__ void __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index dbac414fff..9daa559bb1 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -7402,7 +7402,9 @@ _mm512_mask_cvtusepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm512_cvtepi32_epi8 (__m512i __A) { - return (__m128i)__builtin_convertvector((__v16si)__A, __v16qi); + return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, + (__v16qi) _mm_undefined_si128 (), + (__mmask16) -1); } static __inline__ __m128i __DEFAULT_FN_ATTRS @@ -7429,7 +7431,9 @@ _mm512_mask_cvtepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_cvtepi32_epi16 (__m512i __A) { - return (__m256i)__builtin_convertvector((__v16si)__A, __v16hi); + return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, + (__v16hi) _mm256_undefined_si256 (), + (__mmask16) -1); } static __inline__ __m256i __DEFAULT_FN_ATTRS @@ -7485,23 +7489,24 @@ _mm512_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_cvtepi64_epi32 (__m512i __A) { - return (__m256i)__builtin_convertvector((__v8di) __A, __v8si); + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) _mm256_undefined_si256 (), + (__mmask8) -1); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_mask_cvtepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) { - return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, - (__v8si)_mm512_cvtepi64_epi32(__A), - (__v8si)__O); + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) __O, __M); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A) { - return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, - (__v8si)_mm512_cvtepi64_epi32(__A), - (__v8si)_mm256_setzero_si256()); + return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, + (__v8si) _mm256_setzero_si256 (), + __M); } static __inline__ void __DEFAULT_FN_ATTRS @@ -7513,7 +7518,9 @@ _mm512_mask_cvtepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm512_cvtepi64_epi16 (__m512i __A) { - return (__m128i)__builtin_convertvector((__v8di)__A, __v8hi); + return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, + (__v8hi) _mm_undefined_si128 (), + (__mmask8) -1); } static __inline__ __m128i __DEFAULT_FN_ATTRS -- GitLab From aa824e5dbd4bc914a4f47eeaf3f1827f7ae8b413 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 8 Jun 2018 22:19:42 +0000 Subject: [PATCH 0069/1023] [X86] Add avx512 feature flags to __builtin_ia32_select*. There are many masked intrinsics that just wrap a select around a legacy intrinsic from a pre-avx512 instruciton set. If that intrinsic is implemented as a macro, nothing prevents it from being used when only the older feature was enabled. This likely generates very poor code since we don't have a good way to convert from the scalar masked type used by the intrinsic into a vector control for a legacy blend instruction. If we even have a blend instruction to use. By adding a feature to the select builtins we can prevent and diagnose misuse of these intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334334 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 24c1553004..6be561fc0c 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1793,24 +1793,24 @@ TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "nc" TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "nc", "avx512vbmi,avx512vl") // generic select intrinsics -TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "nc", "") +TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "nc", "avx512f") // MONITORX/MWAITX TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx") -- GitLab From 07451f99826a362ce71558950877aaf5e2323aef Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 9 Jun 2018 00:30:45 +0000 Subject: [PATCH 0070/1023] Use SmallPtrSet instead of SmallSet in places where we iterate over the set. SmallSet forwards to SmallPtrSet for pointer types. SmallPtrSet supports iteration, but a normal SmallSet doesn't. So if it wasn't for the forwarding, this wouldn't work. These places were found by hiding the begin/end methods in the SmallSet forwarding. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334339 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BackendUtil.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index f9855f03a4..4125d507a1 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -1293,7 +1293,7 @@ void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, // Save llvm.compiler.used and remote it. SmallVector UsedArray; - SmallSet UsedGlobals; + SmallPtrSet UsedGlobals; Type *UsedElementType = Type::getInt8Ty(M->getContext())->getPointerTo(0); GlobalVariable *Used = collectUsedGlobalVariables(*M, UsedGlobals, true); for (auto *GV : UsedGlobals) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8dbf5e7ac1..55517fc3f6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -15054,9 +15054,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { static void DelegatingCycleHelper(CXXConstructorDecl* Ctor, - llvm::SmallSet &Valid, - llvm::SmallSet &Invalid, - llvm::SmallSet &Current, + llvm::SmallPtrSet &Valid, + llvm::SmallPtrSet &Invalid, + llvm::SmallPtrSet &Current, Sema &S) { if (Ctor->isInvalidDecl()) return; @@ -15118,7 +15118,7 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, void Sema::CheckDelegatingCtorCycles() { - llvm::SmallSet Valid, Invalid, Current; + llvm::SmallPtrSet Valid, Invalid, Current; for (DelegatingCtorDeclsType::iterator I = DelegatingCtorDecls.begin(ExternalSource), @@ -15126,9 +15126,7 @@ void Sema::CheckDelegatingCtorCycles() { I != E; ++I) DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); - for (llvm::SmallSet::iterator CI = Invalid.begin(), - CE = Invalid.end(); - CI != CE; ++CI) + for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) (*CI)->setInvalidDecl(); } -- GitLab From 694f835265f40cbfbb02bd64ee766d1acd879dc6 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 9 Jun 2018 13:03:49 +0000 Subject: [PATCH 0071/1023] [analyzer] Add dangling internal buffer check. This check will mark raw pointers to C++ standard library container internal buffers 'released' when the objects themselves are destroyed. Such information can be used by MallocChecker to warn about use-after-free problems. In this first version, 'std::basic_string's are supported. Differential Revision: https://reviews.llvm.org/D47135 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334348 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 5 ++ lib/StaticAnalyzer/Checkers/AllocationState.h | 28 ++++++ lib/StaticAnalyzer/Checkers/CMakeLists.txt | 1 + .../DanglingInternalBufferChecker.cpp | 88 +++++++++++++++++++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 24 ++++- test/Analysis/dangling-internal-buffer.cpp | 71 +++++++++++++++ 6 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 lib/StaticAnalyzer/Checkers/AllocationState.h create mode 100644 lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp create mode 100644 test/Analysis/dangling-internal-buffer.cpp diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index eb91155d9d..7887780945 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -300,6 +300,11 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { +def DanglingInternalBufferChecker : Checker<"DanglingInternalBuffer">, + HelpText<"Check for internal raw pointers of C++ standard library containers " + "used after deallocation">, + DescFile<"DanglingInternalBufferChecker.cpp">; + def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, diff --git a/lib/StaticAnalyzer/Checkers/AllocationState.h b/lib/StaticAnalyzer/Checkers/AllocationState.h new file mode 100644 index 0000000000..f87c093a4e --- /dev/null +++ b/lib/StaticAnalyzer/Checkers/AllocationState.h @@ -0,0 +1,28 @@ +//===--- AllocationState.h ------------------------------------- *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +namespace clang { +namespace ento { + +namespace allocation_state { + +ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, + const Expr *Origin); + +} // end namespace allocation_state + +} // end namespace ento +} // end namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index c1c1b99832..c615ad8a4c 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -27,6 +27,7 @@ add_clang_library(clangStaticAnalyzerCheckers CloneChecker.cpp ConversionChecker.cpp CXXSelfAssignmentChecker.cpp + DanglingInternalBufferChecker.cpp DeadStoresChecker.cpp DebugCheckers.cpp DeleteWithNonVirtualDtorChecker.cpp diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp new file mode 100644 index 0000000000..e7884ee104 --- /dev/null +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -0,0 +1,88 @@ +//=== DanglingInternalBufferChecker.cpp ---------------------------*- C++ -*--// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a check that marks a raw pointer to a C++ standard library +// container's inner buffer released when the object is destroyed. This +// information can be used by MallocChecker to detect use-after-free problems. +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "AllocationState.h" + +using namespace clang; +using namespace ento; + +namespace { + +class DanglingInternalBufferChecker : public Checker { + CallDescription CStrFn; + +public: + DanglingInternalBufferChecker() : CStrFn("c_str") {} + + /// Record the connection between the symbol returned by c_str() and the + /// corresponding string object region in the ProgramState. Mark the symbol + /// released if the string object is destroyed. + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; +}; + +} // end anonymous namespace + +// FIXME: c_str() may be called on a string object many times, so it should +// have a list of symbols associated with it. +REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) + +void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { + const auto *ICall = dyn_cast(&Call); + if (!ICall) + return; + + SVal Obj = ICall->getCXXThisVal(); + const auto *TypedR = dyn_cast_or_null(Obj.getAsRegion()); + if (!TypedR) + return; + + auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl(); + if (TypeDecl->getName() != "basic_string") + return; + + ProgramStateRef State = C.getState(); + + if (Call.isCalled(CStrFn)) { + SVal RawPtr = Call.getReturnValue(); + if (!RawPtr.isUnknown()) { + State = State->set(TypedR, RawPtr.getAsSymbol()); + C.addTransition(State); + } + return; + } + + if (isa(ICall)) { + if (State->contains(TypedR)) { + const SymbolRef *StrBufferPtr = State->get(TypedR); + // FIXME: What if Origin is null? + const Expr *Origin = Call.getOriginExpr(); + State = allocation_state::markReleased(State, *StrBufferPtr, Origin); + C.addTransition(State); + return; + } + } +} + +void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) { + registerNewDeleteChecker(Mgr); + Mgr.registerChecker(); +} diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 341fdd2e88..2ab817a1cc 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "AllocationState.h" #include #include @@ -45,7 +46,8 @@ enum AllocationFamily { AF_CXXNew, AF_CXXNewArray, AF_IfNameIndex, - AF_Alloca + AF_Alloca, + AF_InternalBuffer }; class RefState { @@ -1467,6 +1469,7 @@ void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C, case AF_CXXNew: os << "'new'"; return; case AF_CXXNewArray: os << "'new[]'"; return; case AF_IfNameIndex: os << "'if_nameindex()'"; return; + case AF_InternalBuffer: os << "container-specific allocator"; return; case AF_Alloca: case AF_None: llvm_unreachable("not a deallocation expression"); } @@ -1479,6 +1482,7 @@ void MallocChecker::printExpectedDeallocName(raw_ostream &os, case AF_CXXNew: os << "'delete'"; return; case AF_CXXNewArray: os << "'delete[]'"; return; case AF_IfNameIndex: os << "'if_freenameindex()'"; return; + case AF_InternalBuffer: os << "container-specific deallocator"; return; case AF_Alloca: case AF_None: llvm_unreachable("suspicious argument"); } @@ -1653,7 +1657,9 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family, return Optional(); } case AF_CXXNew: - case AF_CXXNewArray: { + case AF_CXXNewArray: + // FIXME: Add new CheckKind for AF_InternalBuffer. + case AF_InternalBuffer: { if (IsALeakCheck) { if (ChecksEnabled[CK_NewDeleteLeaksChecker]) return CK_NewDeleteLeaksChecker; @@ -2991,6 +2997,20 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State, } } +namespace clang { +namespace ento { +namespace allocation_state { + +ProgramStateRef +markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) { + AllocationFamily Family = AF_InternalBuffer; + return State->set(Sym, RefState::getReleased(Family, Origin)); +} + +} // end namespace allocation_state +} // end namespace ento +} // end namespace clang + void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) { registerCStringCheckerBasic(mgr); MallocChecker *checker = mgr.registerChecker(); diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp new file mode 100644 index 0000000000..791bb96047 --- /dev/null +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -0,0 +1,71 @@ +//RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.DanglingInternalBuffer %s -analyzer-output=text -verify + +namespace std { + +template< typename CharT > +class basic_string { +public: + ~basic_string(); + const CharT *c_str(); +}; + +typedef basic_string string; +typedef basic_string wstring; +typedef basic_string u16string; +typedef basic_string u32string; + +} // end namespace std + +void consume(const char *) {} +void consume(const wchar_t *) {} +void consume(const char16_t *) {} +void consume(const char32_t *) {} + +void deref_after_scope_char() { + const char *c; + { + std::string s; + c = s.c_str(); + } + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_wchar_t() { + const wchar_t *w; + { + std::wstring ws; + w = ws.c_str(); + } + consume(w); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_char16_t() { + const char16_t *c16; + { + std::u16string s16; + c16 = s16.c_str(); + } + consume(c16); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_char32_t() { + const char32_t *c32; + { + std::u32string s32; + c32 = s32.c_str(); + } + consume(c32); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_ok() { + const char *c; + std::string s; + { + c = s.c_str(); + } + consume(c); // no-warning +} -- GitLab From 79d87e56ee55943d1d1b9f50fdf8374bc858e782 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 9 Jun 2018 21:08:27 +0000 Subject: [PATCH 0072/1023] [analyzer] Clean up the program state map of DanglingInternalBufferChecker. Symbols are cleaned up from the program state map when they go out of scope. Memory regions are cleaned up when the corresponding object is destroyed, and additionally in 'checkDeadSymbols' in case destructor modeling was incomplete. Differential Revision: https://reviews.llvm.org/D47416 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334352 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../DanglingInternalBufferChecker.cpp | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp index e7884ee104..18f0a22e4a 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -26,7 +26,8 @@ using namespace ento; namespace { -class DanglingInternalBufferChecker : public Checker { +class DanglingInternalBufferChecker : public Checker { CallDescription CStrFn; public: @@ -36,6 +37,9 @@ public: /// corresponding string object region in the ProgramState. Mark the symbol /// released if the string object is destroyed. void checkPostCall(const CallEvent &Call, CheckerContext &C) const; + + /// Clean up the ProgramState map. + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; }; } // end anonymous namespace @@ -76,12 +80,29 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, // FIXME: What if Origin is null? const Expr *Origin = Call.getOriginExpr(); State = allocation_state::markReleased(State, *StrBufferPtr, Origin); + State = State->remove(TypedR); C.addTransition(State); return; } } } +void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + RawPtrMapTy RPM = State->get(); + for (const auto Entry : RPM) { + if (!SymReaper.isLive(Entry.second)) + State = State->remove(Entry.first); + if (!SymReaper.isLiveRegion(Entry.first)) { + // Due to incomplete destructor support, some dead regions might still + // remain in the program state map. Clean them up. + State = State->remove(Entry.first); + } + } + C.addTransition(State); +} + void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) { registerNewDeleteChecker(Mgr); Mgr.registerChecker(); -- GitLab From 8c949cc5961e861aa79b1d780dc070a459045b19 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 10 Jun 2018 06:01:42 +0000 Subject: [PATCH 0073/1023] [X86] Remove masking from the 512-bit packed floating point add/sub/mul/div builtins. Use select in IR instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334359 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 16 +-- lib/Headers/avx512fintrin.h | 172 +++++++++++----------------- lib/Sema/SemaChecking.cpp | 16 +-- test/CodeGen/avx512f-builtins.c | 64 +++++++---- 4 files changed, 126 insertions(+), 142 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 6be561fc0c..fc580df083 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1087,14 +1087,14 @@ TARGET_BUILTIN(__builtin_ia32_pmulhrsw512, "V32sV32sV32s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pmulhuw512, "V32sV32sV32s", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pmulhw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_addpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_addps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subps512, "V16fV16fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_pmaddubsw512, "V32sV64cV64c", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pmaddwd512, "V16iV32sV32s", "nc", "avx512bw") diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 9daa559bb1..a4c0101959 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -2060,40 +2060,32 @@ _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { } #define _mm512_add_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_addpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) #define _mm512_mask_add_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_add_round_pd((A), (B), (R)), \ + (__v8df)(__m512d)(W)); #define _mm512_maskz_add_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_addpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_add_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()); #define _mm512_add_round_ps(A, B, R) \ - (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_addps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) #define _mm512_mask_add_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_add_round_ps((A), (B), (R)), \ + (__v16sf)(__m512)(W)); #define _mm512_maskz_add_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_addps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_add_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()); static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { @@ -2195,40 +2187,32 @@ _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { } #define _mm512_sub_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_subpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) #define _mm512_mask_sub_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_sub_round_pd((A), (B), (R)), \ + (__v8df)(__m512d)(W)); #define _mm512_maskz_sub_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_subpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_sub_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()); #define _mm512_sub_round_ps(A, B, R) \ - (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_subps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) -#define _mm512_mask_sub_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) +#define _mm512_mask_sub_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \ + (__v16sf)(__m512)(W)); -#define _mm512_maskz_sub_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_subps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) +#define _mm512_maskz_sub_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()); static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { @@ -2330,40 +2314,32 @@ _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { } #define _mm512_mul_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_mulpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) #define _mm512_mask_mul_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_mul_round_pd((A), (B), (R)), \ + (__v8df)(__m512d)(W)); #define _mm512_maskz_mul_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_mulpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_mul_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()); #define _mm512_mul_round_ps(A, B, R) \ - (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_mulps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) -#define _mm512_mask_mul_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) +#define _mm512_mask_mul_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \ + (__v16sf)(__m512)(W)); -#define _mm512_maskz_mul_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_mulps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) +#define _mm512_maskz_mul_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()); static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { @@ -2478,40 +2454,32 @@ _mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) { } #define _mm512_div_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_divpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) #define _mm512_mask_div_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_div_round_pd((A), (B), (R)), \ + (__v8df)(__m512d)(W)); #define _mm512_maskz_div_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_divpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_div_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()); #define _mm512_div_round_ps(A, B, R) \ - (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_divps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) -#define _mm512_mask_div_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) +#define _mm512_mask_div_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_div_round_ps((A), (B), (R)), \ + (__v16sf)(__m512)(W)); -#define _mm512_maskz_div_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_divps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) +#define _mm512_maskz_div_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_div_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()); #define _mm512_roundscale_ps(A, B) \ (__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(__m512)(A), (int)(B), \ diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index ae9c2f021f..bf1e3a8b4d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2359,6 +2359,14 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { ArgNum = 1; HasRC = true; break; + case X86::BI__builtin_ia32_addpd512: + case X86::BI__builtin_ia32_addps512: + case X86::BI__builtin_ia32_divpd512: + case X86::BI__builtin_ia32_divps512: + case X86::BI__builtin_ia32_mulpd512: + case X86::BI__builtin_ia32_mulps512: + case X86::BI__builtin_ia32_subpd512: + case X86::BI__builtin_ia32_subps512: case X86::BI__builtin_ia32_cvtsi2sd64: case X86::BI__builtin_ia32_cvtsi2ss32: case X86::BI__builtin_ia32_cvtsi2ss64: @@ -2384,14 +2392,6 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { ArgNum = 3; HasRC = true; break; - case X86::BI__builtin_ia32_addpd512_mask: - case X86::BI__builtin_ia32_addps512_mask: - case X86::BI__builtin_ia32_divpd512_mask: - case X86::BI__builtin_ia32_divps512_mask: - case X86::BI__builtin_ia32_mulpd512_mask: - case X86::BI__builtin_ia32_mulps512_mask: - case X86::BI__builtin_ia32_subpd512_mask: - case X86::BI__builtin_ia32_subps512_mask: case X86::BI__builtin_ia32_addss_round_mask: case X86::BI__builtin_ia32_addsd_round_mask: case X86::BI__builtin_ia32_divss_round_mask: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index dab1c41912..89be9ae0d7 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -2229,17 +2229,19 @@ __m512i test_mm512_mask_mullox_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __ __m512d test_mm512_add_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_add_round_pd - // CHECK: @llvm.x86.avx512.mask.add.pd.512 + // CHECK: @llvm.x86.avx512.add.pd.512 return _mm512_add_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_add_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_add_round_pd - // CHECK: @llvm.x86.avx512.mask.add.pd.512 + // CHECK: @llvm.x86.avx512.add.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_add_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_maskz_add_round_pd(__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_add_round_pd - // CHECK: @llvm.x86.avx512.mask.add.pd.512 + // CHECK: @llvm.x86.avx512.add.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_add_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { @@ -2256,17 +2258,19 @@ __m512d test_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) { } __m512 test_mm512_add_round_ps(__m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_add_round_ps - // CHECK: @llvm.x86.avx512.mask.add.ps.512 + // CHECK: @llvm.x86.avx512.add.ps.512 return _mm512_add_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_add_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_add_round_ps - // CHECK: @llvm.x86.avx512.mask.add.ps.512 + // CHECK: @llvm.x86.avx512.add.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_add_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_maskz_add_round_ps(__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_add_round_ps - // CHECK: @llvm.x86.avx512.mask.add.ps.512 + // CHECK: @llvm.x86.avx512.add.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_add_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { @@ -2333,17 +2337,19 @@ __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { } __m512d test_mm512_sub_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_sub_round_pd - // CHECK: @llvm.x86.avx512.mask.sub.pd.512 + // CHECK: @llvm.x86.avx512.sub.pd.512 return _mm512_sub_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_sub_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_sub_round_pd - // CHECK: @llvm.x86.avx512.mask.sub.pd.512 + // CHECK: @llvm.x86.avx512.sub.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_sub_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_maskz_sub_round_pd(__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_sub_round_pd - // CHECK: @llvm.x86.avx512.mask.sub.pd.512 + // CHECK: @llvm.x86.avx512.sub.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_sub_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { @@ -2360,17 +2366,19 @@ __m512d test_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) { } __m512 test_mm512_sub_round_ps(__m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_sub_round_ps - // CHECK: @llvm.x86.avx512.mask.sub.ps.512 + // CHECK: @llvm.x86.avx512.sub.ps.512 return _mm512_sub_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_sub_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_sub_round_ps - // CHECK: @llvm.x86.avx512.mask.sub.ps.512 + // CHECK: @llvm.x86.avx512.sub.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_sub_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_maskz_sub_round_ps(__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_sub_round_ps - // CHECK: @llvm.x86.avx512.mask.sub.ps.512 + // CHECK: @llvm.x86.avx512.sub.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_sub_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { @@ -2437,17 +2445,19 @@ __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { } __m512d test_mm512_mul_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mul_round_pd - // CHECK: @llvm.x86.avx512.mask.mul.pd.512 + // CHECK: @llvm.x86.avx512.mul.pd.512 return _mm512_mul_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_mul_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_mul_round_pd - // CHECK: @llvm.x86.avx512.mask.mul.pd.512 + // CHECK: @llvm.x86.avx512.mul.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_mul_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_maskz_mul_round_pd(__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_mul_round_pd - // CHECK: @llvm.x86.avx512.mask.mul.pd.512 + // CHECK: @llvm.x86.avx512.mul.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_mul_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { @@ -2464,17 +2474,19 @@ __m512d test_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) { } __m512 test_mm512_mul_round_ps(__m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mul_round_ps - // CHECK: @llvm.x86.avx512.mask.mul.ps.512 + // CHECK: @llvm.x86.avx512.mul.ps.512 return _mm512_mul_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_mul_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_mul_round_ps - // CHECK: @llvm.x86.avx512.mask.mul.ps.512 + // CHECK: @llvm.x86.avx512.mul.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_mul_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_maskz_mul_round_ps(__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_mul_round_ps - // CHECK: @llvm.x86.avx512.mask.mul.ps.512 + // CHECK: @llvm.x86.avx512.mul.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_mul_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { @@ -2541,17 +2553,19 @@ __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { } __m512d test_mm512_div_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_div_round_pd - // CHECK: @llvm.x86.avx512.mask.div.pd.512 + // CHECK: @llvm.x86.avx512.div.pd.512 return _mm512_div_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_mask_div_round_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_div_round_pd - // CHECK: @llvm.x86.avx512.mask.div.pd.512 + // CHECK: @llvm.x86.avx512.div.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_div_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_maskz_div_round_pd(__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_div_round_pd - // CHECK: @llvm.x86.avx512.mask.div.pd.512 + // CHECK: @llvm.x86.avx512.div.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_div_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_div_pd(__m512d __a, __m512d __b) { @@ -2573,17 +2587,19 @@ __m512d test_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) { } __m512 test_mm512_div_round_ps(__m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_div_round_ps - // CHECK: @llvm.x86.avx512.mask.div.ps.512 + // CHECK: @llvm.x86.avx512.div.ps.512 return _mm512_div_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_mask_div_round_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_div_round_ps - // CHECK: @llvm.x86.avx512.mask.div.ps.512 + // CHECK: @llvm.x86.avx512.div.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_div_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_maskz_div_round_ps(__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_div_round_ps - // CHECK: @llvm.x86.avx512.mask.div.ps.512 + // CHECK: @llvm.x86.avx512.div.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_div_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_div_ps(__m512 __A, __m512 __B) { -- GitLab From b911437b328ad5dfac375c5fc633961dc9e8436c Mon Sep 17 00:00:00 2001 From: "Ivan A. Kosarev" Date: Sun, 10 Jun 2018 09:28:10 +0000 Subject: [PATCH 0074/1023] [NEON] Support VST1xN intrinsics in AArch32 mode (Clang part) We currently support them only in AArch64. The NEON Reference, however, says they are 'ARMv7, ARMv8' intrinsics. Differential Revision: https://reviews.llvm.org/D47446 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334362 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 15 +- lib/CodeGen/CGBuiltin.cpp | 57 +- test/CodeGen/aarch64-neon-intrinsics.c | 2364 ++---------------------- test/CodeGen/arm-neon-vst.c | 2312 +++++++++++++++++++++++ 4 files changed, 2488 insertions(+), 2260 deletions(-) create mode 100644 test/CodeGen/arm-neon-vst.c diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 9c149714f3..170fbfb061 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -350,6 +350,12 @@ def VLD1_DUP : WInst<"vld1_dup", "dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VST1 : WInst<"vst1", "vpd", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST1_X2 : WInst<"vst1_x2", "vp2", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VST1_X3 : WInst<"vst1_x3", "vp3", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VST1_X4 : WInst<"vst1_x4", "vp4", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; def VST1_LANE : WInst<"vst1_lane", "vpdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; @@ -581,12 +587,9 @@ def LD1_X3 : WInst<"vld1_x3", "3c", def LD1_X4 : WInst<"vld1_x4", "4c", "dQdPlQPl">; -def ST1_X2 : WInst<"vst1_x2", "vp2", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def ST1_X3 : WInst<"vst1_x3", "vp3", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def ST1_X4 : WInst<"vst1_x4", "vp4", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; +def ST1_X2 : WInst<"vst1_x2", "vp2", "dQdPlQPl">; +def ST1_X3 : WInst<"vst1_x3", "vp3", "dQdPlQPl">; +def ST1_X4 : WInst<"vst1_x4", "vp4", "dQdPlQPl">; def LD1_LANE : WInst<"vld1_lane", "dcdi", "dQdPlQPl">; def LD2_LANE : WInst<"vld2_lane", "2c2i", "lUlQcQUcQPcQlQUldQdPlQPl">; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 9106df0f1c..175e58af78 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -4181,7 +4181,13 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = { NEONMAP0(vshrn_n_v), NEONMAP0(vshrq_n_v), NEONMAP1(vst1_v, arm_neon_vst1, 0), + NEONMAP1(vst1_x2_v, arm_neon_vst1x2, 0), + NEONMAP1(vst1_x3_v, arm_neon_vst1x3, 0), + NEONMAP1(vst1_x4_v, arm_neon_vst1x4, 0), NEONMAP1(vst1q_v, arm_neon_vst1, 0), + NEONMAP1(vst1q_x2_v, arm_neon_vst1x2, 0), + NEONMAP1(vst1q_x3_v, arm_neon_vst1x3, 0), + NEONMAP1(vst1q_x4_v, arm_neon_vst1x4, 0), NEONMAP1(vst2_lane_v, arm_neon_vst2lane, 0), NEONMAP1(vst2_v, arm_neon_vst2, 0), NEONMAP1(vst2q_lane_v, arm_neon_vst2lane, 0), @@ -4341,6 +4347,12 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = { NEONMAP0(vshr_n_v), NEONMAP0(vshrn_n_v), NEONMAP0(vshrq_n_v), + NEONMAP1(vst1_x2_v, aarch64_neon_st1x2, 0), + NEONMAP1(vst1_x3_v, aarch64_neon_st1x3, 0), + NEONMAP1(vst1_x4_v, aarch64_neon_st1x4, 0), + NEONMAP1(vst1q_x2_v, aarch64_neon_st1x2, 0), + NEONMAP1(vst1q_x3_v, aarch64_neon_st1x3, 0), + NEONMAP1(vst1q_x4_v, aarch64_neon_st1x4, 0), NEONMAP0(vsubhn_v), NEONMAP0(vtst_v), NEONMAP0(vtstq_v), @@ -5116,6 +5128,23 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( Ops.push_back(getAlignmentValue32(PtrOp0)); return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, ""); } + case NEON::BI__builtin_neon_vst1_x2_v: + case NEON::BI__builtin_neon_vst1q_x2_v: + case NEON::BI__builtin_neon_vst1_x3_v: + case NEON::BI__builtin_neon_vst1q_x3_v: + case NEON::BI__builtin_neon_vst1_x4_v: + case NEON::BI__builtin_neon_vst1q_x4_v: { + llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType()); + // TODO: Currently in AArch32 mode the pointer operand comes first, whereas + // in AArch64 it comes last. We may want to stick to one or another. + if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) { + llvm::Type *Tys[2] = { VTy, PTy }; + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end()); + return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, ""); + } + llvm::Type *Tys[2] = { PTy, VTy }; + return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, ""); + } case NEON::BI__builtin_neon_vsubhn_v: { llvm::VectorType *SrcTy = llvm::VectorType::getExtendedElementVectorType(VTy); @@ -8075,34 +8104,6 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, llvm::Value *tmp = EmitNeonCall(F, TmpOps, "vrshr_n", 1, true); Ops[0] = Builder.CreateBitCast(Ops[0], VTy); return Builder.CreateAdd(Ops[0], tmp); - } - // FIXME: Sharing loads & stores with 32-bit is complicated by the absence - // of an Align parameter here. - case NEON::BI__builtin_neon_vst1_x2_v: - case NEON::BI__builtin_neon_vst1q_x2_v: - case NEON::BI__builtin_neon_vst1_x3_v: - case NEON::BI__builtin_neon_vst1q_x3_v: - case NEON::BI__builtin_neon_vst1_x4_v: - case NEON::BI__builtin_neon_vst1q_x4_v: { - llvm::Type *PTy = llvm::PointerType::getUnqual(VTy->getVectorElementType()); - llvm::Type *Tys[2] = { VTy, PTy }; - unsigned Int; - switch (BuiltinID) { - case NEON::BI__builtin_neon_vst1_x2_v: - case NEON::BI__builtin_neon_vst1q_x2_v: - Int = Intrinsic::aarch64_neon_st1x2; - break; - case NEON::BI__builtin_neon_vst1_x3_v: - case NEON::BI__builtin_neon_vst1q_x3_v: - Int = Intrinsic::aarch64_neon_st1x3; - break; - case NEON::BI__builtin_neon_vst1_x4_v: - case NEON::BI__builtin_neon_vst1q_x4_v: - Int = Intrinsic::aarch64_neon_st1x4; - break; - } - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end()); - return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, ""); } case NEON::BI__builtin_neon_vld1_v: case NEON::BI__builtin_neon_vld1q_v: { diff --git a/test/CodeGen/aarch64-neon-intrinsics.c b/test/CodeGen/aarch64-neon-intrinsics.c index c013e61c11..40e39912be 100644 --- a/test/CodeGen/aarch64-neon-intrinsics.c +++ b/test/CodeGen/aarch64-neon-intrinsics.c @@ -13277,254 +13277,6 @@ poly64x1x4_t test_vld1_p64_x4(poly64_t const *a) { return vld1_p64_x4(a); } -// CHECK-LABEL: @test_vst1q_u8_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1q_u8_x2(uint8_t *a, uint8x16x2_t b) { - vst1q_u8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_u16_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1q_u16_x2(uint16_t *a, uint16x8x2_t b) { - vst1q_u16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_u32_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]]) -// CHECK: ret void -void test_vst1q_u32_x2(uint32_t *a, uint32x4x2_t b) { - vst1q_u32_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_u64_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]]) -// CHECK: ret void -void test_vst1q_u64_x2(uint64_t *a, uint64x2x2_t b) { - vst1q_u64_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_s8_x2( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1q_s8_x2(int8_t *a, int8x16x2_t b) { - vst1q_s8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_s16_x2( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1q_s16_x2(int16_t *a, int16x8x2_t b) { - vst1q_s16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_s32_x2( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]]) -// CHECK: ret void -void test_vst1q_s32_x2(int32_t *a, int32x4x2_t b) { - vst1q_s32_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_s64_x2( -// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]]) -// CHECK: ret void -void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) { - vst1q_s64_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_f16_x2( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x2.v8f16.p0f16(<8 x half> [[TMP7]], <8 x half> [[TMP8]], half* [[TMP9]]) -// CHECK: ret void -void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) { - vst1q_f16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_f32_x2( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4f32.p0f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], float* [[TMP9]]) -// CHECK: ret void -void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) { - vst1q_f32_x2(a, b); -} - // CHECK-LABEL: @test_vst1q_f64_x2( // CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16 @@ -13551,52 +13303,6 @@ void test_vst1q_f64_x2(float64_t *a, float64x2x2_t b) { vst1q_f64_x2(a, b); } -// CHECK-LABEL: @test_vst1q_p8_x2( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1q_p8_x2(poly8_t *a, poly8x16x2_t b) { - vst1q_p8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1q_p16_x2( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) { - vst1q_p16_x2(a, b); -} - // CHECK-LABEL: @test_vst1q_p64_x2( // CHECK: [[B:%.*]] = alloca %struct.poly64x2x2_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16 @@ -13623,261 +13329,13 @@ void test_vst1q_p64_x2(poly64_t *a, poly64x2x2_t b) { vst1q_p64_x2(a, b); } -// CHECK-LABEL: @test_vst1_u8_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1_u8_x2(uint8_t *a, uint8x8x2_t b) { - vst1_u8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_u16_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1_u16_x2(uint16_t *a, uint16x4x2_t b) { - vst1_u16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_u32_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]]) -// CHECK: ret void -void test_vst1_u32_x2(uint32_t *a, uint32x2x2_t b) { - vst1_u32_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_u64_x2( -// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]]) -// CHECK: ret void -void test_vst1_u64_x2(uint64_t *a, uint64x1x2_t b) { - vst1_u64_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_s8_x2( -// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1_s8_x2(int8_t *a, int8x8x2_t b) { - vst1_s8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_s16_x2( -// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1_s16_x2(int16_t *a, int16x4x2_t b) { - vst1_s16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_s32_x2( -// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]]) -// CHECK: ret void -void test_vst1_s32_x2(int32_t *a, int32x2x2_t b) { - vst1_s32_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_s64_x2( -// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]]) -// CHECK: ret void -void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) { - vst1_s64_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_f16_x2( -// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4f16.p0f16(<4 x half> [[TMP7]], <4 x half> [[TMP8]], half* [[TMP9]]) -// CHECK: ret void -void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) { - vst1_f16_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_f32_x2( -// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x2.v2f32.p0f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], float* [[TMP9]]) -// CHECK: ret void -void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) { - vst1_f32_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_f64_x2( -// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8* +// CHECK-LABEL: @test_vst1_f64_x2( +// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[B]], i32 0, i32 0 +// CHECK: store [2 x <1 x double>] [[B]].coerce, [2 x <1 x double>]* [[COERCE_DIVE]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x2_t* [[B]] to i8* // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) // CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[__S1]], i32 0, i32 0 @@ -13897,52 +13355,6 @@ void test_vst1_f64_x2(float64_t *a, float64x1x2_t b) { vst1_f64_x2(a, b); } -// CHECK-LABEL: @test_vst1_p8_x2( -// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) -// CHECK: ret void -void test_vst1_p8_x2(poly8_t *a, poly8x8x2_t b) { - vst1_p8_x2(a, b); -} - -// CHECK-LABEL: @test_vst1_p16_x2( -// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[B]], i32 0, i32 0 -// CHECK: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 16, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) -// CHECK: ret void -void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) { - vst1_p16_x2(a, b); -} - // CHECK-LABEL: @test_vst1_p64_x2( // CHECK: [[B:%.*]] = alloca %struct.poly64x1x2_t, align 8 // CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8 @@ -13969,307 +13381,13 @@ void test_vst1_p64_x2(poly64_t *a, poly64x1x2_t b) { vst1_p64_x2(a, b); } -// CHECK-LABEL: @test_vst1q_u8_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1q_u8_x3(uint8_t *a, uint8x16x3_t b) { - vst1q_u8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_u16_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1q_u16_x3(uint16_t *a, uint16x8x3_t b) { - vst1q_u16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_u32_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]]) -// CHECK: ret void -void test_vst1q_u32_x3(uint32_t *a, uint32x4x3_t b) { - vst1q_u32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_u64_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1q_u64_x3(uint64_t *a, uint64x2x3_t b) { - vst1q_u64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_s8_x3( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1q_s8_x3(int8_t *a, int8x16x3_t b) { - vst1q_s8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_s16_x3( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1q_s16_x3(int16_t *a, int16x8x3_t b) { - vst1q_s16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_s32_x3( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]]) -// CHECK: ret void -void test_vst1q_s32_x3(int32_t *a, int32x4x3_t b) { - vst1q_s32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_s64_x3( -// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) { - vst1q_s64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_f16_x3( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x3.v8f16.p0f16(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], half* [[TMP12]]) -// CHECK: ret void -void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) { - vst1q_f16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_f32_x3( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4f32.p0f32(<4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]], float* [[TMP12]]) -// CHECK: ret void -void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) { - vst1q_f32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_f64_x3( -// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8* +// CHECK-LABEL: @test_vst1q_f64_x3( +// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[B]], i32 0, i32 0 +// CHECK: store [3 x <2 x double>] [[B]].coerce, [3 x <2 x double>]* [[COERCE_DIVE]], align 16 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x3_t* [[B]] to i8* // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) // CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* // CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[__S1]], i32 0, i32 0 @@ -14294,60 +13412,6 @@ void test_vst1q_f64_x3(float64_t *a, float64x2x3_t b) { vst1q_f64_x3(a, b); } -// CHECK-LABEL: @test_vst1q_p8_x3( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1q_p8_x3(poly8_t *a, poly8x16x3_t b) { - vst1q_p8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_p16_x3( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 48, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) { - vst1q_p16_x3(a, b); -} - // CHECK-LABEL: @test_vst1q_p64_x3( // CHECK: [[B:%.*]] = alloca %struct.poly64x2x3_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16 @@ -14370,1237 +13434,147 @@ void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) { // CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 // CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> // CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1q_p64_x3(poly64_t *a, poly64x2x3_t b) { - vst1q_p64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_u8_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1_u8_x3(uint8_t *a, uint8x8x3_t b) { - vst1_u8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_u16_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1_u16_x3(uint16_t *a, uint16x4x3_t b) { - vst1_u16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_u32_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]]) -// CHECK: ret void -void test_vst1_u32_x3(uint32_t *a, uint32x2x3_t b) { - vst1_u32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_u64_x3( -// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1_u64_x3(uint64_t *a, uint64x1x3_t b) { - vst1_u64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_s8_x3( -// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1_s8_x3(int8_t *a, int8x8x3_t b) { - vst1_s8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_s16_x3( -// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1_s16_x3(int16_t *a, int16x4x3_t b) { - vst1_s16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_s32_x3( -// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]]) -// CHECK: ret void -void test_vst1_s32_x3(int32_t *a, int32x2x3_t b) { - vst1_s32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_s64_x3( -// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) { - vst1_s64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_f16_x3( -// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4f16.p0f16(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], half* [[TMP12]]) -// CHECK: ret void -void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) { - vst1_f16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_f32_x3( -// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x3.v2f32.p0f32(<2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]], float* [[TMP12]]) -// CHECK: ret void -void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) { - vst1_f32_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_f64_x3( -// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x double> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x double> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <1 x double> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x double> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x double> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x double> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to double* -// CHECK: call void @llvm.aarch64.neon.st1x3.v1f64.p0f64(<1 x double> [[TMP9]], <1 x double> [[TMP10]], <1 x double> [[TMP11]], double* [[TMP12]]) -// CHECK: ret void -void test_vst1_f64_x3(float64_t *a, float64x1x3_t b) { - vst1_f64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_p8_x3( -// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) -// CHECK: ret void -void test_vst1_p8_x3(poly8_t *a, poly8x8x3_t b) { - vst1_p8_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_p16_x3( -// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) -// CHECK: ret void -void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) { - vst1_p16_x3(a, b); -} - -// CHECK-LABEL: @test_vst1_p64_x3( -// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[B]], i32 0, i32 0 -// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> -// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> -// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) -// CHECK: ret void -void test_vst1_p64_x3(poly64_t *a, poly64x1x3_t b) { - vst1_p64_x3(a, b); -} - -// CHECK-LABEL: @test_vst1q_u8_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1q_u8_x4(uint8_t *a, uint8x16x4_t b) { - vst1q_u8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_u16_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1q_u16_x4(uint16_t *a, uint16x8x4_t b) { - vst1q_u16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_u32_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]]) -// CHECK: ret void -void test_vst1q_u32_x4(uint32_t *a, uint32x4x4_t b) { - vst1q_u32_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_u64_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) -// CHECK: ret void -void test_vst1q_u64_x4(uint64_t *a, uint64x2x4_t b) { - vst1q_u64_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_s8_x4( -// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1q_s8_x4(int8_t *a, int8x16x4_t b) { - vst1q_s8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_s16_x4( -// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1q_s16_x4(int16_t *a, int16x8x4_t b) { - vst1q_s16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_s32_x4( -// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]]) -// CHECK: ret void -void test_vst1q_s32_x4(int32_t *a, int32x4x4_t b) { - vst1q_s32_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_s64_x4( -// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) -// CHECK: ret void -void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) { - vst1q_s64_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_f16_x4( -// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x half> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x half> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x half> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x half> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x4.v8f16.p0f16(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], half* [[TMP15]]) -// CHECK: ret void -void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) { - vst1q_f16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_f32_x4( -// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4f32.p0f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]], float* [[TMP15]]) -// CHECK: ret void -void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) { - vst1q_f32_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_f64_x4( -// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x double> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x double> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x double> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <2 x double> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x double> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x double> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x double> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x double> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to double* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2f64.p0f64(<2 x double> [[TMP11]], <2 x double> [[TMP12]], <2 x double> [[TMP13]], <2 x double> [[TMP14]], double* [[TMP15]]) -// CHECK: ret void -void test_vst1q_f64_x4(float64_t *a, float64x2x4_t b) { - vst1q_f64_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_p8_x4( -// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align 16 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align 16 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align 16 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align 16 -// CHECK: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1q_p8_x4(poly8_t *a, poly8x16x4_t b) { - vst1q_p8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_p16_x4( -// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) { - vst1q_p16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1q_p64_x4( -// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16 -// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16 -// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> -// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> -// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> -// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) -// CHECK: ret void -void test_vst1q_p64_x4(poly64_t *a, poly64x2x4_t b) { - vst1q_p64_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_u8_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1_u8_x4(uint8_t *a, uint8x8x4_t b) { - vst1_u8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_u16_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1_u16_x4(uint16_t *a, uint16x4x4_t b) { - vst1_u16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_u32_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]]) -// CHECK: ret void -void test_vst1_u32_x4(uint32_t *a, uint32x2x4_t b) { - vst1_u32_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_u64_x4( -// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]]) -// CHECK: ret void -void test_vst1_u64_x4(uint64_t *a, uint64x1x4_t b) { - vst1_u64_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_s8_x4( -// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1_s8_x4(int8_t *a, int8x8x4_t b) { - vst1_s8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_s16_x4( -// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1_s16_x4(int16_t *a, int16x4x4_t b) { - vst1_s16_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_s32_x4( -// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]]) +// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) // CHECK: ret void -void test_vst1_s32_x4(int32_t *a, int32x2x4_t b) { - vst1_s32_x4(a, b); +void test_vst1q_p64_x3(poly64_t *a, poly64x2x3_t b) { + vst1q_p64_x3(a, b); } -// CHECK-LABEL: @test_vst1_s64_x4( -// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) +// CHECK-LABEL: @test_vst1_f64_x3( +// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[B]], i32 0, i32 0 +// CHECK: store [3 x <1 x double>] [[B]].coerce, [3 x <1 x double>]* [[COERCE_DIVE]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x1x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL]], i64 0, i64 0 +// CHECK: [[TMP3:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x double> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL1]], i64 0, i64 1 +// CHECK: [[TMP5:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x double> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x double>], [3 x <1 x double>]* [[VAL3]], i64 0, i64 2 +// CHECK: [[TMP7:%.*]] = load <1 x double>, <1 x double>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <1 x double> [[TMP7]] to <8 x i8> +// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x double> +// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x double> +// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x double> +// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to double* +// CHECK: call void @llvm.aarch64.neon.st1x3.v1f64.p0f64(<1 x double> [[TMP9]], <1 x double> [[TMP10]], <1 x double> [[TMP11]], double* [[TMP12]]) +// CHECK: ret void +void test_vst1_f64_x3(float64_t *a, float64x1x3_t b) { + vst1_f64_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_p64_x3( +// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[B]], i32 0, i32 0 +// CHECK: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x1x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 24, i1 false) // CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], i64 0, i64 0 +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], i64 0, i64 0 // CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 // CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], i64 0, i64 1 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], i64 0, i64 1 // CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 // CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], i64 0, i64 2 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], i64 0, i64 2 // CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 // CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* -// CHECK: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]]) +// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> +// CHECK: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) // CHECK: ret void -void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) { - vst1_s64_x4(a, b); +void test_vst1_p64_x3(poly64_t *a, poly64x1x3_t b) { + vst1_p64_x3(a, b); } -// CHECK-LABEL: @test_vst1_f16_x4( -// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x half> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x half> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x half> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x half> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to half* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4f16.p0f16(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], half* [[TMP15]]) +// CHECK-LABEL: @test_vst1q_f64_x4( +// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[B]], i32 0, i32 0 +// CHECK: store [4 x <2 x double>] [[B]].coerce, [4 x <2 x double>]* [[COERCE_DIVE]], align 16 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float64x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast double* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL]], i64 0, i64 0 +// CHECK: [[TMP3:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX]], align 16 +// CHECK: [[TMP4:%.*]] = bitcast <2 x double> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL1]], i64 0, i64 1 +// CHECK: [[TMP5:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX2]], align 16 +// CHECK: [[TMP6:%.*]] = bitcast <2 x double> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL3]], i64 0, i64 2 +// CHECK: [[TMP7:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX4]], align 16 +// CHECK: [[TMP8:%.*]] = bitcast <2 x double> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x double>], [4 x <2 x double>]* [[VAL5]], i64 0, i64 3 +// CHECK: [[TMP9:%.*]] = load <2 x double>, <2 x double>* [[ARRAYIDX6]], align 16 +// CHECK: [[TMP10:%.*]] = bitcast <2 x double> [[TMP9]] to <16 x i8> +// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x double> +// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x double> +// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x double> +// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x double> +// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to double* +// CHECK: call void @llvm.aarch64.neon.st1x4.v2f64.p0f64(<2 x double> [[TMP11]], <2 x double> [[TMP12]], <2 x double> [[TMP13]], <2 x double> [[TMP14]], double* [[TMP15]]) // CHECK: ret void -void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) { - vst1_f16_x4(a, b); +void test_vst1q_f64_x4(float64_t *a, float64x2x4_t b) { + vst1q_f64_x4(a, b); } -// CHECK-LABEL: @test_vst1_f32_x4( -// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <2 x float> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float* -// CHECK: call void @llvm.aarch64.neon.st1x4.v2f32.p0f32(<2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]], float* [[TMP15]]) +// CHECK-LABEL: @test_vst1q_p64_x4( +// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16 +// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[B]], i32 0, i32 0 +// CHECK: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly64x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP0]], i8* align 16 [[TMP1]], i64 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], i64 0, i64 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align 16 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], i64 0, i64 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align 16 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], i64 0, i64 2 +// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align 16 +// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], i64 0, i64 3 +// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align 16 +// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> +// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> +// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) // CHECK: ret void -void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) { - vst1_f32_x4(a, b); +void test_vst1q_p64_x4(poly64_t *a, poly64x2x4_t b) { + vst1q_p64_x4(a, b); } // CHECK-LABEL: @test_vst1_f64_x4( @@ -15639,68 +13613,6 @@ void test_vst1_f64_x4(float64_t *a, float64x1x4_t b) { vst1_f64_x4(a, b); } -// CHECK-LABEL: @test_vst1_p8_x4( -// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 -// CHECK: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) -// CHECK: ret void -void test_vst1_p8_x4(poly8_t *a, poly8x8x4_t b) { - vst1_p8_x4(a, b); -} - -// CHECK-LABEL: @test_vst1_p16_x4( -// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[B]], i32 0, i32 0 -// CHECK: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], i64 32, i1 false) -// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], i64 0, i64 0 -// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 -// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> -// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], i64 0, i64 1 -// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 -// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], i64 0, i64 2 -// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 -// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> -// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 -// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], i64 0, i64 3 -// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 -// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> -// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> -// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> -// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> -// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> -// CHECK: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* -// CHECK: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) -// CHECK: ret void -void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) { - vst1_p16_x4(a, b); -} - // CHECK-LABEL: @test_vst1_p64_x4( // CHECK: [[B:%.*]] = alloca %struct.poly64x1x4_t, align 8 // CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8 diff --git a/test/CodeGen/arm-neon-vst.c b/test/CodeGen/arm-neon-vst.c new file mode 100644 index 0000000000..404c4d9c29 --- /dev/null +++ b/test/CodeGen/arm-neon-vst.c @@ -0,0 +1,2312 @@ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ +// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \ +// RUN: FileCheck -check-prefixes=CHECK,CHECK-A64 %s +// RUN: %clang_cc1 -triple armv8-none-linux-gnueabi -target-feature +neon \ +// RUN: -S -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | \ +// RUN: FileCheck -check-prefixes=CHECK,CHECK-A32 %s + +#include + +// CHECK-LABEL: @test_vst1_f16_x2( +// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x half>] [[B]].coerce, [2 x <4 x half>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x half>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x2_t, %struct.float16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x half>], [2 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF:(half|i16)]]> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4f16.p0f16(<4 x half> [[TMP7]], <4 x half> [[TMP8]], half* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) { + vst1_f16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_f16_x3( +// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x half>] [[B]].coerce, [3 x <4 x half>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x half>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x3_t, %struct.float16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x half>], [3 x <4 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4f16.p0f16(<4 x half> [[TMP9]], <4 x half> [[TMP10]], <4 x half> [[TMP11]], half* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) { + vst1_f16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_f16_x4( +// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x half>] [[B]].coerce, [4 x <4 x half>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x half>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x half> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x half> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x4x4_t, %struct.float16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x half>], [4 x <4 x half>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x half>, <4 x half>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <4 x half> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x [[HALF]]> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4f16.p0f16(<4 x half> [[TMP11]], <4 x half> [[TMP12]], <4 x half> [[TMP13]], <4 x half> [[TMP14]], half* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) { + vst1_f16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_f32_x2( +// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <2 x float>] [[B]].coerce, [2 x <2 x float>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x float>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x float>], [2 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2f32.p0f32(<2 x float> [[TMP7]], <2 x float> [[TMP8]], float* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0f32.v2f32(float* [[TMP9]], <2 x float> [[TMP7]], <2 x float> [[TMP8]]) +// CHECK: ret void +void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) { + vst1_f32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_f32_x3( +// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <2 x float>] [[B]].coerce, [3 x <2 x float>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x float>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x3_t, %struct.float32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x float>], [3 x <2 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2f32.p0f32(<2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]], float* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0f32.v2f32(float* [[TMP12]], <2 x float> [[TMP9]], <2 x float> [[TMP10]], <2 x float> [[TMP11]]) +// CHECK: ret void +void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) { + vst1_f32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_f32_x4( +// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <2 x float>] [[B]].coerce, [4 x <2 x float>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x float>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x float> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x float> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x2x4_t, %struct.float32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x float>], [4 x <2 x float>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <2 x float>, <2 x float>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <2 x float> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x float> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2f32.p0f32(<2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]], float* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0f32.v2f32(float* [[TMP15]], <2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], <2 x float> [[TMP14]]) +// CHECK: ret void +void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) { + vst1_f32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_p16_x2( +// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) { + vst1_p16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_p16_x3( +// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) { + vst1_p16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_p16_x4( +// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) { + vst1_p16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_p8_x2( +// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1_p8_x2(poly8_t *a, poly8x8x2_t b) { + vst1_p8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_p8_x3( +// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1_p8_x3(poly8_t *a, poly8x8x3_t b) { + vst1_p8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_p8_x4( +// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1_p8_x4(poly8_t *a, poly8x8x4_t b) { + vst1_p8_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_s16_x2( +// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1_s16_x2(int16_t *a, int16x4x2_t b) { + vst1_s16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_s16_x3( +// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x3_t, %struct.int16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1_s16_x3(int16_t *a, int16x4x3_t b) { + vst1_s16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_s16_x4( +// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x4x4_t, %struct.int16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1_s16_x4(int16_t *a, int16x4x4_t b) { + vst1_s16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_s32_x2( +// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i32>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v2i32(i32* [[TMP9]], <2 x i32> [[TMP7]], <2 x i32> [[TMP8]]) +// CHECK: ret void +void test_vst1_s32_x2(int32_t *a, int32x2x2_t b) { + vst1_s32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_s32_x3( +// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i32>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x3_t, %struct.int32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v2i32(i32* [[TMP12]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]]) +// CHECK: ret void +void test_vst1_s32_x3(int32_t *a, int32x2x3_t b) { + vst1_s32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_s32_x4( +// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i32>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x2x4_t, %struct.int32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v2i32(i32* [[TMP15]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]]) +// CHECK: ret void +void test_vst1_s32_x4(int32_t *a, int32x2x4_t b) { + vst1_s32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_s64_x2( +// CHECK: [[B:%.*]] = alloca %struct.int64x1x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <1 x i64>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x2_t, %struct.int64x1x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v1i64(i64* [[TMP9]], <1 x i64> [[TMP7]], <1 x i64> [[TMP8]]) +// CHECK: ret void +void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) { + vst1_s64_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_s64_x3( +// CHECK: [[B:%.*]] = alloca %struct.int64x1x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <1 x i64>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x3_t, %struct.int64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v1i64(i64* [[TMP12]], <1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]]) +// CHECK: ret void +void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) { + vst1_s64_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_s64_x4( +// CHECK: [[B:%.*]] = alloca %struct.int64x1x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int64x1x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <1 x i64>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x1x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x1x4_t, %struct.int64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v1i64(i64* [[TMP15]], <1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]]) +// CHECK: ret void +void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) { + vst1_s64_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_s8_x2( +// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1_s8_x2(int8_t *a, int8x8x2_t b) { + vst1_s8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_s8_x3( +// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1_s8_x3(int8_t *a, int8x8x3_t b) { + vst1_s8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_s8_x4( +// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1_s8_x4(int8_t *a, int8x8x4_t b) { + vst1_s8_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_u16_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x i16>] [[B]].coerce, [2 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i16>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i16>], [2 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i16.p0i16(<4 x i16> [[TMP7]], <4 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v4i16(i16* [[TMP9]], <4 x i16> [[TMP7]], <4 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1_u16_x2(uint16_t *a, uint16x4x2_t b) { + vst1_u16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_u16_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x i16>] [[B]].coerce, [3 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i16>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i16>], [3 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i16.p0i16(<4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v4i16(i16* [[TMP12]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1_u16_x3(uint16_t *a, uint16x4x3_t b) { + vst1_u16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_u16_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x i16>] [[B]].coerce, [4 x <4 x i16>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i16>], [4 x <4 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x i16>, <4 x i16>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i16.p0i16(<4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v4i16(i16* [[TMP15]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1_u16_x4(uint16_t *a, uint16x4x4_t b) { + vst1_u16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_u32_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <2 x i32>] [[B]].coerce, [2 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i32>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i32>], [2 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i32.p0i32(<2 x i32> [[TMP7]], <2 x i32> [[TMP8]], i32* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v2i32(i32* [[TMP9]], <2 x i32> [[TMP7]], <2 x i32> [[TMP8]]) +// CHECK: ret void +void test_vst1_u32_x2(uint32_t *a, uint32x2x2_t b) { + vst1_u32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_u32_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <2 x i32>] [[B]].coerce, [3 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i32>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i32>], [3 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i32.p0i32(<2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]], i32* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v2i32(i32* [[TMP12]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> [[TMP11]]) +// CHECK: ret void +void test_vst1_u32_x3(uint32_t *a, uint32x2x3_t b) { + vst1_u32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_u32_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <2 x i32>] [[B]].coerce, [4 x <2 x i32>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i32>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <2 x i32> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <2 x i32> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <2 x i32>, <2 x i32>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <2 x i32> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <2 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i32.p0i32(<2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], i32* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v2i32(i32* [[TMP15]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]]) +// CHECK: ret void +void test_vst1_u32_x4(uint32_t *a, uint32x2x4_t b) { + vst1_u32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_u64_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint64x1x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <1 x i64>] [[B]].coerce, [2 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <1 x i64>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <1 x i64>], [2 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v1i64.p0i64(<1 x i64> [[TMP7]], <1 x i64> [[TMP8]], i64* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v1i64(i64* [[TMP9]], <1 x i64> [[TMP7]], <1 x i64> [[TMP8]]) +// CHECK: ret void +void test_vst1_u64_x2(uint64_t *a, uint64x1x2_t b) { + vst1_u64_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_u64_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint64x1x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <1 x i64>] [[B]].coerce, [3 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <1 x i64>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <1 x i64>], [3 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v1i64.p0i64(<1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]], i64* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v1i64(i64* [[TMP12]], <1 x i64> [[TMP9]], <1 x i64> [[TMP10]], <1 x i64> [[TMP11]]) +// CHECK: ret void +void test_vst1_u64_x3(uint64_t *a, uint64x1x3_t b) { + vst1_u64_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_u64_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint64x1x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x1x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <1 x i64>] [[B]].coerce, [4 x <1 x i64>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <1 x i64>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x1x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX]], align 8 +// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[TMP3]] to <8 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX2]], align 8 +// CHECK: [[TMP6:%.*]] = bitcast <1 x i64> [[TMP5]] to <8 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX4]], align 8 +// CHECK: [[TMP8:%.*]] = bitcast <1 x i64> [[TMP7]] to <8 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <1 x i64>], [4 x <1 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <1 x i64>, <1 x i64>* [[ARRAYIDX6]], align 8 +// CHECK: [[TMP10:%.*]] = bitcast <1 x i64> [[TMP9]] to <8 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP4]] to <1 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP6]] to <1 x i64> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP8]] to <1 x i64> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP10]] to <1 x i64> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v1i64.p0i64(<1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]], i64* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v1i64(i64* [[TMP15]], <1 x i64> [[TMP11]], <1 x i64> [[TMP12]], <1 x i64> [[TMP13]], <1 x i64> [[TMP14]]) +// CHECK: ret void +void test_vst1_u64_x4(uint64_t *a, uint64x1x4_t b) { + vst1_u64_x4(a, b); +} + +// CHECK-LABEL: @test_vst1_u8_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i8>] [[B]].coerce, [2 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i8>]* %coerce.dive to [2 x i64]* +// CHECK-A32: store [2 x i64] %b.coerce, [2 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 16, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i8>], [2 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1_u8_x2(uint8_t *a, uint8x8x2_t b) { + vst1_u8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1_u8_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i8>] [[B]].coerce, [3 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i8>]* %coerce.dive to [3 x i64]* +// CHECK-A32: store [3 x i64] %b.coerce, [3 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 24, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i8>], [3 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1_u8_x3(uint8_t *a, uint8x8x3_t b) { + vst1_u8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1_u8_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8 +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8 +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i8>] [[B]].coerce, [4 x <8 x i8>]* [[COERCE_DIVE]], align 8 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP0]], i8* align 8 [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX]], align 8 +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8 +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8 +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i8>], [4 x <8 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8 +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i8.p0i8(<8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v8i8(i8* %a, <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <8 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1_u8_x4(uint8_t *a, uint8x8x4_t b) { + vst1_u8_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_f16_x2( +// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align [[QALIGN:(16|8)]] +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x half>] [[B]].coerce, [2 x <8 x half>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x half>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x2_t, %struct.float16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x half>], [2 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8f16.p0f16(<8 x half> [[TMP7]], <8 x half> [[TMP8]], half* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) { + vst1q_f16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_f16_x3( +// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x half>] [[B]].coerce, [3 x <8 x half>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x half>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x3_t, %struct.float16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x half>], [3 x <8 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8f16.p0f16(<8 x half> [[TMP9]], <8 x half> [[TMP10]], <8 x half> [[TMP11]], half* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) { + vst1q_f16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_f16_x4( +// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x half>] [[B]].coerce, [4 x <8 x half>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x half>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float16x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast half* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x half> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x half> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float16x8x4_t, %struct.float16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x half>], [4 x <8 x half>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <8 x half>, <8 x half>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <8 x half> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x [[HALF]]> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to [[HALF]]* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8f16.p0f16(<8 x half> [[TMP11]], <8 x half> [[TMP12]], <8 x half> [[TMP13]], <8 x half> [[TMP14]], half* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) { + vst1q_f16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_f32_x2( +// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x float>] [[B]].coerce, [2 x <4 x float>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x float>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x float>], [2 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4f32.p0f32(<4 x float> [[TMP7]], <4 x float> [[TMP8]], float* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0f32.v4f32(float* [[TMP9]], <4 x float> [[TMP7]], <4 x float> [[TMP8]]) +// CHECK: ret void +void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) { + vst1q_f32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_f32_x3( +// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x float>] [[B]].coerce, [3 x <4 x float>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x float>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x3_t, %struct.float32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x float>], [3 x <4 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4f32.p0f32(<4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]], float* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0f32.v4f32(float* [[TMP12]], <4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x float> [[TMP11]]) +// CHECK: ret void +void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) { + vst1q_f32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_f32_x4( +// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x float>] [[B]].coerce, [4 x <4 x float>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x float>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.float32x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast float* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x float> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x float> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.float32x4x4_t, %struct.float32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x float>], [4 x <4 x float>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x float>, <4 x float>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <4 x float> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x float> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to float* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4f32.p0f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]], float* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0f32.v4f32(float* [[TMP15]], <4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], <4 x float> [[TMP14]]) +// CHECK: ret void +void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) { + vst1q_f32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_p16_x2( +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) { + vst1q_p16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_p16_x3( +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) { + vst1q_p16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_p16_x4( +// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly16x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) { + vst1q_p16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_p8_x2( +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1q_p8_x2(poly8_t *a, poly8x16x2_t b) { + vst1q_p8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_p8_x3( +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1q_p8_x3(poly8_t *a, poly8x16x3_t b) { + vst1q_p8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_p8_x4( +// CHECK: [[B:%.*]] = alloca %struct.poly8x16x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.poly8x16x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.poly8x16x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1q_p8_x4(poly8_t *a, poly8x16x4_t b) { + vst1q_p8_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_s16_x2( +// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1q_s16_x2(int16_t *a, int16x8x2_t b) { + vst1q_s16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_s16_x3( +// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x3_t, %struct.int16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1q_s16_x3(int16_t *a, int16x8x3_t b) { + vst1q_s16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_s16_x4( +// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int16x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int16x8x4_t, %struct.int16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1q_s16_x4(int16_t *a, int16x8x4_t b) { + vst1q_s16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_s32_x2( +// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i32>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v4i32(i32* [[TMP9]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]]) +// CHECK: ret void +void test_vst1q_s32_x2(int32_t *a, int32x4x2_t b) { + vst1q_s32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_s32_x3( +// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i32>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x3_t, %struct.int32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v4i32(i32* [[TMP12]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]]) +// CHECK: ret void +void test_vst1q_s32_x3(int32_t *a, int32x4x3_t b) { + vst1q_s32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_s32_x4( +// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i32>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int32x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int32x4x4_t, %struct.int32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v4i32(i32* [[TMP15]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]]) +// CHECK: ret void +void test_vst1q_s32_x4(int32_t *a, int32x4x4_t b) { + vst1q_s32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_s64_x2( +// CHECK: [[B:%.*]] = alloca %struct.int64x2x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i64>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x2_t, %struct.int64x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v2i64(i64* [[TMP9]], <2 x i64> [[TMP7]], <2 x i64> [[TMP8]]) +// CHECK: ret void +void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) { + vst1q_s64_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_s64_x3( +// CHECK: [[B:%.*]] = alloca %struct.int64x2x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i64>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x3_t, %struct.int64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v2i64(i64* [[TMP12]], <2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]]) +// CHECK: ret void +void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) { + vst1q_s64_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_s64_x4( +// CHECK: [[B:%.*]] = alloca %struct.int64x2x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int64x2x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i64>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int64x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int64x2x4_t, %struct.int64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v2i64(i64* [[TMP15]], <2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]]) +// CHECK: ret void +void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) { + vst1q_s64_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_s8_x2( +// CHECK: [[B:%.*]] = alloca %struct.int8x16x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x2_t, %struct.int8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1q_s8_x2(int8_t *a, int8x16x2_t b) { + vst1q_s8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_s8_x3( +// CHECK: [[B:%.*]] = alloca %struct.int8x16x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x3_t, %struct.int8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1q_s8_x3(int8_t *a, int8x16x3_t b) { + vst1q_s8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_s8_x4( +// CHECK: [[B:%.*]] = alloca %struct.int8x16x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.int8x16x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.int8x16x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.int8x16x4_t, %struct.int8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1q_s8_x4(int8_t *a, int8x16x4_t b) { + vst1q_s8_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_u16_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <8 x i16>] [[B]].coerce, [2 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <8 x i16>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <8 x i16>], [2 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v8i16.p0i16(<8 x i16> [[TMP7]], <8 x i16> [[TMP8]], i16* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i16.v8i16(i16* [[TMP9]], <8 x i16> [[TMP7]], <8 x i16> [[TMP8]]) +// CHECK: ret void +void test_vst1q_u16_x2(uint16_t *a, uint16x8x2_t b) { + vst1q_u16_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_u16_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <8 x i16>] [[B]].coerce, [3 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <8 x i16>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <8 x i16>], [3 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v8i16.p0i16(<8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]], i16* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i16.v8i16(i16* [[TMP12]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], <8 x i16> [[TMP11]]) +// CHECK: ret void +void test_vst1q_u16_x3(uint16_t *a, uint16x8x3_t b) { + vst1q_u16_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_u16_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <8 x i16>] [[B]].coerce, [4 x <8 x i16>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <8 x i16>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint16x8x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i16* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <8 x i16> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <8 x i16> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <8 x i16>], [4 x <8 x i16>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <8 x i16>, <8 x i16>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <8 x i16> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <8 x i16> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i16* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v8i16.p0i16(<8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], i16* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i16.v8i16(i16* [[TMP15]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]]) +// CHECK: ret void +void test_vst1q_u16_x4(uint16_t *a, uint16x8x4_t b) { + vst1q_u16_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_u32_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <4 x i32>] [[B]].coerce, [2 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <4 x i32>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <4 x i32>], [2 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v4i32.p0i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i32.v4i32(i32* [[TMP9]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]]) +// CHECK: ret void +void test_vst1q_u32_x2(uint32_t *a, uint32x4x2_t b) { + vst1q_u32_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_u32_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <4 x i32>] [[B]].coerce, [3 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <4 x i32>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <4 x i32>], [3 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v4i32.p0i32(<4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], i32* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i32.v4i32(i32* [[TMP12]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]]) +// CHECK: ret void +void test_vst1q_u32_x3(uint32_t *a, uint32x4x3_t b) { + vst1q_u32_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_u32_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <4 x i32>] [[B]].coerce, [4 x <4 x i32>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <4 x i32>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint32x4x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i32* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <4 x i32> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <4 x i32>], [4 x <4 x i32>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <4 x i32>, <4 x i32>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <4 x i32> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <4 x i32> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i32* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v4i32.p0i32(<4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], i32* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i32.v4i32(i32* [[TMP15]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]]) +// CHECK: ret void +void test_vst1q_u32_x4(uint32_t *a, uint32x4x4_t b) { + vst1q_u32_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_u64_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint64x2x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <2 x i64>] [[B]].coerce, [2 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <2 x i64>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x2_t, %struct.uint64x2x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <2 x i64>], [2 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK-DAG: [[TMP7:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP8:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP9:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v2i64.p0i64(<2 x i64> [[TMP7]], <2 x i64> [[TMP8]], i64* [[TMP9]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i64.v2i64(i64* [[TMP9]], <2 x i64> [[TMP7]], <2 x i64> [[TMP8]]) +// CHECK: ret void +void test_vst1q_u64_x2(uint64_t *a, uint64x2x2_t b) { + vst1q_u64_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_u64_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint64x2x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <2 x i64>] [[B]].coerce, [3 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <2 x i64>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x3_t, %struct.uint64x2x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <2 x i64>], [3 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> +// CHECK-DAG: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v2i64.p0i64(<2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]], i64* [[TMP12]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i64.v2i64(i64* [[TMP12]], <2 x i64> [[TMP9]], <2 x i64> [[TMP10]], <2 x i64> [[TMP11]]) +// CHECK: ret void +void test_vst1q_u64_x3(uint64_t *a, uint64x2x3_t b) { + vst1q_u64_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_u64_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint64x2x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint64x2x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <2 x i64>] [[B]].coerce, [4 x <2 x i64>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <2 x i64>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x2x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint64x2x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[TMP2:%.*]] = bitcast i64* %a to i8* +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[TMP3]] to <16 x i8> +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[TMP6:%.*]] = bitcast <2 x i64> [[TMP5]] to <16 x i8> +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[TMP8:%.*]] = bitcast <2 x i64> [[TMP7]] to <16 x i8> +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint64x2x4_t, %struct.uint64x2x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <2 x i64>], [4 x <2 x i64>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP9:%.*]] = load <2 x i64>, <2 x i64>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK: [[TMP10:%.*]] = bitcast <2 x i64> [[TMP9]] to <16 x i8> +// CHECK-DAG: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP4]] to <2 x i64> +// CHECK-DAG: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP6]] to <2 x i64> +// CHECK-DAG: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP8]] to <2 x i64> +// CHECK-DAG: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP10]] to <2 x i64> +// CHECK-DAG: [[TMP15:%.*]] = bitcast i8* [[TMP2]] to i64* +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v2i64.p0i64(<2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]], i64* [[TMP15]]) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i64.v2i64(i64* [[TMP15]], <2 x i64> [[TMP11]], <2 x i64> [[TMP12]], <2 x i64> [[TMP13]], <2 x i64> [[TMP14]]) +// CHECK: ret void +void test_vst1q_u64_x4(uint64_t *a, uint64x2x4_t b) { + vst1q_u64_x4(a, b); +} + +// CHECK-LABEL: @test_vst1q_u8_x2( +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x2_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x2_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [2 x <16 x i8>] [[B]].coerce, [2 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [2 x <16 x i8>]* %coerce.dive to [4 x i64]* +// CHECK-A32: store [4 x i64] %b.coerce, [4 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x2_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 32, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x <16 x i8>], [2 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x2.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x2.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]]) +// CHECK: ret void +void test_vst1q_u8_x2(uint8_t *a, uint8x16x2_t b) { + vst1q_u8_x2(a, b); +} + +// CHECK-LABEL: @test_vst1q_u8_x3( +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x3_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x3_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [3 x <16 x i8>] [[B]].coerce, [3 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [3 x <16 x i8>]* %coerce.dive to [6 x i64]* +// CHECK-A32: store [6 x i64] %b.coerce, [6 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x3_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 48, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [3 x <16 x i8>], [3 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x3.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x3.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]]) +// CHECK: ret void +void test_vst1q_u8_x3(uint8_t *a, uint8x16x3_t b) { + vst1q_u8_x3(a, b); +} + +// CHECK-LABEL: @test_vst1q_u8_x4( +// CHECK: [[B:%.*]] = alloca %struct.uint8x16x4_t, align [[QALIGN]] +// CHECK: [[__S1:%.*]] = alloca %struct.uint8x16x4_t, align [[QALIGN]] +// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[B]], i32 0, i32 0 +// CHECK-A64: store [4 x <16 x i8>] [[B]].coerce, [4 x <16 x i8>]* [[COERCE_DIVE]], align 16 +// CHECK-A32: [[COERCE_DIVE_TMP:%.*]] = bitcast [4 x <16 x i8>]* %coerce.dive to [8 x i64]* +// CHECK-A32: store [8 x i64] %b.coerce, [8 x i64]* [[COERCE_DIVE_TMP]], align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__S1]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast %struct.uint8x16x4_t* [[B]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align [[QALIGN]] [[TMP0]], i8* align [[QALIGN]] [[TMP1]], {{i64|i32}} 64, i1 false) +// CHECK: [[VAL:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL]], {{i64|i32}} 0, {{i64|i32}} 0 +// CHECK: [[TMP2:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX]], align [[QALIGN]] +// CHECK: [[VAL1:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL1]], {{i64|i32}} 0, {{i64|i32}} 1 +// CHECK: [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX2]], align [[QALIGN]] +// CHECK: [[VAL3:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX4:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL3]], {{i64|i32}} 0, {{i64|i32}} 2 +// CHECK: [[TMP4:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX4]], align [[QALIGN]] +// CHECK: [[VAL5:%.*]] = getelementptr inbounds %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[__S1]], i32 0, i32 0 +// CHECK: [[ARRAYIDX6:%.*]] = getelementptr inbounds [4 x <16 x i8>], [4 x <16 x i8>]* [[VAL5]], {{i64|i32}} 0, {{i64|i32}} 3 +// CHECK: [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[ARRAYIDX6]], align [[QALIGN]] +// CHECK-A64: call void @llvm.aarch64.neon.st1x4.v16i8.p0i8(<16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]], i8* %a) +// CHECK-A32: call void @llvm.arm.neon.vst1x4.p0i8.v16i8(i8* %a, <16 x i8> [[TMP2]], <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i8> [[TMP5]]) +// CHECK: ret void +void test_vst1q_u8_x4(uint8_t *a, uint8x16x4_t b) { + vst1q_u8_x4(a, b); +} -- GitLab From ceda64df0e97dfc30c4f30f23bc27a786a4bd3d2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 10 Jun 2018 17:27:05 +0000 Subject: [PATCH 0075/1023] [X86] Use target independent masked expandload and compressstore intrinsics to implement expandload/compressstore builtins. Summary: We've had these target independent intrinsics for at least a year and a half. Looks like they do exactly what we need here and the backend already supports them. Reviewers: RKSimon, delena, spatel, GBuella Reviewed By: RKSimon Subscribers: cfe-commits, llvm-commits Differential Revision: https://reviews.llvm.org/D47693 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334366 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 74 +++++++++++++++++++++++++++ test/CodeGen/avx512f-builtins.c | 32 ++++++++---- test/CodeGen/avx512vbmi2-builtins.c | 12 ++--- test/CodeGen/avx512vl-builtins.c | 48 ++++++++--------- test/CodeGen/avx512vlvbmi2-builtins.c | 24 ++++----- 5 files changed, 138 insertions(+), 52 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 175e58af78..674cb487ee 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8496,6 +8496,40 @@ static Value *EmitX86MaskedLoad(CodeGenFunction &CGF, return CGF.Builder.CreateMaskedLoad(Ptr, Align, MaskVec, Ops[1]); } +static Value *EmitX86ExpandLoad(CodeGenFunction &CGF, + ArrayRef Ops) { + llvm::Type *ResultTy = Ops[1]->getType(); + llvm::Type *PtrTy = ResultTy->getVectorElementType(); + + // Cast the pointer to element type. + Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], + llvm::PointerType::getUnqual(PtrTy)); + + Value *MaskVec = getMaskVecValue(CGF, Ops[2], + ResultTy->getVectorNumElements()); + + llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_expandload, + ResultTy); + return CGF.Builder.CreateCall(F, { Ptr, MaskVec, Ops[1] }); +} + +static Value *EmitX86CompressStore(CodeGenFunction &CGF, + ArrayRef Ops) { + llvm::Type *ResultTy = Ops[1]->getType(); + llvm::Type *PtrTy = ResultTy->getVectorElementType(); + + // Cast the pointer to element type. + Value *Ptr = CGF.Builder.CreateBitCast(Ops[0], + llvm::PointerType::getUnqual(PtrTy)); + + Value *MaskVec = getMaskVecValue(CGF, Ops[2], + ResultTy->getVectorNumElements()); + + llvm::Function *F = CGF.CGM.getIntrinsic(Intrinsic::masked_compressstore, + ResultTy); + return CGF.Builder.CreateCall(F, { Ops[1], Ptr, MaskVec }); +} + static Value *EmitX86MaskLogic(CodeGenFunction &CGF, Instruction::BinaryOps Opc, unsigned NumElts, ArrayRef Ops, bool InvertLHS = false) { @@ -9219,6 +9253,46 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return EmitX86MaskedLoad(*this, Ops, Align); } + case X86::BI__builtin_ia32_expandloaddf128_mask: + case X86::BI__builtin_ia32_expandloaddf256_mask: + case X86::BI__builtin_ia32_expandloaddf512_mask: + case X86::BI__builtin_ia32_expandloadsf128_mask: + case X86::BI__builtin_ia32_expandloadsf256_mask: + case X86::BI__builtin_ia32_expandloadsf512_mask: + case X86::BI__builtin_ia32_expandloaddi128_mask: + case X86::BI__builtin_ia32_expandloaddi256_mask: + case X86::BI__builtin_ia32_expandloaddi512_mask: + case X86::BI__builtin_ia32_expandloadsi128_mask: + case X86::BI__builtin_ia32_expandloadsi256_mask: + case X86::BI__builtin_ia32_expandloadsi512_mask: + case X86::BI__builtin_ia32_expandloadhi128_mask: + case X86::BI__builtin_ia32_expandloadhi256_mask: + case X86::BI__builtin_ia32_expandloadhi512_mask: + case X86::BI__builtin_ia32_expandloadqi128_mask: + case X86::BI__builtin_ia32_expandloadqi256_mask: + case X86::BI__builtin_ia32_expandloadqi512_mask: + return EmitX86ExpandLoad(*this, Ops); + + case X86::BI__builtin_ia32_compressstoredf128_mask: + case X86::BI__builtin_ia32_compressstoredf256_mask: + case X86::BI__builtin_ia32_compressstoredf512_mask: + case X86::BI__builtin_ia32_compressstoresf128_mask: + case X86::BI__builtin_ia32_compressstoresf256_mask: + case X86::BI__builtin_ia32_compressstoresf512_mask: + case X86::BI__builtin_ia32_compressstoredi128_mask: + case X86::BI__builtin_ia32_compressstoredi256_mask: + case X86::BI__builtin_ia32_compressstoredi512_mask: + case X86::BI__builtin_ia32_compressstoresi128_mask: + case X86::BI__builtin_ia32_compressstoresi256_mask: + case X86::BI__builtin_ia32_compressstoresi512_mask: + case X86::BI__builtin_ia32_compressstorehi128_mask: + case X86::BI__builtin_ia32_compressstorehi256_mask: + case X86::BI__builtin_ia32_compressstorehi512_mask: + case X86::BI__builtin_ia32_compressstoreqi128_mask: + case X86::BI__builtin_ia32_compressstoreqi256_mask: + case X86::BI__builtin_ia32_compressstoreqi512_mask: + return EmitX86CompressStore(*this, Ops); + case X86::BI__builtin_ia32_storehps: case X86::BI__builtin_ia32_storelps: { llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty); diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 89be9ae0d7..cc34ee5ef6 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -7293,40 +7293,52 @@ __m512i test_mm512_maskz_expand_epi64(__mmask8 __U, __m512i __A) { } __m512i test_mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm512_mask_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.512 + // CHECK: @llvm.masked.expandload.v8i64(i64* %{{.*}}, <8 x i1> %{{.*}}, <8 x i64> %{{.*}}) return _mm512_mask_expandloadu_epi64(__W, __U, __P); } __m512i test_mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm512_maskz_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.512 + // CHECK: @llvm.masked.expandload.v8i64(i64* %{{.*}}, <8 x i1> %{{.*}}, <8 x i64> %{{.*}}) return _mm512_maskz_expandloadu_epi64(__U, __P); } __m512d test_mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm512_mask_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.512 + // CHECK: @llvm.masked.expandload.v8f64(double* %{{.*}}, <8 x i1> %{{.*}}, <8 x double> %{{.*}}) return _mm512_mask_expandloadu_pd(__W, __U, __P); } __m512d test_mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm512_maskz_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.512 + // CHECK: @llvm.masked.expandload.v8f64(double* %{{.*}}, <8 x i1> %{{.*}}, <8 x double> %{{.*}}) return _mm512_maskz_expandloadu_pd(__U, __P); } __m512i test_mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P) { // CHECK-LABEL: @test_mm512_mask_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.512 + // CHECK: @llvm.masked.expandload.v16i32(i32* %{{.*}}, <16 x i1> %{{.*}}, <16 x i32> %{{.*}}) return _mm512_mask_expandloadu_epi32(__W, __U, __P); } __m512i test_mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P) { // CHECK-LABEL: @test_mm512_maskz_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.512 + // CHECK: @llvm.masked.expandload.v16i32(i32* %{{.*}}, <16 x i1> %{{.*}}, <16 x i32> %{{.*}}) return _mm512_maskz_expandloadu_epi32(__U, __P); } +__m512 test_mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P) { + // CHECK-LABEL: @test_mm512_mask_expandloadu_ps + // CHECK: @llvm.masked.expandload.v16f32(float* %{{.*}}, <16 x i1> %{{.*}}, <16 x float> %{{.*}}) + return _mm512_mask_expandloadu_ps(__W, __U, __P); +} + +__m512 test_mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P) { + // CHECK-LABEL: @test_mm512_maskz_expandloadu_ps + // CHECK: @llvm.masked.expandload.v16f32(float* %{{.*}}, <16 x i1> %{{.*}}, <16 x float> %{{.*}}) + return _mm512_maskz_expandloadu_ps(__U, __P); +} + __m512 test_mm512_mask_expand_ps(__m512 __W, __mmask16 __U, __m512 __A) { // CHECK-LABEL: @test_mm512_mask_expand_ps // CHECK: @llvm.x86.avx512.mask.expand.ps.512 @@ -7428,25 +7440,25 @@ __m512 test_mm512_maskz_mov_ps(__mmask16 __U, __m512 __A) { void test_mm512_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m512d __A) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_pd - // CHECK: @llvm.x86.avx512.mask.compress.store.pd.512 + // CHECK: @llvm.masked.compressstore.v8f64(<8 x double> %{{.*}}, double* %{{.*}}, <8 x i1> %{{.*}}) return _mm512_mask_compressstoreu_pd(__P, __U, __A); } void test_mm512_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_epi64 - // CHECK: @llvm.x86.avx512.mask.compress.store.q.512 + // CHECK: @llvm.masked.compressstore.v8i64(<8 x i64> %{{.*}}, i64* %{{.*}}, <8 x i1> %{{.*}}) return _mm512_mask_compressstoreu_epi64(__P, __U, __A); } void test_mm512_mask_compressstoreu_ps(void *__P, __mmask16 __U, __m512 __A) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_ps - // CHECK: @llvm.x86.avx512.mask.compress.store.ps.512 + // CHECK: @llvm.masked.compressstore.v16f32(<16 x float> %{{.*}}, float* %{{.*}}, <16 x i1> %{{.*}}) return _mm512_mask_compressstoreu_ps(__P, __U, __A); } void test_mm512_mask_compressstoreu_epi32(void *__P, __mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_epi32 - // CHECK: @llvm.x86.avx512.mask.compress.store.d.512 + // CHECK: @llvm.masked.compressstore.v16i32(<16 x i32> %{{.*}}, i32* %{{.*}}, <16 x i1> %{{.*}}) return _mm512_mask_compressstoreu_epi32(__P, __U, __A); } diff --git a/test/CodeGen/avx512vbmi2-builtins.c b/test/CodeGen/avx512vbmi2-builtins.c index 4da21e39d4..6d20f9d2ee 100644 --- a/test/CodeGen/avx512vbmi2-builtins.c +++ b/test/CodeGen/avx512vbmi2-builtins.c @@ -28,13 +28,13 @@ __m512i test_mm512_maskz_compress_epi8(__mmask64 __U, __m512i __D) { void test_mm512_mask_compressstoreu_epi16(void *__P, __mmask32 __U, __m512i __D) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_epi16 - // CHECK: @llvm.x86.avx512.mask.compress.store.w.512 + // CHECK: @llvm.masked.compressstore.v32i16(<32 x i16> %{{.*}}, i16* %{{.*}}, <32 x i1> %{{.*}}) _mm512_mask_compressstoreu_epi16(__P, __U, __D); } void test_mm512_mask_compressstoreu_epi8(void *__P, __mmask64 __U, __m512i __D) { // CHECK-LABEL: @test_mm512_mask_compressstoreu_epi8 - // CHECK: @llvm.x86.avx512.mask.compress.store.b.512 + // CHECK: @llvm.masked.compressstore.v64i8(<64 x i8> %{{.*}}, i8* %{{.*}}, <64 x i1> %{{.*}}) _mm512_mask_compressstoreu_epi8(__P, __U, __D); } @@ -64,25 +64,25 @@ __m512i test_mm512_maskz_expand_epi8(__mmask64 __U, __m512i __D) { __m512i test_mm512_mask_expandloadu_epi16(__m512i __S, __mmask32 __U, void const* __P) { // CHECK-LABEL: @test_mm512_mask_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.512 + // CHECK: @llvm.masked.expandload.v32i16(i16* %{{.*}}, <32 x i1> %{{.*}}, <32 x i16> %{{.*}}) return _mm512_mask_expandloadu_epi16(__S, __U, __P); } __m512i test_mm512_maskz_expandloadu_epi16(__mmask32 __U, void const* __P) { // CHECK-LABEL: @test_mm512_maskz_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.512 + // CHECK: @llvm.masked.expandload.v32i16(i16* %{{.*}}, <32 x i1> %{{.*}}, <32 x i16> %{{.*}}) return _mm512_maskz_expandloadu_epi16(__U, __P); } __m512i test_mm512_mask_expandloadu_epi8(__m512i __S, __mmask64 __U, void const* __P) { // CHECK-LABEL: @test_mm512_mask_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.512 + // CHECK: @llvm.masked.expandload.v64i8(i8* %{{.*}}, <64 x i1> %{{.*}}, <64 x i8> %{{.*}}) return _mm512_mask_expandloadu_epi8(__S, __U, __P); } __m512i test_mm512_maskz_expandloadu_epi8(__mmask64 __U, void const* __P) { // CHECK-LABEL: @test_mm512_maskz_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.512 + // CHECK: @llvm.masked.expandload.v64i8(i8* %{{.*}}, <64 x i1> %{{.*}}, <64 x i8> %{{.*}}) return _mm512_maskz_expandloadu_epi8(__U, __P); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 31dd0ec7b2..3cf63b17bc 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -2043,42 +2043,42 @@ __m256i test_mm256_maskz_compress_epi32(__mmask8 __U, __m256i __A) { } void test_mm_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m128d __A) { // CHECK-LABEL: @test_mm_mask_compressstoreu_pd - // CHECK: @llvm.x86.avx512.mask.compress.store.pd.128 + // CHECK: @llvm.masked.compressstore.v2f64(<2 x double> %{{.*}}, double* %{{.*}}, <2 x i1> %{{.*}}) return _mm_mask_compressstoreu_pd(__P,__U,__A); } void test_mm256_mask_compressstoreu_pd(void *__P, __mmask8 __U, __m256d __A) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_pd - // CHECK: @llvm.x86.avx512.mask.compress.store.pd.256 + // CHECK: @llvm.masked.compressstore.v4f64(<4 x double> %{{.*}}, double* %{{.*}}, <4 x i1> %{{.*}}) return _mm256_mask_compressstoreu_pd(__P,__U,__A); } void test_mm_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_compressstoreu_epi64 - // CHECK: @llvm.x86.avx512.mask.compress.store.q.128 + // CHECK: @llvm.masked.compressstore.v2i64(<2 x i64> %{{.*}}, i64* %{{.*}}, <2 x i1> %{{.*}}) return _mm_mask_compressstoreu_epi64(__P,__U,__A); } void test_mm256_mask_compressstoreu_epi64(void *__P, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_epi64 - // CHECK: @llvm.x86.avx512.mask.compress.store.q.256 + // CHECK: @llvm.masked.compressstore.v4i64(<4 x i64> %{{.*}}, i64* %{{.*}}, <4 x i1> %{{.*}}) return _mm256_mask_compressstoreu_epi64(__P,__U,__A); } void test_mm_mask_compressstoreu_ps(void *__P, __mmask8 __U, __m128 __A) { // CHECK-LABEL: @test_mm_mask_compressstoreu_ps - // CHECK: @llvm.x86.avx512.mask.compress.store.ps.128 + // CHECK: @llvm.masked.compressstore.v4f32(<4 x float> %{{.*}}, float* %{{.*}}, <4 x i1> %{{.*}}) return _mm_mask_compressstoreu_ps(__P,__U,__A); } void test_mm256_mask_compressstoreu_ps(void *__P, __mmask8 __U, __m256 __A) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_ps - // CHECK: @llvm.x86.avx512.mask.compress.store.ps.256 + // CHECK: @llvm.masked.compressstore.v8f32(<8 x float> %{{.*}}, float* %{{.*}}, <8 x i1> %{{.*}}) return _mm256_mask_compressstoreu_ps(__P,__U,__A); } void test_mm_mask_compressstoreu_epi32(void *__P, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_compressstoreu_epi32 - // CHECK: @llvm.x86.avx512.mask.compress.store.d.128 + // CHECK: @llvm.masked.compressstore.v4i32(<4 x i32> %{{.*}}, i32* %{{.*}}, <4 x i1> %{{.*}}) return _mm_mask_compressstoreu_epi32(__P,__U,__A); } void test_mm256_mask_compressstoreu_epi32(void *__P, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_epi32 - // CHECK: @llvm.x86.avx512.mask.compress.store.d.256 + // CHECK: @llvm.masked.compressstore.v8i32(<8 x i32> %{{.*}}, i32* %{{.*}}, <8 x i1> %{{.*}}) return _mm256_mask_compressstoreu_epi32(__P,__U,__A); } __m128d test_mm_mask_cvtepi32_pd(__m128d __W, __mmask8 __U, __m128i __A) { @@ -2550,82 +2550,82 @@ __m256i test_mm256_maskz_expand_epi64(__mmask8 __U, __m256i __A) { } __m128d test_mm_mask_expandloadu_pd(__m128d __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_mask_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.128 + // CHECK: @llvm.masked.expandload.v2f64(double* %{{.*}}, <2 x i1> %{{.*}}, <2 x double> %{{.*}}) return _mm_mask_expandloadu_pd(__W,__U,__P); } __m128d test_mm_maskz_expandloadu_pd(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.128 + // CHECK: @llvm.masked.expandload.v2f64(double* %{{.*}}, <2 x i1> %{{.*}}, <2 x double> %{{.*}}) return _mm_maskz_expandloadu_pd(__U,__P); } __m256d test_mm256_mask_expandloadu_pd(__m256d __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.256 + // CHECK: @llvm.masked.expandload.v4f64(double* %{{.*}}, <4 x i1> %{{.*}}, <4 x double> %{{.*}}) return _mm256_mask_expandloadu_pd(__W,__U,__P); } __m256d test_mm256_maskz_expandloadu_pd(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_pd - // CHECK: @llvm.x86.avx512.mask.expand.load.pd.256 + // CHECK: @llvm.masked.expandload.v4f64(double* %{{.*}}, <4 x i1> %{{.*}}, <4 x double> %{{.*}}) return _mm256_maskz_expandloadu_pd(__U,__P); } __m128i test_mm_mask_expandloadu_epi64(__m128i __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_mask_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.128 + // CHECK: @llvm.masked.expandload.v2i64(i64* %{{.*}}, <2 x i1> %{{.*}}, <2 x i64> %{{.*}}) return _mm_mask_expandloadu_epi64(__W,__U,__P); } __m128i test_mm_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.128 + // CHECK: @llvm.masked.expandload.v2i64(i64* %{{.*}}, <2 x i1> %{{.*}}, <2 x i64> %{{.*}}) return _mm_maskz_expandloadu_epi64(__U,__P); } __m256i test_mm256_mask_expandloadu_epi64(__m256i __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.256 + // CHECK: @llvm.masked.expandload.v4i64(i64* %{{.*}}, <4 x i1> %{{.*}}, <4 x i64> %{{.*}}) return _mm256_mask_expandloadu_epi64(__W,__U,__P); } __m256i test_mm256_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_epi64 - // CHECK: @llvm.x86.avx512.mask.expand.load.q.256 + // CHECK: @llvm.masked.expandload.v4i64(i64* %{{.*}}, <4 x i1> %{{.*}}, <4 x i64> %{{.*}}) return _mm256_maskz_expandloadu_epi64(__U,__P); } __m128 test_mm_mask_expandloadu_ps(__m128 __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_mask_expandloadu_ps - // CHECK: @llvm.x86.avx512.mask.expand.load.ps.128 + // CHECK: @llvm.masked.expandload.v4f32(float* %{{.*}}, <4 x i1> %{{.*}}, <4 x float> %{{.*}}) return _mm_mask_expandloadu_ps(__W,__U,__P); } __m128 test_mm_maskz_expandloadu_ps(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_ps - // CHECK: @llvm.x86.avx512.mask.expand.load.ps.128 + // CHECK: @llvm.masked.expandload.v4f32(float* %{{.*}}, <4 x i1> %{{.*}}, <4 x float> %{{.*}}) return _mm_maskz_expandloadu_ps(__U,__P); } __m256 test_mm256_mask_expandloadu_ps(__m256 __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_ps - // CHECK: @llvm.x86.avx512.mask.expand.load.ps.256 + // CHECK: @llvm.masked.expandload.v8f32(float* %{{.*}}, <8 x i1> %{{.*}}, <8 x float> %{{.*}}) return _mm256_mask_expandloadu_ps(__W,__U,__P); } __m256 test_mm256_maskz_expandloadu_ps(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_ps - // CHECK: @llvm.x86.avx512.mask.expand.load.ps.256 + // CHECK: @llvm.masked.expandload.v8f32(float* %{{.*}}, <8 x i1> %{{.*}}, <8 x float> %{{.*}}) return _mm256_maskz_expandloadu_ps(__U,__P); } __m128i test_mm_mask_expandloadu_epi32(__m128i __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_mask_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.128 + // CHECK: @llvm.masked.expandload.v4i32(i32* %{{.*}}, <4 x i1> %{{.*}}, <4 x i32> %{{.*}}) return _mm_mask_expandloadu_epi32(__W,__U,__P); } __m128i test_mm_maskz_expandloadu_epi32(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.128 + // CHECK: @llvm.masked.expandload.v4i32(i32* %{{.*}}, <4 x i1> %{{.*}}, <4 x i32> %{{.*}}) return _mm_maskz_expandloadu_epi32(__U,__P); } __m256i test_mm256_mask_expandloadu_epi32(__m256i __W, __mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.256 + // CHECK: @llvm.masked.expandload.v8i32(i32* %{{.*}}, <8 x i1> %{{.*}}, <8 x i32> %{{.*}}) return _mm256_mask_expandloadu_epi32(__W,__U,__P); } __m256i test_mm256_maskz_expandloadu_epi32(__mmask8 __U, void const *__P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_epi32 - // CHECK: @llvm.x86.avx512.mask.expand.load.d.256 + // CHECK: @llvm.masked.expandload.v8i32(i32* %{{.*}}, <8 x i1> %{{.*}}, <8 x i32> %{{.*}}) return _mm256_maskz_expandloadu_epi32(__U,__P); } __m128 test_mm_mask_expand_ps(__m128 __W, __mmask8 __U, __m128 __A) { diff --git a/test/CodeGen/avx512vlvbmi2-builtins.c b/test/CodeGen/avx512vlvbmi2-builtins.c index 6615616c6f..8ae0ab7da7 100644 --- a/test/CodeGen/avx512vlvbmi2-builtins.c +++ b/test/CodeGen/avx512vlvbmi2-builtins.c @@ -28,13 +28,13 @@ __m128i test_mm_maskz_compress_epi8(__mmask16 __U, __m128i __D) { void test_mm_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D) { // CHECK-LABEL: @test_mm_mask_compressstoreu_epi16 - // CHECK: @llvm.x86.avx512.mask.compress.store.w.128 + // CHECK: @llvm.masked.compressstore.v8i16(<8 x i16> %{{.*}}, i16* %{{.*}}, <8 x i1> %{{.*}}) _mm_mask_compressstoreu_epi16(__P, __U, __D); } void test_mm_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D) { // CHECK-LABEL: @test_mm_mask_compressstoreu_epi8 - // CHECK: @llvm.x86.avx512.mask.compress.store.b.128 + // CHECK: @llvm.masked.compressstore.v16i8(<16 x i8> %{{.*}}, i8* %{{.*}}, <16 x i1> %{{.*}}) _mm_mask_compressstoreu_epi8(__P, __U, __D); } @@ -64,25 +64,25 @@ __m128i test_mm_maskz_expand_epi8(__mmask16 __U, __m128i __D) { __m128i test_mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const* __P) { // CHECK-LABEL: @test_mm_mask_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.128 + // CHECK: @llvm.masked.expandload.v8i16(i16* %{{.*}}, <8 x i1> %{{.*}}, <8 x i16> %{{.*}}) return _mm_mask_expandloadu_epi16(__S, __U, __P); } __m128i test_mm_maskz_expandloadu_epi16(__mmask8 __U, void const* __P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.128 + // CHECK: @llvm.masked.expandload.v8i16(i16* %{{.*}}, <8 x i1> %{{.*}}, <8 x i16> %{{.*}}) return _mm_maskz_expandloadu_epi16(__U, __P); } __m128i test_mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const* __P) { // CHECK-LABEL: @test_mm_mask_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.128 + // CHECK: @llvm.masked.expandload.v16i8(i8* %{{.*}}, <16 x i1> %{{.*}}, <16 x i8> %{{.*}}) return _mm_mask_expandloadu_epi8(__S, __U, __P); } __m128i test_mm_maskz_expandloadu_epi8(__mmask16 __U, void const* __P) { // CHECK-LABEL: @test_mm_maskz_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.128 + // CHECK: @llvm.masked.expandload.v16i8(i8* %{{.*}}, <16 x i1> %{{.*}}, <16 x i8> %{{.*}}) return _mm_maskz_expandloadu_epi8(__U, __P); } @@ -112,13 +112,13 @@ __m256i test_mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D) { void test_mm256_mask_compressstoreu_epi16(void *__P, __mmask16 __U, __m256i __D) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_epi16 - // CHECK: @llvm.x86.avx512.mask.compress.store.w.256 + // CHECK: @llvm.masked.compressstore.v16i16(<16 x i16> %{{.*}}, i16* %{{.*}}, <16 x i1> %{{.*}}) _mm256_mask_compressstoreu_epi16(__P, __U, __D); } void test_mm256_mask_compressstoreu_epi8(void *__P, __mmask32 __U, __m256i __D) { // CHECK-LABEL: @test_mm256_mask_compressstoreu_epi8 - // CHECK: @llvm.x86.avx512.mask.compress.store.b.256 + // CHECK: @llvm.masked.compressstore.v32i8(<32 x i8> %{{.*}}, i8* %{{.*}}, <32 x i1> %{{.*}}) _mm256_mask_compressstoreu_epi8(__P, __U, __D); } @@ -148,25 +148,25 @@ __m256i test_mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D) { __m256i test_mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const* __P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.256 + // CHECK: @llvm.masked.expandload.v16i16(i16* %{{.*}}, <16 x i1> %{{.*}}, <16 x i16> %{{.*}}) return _mm256_mask_expandloadu_epi16(__S, __U, __P); } __m256i test_mm256_maskz_expandloadu_epi16(__mmask16 __U, void const* __P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_epi16 - // CHECK: @llvm.x86.avx512.mask.expand.load.w.256 + // CHECK: @llvm.masked.expandload.v16i16(i16* %{{.*}}, <16 x i1> %{{.*}}, <16 x i16> %{{.*}}) return _mm256_maskz_expandloadu_epi16(__U, __P); } __m256i test_mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const* __P) { // CHECK-LABEL: @test_mm256_mask_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.256 + // CHECK: @llvm.masked.expandload.v32i8(i8* %{{.*}}, <32 x i1> %{{.*}}, <32 x i8> %{{.*}}) return _mm256_mask_expandloadu_epi8(__S, __U, __P); } __m256i test_mm256_maskz_expandloadu_epi8(__mmask32 __U, void const* __P) { // CHECK-LABEL: @test_mm256_maskz_expandloadu_epi8 - // CHECK: @llvm.x86.avx512.mask.expand.load.b.256 + // CHECK: @llvm.masked.expandload.v32i8(i8* %{{.*}}, <32 x i1> %{{.*}}, <32 x i8> %{{.*}}) return _mm256_maskz_expandloadu_epi8(__U, __P); } -- GitLab From adc6bb61d2581c4a5825aca5941b4e84d5a170d8 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 11 Jun 2018 06:18:29 +0000 Subject: [PATCH 0076/1023] [X86] Remove masking from dbpsadbw builtins, use select builtin instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334385 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 6 ++--- lib/Headers/avx512bwintrin.h | 20 ++++++--------- lib/Headers/avx512vlbwintrin.h | 40 ++++++++++++----------------- lib/Sema/SemaChecking.cpp | 6 ++--- test/CodeGen/avx512bw-builtins.c | 8 +++--- test/CodeGen/avx512vlbw-builtins.c | 16 +++++++----- 6 files changed, 45 insertions(+), 51 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index fc580df083..6a3016bcd3 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1745,9 +1745,9 @@ TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw128_mask, "V8sV16cV16cIiV8sUc", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw256_mask, "V16sV32cV32cIiV16sUs", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw512_mask, "V32sV64cV64cIiV32sUi", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "nc", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw512, "V32sV64cV64cIi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc", "nc", "avx512f") diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index 2590ec7154..471ec38191 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -1819,22 +1819,18 @@ _mm512_mask_permutexvar_epi16 (__m512i __W, __mmask32 __M, __m512i __A, (__v64qi)(__m512i)_mm512_setzero_si512()) #define _mm512_dbsad_epu8(A, B, imm) \ - (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \ - (__v64qi)(__m512i)(B), (int)(imm), \ - (__v32hi)_mm512_undefined_epi32(), \ - (__mmask32)-1) + (__m512i)__builtin_ia32_dbpsadbw512((__v64qi)(__m512i)(A), \ + (__v64qi)(__m512i)(B), (int)(imm)) #define _mm512_mask_dbsad_epu8(W, U, A, B, imm) \ - (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \ - (__v64qi)(__m512i)(B), (int)(imm), \ - (__v32hi)(__m512i)(W), \ - (__mmask32)(U)) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_dbsad_epu8((A), (B), (imm)), \ + (__v32hi)(__m512i)(W)) #define _mm512_maskz_dbsad_epu8(U, A, B, imm) \ - (__m512i)__builtin_ia32_dbpsadbw512_mask((__v64qi)(__m512i)(A), \ - (__v64qi)(__m512i)(B), (int)(imm), \ - (__v32hi)_mm512_setzero_si512(), \ - (__mmask32)(U)) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_dbsad_epu8((A), (B), (imm)), \ + (__v32hi)_mm512_setzero_si512()) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_sad_epu8 (__m512i __A, __m512i __B) diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h index a04ef6f17c..f2dfb567dd 100644 --- a/lib/Headers/avx512vlbwintrin.h +++ b/lib/Headers/avx512vlbwintrin.h @@ -2714,40 +2714,32 @@ _mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A, (__v32qi)_mm256_setzero_si256()) #define _mm_dbsad_epu8(A, B, imm) \ - (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \ - (__v16qi)(__m128i)(B), (int)(imm), \ - (__v8hi)_mm_setzero_si128(), \ - (__mmask8)-1) + (__m128i)__builtin_ia32_dbpsadbw128((__v16qi)(__m128i)(A), \ + (__v16qi)(__m128i)(B), (int)(imm)) #define _mm_mask_dbsad_epu8(W, U, A, B, imm) \ - (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \ - (__v16qi)(__m128i)(B), (int)(imm), \ - (__v8hi)(__m128i)(W), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_dbsad_epu8((A), (B), (imm)), \ + (__v8hi)(__m128i)(W)) #define _mm_maskz_dbsad_epu8(U, A, B, imm) \ - (__m128i)__builtin_ia32_dbpsadbw128_mask((__v16qi)(__m128i)(A), \ - (__v16qi)(__m128i)(B), (int)(imm), \ - (__v8hi)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_dbsad_epu8((A), (B), (imm)), \ + (__v8hi)_mm_setzero_si128()) #define _mm256_dbsad_epu8(A, B, imm) \ - (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \ - (__v32qi)(__m256i)(B), (int)(imm), \ - (__v16hi)_mm256_setzero_si256(), \ - (__mmask16)-1) + (__m256i)__builtin_ia32_dbpsadbw256((__v32qi)(__m256i)(A), \ + (__v32qi)(__m256i)(B), (int)(imm)) #define _mm256_mask_dbsad_epu8(W, U, A, B, imm) \ - (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \ - (__v32qi)(__m256i)(B), (int)(imm), \ - (__v16hi)(__m256i)(W), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_dbsad_epu8((A), (B), (imm)), \ + (__v16hi)(__m256i)(W)) #define _mm256_maskz_dbsad_epu8(U, A, B, imm) \ - (__m256i)__builtin_ia32_dbpsadbw256_mask((__v32qi)(__m256i)(A), \ - (__v32qi)(__m256i)(B), (int)(imm), \ - (__v16hi)_mm256_setzero_si256(), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_dbsad_epu8((A), (B), (imm)), \ + (__v16hi)_mm256_setzero_si256()) #undef __DEFAULT_FN_ATTRS diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index bf1e3a8b4d..8730408c8d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2838,9 +2838,9 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_shufps: case X86::BI__builtin_ia32_shufps256: case X86::BI__builtin_ia32_shufps512: - case X86::BI__builtin_ia32_dbpsadbw128_mask: - case X86::BI__builtin_ia32_dbpsadbw256_mask: - case X86::BI__builtin_ia32_dbpsadbw512_mask: + case X86::BI__builtin_ia32_dbpsadbw128: + case X86::BI__builtin_ia32_dbpsadbw256: + case X86::BI__builtin_ia32_dbpsadbw512: case X86::BI__builtin_ia32_vpshldd128_mask: case X86::BI__builtin_ia32_vpshldd256_mask: case X86::BI__builtin_ia32_vpshldd512_mask: diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c index 6803652a79..7d2e1fadf4 100644 --- a/test/CodeGen/avx512bw-builtins.c +++ b/test/CodeGen/avx512bw-builtins.c @@ -1934,19 +1934,21 @@ __m512i test_mm512_maskz_alignr_epi8(__mmask64 __U, __m512i __A,__m512i __B){ __m512i test_mm512_mm_dbsad_epu8(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mm_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512 + // CHECK: @llvm.x86.avx512.dbpsadbw.512 return _mm512_dbsad_epu8(__A, __B, 170); } __m512i test_mm512_mm_mask_dbsad_epu8(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mm_mask_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512 + // CHECK: @llvm.x86.avx512.dbpsadbw.512 + //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_dbsad_epu8(__W, __U, __A, __B, 170); } __m512i test_mm512_mm_maskz_dbsad_epu8(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mm_maskz_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.512 + // CHECK: @llvm.x86.avx512.dbpsadbw.512 + //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_dbsad_epu8(__U, __A, __B, 170); } diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c index 9cc58b6505..427037cafb 100644 --- a/test/CodeGen/avx512vlbw-builtins.c +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -2964,37 +2964,41 @@ __m256i test_mm256_maskz_alignr_epi8(__mmask32 __U, __m256i __A, __m256i __B) { __m128i test_mm_dbsad_epu8(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128 + // CHECK: @llvm.x86.avx512.dbpsadbw.128 return _mm_dbsad_epu8(__A, __B, 170); } __m128i test_mm_mask_dbsad_epu8(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128 + // CHECK: @llvm.x86.avx512.dbpsadbw.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_dbsad_epu8(__W, __U, __A, __B, 170); } __m128i test_mm_maskz_dbsad_epu8(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.128 + // CHECK: @llvm.x86.avx512.dbpsadbw.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_dbsad_epu8(__U, __A, __B, 170); } __m256i test_mm256_dbsad_epu8(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256 + // CHECK: @llvm.x86.avx512.dbpsadbw.256 return _mm256_dbsad_epu8(__A, __B, 170); } __m256i test_mm256_mask_dbsad_epu8(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256 + // CHECK: @llvm.x86.avx512.dbpsadbw.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_dbsad_epu8(__W, __U, __A, __B, 170); } __m256i test_mm256_maskz_dbsad_epu8(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_dbsad_epu8 - // CHECK: @llvm.x86.avx512.mask.dbpsadbw.256 + // CHECK: @llvm.x86.avx512.dbpsadbw.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_dbsad_epu8(__U, __A, __B, 170); } __mmask8 test_mm_movepi16_mask(__m128i __A) { -- GitLab From 31ffb93ee67c05611c1ac53063d1da76021160fe Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 11 Jun 2018 06:54:23 +0000 Subject: [PATCH 0077/1023] [MS ABI] Mangle unnamed empty enums (PR37723) Differential Revision: https://reviews.llvm.org/D47875 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334388 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 10 ++++++---- test/CodeGenCXX/mangle-ms-cxx11.cpp | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index e947479196..94e41991c9 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -884,11 +884,13 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // associate typedef mangled in if they have one. Name += "getName(); - } else if (auto *ED = dyn_cast(TD)) { - auto EnumeratorI = ED->enumerator_begin(); - assert(EnumeratorI != ED->enumerator_end()); + } else if (isa(TD) && + cast(TD)->enumerator_begin() != + cast(TD)->enumerator_end()) { + // Anonymous non-empty enums mangle in the first enumerator. + auto *ED = cast(TD); Name += "getName(); + Name += ED->enumerator_begin()->getName(); } else { // Otherwise, number the types using a $S prefix. Name += " @@ -350,3 +351,10 @@ enum { enumerator }; void f(decltype(enumerator)) {} // CHECK-DAG: define internal void @"?f@@YAXW4@@@Z"( void use_f() { f(enumerator); } + +namespace pr37723 { +struct s { enum {}; enum {}; }; +// DBG-DAG: DW_TAG_enumeration_type{{.*}}identifier: ".?AW4@s@pr37723@@" +// DBG-DAG: DW_TAG_enumeration_type{{.*}}identifier: ".?AW4@s@pr37723@@" +s x; +} -- GitLab From b55ee77aa74ce8eea68ce3f31165286c0b1e2b5e Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 11 Jun 2018 10:28:04 +0000 Subject: [PATCH 0078/1023] Move VersionTuple from clang/Basic to llvm/Support Summary: This kind of functionality is useful to other project apart from clang. LLDB works with version numbers a lot, but it does not have a convenient abstraction for this. Moving this class to a lower level library allows it to be freely used within LLDB. Since this class is used in a lot of places in clang, and it used to be in the clang namespace, it seemed appropriate to add it to the list of adopted classes in LLVM.h to avoid prefixing all uses with "llvm::". Also, I didn't find any tests specific for this class, so I wrote a couple of quick ones for the more interesting bits of functionality. Reviewers: zturner, erik.pilkington Subscribers: mgorny, cfe-commits, llvm-commits Differential Revision: https://reviews.llvm.org/D47887 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334399 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Attr.h | 2 +- include/clang/AST/Availability.h | 2 +- include/clang/AST/DeclBase.h | 2 +- include/clang/AST/ExprObjC.h | 2 +- include/clang/Basic/AlignedAllocation.h | 2 +- include/clang/Basic/LLVM.h | 12 +- include/clang/Basic/ObjCRuntime.h | 2 +- include/clang/Basic/TargetInfo.h | 2 +- include/clang/Basic/VersionTuple.h | 153 ------------------------ include/clang/Driver/ToolChain.h | 2 +- include/clang/Parse/Parser.h | 1 - include/clang/Sema/AttributeList.h | 2 +- include/clang/Serialization/ASTReader.h | 2 +- include/clang/Serialization/ASTWriter.h | 1 - lib/AST/DeclBase.cpp | 2 +- lib/Basic/CMakeLists.txt | 1 - lib/Basic/ObjCRuntime.cpp | 2 +- lib/Basic/VersionTuple.cpp | 100 ---------------- lib/Driver/ToolChain.cpp | 4 +- lib/Driver/ToolChains/Cuda.h | 4 +- lib/Frontend/CompilerInvocation.cpp | 2 +- lib/Serialization/ASTReader.cpp | 4 +- lib/Serialization/ASTWriter.cpp | 2 +- 23 files changed, 27 insertions(+), 281 deletions(-) delete mode 100644 include/clang/Basic/VersionTuple.h delete mode 100644 lib/Basic/VersionTuple.cpp diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 390e840b33..32a61c59d2 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -23,9 +23,9 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/include/clang/AST/Availability.h b/include/clang/AST/Availability.h index e1f5671b8c..28f3c3c01d 100644 --- a/include/clang/AST/Availability.h +++ b/include/clang/AST/Availability.h @@ -15,8 +15,8 @@ #define LLVM_CLANG_AST_AVAILABILITY_H #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" namespace clang { diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index ae7cd4d10d..229e7cd839 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -19,7 +19,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" @@ -28,6 +27,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/VersionTuple.h" #include #include #include diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 361aa48cb2..5dac0e037d 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -25,7 +25,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -36,6 +35,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/type_traits.h" #include #include diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h index 853f8dad25..a84d22dda8 100644 --- a/include/clang/Basic/AlignedAllocation.h +++ b/include/clang/Basic/AlignedAllocation.h @@ -16,9 +16,9 @@ #ifndef LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H #define LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" namespace clang { diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index 885fba6afb..8a432db911 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -28,6 +28,7 @@ namespace llvm { // ADT's. class StringRef; class Twine; + class VersionTuple; template class ArrayRef; template class MutableArrayRef; template class OwningArrayRef; @@ -60,17 +61,18 @@ namespace clang { using llvm::cast_or_null; // ADT's. - using llvm::None; - using llvm::Optional; - using llvm::StringRef; - using llvm::Twine; using llvm::ArrayRef; using llvm::MutableArrayRef; + using llvm::None; + using llvm::Optional; using llvm::OwningArrayRef; + using llvm::SaveAndRestore; using llvm::SmallString; using llvm::SmallVector; using llvm::SmallVectorImpl; - using llvm::SaveAndRestore; + using llvm::StringRef; + using llvm::Twine; + using llvm::VersionTuple; // Error handling. using llvm::Expected; diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index bc51574cf3..d5f4f50fe3 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -16,10 +16,10 @@ #define LLVM_CLANG_BASIC_OBJCRUNTIME_H #include "clang/Basic/LLVM.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" #include namespace clang { diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 08e33f58f5..c5a187e6f8 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -20,7 +20,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetOptions.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" @@ -30,6 +29,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/IR/DataLayout.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/VersionTuple.h" #include #include #include diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h deleted file mode 100644 index e7385b0b3b..0000000000 --- a/include/clang/Basic/VersionTuple.h +++ /dev/null @@ -1,153 +0,0 @@ -//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Defines the clang::VersionTuple class, which represents a version in -/// the form major[.minor[.subminor]]. -/// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H -#define LLVM_CLANG_BASIC_VERSIONTUPLE_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/Optional.h" -#include -#include - -namespace clang { - -/// Represents a version number in the form major[.minor[.subminor[.build]]]. -class VersionTuple { - unsigned Major : 32; - - unsigned Minor : 31; - unsigned HasMinor : 1; - - unsigned Subminor : 31; - unsigned HasSubminor : 1; - - unsigned Build : 31; - unsigned HasBuild : 1; - -public: - VersionTuple() - : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false), - Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major) - : Major(Major), Minor(0), HasMinor(false), Subminor(0), - HasSubminor(false), Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor) - : Major(Major), Minor(Minor), HasMinor(true), Subminor(0), - HasSubminor(false), Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) - : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), - HasSubminor(true), Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, - unsigned Build) - : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), - HasSubminor(true), Build(Build), HasBuild(true) {} - - /// Determine whether this version information is empty - /// (e.g., all version components are zero). - bool empty() const { - return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0; - } - - /// Retrieve the major version number. - unsigned getMajor() const { return Major; } - - /// Retrieve the minor version number, if provided. - Optional getMinor() const { - if (!HasMinor) - return None; - return Minor; - } - - /// Retrieve the subminor version number, if provided. - Optional getSubminor() const { - if (!HasSubminor) - return None; - return Subminor; - } - - /// Retrieve the build version number, if provided. - Optional getBuild() const { - if (!HasBuild) - return None; - return Build; - } - - /// Determine if two version numbers are equivalent. If not - /// provided, minor and subminor version numbers are considered to be zero. - friend bool operator==(const VersionTuple& X, const VersionTuple &Y) { - return X.Major == Y.Major && X.Minor == Y.Minor && - X.Subminor == Y.Subminor && X.Build == Y.Build; - } - - /// Determine if two version numbers are not equivalent. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { - return !(X == Y); - } - - /// Determine whether one version number precedes another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { - return std::tie(X.Major, X.Minor, X.Subminor, X.Build) < - std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build); - } - - /// Determine whether one version number follows another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { - return Y < X; - } - - /// Determine whether one version number precedes or is - /// equivalent to another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { - return !(Y < X); - } - - /// Determine whether one version number follows or is - /// equivalent to another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { - return !(X < Y); - } - - /// Retrieve a string representation of the version number. - std::string getAsString() const; - - /// Try to parse the given string as a version number. - /// \returns \c true if the string does not match the regular expression - /// [0-9]+(\.[0-9]+){0,3} - bool tryParse(StringRef string); -}; - -/// Print a version number. -raw_ostream& operator<<(raw_ostream &Out, const VersionTuple &V); - -} // end namespace clang -#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index f94a210bd9..addf7aa6a9 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -12,7 +12,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/Sanitizers.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" @@ -22,6 +21,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Option/Option.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Target/TargetOptions.h" #include #include diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 49d6182cd2..6e911230b2 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -45,7 +45,6 @@ namespace clang { class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; class PoisonSEHIdentifiersRAIIObject; - class VersionTuple; class OMPClause; class ObjCTypeParamList; class ObjCTypeParameter; diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 0376150180..dd15b7a2f5 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -18,11 +18,11 @@ #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/VersionTuple.h" #include #include #include diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index d9e9174b74..7de511ad61 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -28,7 +28,6 @@ #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/PreprocessingRecord.h" @@ -62,6 +61,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VersionTuple.h" #include #include #include diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 9d4a3f9cf5..28db00df89 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -93,7 +93,6 @@ class SwitchCase; class TemplateParameterList; class Token; class TypeSourceInfo; -class VersionTuple; /// Writes an AST file containing the contents of a translation unit. /// diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 3db886957c..7b7febdc41 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -34,7 +34,6 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" @@ -42,6 +41,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index 2e394916b5..e82f451dea 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -93,7 +93,6 @@ add_clang_library(clangBasic Targets/XCore.cpp TokenKinds.cpp Version.cpp - VersionTuple.cpp VirtualFileSystem.cpp Warnings.cpp XRayInstr.cpp diff --git a/lib/Basic/ObjCRuntime.cpp b/lib/Basic/ObjCRuntime.cpp index 15f38d1156..8fa0afbe03 100644 --- a/lib/Basic/ObjCRuntime.cpp +++ b/lib/Basic/ObjCRuntime.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/ObjCRuntime.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/lib/Basic/VersionTuple.cpp b/lib/Basic/VersionTuple.cpp deleted file mode 100644 index 7a9176a808..0000000000 --- a/lib/Basic/VersionTuple.cpp +++ /dev/null @@ -1,100 +0,0 @@ -//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the VersionTuple class, which represents a version in -// the form major[.minor[.subminor]]. -// -//===----------------------------------------------------------------------===// -#include "clang/Basic/VersionTuple.h" -#include "llvm/Support/raw_ostream.h" - -using namespace clang; - -std::string VersionTuple::getAsString() const { - std::string Result; - { - llvm::raw_string_ostream Out(Result); - Out << *this; - } - return Result; -} - -raw_ostream& clang::operator<<(raw_ostream &Out, - const VersionTuple &V) { - Out << V.getMajor(); - if (Optional Minor = V.getMinor()) - Out << '.' << *Minor; - if (Optional Subminor = V.getSubminor()) - Out << '.' << *Subminor; - if (Optional Build = V.getBuild()) - Out << '.' << *Build; - return Out; -} - -static bool parseInt(StringRef &input, unsigned &value) { - assert(value == 0); - if (input.empty()) return true; - - char next = input[0]; - input = input.substr(1); - if (next < '0' || next > '9') return true; - value = (unsigned) (next - '0'); - - while (!input.empty()) { - next = input[0]; - if (next < '0' || next > '9') return false; - input = input.substr(1); - value = value * 10 + (unsigned) (next - '0'); - } - - return false; -} - -bool VersionTuple::tryParse(StringRef input) { - unsigned major = 0, minor = 0, micro = 0, build = 0; - - // Parse the major version, [0-9]+ - if (parseInt(input, major)) return true; - - if (input.empty()) { - *this = VersionTuple(major); - return false; - } - - // If we're not done, parse the minor version, \.[0-9]+ - if (input[0] != '.') return true; - input = input.substr(1); - if (parseInt(input, minor)) return true; - - if (input.empty()) { - *this = VersionTuple(major, minor); - return false; - } - - // If we're not done, parse the micro version, \.[0-9]+ - if (input[0] != '.') return true; - input = input.substr(1); - if (parseInt(input, micro)) return true; - - if (input.empty()) { - *this = VersionTuple(major, minor, micro); - return false; - } - - // If we're not done, parse the micro version, \.[0-9]+ - if (input[0] != '.') return true; - input = input.substr(1); - if (parseInt(input, build)) return true; - - // If we have characters left over, it's an error. - if (!input.empty()) return true; - - *this = VersionTuple(major, minor, micro, build); - return false; -} diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index a3799ac613..a56a038054 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -13,7 +13,6 @@ #include "ToolChains/Clang.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -29,6 +28,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/llvm-config.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" @@ -36,9 +36,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/VersionTuple.h" #include #include #include diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h index 057eb220c2..99d5a4a628 100644 --- a/lib/Driver/ToolChains/Cuda.h +++ b/lib/Driver/ToolChains/Cuda.h @@ -11,14 +11,14 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H #include "clang/Basic/Cuda.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" -#include "clang/Driver/ToolChain.h" #include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/VersionTuple.h" #include #include diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b10155da96..a959cdb234 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -23,7 +23,6 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Basic/VirtualFileSystem.h" #include "clang/Basic/Visibility.h" #include "clang/Basic/XRayInstr.h" @@ -76,6 +75,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Regex.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" #include diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4dd7972027..89dff67446 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -61,7 +61,6 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/TokenKinds.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Frontend/PCHContainerOperations.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -104,8 +103,8 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -115,6 +114,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index c1f552e536..1e3a098b09 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -53,7 +53,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -97,6 +96,7 @@ #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include -- GitLab From 78925906a9022bae74e22f9181e91dd63d45bba2 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 11 Jun 2018 12:53:25 +0000 Subject: [PATCH 0079/1023] [clang-format] text protos: put entries on separate lines if there is a submessage Summary: This patch updates clang-format text protos to put entries of a submessage into separate lines if the submessage contains at least two entries and contains at least one submessage entry. For example, the entries here are kept on separate lines even if putting them on a single line would be under the column limit: ``` message: { entry: 1 submessage: { key: value } } ``` Messages containing a single submessage or several scalar entries can still be put on one line if they fit: ``` message { submessage { key: value } } message { x: 1 y: 2 z: 3 } ``` Reviewers: sammccall Reviewed By: sammccall Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D46757 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334401 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 68 +++++++++ unittests/Format/FormatTestProto.cpp | 131 ++++++++++++++++++ unittests/Format/FormatTestRawStrings.cpp | 18 ++- unittests/Format/FormatTestTextProto.cpp | 161 ++++++++++++++++++++-- 4 files changed, 362 insertions(+), 16 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 56f1841222..1ffdb1c864 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -2924,6 +2924,74 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.is(TT_ProtoExtensionLSquare)) return true; + // In text proto instances if a submessage contains at least 2 entries and at + // least one of them is a submessage, like A { ... B { ... } ... }, + // put all of the entries of A on separate lines by forcing the selector of + // the submessage B to be put on a newline. + // + // Example: these can stay on one line: + // a { scalar_1: 1 scalar_2: 2 } + // a { b { key: value } } + // + // and these entries need to be on a new line even if putting them all in one + // line is under the column limit: + // a { + // scalar: 1 + // b { key: value } + // } + // + // We enforce this by breaking before a submessage field that has previous + // siblings, *and* breaking before a field that follows a submessage field. + // + // Be careful to exclude the case [proto.ext] { ... } since the `]` is + // the TT_SelectorName there, but we don't want to break inside the brackets. + // We ensure elsewhere that extensions are always on their own line. + if ((Style.Language == FormatStyle::LK_Proto || + Style.Language == FormatStyle::LK_TextProto) && + Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) { + // Look for the scope opener after selector in cases like: + // selector { ... + // selector: { ... + FormatToken *LBrace = + Right.Next->is(tok::colon) ? Right.Next->Next : Right.Next; + if (LBrace && + // The scope opener is one of {, [, <: + // selector { ... } + // selector [ ... ] + // selector < ... > + // + // In case of selector { ... }, the l_brace is TT_DictLiteral. + // In case of an empty selector {}, the l_brace is not TT_DictLiteral, + // so we check for immediately following r_brace. + ((LBrace->is(tok::l_brace) && + (LBrace->is(TT_DictLiteral) || + (LBrace->Next && LBrace->Next->is(tok::r_brace)))) || + LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) { + // If Left.ParameterCount is 0, then this submessage entry is not the + // first in its parent submessage, and we want to break before this entry. + // If Left.ParameterCount is greater than 0, then its parent submessage + // might contain 1 or more entries and we want to break before this entry + // if it contains at least 2 entries. We deal with this case later by + // detecting and breaking before the next entry in the parent submessage. + if (Left.ParameterCount == 0) + return true; + // However, if this submessage is the first entry in its parent + // submessage, Left.ParameterCount might be 1 in some cases. + // We deal with this case later by detecting an entry + // following a closing paren of this submessage. + } + + // If this is an entry immediately following a submessage, it will be + // preceded by a closing paren of that submessage, like in: + // left---. .---right + // v v + // sub: { ... } key: value + // If there was a comment between `}` an `key` above, then `key` would be + // put on a new line anyways. + if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square)) + return true; + } + return false; } diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp index 779a5ec7d7..a15ba62ffc 100644 --- a/unittests/Format/FormatTestProto.cpp +++ b/unittests/Format/FormatTestProto.cpp @@ -493,5 +493,136 @@ TEST_F(FormatTestProto, AcceptsOperatorAsKeyInOptions) { "};"); } +TEST_F(FormatTestProto, BreaksEntriesOfSubmessagesContainingSubmessages) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; + // The column limit allows for the keys submessage to be put on 1 line, but we + // break it since it contains a submessage an another entry. + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub <>\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub {}\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub {}\n" + " sub: <>\n" + " sub: []\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub { msg: 1 }\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: { msg: 1 }\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub < msg: 1 >\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ msg: 1 ]\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: <\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ 1, 2 ]\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub {}\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: []\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub <>\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub { key: value }\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: data\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " item: data\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " sub: {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + " }\n" + "}"); +} + } // end namespace tooling } // end namespace clang diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp index 84bb4a12aa..3ec6bb9cb4 100644 --- a/unittests/Format/FormatTestRawStrings.cpp +++ b/unittests/Format/FormatTestRawStrings.cpp @@ -199,12 +199,6 @@ TEST_F(FormatTestRawStrings, ReformatsShortRawStringsOnSingleLine) { format( R"test(P p = TP(R"pb(item_1:1 item_2:2)pb");)test", getRawStringPbStyleWithColumns(40))); - expect_eq( - R"test(P p = TP(R"pb(item_1 < 1 > item_2: { 2 })pb");)test", - format( - R"test(P p = TP(R"pb(item_1<1> item_2:{2})pb");)test", - getRawStringPbStyleWithColumns(40))); - // Merge two short lines into one. expect_eq(R"test( std::string s = R"pb( @@ -220,6 +214,18 @@ std::string s = R"pb( getRawStringPbStyleWithColumns(40))); } +TEST_F(FormatTestRawStrings, BreaksShortRawStringsWhenNeeded) { + // The raw string contains multiple submessage entries, so break for + // readability. + expect_eq(R"test( +P p = TP(R"pb(item_1 < 1 > + item_2: { 2 })pb");)test", + format( + R"test( +P p = TP(R"pb(item_1<1> item_2:{2})pb");)test", + getRawStringPbStyleWithColumns(40))); +} + TEST_F(FormatTestRawStrings, BreaksRawStringsExceedingColumnLimit) { expect_eq(R"test( P p = TPPPPPPPPPPPPPPP( diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index fcf118eee8..d62975feb4 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -171,17 +171,48 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { verifyFormat("msg_field < field_a < field_b <> > >"); verifyFormat("msg_field: < field_a < field_b: <> > >"); verifyFormat("msg_field < field_a: OK, field_b: \"OK\" >"); - verifyFormat("msg_field < field_a: OK field_b: <>, field_c: OK >"); - verifyFormat("msg_field < field_a { field_b: 1 }, field_c: < f_d: 2 > >"); verifyFormat("msg_field: < field_a: OK, field_b: \"OK\" >"); - verifyFormat("msg_field: < field_a: OK field_b: <>, field_c: OK >"); - verifyFormat("msg_field: < field_a { field_b: 1 }, field_c: < fd_d: 2 > >"); - verifyFormat("field_a: \"OK\", msg_field: < field_b: 123 >, field_c: {}"); - verifyFormat("field_a < field_b: 1 >, msg_fid: < fiel_b: 123 >, field_c <>"); - verifyFormat("field_a < field_b: 1 > msg_fied: < field_b: 123 > field_c <>"); - verifyFormat("field < field < field: <> >, field <> > field: < field: 1 >"); - // Multiple lines tests + verifyFormat("msg_field <\n" + " field_a: OK\n" + " field_b: <>,\n" + " field_c: OK\n" + ">"); + + verifyFormat("msg_field <\n" + " field_a { field_b: 1 },\n" + " field_c: < f_d: 2 >\n" + ">"); + + verifyFormat("msg_field: <\n" + " field_a: OK\n" + " field_b: <>,\n" + " field_c: OK\n" + ">"); + + verifyFormat("msg_field: <\n" + " field_a { field_b: 1 },\n" + " field_c: < fd_d: 2 >\n" + ">"); + + verifyFormat("field_a: \"OK\",\n" + "msg_field: < field_b: 123 >,\n" + "field_c: {}"); + + verifyFormat("field_a < field_b: 1 >,\n" + "msg_fid: < fiel_b: 123 >,\n" + "field_c <>"); + + verifyFormat("field_a < field_b: 1 >\n" + "msg_fied: < field_b: 123 >\n" + "field_c <>"); + + verifyFormat("field <\n" + " field < field: <> >,\n" + " field <>\n" + ">\n" + "field: < field: 1 >"); + verifyFormat("msg_field <\n" " field_a: OK\n" " field_b: \"OK\"\n" @@ -242,7 +273,10 @@ TEST_F(FormatTestTextProto, SupportsAngleBracketMessageFields) { " field_d: ok\n" "}"); - verifyFormat("field_a: < f1: 1, f2: <> >\n" + verifyFormat("field_a: <\n" + " f1: 1,\n" + " f2: <>\n" + ">\n" "field_b <\n" " field_b1: <>\n" " field_b2: ok,\n" @@ -529,5 +563,112 @@ TEST_F(FormatTestTextProto, BreaksAfterBraceFollowedByClosingBraceOnNextLine) { ">"); } +TEST_F(FormatTestTextProto, BreaksEntriesOfSubmessagesContainingSubmessages) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto); + Style.ColumnLimit = 60; + // The column limit allows for the keys submessage to be put on 1 line, but we + // break it since it contains a submessage an another entry. + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub <>\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " sub {}\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub {}\n" + " sub: <>\n" + " sub: []\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub { msg: 1 }\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: { msg: 1 }\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub < msg: 1 >\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ msg: 1 ]\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: <\n" + " item: 'aaaaaaaaaaa'\n" + " sub: [ 1, 2 ]\n" + ">"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub {}\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub: []\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub <>\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub { key: value }\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: data\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("key: valueeeeeeee\n" + "keys: {\n" + " item: data\n" + " sub < sub_2: {} >\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("sub: {\n" + " key: valueeeeeeee\n" + " keys: {\n" + " sub: [ 1, 2 ]\n" + " item: 'aaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("sub: {\n" + " key: 1\n" + " sub: {}\n" + "}\n" + "# comment\n"); + verifyFormat("sub: {\n" + " key: 1\n" + " # comment\n" + " sub: {}\n" + "}"); +} + } // end namespace tooling } // end namespace clang -- GitLab From a1f8bd3778cc5a53236a53500c6ab184e945eefa Mon Sep 17 00:00:00 2001 From: Francois Ferrand Date: Mon, 11 Jun 2018 14:41:26 +0000 Subject: [PATCH 0080/1023] clang-format: Introduce BreakInheritanceList option Summary: This option replaces the BreakBeforeInheritanceComma option with an enum, thus introducing a mode where the colon stays on the same line as constructor declaration: // When it fits on line: class A : public B, public C { ... }; // When it does not fit: class A : public B, public C { ... }; This matches the behavior of the `BreakConstructorInitializers` option, introduced in https://reviews.llvm.org/D32479. Reviewers: djasper, klimek Reviewed By: djasper Subscribers: mzeren-vmw, cfe-commits Differential Revision: https://reviews.llvm.org/D43015 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334408 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangFormatStyleOptions.rst | 50 +++++++++++----- include/clang/Format/Format.h | 43 ++++++++++---- lib/Format/ContinuationIndenter.cpp | 13 ++++- lib/Format/Format.cpp | 27 ++++++++- lib/Format/TokenAnnotator.cpp | 13 +++-- unittests/Format/FormatTest.cpp | 91 ++++++++++++++++++++++++++--- 6 files changed, 194 insertions(+), 43 deletions(-) diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 487660a6ee..24ce4fba77 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -994,18 +994,6 @@ the configuration (without a prefix: ``Auto``). -**BreakBeforeInheritanceComma** (``bool``) - If ``true``, in the class inheritance expression clang-format will - break before ``:`` and ``,`` if there is multiple inheritance. - - .. code-block:: c++ - - true: false: - class MyClass vs. class MyClass : public X, public Y { - : public X }; - , public Y { - }; - **BreakBeforeTernaryOperators** (``bool``) If ``true``, ternary operators will be placed after line breaks. @@ -1056,6 +1044,42 @@ the configuration (without a prefix: ``Auto``). +**BreakInheritanceList** (``BreakInheritanceListStyle``) + The inheritance list style to use. + + Possible values: + + * ``BILS_BeforeColon`` (in configuration: ``BeforeColon``) + Break inheritance list before the colon and after the commas. + + .. code-block:: c++ + + class Foo + : Base1, + Base2 + {}; + + * ``BILS_BeforeComma`` (in configuration: ``BeforeComma``) + Break inheritance list before the colon and commas, and align + the commas with the colon. + + .. code-block:: c++ + + Constructor() + : initializer1() + , initializer2() + + * ``BILS_AfterColon`` (in configuration: ``AfterColon``) + Break inheritance list after the colon and commas. + + .. code-block:: c++ + + Constructor() : + initializer1(), + initializer2() + + + **BreakStringLiterals** (``bool``) Allow breaking string literals when formatting. @@ -1122,7 +1146,7 @@ the configuration (without a prefix: ``Auto``). **ConstructorInitializerIndentWidth** (``unsigned``) The number of characters to use for indentation of constructor - initializer lists. + initializer lists as well as inheritance lists. **ContinuationIndentWidth** (``unsigned``) Indent width for line continuations. diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 7565487541..66b7762893 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -893,16 +893,35 @@ struct FormatStyle { /// \endcode std::string CommentPragmas; - /// If ``true``, in the class inheritance expression clang-format will - /// break before ``:`` and ``,`` if there is multiple inheritance. - /// \code - /// true: false: - /// class MyClass vs. class MyClass : public X, public Y { - /// : public X }; - /// , public Y { - /// }; - /// \endcode - bool BreakBeforeInheritanceComma; + /// Different ways to break inheritance list. + enum BreakInheritanceListStyle { + /// Break inheritance list before the colon and after the commas. + /// \code + /// class Foo + /// : Base1, + /// Base2 + /// {}; + /// \endcode + BILS_BeforeColon, + /// Break inheritance list before the colon and commas, and align + /// the commas with the colon. + /// \code + /// Constructor() + /// : initializer1() + /// , initializer2() + /// \endcode + BILS_BeforeComma, + /// Break inheritance list after the colon and commas. + /// \code + /// Constructor() : + /// initializer1(), + /// initializer2() + /// \endcode + BILS_AfterColon + }; + + /// The inheritance list style to use. + BreakInheritanceListStyle BreakInheritanceList; /// If ``true``, consecutive namespace declarations will be on the same /// line. If ``false``, each namespace is declared on a new line. @@ -946,7 +965,7 @@ struct FormatStyle { bool ConstructorInitializerAllOnOneLineOrOnePerLine; /// The number of characters to use for indentation of constructor - /// initializer lists. + /// initializer lists as well as inheritance lists. unsigned ConstructorInitializerIndentWidth; /// Indent width for line continuations. @@ -1673,7 +1692,7 @@ struct FormatStyle { BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations && BreakStringLiterals == R.BreakStringLiterals && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && - BreakBeforeInheritanceComma == R.BreakBeforeInheritanceComma && + BreakInheritanceList == R.BreakInheritanceList && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && ConstructorInitializerIndentWidth == diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index eacdfdc6e0..294c58d621 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -131,7 +131,7 @@ static bool startsNextParameter(const FormatToken &Current, Style.BreakConstructorInitializers != FormatStyle::BCIS_BeforeComma) && (Previous.isNot(TT_InheritanceComma) || - !Style.BreakBeforeInheritanceComma)); + Style.BreakInheritanceList != FormatStyle::BILS_BeforeComma)); } static bool opensProtoMessageField(const FormatToken &LessTok, @@ -576,7 +576,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // If "BreakBeforeInheritanceComma" mode, don't break within the inheritance // declaration unless there is multiple inheritance. - if (Style.BreakBeforeInheritanceComma && Current.is(TT_InheritanceColon)) + if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma && + Current.is(TT_InheritanceColon)) + State.Stack.back().NoLineBreak = true; + if (Style.BreakInheritanceList == FormatStyle::BILS_AfterColon && + Previous.is(TT_InheritanceColon)) State.Stack.back().NoLineBreak = true; if (Current.is(TT_SelectorName) && @@ -1019,6 +1023,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { if (PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) return State.Stack.back().Indent; + if (PreviousNonComment && PreviousNonComment->is(TT_InheritanceColon) && + Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) + return State.Stack.back().Indent; if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon, TT_InheritanceComma)) return State.FirstIndent + Style.ConstructorInitializerIndentWidth; @@ -1103,7 +1110,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, } if (Current.is(TT_InheritanceColon)) State.Stack.back().Indent = - State.FirstIndent + Style.ContinuationIndentWidth; + State.FirstIndent + Style.ConstructorInitializerIndentWidth; if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline) State.Stack.back().NestedBlockIndent = State.Column + Current.ColumnWidth + 1; diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index d1a5dc8e6c..7e62d1596c 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -148,6 +148,16 @@ struct ScalarEnumerationTraits { } }; +template <> +struct ScalarEnumerationTraits { + static void + enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value) { + IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon); + IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma); + IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { @@ -350,8 +360,19 @@ template <> struct MappingTraits { IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); + + bool BreakBeforeInheritanceComma = false; IO.mapOptional("BreakBeforeInheritanceComma", - Style.BreakBeforeInheritanceComma); + BreakBeforeInheritanceComma); + IO.mapOptional("BreakInheritanceList", + Style.BreakInheritanceList); + // If BreakBeforeInheritanceComma was specified but + // BreakInheritance was not, initialize the latter from the + // former for backwards compatibility. + if (BreakBeforeInheritanceComma && + Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) + Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + IO.mapOptional("BreakBeforeTernaryOperators", Style.BreakBeforeTernaryOperators); @@ -624,7 +645,7 @@ FormatStyle getLLVMStyle() { false, false, true, true, true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; - LLVMStyle.BreakBeforeInheritanceComma = false; + LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; LLVMStyle.BreakStringLiterals = true; LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; @@ -840,7 +861,7 @@ FormatStyle getMozillaStyle() { MozillaStyle.BinPackArguments = false; MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; - MozillaStyle.BreakBeforeInheritanceComma = true; + MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; MozillaStyle.ConstructorInitializerIndentWidth = 2; MozillaStyle.ContinuationIndentWidth = 2; MozillaStyle.Cpp11BracedListStyle = false; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 1ffdb1c864..0a026159a0 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -2888,7 +2888,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) return true; // Break only if we have multiple inheritance. - if (Style.BreakBeforeInheritanceComma && Right.is(TT_InheritanceComma)) + if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma && + Right.is(TT_InheritanceComma)) return true; if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\"")) // Multiline raw string literals are special wrt. line breaks. The author @@ -3085,8 +3086,10 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return Style.BreakBeforeTernaryOperators; if (Left.is(TT_ConditionalExpr) || Left.is(tok::question)) return !Style.BreakBeforeTernaryOperators; + if (Left.is(TT_InheritanceColon)) + return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon; if (Right.is(TT_InheritanceColon)) - return true; + return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon; if (Right.is(TT_ObjCMethodExpr) && !Right.is(tok::r_square) && Left.isNot(TT_SelectorName)) return true; @@ -3174,9 +3177,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Right.is(TT_CtorInitializerComma) && Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) return true; - if (Left.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma) + if (Left.is(TT_InheritanceComma) && + Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) return false; - if (Right.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma) + if (Right.is(TT_InheritanceComma) && + Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) return true; if ((Left.is(tok::greater) && Right.is(tok::greater)) || (Left.is(tok::less) && Right.is(tok::less))) diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 73c1a2d490..399503a528 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -1316,15 +1316,40 @@ TEST_F(FormatTest, FormatsClasses) { verifyFormat("class ::A::B {};"); } -TEST_F(FormatTest, BreakBeforeInheritanceComma) { - FormatStyle StyleWithInheritanceBreak = getLLVMStyle(); - StyleWithInheritanceBreak.BreakBeforeInheritanceComma = true; - - verifyFormat("class MyClass : public X {};", StyleWithInheritanceBreak); +TEST_F(FormatTest, BreakInheritanceStyle) { + FormatStyle StyleWithInheritanceBreakBeforeComma = getLLVMStyle(); + StyleWithInheritanceBreakBeforeComma.BreakInheritanceList = + FormatStyle::BILS_BeforeComma; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakBeforeComma); verifyFormat("class MyClass\n" " : public X\n" " , public Y {};", - StyleWithInheritanceBreak); + StyleWithInheritanceBreakBeforeComma); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA\n" + " : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n" + " , public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakBeforeComma); + verifyFormat("struct aaaaaaaaaaaaa\n" + " : public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakBeforeComma); + + FormatStyle StyleWithInheritanceBreakAfterColon = getLLVMStyle(); + StyleWithInheritanceBreakAfterColon.BreakInheritanceList = + FormatStyle::BILS_AfterColon; + verifyFormat("class MyClass : public X {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class MyClass : public X, public Y {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA :\n" + " public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n" + " public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};", + StyleWithInheritanceBreakAfterColon); + verifyFormat("struct aaaaaaaaaaaaa :\n" + " public aaaaaaaaaaaaaaaaaaa< // break\n" + " aaaaaaaaaaaaaaaa> {};", + StyleWithInheritanceBreakAfterColon); } TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) { @@ -3726,6 +3751,23 @@ TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}", Style); + + // `ConstructorInitializerIndentWidth` actually applies to InheritanceList as well + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class SomeClass\n" + " : public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); + Style.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class SomeClass :\n" + " public aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {};", + Style); } #ifndef EXPENSIVE_CHECKS @@ -9164,7 +9206,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { " bbbbbbbbbbbbbbbb(2) {}", CtorInitializerStyle); - FormatStyle InheritanceStyle = getLLVMStyle(); + FormatStyle InheritanceStyle = getLLVMStyleWithColumns(30); InheritanceStyle.SpaceBeforeInheritanceColon = false; verifyFormat("class Foo: public Bar {};", InheritanceStyle); verifyFormat("Foo::Foo() : foo(1) {}", InheritanceStyle); @@ -9180,6 +9222,29 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { "default:\n" "}", InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_AfterColon; + verifyFormat("class Foooooooooooooooooooooo:\n" + " public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa\n" + " , public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + verifyFormat("class Foooooooooooooooooooooo\n" + " : public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {\n" + "}", + InheritanceStyle); + InheritanceStyle.ConstructorInitializerIndentWidth = 0; + verifyFormat("class Foooooooooooooooooooooo\n" + ": public aaaaaaaaaaaaaaaaaa,\n" + " public bbbbbbbbbbbbbbbbbb {}", + InheritanceStyle); FormatStyle ForLoopStyle = getLLVMStyle(); ForLoopStyle.SpaceBeforeRangeBasedForLoopColon = false; @@ -10534,7 +10599,6 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations); CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakStringLiterals); - CHECK_PARSE_BOOL(BreakBeforeInheritanceComma) CHECK_PARSE_BOOL(CompactNamespaces); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); CHECK_PARSE_BOOL(DerivePointerAlignment); @@ -10651,6 +10715,17 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("BreakConstructorInitializersBeforeComma: true", BreakConstructorInitializers, FormatStyle::BCIS_BeforeComma); + Style.BreakInheritanceList = FormatStyle::BILS_BeforeColon; + CHECK_PARSE("BreakInheritanceList: BeforeComma", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + CHECK_PARSE("BreakInheritanceList: AfterColon", + BreakInheritanceList, FormatStyle::BILS_AfterColon); + CHECK_PARSE("BreakInheritanceList: BeforeColon", + BreakInheritanceList, FormatStyle::BILS_BeforeColon); + // For backward compatibility: + CHECK_PARSE("BreakBeforeInheritanceComma: true", + BreakInheritanceList, FormatStyle::BILS_BeforeComma); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; CHECK_PARSE("AlignAfterOpenBracket: Align", AlignAfterOpenBracket, FormatStyle::BAS_Align); -- GitLab From 7236596c7c2555a2a6c7c31e4721c169ee3b374e Mon Sep 17 00:00:00 2001 From: Mikhail Maltsev Date: Mon, 11 Jun 2018 16:10:06 +0000 Subject: [PATCH 0081/1023] [Driver] Add aliases for -Qn/-Qy This patch adds aliases for -Qn (-fno-ident) and -Qy (-fident) which look less cryptic than -Qn/-Qy. The aliases are compatible with GCC. Differential Revision: https://reviews.llvm.org/D48021 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334414 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 3 ++- test/CodeGen/no-ident-version.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 093706f279..e5aaeb93de 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -404,6 +404,8 @@ def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>, HelpText<"Emit metadata containing compiler name and version">; def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>, HelpText<"Do not emit metadata containing compiler name and version">; +def : Flag<["-"], "fident">, Group, Alias, Flags<[CC1Option]>; +def : Flag<["-"], "fno-ident">, Group, Alias, Flags<[CC1Option]>; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<["-"], "Q">, IgnoredGCCCompat; @@ -2840,7 +2842,6 @@ defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group, Group; defm gcse_sm: BooleanFFlag<"gcse-sm">, Group; defm gnu : BooleanFFlag<"gnu">, Group; -defm ident : BooleanFFlag<"ident">, Group; defm implicit_templates : BooleanFFlag<"implicit-templates">, Group; defm implement_inlines : BooleanFFlag<"implement-inlines">, Group; defm merge_constants : BooleanFFlag<"merge-constants">, Group; diff --git a/test/CodeGen/no-ident-version.c b/test/CodeGen/no-ident-version.c index ad2a7db2d3..3765a605a9 100644 --- a/test/CodeGen/no-ident-version.c +++ b/test/CodeGen/no-ident-version.c @@ -2,8 +2,12 @@ // RUN: | FileCheck --check-prefix=CHECK-NONE %s // RUN: %clang_cc1 -Qn -emit-llvm -debug-info-kind=limited -o - %s \ // RUN: | FileCheck --check-prefix=CHECK-QN %s +// RUN: %clang_cc1 -fno-ident -emit-llvm -debug-info-kind=limited -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-QN %s // RUN: %clang_cc1 -Qy -emit-llvm -debug-info-kind=limited -o - %s \ // RUN: | FileCheck --check-prefix=CHECK-QY %s +// RUN: %clang_cc1 -fident -emit-llvm -debug-info-kind=limited -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-QY %s // CHECK-NONE: @main // CHECK-NONE: llvm.ident -- GitLab From 1e2253b777d0ab7b7424dcb60fc24d42061ae546 Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Mon, 11 Jun 2018 16:20:13 +0000 Subject: [PATCH 0082/1023] clang-format: [JS] strict prop init annotation. Summary: TypeScript uses the `!` token for strict property initialization assertions, as in: class X { strictPropAsserted!: string; } Previously, clang-format would wrap between the `!` and the `:` for overly long lines. This patch fixes that by generally preventing the wrap in that location. Reviewers: krasimir Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48030 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334415 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 5 ++++- unittests/Format/FormatTestJS.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 0a026159a0..5dce9d248a 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -2981,7 +2981,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // We deal with this case later by detecting an entry // following a closing paren of this submessage. } - + // If this is an entry immediately following a submessage, it will be // preceded by a closing paren of that submessage, like in: // left---. .---right @@ -3027,6 +3027,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return false; if (Left.is(TT_JsTypeColon)) return true; + // Don't wrap between ":" and "!" of a strict prop init ("field!: type;"). + if (Left.is(tok::exclaim) && Right.is(tok::colon)) + return false; if (Right.is(Keywords.kw_is)) return false; if (Left.is(Keywords.kw_in)) diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 1d61055577..9975b7d311 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -1540,6 +1540,15 @@ TEST_F(FormatTestJS, ClassDeclarations) { "}"); } +TEST_F(FormatTestJS, StrictPropInitWrap) { + const FormatStyle &Style = getGoogleJSStyleWithColumns(22); + verifyFormat("class X {\n" + " strictPropInitField!:\n" + " string;\n" + "}", + Style); +} + TEST_F(FormatTestJS, InterfaceDeclarations) { verifyFormat("interface I {\n" " x: string;\n" -- GitLab From 638e493dcac9873d12a33a04753b3ef99fbf0b1c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 11 Jun 2018 16:34:10 +0000 Subject: [PATCH 0083/1023] [X86] Properly account for the immediate being multiplied by 8 in the immediate range checking for BI__builtin_ia32_psrldqi128 and friends. The limit was set to 1023 which only up to 127*8. It needs to be 2047 to allow 255*8. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334416 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 8730408c8d..6648ffc13f 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2911,7 +2911,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_psrldqi128: case X86::BI__builtin_ia32_psrldqi256: case X86::BI__builtin_ia32_psrldqi512: - i = 1; l = 0; u = 1023; + i = 1; l = 0; u = 2047; break; } return SemaBuiltinConstantArgRange(TheCall, i, l, u); -- GitLab From 5083d1e70982308a1b7773edaa19da73d2834dd3 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 11 Jun 2018 16:49:43 +0000 Subject: [PATCH 0084/1023] [MS] Use mangled names and comdats for string merging with ASan This should reduce the binary size penalty of ASan on Windows. After r334313, ASan will add red zones to globals in comdats, so we will still find OOB accesses to string literals. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334417 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 19cfffd81c..814eda4381 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -4114,15 +4114,13 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef GlobalVariableName; llvm::GlobalValue::LinkageTypes LT; - // Mangle the string literal if the ABI allows for it. However, we cannot - // do this if we are compiling with ASan or -fwritable-strings because they - // rely on strings having normal linkage. - if (!LangOpts.WritableStrings && - !LangOpts.Sanitize.has(SanitizerKind::Address) && - getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) { + // Mangle the string literal if that's how the ABI merges duplicate strings. + // Don't do it if they are writable, since we don't want writes in one TU to + // affect strings in another. + if (getCXXABI().getMangleContext().shouldMangleStringLiteral(S) && + !LangOpts.WritableStrings) { llvm::raw_svector_ostream Out(MangledNameBuffer); getCXXABI().getMangleContext().mangleStringLiteral(S, Out); - LT = llvm::GlobalValue::LinkOnceODRLinkage; GlobalVariableName = MangledNameBuffer; } else { -- GitLab From 4d5dfc4a703d273038717b5c8f481891984196f5 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 11 Jun 2018 16:50:07 +0000 Subject: [PATCH 0085/1023] Enable crash recovery tests on Windows, globs work in the lit internal shell now git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334418 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-report-header.h | 3 --- test/Driver/crash-report-modules.m | 8 +------- test/Driver/crash-report-spaces.c | 3 --- test/Driver/crash-report.c | 3 --- 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/test/Driver/crash-report-header.h b/test/Driver/crash-report-header.h index e0193cbe45..3580b60029 100644 --- a/test/Driver/crash-report-header.h +++ b/test/Driver/crash-report-header.h @@ -5,9 +5,6 @@ // RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery -// because of the glob (*.h, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.h diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index 16af75ca70..f563fba2b0 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -9,12 +9,6 @@ // RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-report-*.sh // REQUIRES: crash-recovery -// because of the glob (*.m, *.sh) -// REQUIRES: shell - -// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? -// XFAIL: mingw32 - @import simple; const int x = MODULE_MACRO; @@ -34,4 +28,4 @@ const int x = MODULE_MACRO; // CHECKSH: "-D" "FOO=BAR" // CHECKSH-NOT: "-fmodules-cache-path=" // CHECKSH: "crash-report-modules-{{[^ ]*}}.m" -// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache/vfs/vfs.yaml" +// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache{{(/|\\\\)}}vfs{{(/|\\\\)}}vfs.yaml" diff --git a/test/Driver/crash-report-spaces.c b/test/Driver/crash-report-spaces.c index 3e95a0de25..907ad0f5ff 100644 --- a/test/Driver/crash-report-spaces.c +++ b/test/Driver/crash-report-spaces.c @@ -6,9 +6,6 @@ // RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery -// because of the glob (*.c, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.c diff --git a/test/Driver/crash-report.c b/test/Driver/crash-report.c index a3f1f9e72a..d9bc2aa820 100644 --- a/test/Driver/crash-report.c +++ b/test/Driver/crash-report.c @@ -13,9 +13,6 @@ // RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery -// because of the glob (*.c, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c -- GitLab From 5499ad8b2271766acdc08b1e46d58d9f1cff0498 Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Mon, 11 Jun 2018 17:05:45 +0000 Subject: [PATCH 0086/1023] [clang-fuzzer] Modified protobuf and converter to add new signature, remove conditionals. Changed the function signature and removed conditionals from loop body. Patch By: emmettneyman Differential Revision: https://reviews.llvm.org/D47964 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334421 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/cxx_loop_proto.proto | 19 +++++++++++----- .../proto-to-cxx/loop_proto_to_cxx.cpp | 22 +++++++++++++------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto index 98b9bbf2a0..7538fc636a 100644 --- a/tools/clang-fuzzer/cxx_loop_proto.proto +++ b/tools/clang-fuzzer/cxx_loop_proto.proto @@ -11,7 +11,7 @@ /// This file describes a subset of C++ as a protobuf. It is used to /// more easily find interesting inputs for fuzzing Clang. This subset /// differs from the one defined in cxx_proto.proto by eliminating while -/// loops and Lvalues. The goal is that the C++ code generated will be +/// loops and conditionals. The goal is that the C++ code generated will be /// more likely to stress the LLVM loop vectorizer. /// //===----------------------------------------------------------------------===// @@ -22,6 +22,16 @@ message Const { required int32 val = 1; } +message VarRef { + // Add an enum for each array in function signature + enum Arr { + ARR_A = 0; + ARR_B = 1; + ARR_C = 2; + }; + required Arr arr = 1; +} + message BinaryOp { enum Op { PLUS = 0; @@ -48,10 +58,12 @@ message Rvalue { oneof rvalue_oneof { Const cons = 1; BinaryOp binop = 2; + VarRef varref = 3; } } message AssignmentStatement { + required VarRef varref = 1; required Rvalue rvalue = 2; } @@ -62,10 +74,7 @@ message IfElse { } message Statement { - oneof stmt_oneof { - AssignmentStatement assignment = 1; - IfElse ifelse = 2; - } + required AssignmentStatement assignment = 1; } message StatementSeq { diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp index fa6ba307ac..adebe920f7 100644 --- a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp @@ -36,11 +36,23 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x); std::ostream &operator<<(std::ostream &os, const Const &x) { return os << "(" << x.val() << ")"; } +std::ostream &operator<<(std::ostream &os, const VarRef &x) { + switch (x.arr()) { + case VarRef::ARR_A: + return os << "a[i]"; + case VarRef::ARR_B: + return os << "b[i]"; + case VarRef::ARR_C: + return os << "c[i]"; + } +} std::ostream &operator<<(std::ostream &os, const Rvalue &x) { if (x.has_cons()) return os << x.cons(); if (x.has_binop()) return os << x.binop(); + if (x.has_varref()) + return os << x.varref(); return os << "1"; } std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { @@ -92,7 +104,7 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { return os << x.right() << ")"; } std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { - return os << "a[i]=" << x.rvalue(); + return os << x.varref() << "=" << x.rvalue() << ";\n"; } std::ostream &operator<<(std::ostream &os, const IfElse &x) { return os << "if (" << x.cond() << "){\n" @@ -100,11 +112,7 @@ std::ostream &operator<<(std::ostream &os, const IfElse &x) { << x.else_body() << "}\n"; } std::ostream &operator<<(std::ostream &os, const Statement &x) { - if (x.has_assignment()) - return os << x.assignment() << ";\n"; - if (x.has_ifelse()) - return os << x.ifelse(); - return os << "(void)0;\n"; + return os << x.assignment(); } std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { for (auto &st : x.statements()) @@ -112,7 +120,7 @@ std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { return os; } std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { - return os << "void foo(int *a, size_t s) {\n" + return os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n" << "for (int i=0; i Date: Mon, 11 Jun 2018 17:06:01 +0000 Subject: [PATCH 0087/1023] [X86] Fix operand order in the shuffle created for blend builtins. This was broken when the builtin was added in r334249. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334422 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 674cb487ee..9325839794 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9430,7 +9430,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i != NumElts; ++i) Indices[i] = ((Imm >> (i % 8)) & 0x1) ? NumElts + i : i; - return Builder.CreateShuffleVector(Ops[1], Ops[0], + return Builder.CreateShuffleVector(Ops[0], Ops[1], makeArrayRef(Indices, NumElts), "blend"); } -- GitLab From 62a3eb3a5ba23f34b10c90509f6ddec024fddfd6 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 11 Jun 2018 20:59:31 +0000 Subject: [PATCH 0088/1023] [CMake] Allow specifying extra dependencies of bootstrap stage This allows adding additional bootstrap dependencies to the bootstrap compiler that may be needed by later stages. Differential Revision: https://reviews.llvm.org/D47355 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334437 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc7a3889a7..ab81ec34b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -583,6 +583,10 @@ if (CLANG_ENABLE_BOOTSTRAP) endif() endif() + if(CLANG_BOOTSTRAP_EXTRA_DEPS) + add_dependencies(clang-bootstrap-deps ${CLANG_BOOTSTRAP_EXTRA_DEPS}) + endif() + add_custom_target(${NEXT_CLANG_STAGE}-clear DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-cleared ) -- GitLab From 41c96f035683aee38a29a477c0bdb03158df6fc0 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 11 Jun 2018 22:06:44 +0000 Subject: [PATCH 0089/1023] [CMake] Use libc++ and compiler-rt for bootstrap Fuchsia Clang We want to build the second stage compiler with libc++ and compiler-rt, also include builtins and runtimes into extra bootstrap components to ensure these get built. Differential Revision: https://reviews.llvm.org/D47356 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334445 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index 3055e8d5d3..ee7b69bc29 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -21,6 +21,9 @@ if(NOT APPLE) set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "") endif() +set(CLANG_DEFAULT_CXX_STDLIB libc++ CACHE STRING "") +set(CLANG_DEFAULT_RTLIB compiler-rt CACHE STRING "") + if(APPLE) set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") @@ -51,6 +54,10 @@ endforeach() # Setup the bootstrap build. set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") +set(CLANG_BOOTSTRAP_EXTRA_DEPS + builtins + runtimes + CACHE STRING "") set(CLANG_BOOTSTRAP_CMAKE_ARGS ${EXTRA_ARGS} -C ${CMAKE_CURRENT_LIST_DIR}/Fuchsia-stage2.cmake -- GitLab From a7ec0762acdeb1af6fd157f9cac3b5d6dd6745c7 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 12 Jun 2018 00:16:33 +0000 Subject: [PATCH 0090/1023] [CUDA][HIP] Set kernel calling convention before arrange function Currently clang set kernel calling convention for CUDA/HIP after arranging function, which causes incorrect kernel function type since it depends on calling convention. This patch moves setting kernel convention before arranging function. Differential Revision: https://reviews.llvm.org/D47733 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334457 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 15 ++++++++++++- lib/CodeGen/CodeGenModule.cpp | 2 -- lib/CodeGen/TargetInfo.cpp | 7 +++--- lib/CodeGen/TargetInfo.h | 2 +- test/CodeGenCUDA/kernel-args.cu | 39 +++++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 test/CodeGenCUDA/kernel-args.cu diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 2d8339ef69..064b5fcb10 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -255,6 +255,16 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, FTP->getCanonicalTypeUnqualified().getAs(), MD); } +/// Set calling convention for CUDA/HIP kernel. +static void setCUDAKernelCallingConvention(CanQualType &FTy, CodeGenModule &CGM, + const FunctionDecl *FD) { + if (FD->hasAttr()) { + const FunctionType *FT = FTy->getAs(); + CGM.getTargetCodeGenInfo().setCUDAKernelCallingConvention(FT); + FTy = FT->getCanonicalTypeUnqualified(); + } +} + /// Arrange the argument and result information for a declaration or /// definition of the given C++ non-static member function. The /// member function must be an ordinary function, i.e. not a @@ -264,7 +274,9 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { assert(!isa(MD) && "wrong method for constructors!"); assert(!isa(MD) && "wrong method for destructors!"); - CanQual prototype = GetFormalType(MD); + CanQualType FT = GetFormalType(MD).getAs(); + setCUDAKernelCallingConvention(FT, CGM, MD); + auto prototype = FT.getAs(); if (MD->isInstance()) { // The abstract case is perfectly fine. @@ -424,6 +436,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); assert(isa(FTy)); + setCUDAKernelCallingConvention(FTy, CGM, FD); // When declaring a function without a prototype, always use a // non-variadic type. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 814eda4381..6595694ebd 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3671,8 +3671,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, MaybeHandleStaticInExternC(D, Fn); - if (D->hasAttr()) - getTargetCodeGenInfo().setCUDAKernelCallingConvention(Fn); maybeSetTrivialComdat(*D, *Fn); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 3ec0055360..b29bcce237 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -7646,7 +7646,7 @@ public: llvm::Function *BlockInvokeFunc, llvm::Value *BlockLiteral) const override; bool shouldEmitStaticExternCAliases() const override; - void setCUDAKernelCallingConvention(llvm::Function *F) const override; + void setCUDAKernelCallingConvention(const FunctionType *&FT) const override; }; } @@ -7783,8 +7783,9 @@ bool AMDGPUTargetCodeGenInfo::shouldEmitStaticExternCAliases() const { } void AMDGPUTargetCodeGenInfo::setCUDAKernelCallingConvention( - llvm::Function *F) const { - F->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); + const FunctionType *&FT) const { + FT = getABIInfo().getContext().adjustFunctionType( + FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel)); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 5c19c71412..b530260ea4 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -302,7 +302,7 @@ public: /// as 'used', and having internal linkage. virtual bool shouldEmitStaticExternCAliases() const { return true; } - virtual void setCUDAKernelCallingConvention(llvm::Function *F) const {} + virtual void setCUDAKernelCallingConvention(const FunctionType *&FT) const {} }; } // namespace CodeGen diff --git a/test/CodeGenCUDA/kernel-args.cu b/test/CodeGenCUDA/kernel-args.cu new file mode 100644 index 0000000000..d0986629f8 --- /dev/null +++ b/test/CodeGenCUDA/kernel-args.cu @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=AMDGCN %s +// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda- -fcuda-is-device \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=NVPTX %s +#include "Inputs/cuda.h" + +struct A { + int a[32]; +}; + +// AMDGCN: define amdgpu_kernel void @_Z6kernel1A(%struct.A %x.coerce) +// NVPTX: define void @_Z6kernel1A(%struct.A* byval align 4 %x) +__global__ void kernel(A x) { +} + +class Kernel { +public: + // AMDGCN: define amdgpu_kernel void @_ZN6Kernel12memberKernelE1A(%struct.A %x.coerce) + // NVPTX: define void @_ZN6Kernel12memberKernelE1A(%struct.A* byval align 4 %x) + static __global__ void memberKernel(A x){} + template static __global__ void templateMemberKernel(T x) {} +}; + + +template +__global__ void templateKernel(T x) {} + +void launch(void*); + +void test() { + Kernel K; + // AMDGCN: define amdgpu_kernel void @_Z14templateKernelI1AEvT_(%struct.A %x.coerce) + // NVPTX: define void @_Z14templateKernelI1AEvT_(%struct.A* byval align 4 %x) + launch((void*)templateKernel); + + // AMDGCN: define amdgpu_kernel void @_ZN6Kernel20templateMemberKernelI1AEEvT_(%struct.A %x.coerce) + // NVPTX: define void @_ZN6Kernel20templateMemberKernelI1AEEvT_(%struct.A* byval align 4 %x) + launch((void*)Kernel::templateMemberKernel); +} -- GitLab From cabce844f33a56eb517eee37c99192f34c5f9ee6 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Tue, 12 Jun 2018 03:43:21 +0000 Subject: [PATCH 0091/1023] Fix that AlignedAllocation.h doesn't compile because of VersionTuple Summary: rL334399 put VersionTuple in the llvm namespace, but this header still assumes it's in the clang namespace. This leads to compilation failures with enabled modules when building Clang. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48062 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334471 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/AlignedAllocation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h index a84d22dda8..9751f41184 100644 --- a/include/clang/Basic/AlignedAllocation.h +++ b/include/clang/Basic/AlignedAllocation.h @@ -22,18 +22,18 @@ namespace clang { -inline VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { +inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { switch (OS) { default: break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: // Earliest supporting version is 10.13. - return VersionTuple(10U, 13U); + return llvm::VersionTuple(10U, 13U); case llvm::Triple::IOS: case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0. - return VersionTuple(11U); + return llvm::VersionTuple(11U); case llvm::Triple::WatchOS: // Earliest supporting version is 4.0.0. - return VersionTuple(4U); + return llvm::VersionTuple(4U); } llvm_unreachable("Unexpected OS"); -- GitLab From 362dc486cc5027ac5562131239604047e1352f50 Mon Sep 17 00:00:00 2001 From: Luke Geeson Date: Tue, 12 Jun 2018 09:54:27 +0000 Subject: [PATCH 0092/1023] [AArch64] Corrected FP16 Intrinsic range checks in Clang + added Sema tests Summary: This fixes the ranges for the vcvth family of FP16 intrinsics in the clang front end. Previously it was accepting incorrect ranges -Changed builtin range checking in SemaChecking -added tests SemaCheck changes - included in their own file since no similar one exists -modified existing tests to reflect new ranges Reviewers: SjoerdMeijer, javed.absar Reviewed By: SjoerdMeijer Subscribers: kristof.beyls, cfe-commits Differential Revision: https://reviews.llvm.org/D47592 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334489 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_fp16.td | 18 +++--- lib/Sema/SemaChecking.cpp | 8 +-- test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c | 48 +++++++-------- test/Sema/aarch64-neon-fp16-ranges.c | 64 ++++++++++++++++++++ utils/TableGen/NeonEmitter.cpp | 13 ++-- 5 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 test/Sema/aarch64-neon-fp16-ranges.c diff --git a/include/clang/Basic/arm_fp16.td b/include/clang/Basic/arm_fp16.td index 5c7e437b72..bc15a22d84 100644 --- a/include/clang/Basic/arm_fp16.td +++ b/include/clang/Basic/arm_fp16.td @@ -75,15 +75,15 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) && defined(__aarc def SCALAR_FCVTPUH : SInst<"vcvtp_u16", "bs", "Sh">; def SCALAR_FCVTPUH1 : SInst<"vcvtp_u32", "Us", "Sh">; def SCALAR_FCVTPUH2 : SInst<"vcvtp_u64", "Os", "Sh">; - - def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "Ysi", "silUsUiUl">; - def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "$si", "Sh">; - def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "Isi", "Sh">; - def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "Lsi", "Sh">; - def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "bsi", "Sh">; - def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "Usi", "Sh">; - def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "Osi", "Sh">; - + let isVCVT_N = 1 in { + def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "Ysi", "silUsUiUl">; + def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "$si", "Sh">; + def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "Isi", "Sh">; + def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "Lsi", "Sh">; + def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "bsi", "Sh">; + def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "Usi", "Sh">; + def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "Osi", "Sh">; + } // Comparison def SCALAR_CMEQRH : SInst<"vceq", "bss", "Sh">; def SCALAR_CMEQZH : SInst<"vceqz", "bs", "Sh">; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6648ffc13f..d5945ef6f6 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1499,10 +1499,10 @@ bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { default: return false; -#define GET_NEON_IMMEDIATE_CHECK -#include "clang/Basic/arm_neon.inc" -#include "clang/Basic/arm_fp16.inc" -#undef GET_NEON_IMMEDIATE_CHECK + #define GET_NEON_IMMEDIATE_CHECK + #include "clang/Basic/arm_neon.inc" + #include "clang/Basic/arm_fp16.inc" + #undef GET_NEON_IMMEDIATE_CHECK } return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); diff --git a/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c b/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c index 0390a87e01..b8e1f92a25 100644 --- a/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c +++ b/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c @@ -486,90 +486,90 @@ uint16_t test_vclth_f16(float16_t a, float16_t b) { // CHECK-LABEL: test_vcvth_n_f16_s16 // CHECK: [[SEXT:%.*]] = sext i16 %a to i32 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 [[SEXT]], i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 [[SEXT]], i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_s16(int16_t a) { - return vcvth_n_f16_s16(a, 0); + return vcvth_n_f16_s16(a, 1); } // CHECK-LABEL: test_vcvth_n_f16_s32 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 %a, i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i32(i32 %a, i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_s32(int32_t a) { - return vcvth_n_f16_s32(a, 0); + return vcvth_n_f16_s32(a, 1); } // CHECK-LABEL: test_vcvth_n_f16_s64 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i64(i64 %a, i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxs2fp.f16.i64(i64 %a, i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_s64(int64_t a) { - return vcvth_n_f16_s64(a, 0); + return vcvth_n_f16_s64(a, 1); } // CHECK-LABEL: test_vcvth_n_s16_f16 -// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1) // CHECK: [[RET:%.*]] = trunc i32 [[CVT]] to i16 // CHECK: ret i16 [[RET]] int16_t test_vcvth_n_s16_f16(float16_t a) { - return vcvth_n_s16_f16(a, 0); + return vcvth_n_s16_f16(a, 1); } // CHECK-LABEL: test_vcvth_n_s32_f16 -// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1) // CHECK: ret i32 [[CVT]] int32_t test_vcvth_n_s32_f16(float16_t a) { - return vcvth_n_s32_f16(a, 0); + return vcvth_n_s32_f16(a, 1); } // CHECK-LABEL: test_vcvth_n_s64_f16 -// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 1) // CHECK: ret i64 [[CVT]] int64_t test_vcvth_n_s64_f16(float16_t a) { - return vcvth_n_s64_f16(a, 0); + return vcvth_n_s64_f16(a, 1); } // CHECK-LABEL: test_vcvth_n_f16_u16 // CHECK: [[SEXT:%.*]] = zext i16 %a to i32 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 [[SEXT]], i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 [[SEXT]], i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_u16(int16_t a) { - return vcvth_n_f16_u16(a, 0); + return vcvth_n_f16_u16(a, 1); } // CHECK-LABEL: test_vcvth_n_f16_u32 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 %a, i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32 %a, i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_u32(int32_t a) { - return vcvth_n_f16_u32(a, 0); + return vcvth_n_f16_u32(a, 1); } // CHECK-LABEL: test_vcvth_n_f16_u64 -// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i64(i64 %a, i32 0) +// CHECK: [[CVT:%.*]] = call half @llvm.aarch64.neon.vcvtfxu2fp.f16.i64(i64 %a, i32 1) // CHECK: ret half [[CVT]] float16_t test_vcvth_n_f16_u64(int64_t a) { - return vcvth_n_f16_u64(a, 0); + return vcvth_n_f16_u64(a, 1); } // CHECK-LABEL: test_vcvth_n_u16_f16 -// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1) // CHECK: [[RET:%.*]] = trunc i32 [[CVT]] to i16 // CHECK: ret i16 [[RET]] int16_t test_vcvth_n_u16_f16(float16_t a) { - return vcvth_n_u16_f16(a, 0); + return vcvth_n_u16_f16(a, 1); } // CHECK-LABEL: test_vcvth_n_u32_f16 -// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1) // CHECK: ret i32 [[CVT]] int32_t test_vcvth_n_u32_f16(float16_t a) { - return vcvth_n_u32_f16(a, 0); + return vcvth_n_u32_f16(a, 1); } // CHECK-LABEL: test_vcvth_n_u64_f16 -// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 0) +// CHECK: [[CVT:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 1) // CHECK: ret i64 [[CVT]] int64_t test_vcvth_n_u64_f16(float16_t a) { - return vcvth_n_u64_f16(a, 0); + return vcvth_n_u64_f16(a, 1); } // CHECK-LABEL: test_vdivh_f16 diff --git a/test/Sema/aarch64-neon-fp16-ranges.c b/test/Sema/aarch64-neon-fp16-ranges.c new file mode 100644 index 0000000000..acd6947446 --- /dev/null +++ b/test/Sema/aarch64-neon-fp16-ranges.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -triple arm64-linux-gnu -fallow-half-arguments-and-returns -target-feature +neon -target-feature +fullfp16 -ffreestanding -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fallow-half-arguments-and-returns -target-feature +fullfp16 -target-feature +neon -ffreestanding -fsyntax-only -verify %s + +#include +#include + +void test_vcvt_f16_16(int16_t a){ + vcvth_n_f16_s16(a, 1); + vcvth_n_f16_s16(a, 16); + vcvth_n_f16_s16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_f16_u16(a, 1); + vcvth_n_f16_u16(a, 16); + vcvth_n_f16_u16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_u16(a, 17); // expected-error {{argument should be a value from 1 to 16}} +} + +void test_vcvt_f16_32(int32_t a){ + vcvth_n_f16_u32(a, 1); + vcvth_n_f16_u32(a, 16); + vcvth_n_f16_u32(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_u32(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_f16_s32(a, 1); + vcvth_n_f16_s32(a, 16); + vcvth_n_f16_s32(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s32(a, 17); // expected-error {{argument should be a value from 1 to 16}} +} + +void test_vcvt_f16_64(int64_t a){ + vcvth_n_f16_s64(a, 1); + vcvth_n_f16_s64(a, 16); + vcvth_n_f16_s64(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s64(a, 17); // expected-error {{argument should be a value from 1 to 16}} +} + + +void test_vcvt_su_f(float16_t a){ + vcvth_n_s16_f16(a, 1); + vcvth_n_s16_f16(a, 16); + vcvth_n_s16_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s16_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_s32_f16(a, 1); + vcvth_n_s32_f16(a, 16); + vcvth_n_s32_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s32_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_s64_f16(a, 1); + vcvth_n_s64_f16(a, 16); + vcvth_n_s64_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s64_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_u16_f16(a, 1); + vcvth_n_u16_f16(a, 16); + vcvth_n_u16_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_u16_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + + vcvth_n_u32_f16(a, 1); + vcvth_n_u32_f16(a, 16); + vcvth_n_u32_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_u32_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} +} diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index f8af4057cb..eca03a5892 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -2162,8 +2162,7 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS, OS << "#endif\n\n"; } -void -NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, +void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, SmallVectorImpl &Defs) { OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; @@ -2188,11 +2187,15 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, Record *R = Def->getRecord(); if (R->getValueAsBit("isVCVT_N")) { // VCVT between floating- and fixed-point values takes an immediate - // in the range [1, 32) for f32 or [1, 64) for f64. + // in the range [1, 32) for f32 or [1, 64) for f64 or [1, 16) for f16. LowerBound = "1"; - if (Def->getBaseType().getElementSizeInBits() == 32) + if (Def->getBaseType().getElementSizeInBits() == 16 || + Def->getName().find('h') != std::string::npos) + // VCVTh operating on FP16 intrinsics in range [1, 16) + UpperBound = "15"; + else if (Def->getBaseType().getElementSizeInBits() == 32) UpperBound = "31"; - else + else UpperBound = "63"; } else if (R->getValueAsBit("isScalarShift")) { // Right shifts have an 'r' in the name, left shifts do not. Convert -- GitLab From 35e906e31f3411eab5db7f713e5ee873a65c6ebe Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 12 Jun 2018 11:33:44 +0000 Subject: [PATCH 0093/1023] Revert r334418 "Enable crash recovery tests on Windows, globs work in the lit internal shell now" The tests fail on Windows bots, and for me locally. > Enable crash recovery tests on Windows, globs work in the lit internal shell now git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334493 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-report-header.h | 3 +++ test/Driver/crash-report-modules.m | 8 +++++++- test/Driver/crash-report-spaces.c | 3 +++ test/Driver/crash-report.c | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/test/Driver/crash-report-header.h b/test/Driver/crash-report-header.h index 3580b60029..e0193cbe45 100644 --- a/test/Driver/crash-report-header.h +++ b/test/Driver/crash-report-header.h @@ -5,6 +5,9 @@ // RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery +// because of the glob (*.h, *.sh) +// REQUIRES: shell + #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.h diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index f563fba2b0..16af75ca70 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -9,6 +9,12 @@ // RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-report-*.sh // REQUIRES: crash-recovery +// because of the glob (*.m, *.sh) +// REQUIRES: shell + +// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? +// XFAIL: mingw32 + @import simple; const int x = MODULE_MACRO; @@ -28,4 +34,4 @@ const int x = MODULE_MACRO; // CHECKSH: "-D" "FOO=BAR" // CHECKSH-NOT: "-fmodules-cache-path=" // CHECKSH: "crash-report-modules-{{[^ ]*}}.m" -// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache{{(/|\\\\)}}vfs{{(/|\\\\)}}vfs.yaml" +// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache/vfs/vfs.yaml" diff --git a/test/Driver/crash-report-spaces.c b/test/Driver/crash-report-spaces.c index 907ad0f5ff..3e95a0de25 100644 --- a/test/Driver/crash-report-spaces.c +++ b/test/Driver/crash-report-spaces.c @@ -6,6 +6,9 @@ // RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery +// because of the glob (*.c, *.sh) +// REQUIRES: shell + #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.c diff --git a/test/Driver/crash-report.c b/test/Driver/crash-report.c index d9bc2aa820..a3f1f9e72a 100644 --- a/test/Driver/crash-report.c +++ b/test/Driver/crash-report.c @@ -13,6 +13,9 @@ // RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery +// because of the glob (*.c, *.sh) +// REQUIRES: shell + #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c -- GitLab From cfbb81c58f753db32562260a08b4c3d42eaf3f28 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 12 Jun 2018 11:51:22 +0000 Subject: [PATCH 0094/1023] Re-apply r334418 "Enable crash recovery tests on Windows, globs work in the lit internal shell now" Plus change run lines from not env FOO=bar %clang to env FOO=bar not %clang To not confuse the internal shell. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334494 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-report-header.h | 5 +---- test/Driver/crash-report-modules.m | 12 +++--------- test/Driver/crash-report-spaces.c | 5 +---- test/Driver/crash-report.c | 7 ++----- 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/test/Driver/crash-report-header.h b/test/Driver/crash-report-header.h index e0193cbe45..c1b0ab3676 100644 --- a/test/Driver/crash-report-header.h +++ b/test/Driver/crash-report-header.h @@ -1,13 +1,10 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: not env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 %clang -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only %s 2>&1 | FileCheck %s // RUN: cat %t/crash-report-header-*.h | FileCheck --check-prefix=CHECKSRC "%s" // RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery -// because of the glob (*.h, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.h diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index 16af75ca70..f5cf76e2a9 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -1,20 +1,14 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/i %t/m %t -// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ -// RUN: %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ +// RUN: env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: not %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ // RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | FileCheck %s // RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-report-*.m // RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-report-*.sh // REQUIRES: crash-recovery -// because of the glob (*.m, *.sh) -// REQUIRES: shell - -// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? -// XFAIL: mingw32 - @import simple; const int x = MODULE_MACRO; @@ -34,4 +28,4 @@ const int x = MODULE_MACRO; // CHECKSH: "-D" "FOO=BAR" // CHECKSH-NOT: "-fmodules-cache-path=" // CHECKSH: "crash-report-modules-{{[^ ]*}}.m" -// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache/vfs/vfs.yaml" +// CHECKSH: "-ivfsoverlay" "crash-report-modules-{{[^ ]*}}.cache{{(/|\\\\)}}vfs{{(/|\\\\)}}vfs.yaml" diff --git a/test/Driver/crash-report-spaces.c b/test/Driver/crash-report-spaces.c index 3e95a0de25..e6da087367 100644 --- a/test/Driver/crash-report-spaces.c +++ b/test/Driver/crash-report-spaces.c @@ -1,14 +1,11 @@ // RUN: rm -rf "%t" // RUN: mkdir "%t" // RUN: cp "%s" "%t/crash report spaces.c" -// RUN: not env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s" +// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s" // RUN: cat "%t/crash report spaces"-*.c | FileCheck --check-prefix=CHECKSRC "%s" // RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s" // REQUIRES: crash-recovery -// because of the glob (*.c, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}.c diff --git a/test/Driver/crash-report.c b/test/Driver/crash-report.c index a3f1f9e72a..711b04ea4d 100644 --- a/test/Driver/crash-report.c +++ b/test/Driver/crash-report.c @@ -1,8 +1,8 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: not env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ +// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \ // RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \ -// RUN: %clang -fsyntax-only %s \ +// RUN: not %clang -fsyntax-only %s \ // RUN: -F/tmp/ -I /tmp/ -idirafter /tmp/ -iquote /tmp/ -isystem /tmp/ \ // RUN: -iprefix /the/prefix -iwithprefix /tmp -iwithprefixbefore /tmp/ \ // RUN: -Xclang -internal-isystem -Xclang /tmp/ \ @@ -13,9 +13,6 @@ // RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s // REQUIRES: crash-recovery -// because of the glob (*.c, *.sh) -// REQUIRES: shell - #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: // CHECK-NEXT: note: diagnostic msg: {{.*}}crash-report-{{.*}}.c -- GitLab From bc6e12cddf13b8c832775cc2add5f7bf914647c3 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 12 Jun 2018 13:59:32 +0000 Subject: [PATCH 0095/1023] Fix overload resolution between Ptr-To-Member and Bool As reported here (https://bugs.llvm.org/show_bug.cgi?id=19808) and discovered independently when looking at plum-hall tests, we incorrectly implemented over.ics.rank, which says "A conversion that is not a conversion of a pointer, or pointer to member, to bool is better than another conversion that is such a conversion.". In the current Draft (N4750), this is phrased slightly differently in paragraph 4.1: A conversion that does not convert a pointer, a pointer to member, or std::nullptr_t to bool is better than one that does. The comment on isPointerConversionToBool (the changed function) also confirms that this is the case (note outdated reference): isPointerConversionToBool - Determines whether this conversion is a conversion of a pointer or pointer-to-member to bool. This is used as part of the ranking of standard conversion sequences (C++ 13.3.3.2p4). However, despite this comment, it didn't check isMemberPointerType on the 'FromType', presumably incorrectly assuming that 'isPointerType' matched it. This patch fixes this by adding isMemberPointerType to this function. Additionally, member function pointers are just MemberPointerTypes that point to functions insted of data, so that is fixed in this patch as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334503 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 1 + test/SemaCXX/overload-call.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5e74b54331..45639a718c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -223,6 +223,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const { // a pointer. if (getToType(1)->isBooleanType() && (getFromType()->isPointerType() || + getFromType()->isMemberPointerType() || getFromType()->isObjCObjectPointerType() || getFromType()->isBlockPointerType() || getFromType()->isNullPtrType() || diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 25c619b242..befa927f06 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -667,3 +667,24 @@ namespace ProduceNotesAfterSFINAEFailure { void f(void*, A); // expected-note {{candidate function not viable}} void g() { f(1, 2); } // expected-error {{no matching function}} } + +namespace PR19808 { + struct B { + int i; + void bar(); + }; + struct D : public B{}; + + void f(bool); + void f(int D::*); + void f(void (D::*)()); + + void Usage() { + int B::*pmem; + void (B::*pmf)(); + + // These should not be ambiguous. + f(pmem); + f(pmf); + } +} -- GitLab From f91c23afb2691f7b7a3a4a0516fb0bb9626f8eb5 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 12 Jun 2018 17:26:31 +0000 Subject: [PATCH 0096/1023] [clang-format] Discourage breaks in submessage entries, hard rule Summary: Currently clang-format allows this for text protos: ``` submessage: { key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' } ``` when it is under the column limit and when putting it all on one line exceeds the column limit. This is not a very intuitive formatting, so I'd prefer having ``` submessage: { key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' } ``` instead, even if it takes one line more. This patch prevents clang-format from inserting a break between `: {` and similar cases. Reviewers: djasper, sammccall Reviewed By: sammccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48063 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334517 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 37 +++++++++++++++++++++--- unittests/Format/FormatTestProto.cpp | 29 +++++++++++++++++++ unittests/Format/FormatTestTextProto.cpp | 34 ++++++++++++++++++++-- 3 files changed, 94 insertions(+), 6 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 5dce9d248a..ea957690ed 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -3101,10 +3101,39 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) return false; if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) { - if ((Style.Language == FormatStyle::LK_Proto || - Style.Language == FormatStyle::LK_TextProto) && - !Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral()) - return false; + if (Style.Language == FormatStyle::LK_Proto || + Style.Language == FormatStyle::LK_TextProto) { + if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral()) + return false; + // Prevent cases like: + // + // submessage: + // { key: valueeeeeeeeeeee } + // + // when the snippet does not fit into one line. + // Prefer: + // + // submessage: { + // key: valueeeeeeeeeeee + // } + // + // instead, even if it is longer by one line. + // + // Note that this allows allows the "{" to go over the column limit + // when the column limit is just between ":" and "{", but that does + // not happen too often and alternative formattings in this case are + // not much better. + // + // The code covers the cases: + // + // submessage: { ... } + // submessage: < ... > + // repeated: [ ... ] + if (((Right.is(tok::l_brace) || Right.is(tok::less)) && + Right.is(TT_DictLiteral)) || + Right.is(TT_ArrayInitializerLSquare)) + return false; + } return true; } if (Right.is(tok::r_square) && Right.MatchingParen && diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp index a15ba62ffc..d25aeb846a 100644 --- a/unittests/Format/FormatTestProto.cpp +++ b/unittests/Format/FormatTestProto.cpp @@ -624,5 +624,34 @@ TEST_F(FormatTestProto, BreaksEntriesOfSubmessagesContainingSubmessages) { "}"); } +TEST_F(FormatTestProto, PreventBreaksBetweenKeyAndSubmessages) { + verifyFormat("option (MyProto.options) = {\n" + " submessage: {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " }\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage: <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " submessage <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " >\n" + "}"); + verifyFormat("option (MyProto.options) = {\n" + " repeatedd: [\n" + " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + " ]\n" + "}"); +} + + } // end namespace tooling } // end namespace clang diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index d62975feb4..8ef4bf9a40 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -485,8 +485,15 @@ TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) { verifyFormat("keys: []"); verifyFormat("keys: [ 1 ]"); verifyFormat("keys: [ 'ala', 'bala' ]"); - verifyFormat("keys:\n" - " [ 'ala', 'bala', 'porto', 'kala', 'too', 'long', 'ng' ]"); + verifyFormat("keys: [\n" + " 'ala',\n" + " 'bala',\n" + " 'porto',\n" + " 'kala',\n" + " 'too',\n" + " 'long',\n" + " 'ng'\n" + "]"); verifyFormat("key: item\n" "keys: [\n" " 'ala',\n" @@ -670,5 +677,28 @@ TEST_F(FormatTestTextProto, BreaksEntriesOfSubmessagesContainingSubmessages) { "}"); } +TEST_F(FormatTestTextProto, PreventBreaksBetweenKeyAndSubmessages) { + verifyFormat("submessage: {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("submessage {\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "}"); + verifyFormat("submessage: <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + ">"); + verifyFormat("submessage <\n" + " key: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + ">"); + verifyFormat("repeatedd: [\n" + " 'eyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'\n" + "]"); + // "{" is going over the column limit. + verifyFormat( + "submessageeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: {\n" + " key: 'aaaaa'\n" + "}"); +} + } // end namespace tooling } // end namespace clang -- GitLab From 65eda1a8360bec118893f240d584aa20e79e972f Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 12 Jun 2018 17:43:52 +0000 Subject: [PATCH 0097/1023] Refactor ExecuteAndWait to take StringRefs. This simplifies some code which had StringRefs to begin with, and makes other code more complicated which had const char* to begin with. In the end, I think this makes for a more idiomatic and platform agnostic API. Not all platforms launch process with null terminated c-string arrays for the environment pointer and argv, but the api was designed that way because it allowed easy pass-through for posix-based platforms. There's a little additional overhead now since on posix based platforms we'll be takign StringRefs which were constructed from null terminated strings and then copying them to null terminate them again, but from a readability and usability standpoint of the API user, I think this API signature is strictly better. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334518 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Job.cpp | 14 +++++------ .../Frontend/AnalysisConsumer.cpp | 4 ++-- .../ClangOffloadBundler.cpp | 23 +++++++++---------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index 71cda62104..74af597ad3 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -317,13 +317,11 @@ int Command::Execute(ArrayRef> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const { SmallVector Argv; - const char **Envp; - if (Environment.empty()) { - Envp = nullptr; - } else { + Optional> Env; + if (!Environment.empty()) { assert(Environment.back() == nullptr && "Environment vector should be null-terminated by now"); - Envp = const_cast(Environment.data()); + Env = llvm::toStringRefArray(Environment.data()); } if (ResponseFile == nullptr) { @@ -331,8 +329,9 @@ int Command::Execute(ArrayRef> Redirects, Argv.append(Arguments.begin(), Arguments.end()); Argv.push_back(nullptr); + auto Args = llvm::toStringRefArray(Argv.data()); return llvm::sys::ExecuteAndWait( - Executable, Argv.data(), Envp, Redirects, /*secondsToWait*/ 0, + Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } @@ -357,7 +356,8 @@ int Command::Execute(ArrayRef> Redirects, return -1; } - return llvm::sys::ExecuteAndWait(Executable, Argv.data(), Envp, Redirects, + auto Args = llvm::toStringRefArray(Argv.data()); + return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 9c5e04cc3c..3d86945a55 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -883,9 +883,9 @@ UbigraphViz::~UbigraphViz() { std::string Ubiviz; if (auto Path = llvm::sys::findProgramByName("ubiviz")) Ubiviz = *Path; - const char *args[] = {Ubiviz.c_str(), Filename.c_str(), nullptr}; + std::array Args = {Ubiviz, Filename}; - if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, {}, 0, 0, &ErrMsg)) { + if (llvm::sys::ExecuteAndWait(Ubiviz, Args, llvm::None, {}, 0, 0, &ErrMsg)) { llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; } diff --git a/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/tools/clang-offload-bundler/ClangOffloadBundler.cpp index d9fb3898b5..29cd9848d1 100644 --- a/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -536,23 +536,22 @@ public: // close it and use the name to pass down to clang. OS.close(); SmallString<128> TargetName = getTriple(TargetNames[HostInputIndex]); - const char *ClangArgs[] = {"clang", - "-r", - "-target", - TargetName.c_str(), - "-o", - OutputFileNames.front().c_str(), - InputFileNames[HostInputIndex].c_str(), - BitcodeFileName.c_str(), - "-nostdlib", - nullptr}; + std::vector ClangArgs = {"clang", + "-r", + "-target", + TargetName.c_str(), + "-o", + OutputFileNames.front().c_str(), + InputFileNames[HostInputIndex].c_str(), + BitcodeFileName.c_str(), + "-nostdlib"}; // If the user asked for the commands to be printed out, we do that instead // of executing it. if (PrintExternalCommands) { errs() << "\"" << ClangBinary.get() << "\""; - for (unsigned I = 1; ClangArgs[I]; ++I) - errs() << " \"" << ClangArgs[I] << "\""; + for (StringRef Arg : ClangArgs) + errs() << " \"" << Arg << "\""; errs() << "\n"; } else { // Write the bitcode contents to the temporary file. -- GitLab From 37a2c4ce05b4463dcfcab8b88e10b584b06af395 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 19:07:41 +0000 Subject: [PATCH 0098/1023] [analyzer] [NFC] Remove unused Extensive diagnostic setting, Rename AlternateExtensive to Extensive. In 2013, five years ago, we have switched to AlternateExtensive diagnostics by default, and Extensive was available under unused, undocumented flag. This change remove the flag, renames the Alternate diagnostic to Extensive (as it's no longer Alternate), and ports the test. Differential Revision: https://reviews.llvm.org/D47670 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334524 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/PathDiagnostic.h | 11 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 575 +------- .../system-header-simulator-for-nullability.h | 1 + .../MismatchedDeallocator-path-notes.cpp | 70 +- test/Analysis/NewDelete-path-notes.cpp | 40 +- test/Analysis/conditional-path-notes.c | 240 ++-- test/Analysis/cxx-for-range.cpp | 2 +- .../diagnostics/deref-track-symbolic-region.c | 2 +- .../report-issues-within-main-file.cpp | 210 +-- .../Analysis/diagnostics/undef-value-caller.c | 36 +- test/Analysis/diagnostics/undef-value-param.c | 138 +- test/Analysis/diagnostics/undef-value-param.m | 70 +- test/Analysis/edges-new.mm | 2 +- test/Analysis/inline-plist.c | 206 +-- test/Analysis/inline-unique-reports.c | 36 +- .../inlining/eager-reclamation-path-notes.c | 142 +- .../inlining/eager-reclamation-path-notes.cpp | 2 +- test/Analysis/inlining/path-notes.c | 244 +++- test/Analysis/inlining/path-notes.cpp | 730 +++++----- test/Analysis/inlining/path-notes.m | 295 +--- test/Analysis/malloc-plist.c | 1192 +++++++---------- test/Analysis/method-call-path-notes.cpp | 2 +- test/Analysis/null-deref-path-notes.m | 2 +- test/Analysis/nullability-notes.m | 2 +- test/Analysis/objc-arc.m | 2 +- test/Analysis/objc-radar17039661.m | 246 +++- test/Analysis/plist-macros.cpp | 2 +- test/Analysis/plist-output-alternate.m | 252 ++-- test/Analysis/plist-output.m | 904 +++++++++++-- test/Analysis/retain-release-path-notes-gc.m | 192 +-- test/Analysis/retain-release-path-notes.m | 1106 ++------------- test/Analysis/unix-fns.c | 206 ++- 32 files changed, 3090 insertions(+), 4070 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index b9116e197a..54920e2d22 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -114,7 +114,16 @@ public: void HandlePathDiagnostic(std::unique_ptr D); - enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; + enum PathGenerationScheme { + /// Only runs visitors, no output generated. + None, + + /// Used for HTML and text output. + Minimal, + + /// Used for plist output, used for "arrows" generation. + Extensive, + }; virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 854e405fb9..ace494c349 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -930,348 +930,6 @@ static bool GenerateMinimalPathDiagnostic( return true; } -//===----------------------------------------------------------------------===// -// "Extensive" PathDiagnostic generation. -//===----------------------------------------------------------------------===// - -static bool IsControlFlowExpr(const Stmt *S) { - const auto *E = dyn_cast(S); - - if (!E) - return false; - - E = E->IgnoreParenCasts(); - - if (isa(E)) - return true; - - if (const auto *B = dyn_cast(E)) - if (B->isLogicalOp()) - return true; - - return false; -} - -namespace { - -class ContextLocation : public PathDiagnosticLocation { - bool IsDead; - -public: - ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) - : PathDiagnosticLocation(L), IsDead(isdead) {} - - void markDead() { IsDead = true; } - bool isDead() const { return IsDead; } -}; - -} // namespace - -static PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, - const LocationContext *LC, - bool firstCharOnly = false) { - if (const Stmt *S = L.asStmt()) { - const Stmt *Original = S; - while (true) { - // Adjust the location for some expressions that are best referenced - // by one of their subexpressions. - switch (S->getStmtClass()) { - default: - break; - case Stmt::ParenExprClass: - case Stmt::GenericSelectionExprClass: - S = cast(S)->IgnoreParens(); - firstCharOnly = true; - continue; - case Stmt::BinaryConditionalOperatorClass: - case Stmt::ConditionalOperatorClass: - S = cast(S)->getCond(); - firstCharOnly = true; - continue; - case Stmt::ChooseExprClass: - S = cast(S)->getCond(); - firstCharOnly = true; - continue; - case Stmt::BinaryOperatorClass: - S = cast(S)->getLHS(); - firstCharOnly = true; - continue; - } - break; - } - - if (S != Original) - L = PathDiagnosticLocation(S, L.getManager(), LC); - } - - if (firstCharOnly) - L = PathDiagnosticLocation::createSingleLocation(L); - - return L; -} - -namespace { - -class EdgeBuilder { - std::vector CLocs; - - using iterator = std::vector::iterator; - - PathDiagnostic &PD; - PathDiagnosticBuilder &PDB; - PathDiagnosticLocation PrevLoc; - - bool IsConsumedExpr(const PathDiagnosticLocation &L); - - bool containsLocation(const PathDiagnosticLocation &Container, - const PathDiagnosticLocation &Containee); - - PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); - - void popLocation() { - if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { - // For contexts, we only one the first character as the range. - rawAddEdge(cleanUpLocation(CLocs.back(), PDB.LC, true)); - } - CLocs.pop_back(); - } - -public: - EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) - : PD(pd), PDB(pdb) { - // If the PathDiagnostic already has pieces, add the enclosing statement - // of the first piece as a context as well. - if (!PD.path.empty()) { - PrevLoc = (*PD.path.begin())->getLocation(); - - if (const Stmt *S = PrevLoc.asStmt()) - addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); - } - } - - ~EdgeBuilder() { - while (!CLocs.empty()) popLocation(); - - // Finally, add an initial edge from the start location of the first - // statement (if it doesn't already exist). - PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin( - PDB.LC, - PDB.getSourceManager()); - if (L.isValid()) - rawAddEdge(L); - } - - void flushLocations() { - while (!CLocs.empty()) - popLocation(); - PrevLoc = PathDiagnosticLocation(); - } - - void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false, - bool IsPostJump = false); - - void rawAddEdge(PathDiagnosticLocation NewLoc); - - void addContext(const Stmt *S); - void addContext(const PathDiagnosticLocation &L); - void addExtendedContext(const Stmt *S); -}; - -} // namespace - -PathDiagnosticLocation -EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { - if (const Stmt *S = L.asStmt()) { - if (IsControlFlowExpr(S)) - return L; - - return PDB.getEnclosingStmtLocation(S); - } - - return L; -} - -bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, - const PathDiagnosticLocation &Containee) { - if (Container == Containee) - return true; - - if (Container.asDecl()) - return true; - - if (const Stmt *S = Containee.asStmt()) - if (const Stmt *ContainerS = Container.asStmt()) { - while (S) { - if (S == ContainerS) - return true; - S = PDB.getParent(S); - } - return false; - } - - // Less accurate: compare using source ranges. - SourceRange ContainerR = Container.asRange(); - SourceRange ContaineeR = Containee.asRange(); - - SourceManager &SM = PDB.getSourceManager(); - SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin()); - SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd()); - SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin()); - SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd()); - - unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg); - unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd); - unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg); - unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd); - - assert(ContainerBegLine <= ContainerEndLine); - assert(ContaineeBegLine <= ContaineeEndLine); - - return (ContainerBegLine <= ContaineeBegLine && - ContainerEndLine >= ContaineeEndLine && - (ContainerBegLine != ContaineeBegLine || - SM.getExpansionColumnNumber(ContainerRBeg) <= - SM.getExpansionColumnNumber(ContaineeRBeg)) && - (ContainerEndLine != ContaineeEndLine || - SM.getExpansionColumnNumber(ContainerREnd) >= - SM.getExpansionColumnNumber(ContaineeREnd))); -} - -void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { - if (!PrevLoc.isValid()) { - PrevLoc = NewLoc; - return; - } - - const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, PDB.LC); - const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, PDB.LC); - - if (PrevLocClean.asLocation().isInvalid()) { - PrevLoc = NewLoc; - return; - } - - if (NewLocClean.asLocation() == PrevLocClean.asLocation()) - return; - - // FIXME: Ignore intra-macro edges for now. - if (NewLocClean.asLocation().getExpansionLoc() == - PrevLocClean.asLocation().getExpansionLoc()) - return; - - PD.getActivePath().push_front( - std::make_shared(NewLocClean, - PrevLocClean)); - PrevLoc = NewLoc; -} - -void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd, - bool IsPostJump) { - if (!alwaysAdd && NewLoc.asLocation().isMacroID()) - return; - - const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); - - while (!CLocs.empty()) { - ContextLocation &TopContextLoc = CLocs.back(); - - // Is the top location context the same as the one for the new location? - if (TopContextLoc == CLoc) { - if (alwaysAdd) { - if (IsConsumedExpr(TopContextLoc)) - TopContextLoc.markDead(); - - rawAddEdge(NewLoc); - } - - if (IsPostJump) - TopContextLoc.markDead(); - return; - } - - if (containsLocation(TopContextLoc, CLoc)) { - if (alwaysAdd) { - rawAddEdge(NewLoc); - - if (IsConsumedExpr(CLoc)) { - CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/true)); - return; - } - } - - CLocs.push_back(ContextLocation(CLoc, /*IsDead=*/IsPostJump)); - return; - } - - // Context does not contain the location. Flush it. - popLocation(); - } - - // If we reach here, there is no enclosing context. Just add the edge. - rawAddEdge(NewLoc); -} - -bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { - if (const auto *X = dyn_cast_or_null(L.asStmt())) - return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); - - return false; -} - -void EdgeBuilder::addExtendedContext(const Stmt *S) { - if (!S) - return; - - const Stmt *Parent = PDB.getParent(S); - while (Parent) { - if (isa(Parent)) - Parent = PDB.getParent(Parent); - else - break; - } - - if (Parent) { - switch (Parent->getStmtClass()) { - case Stmt::DoStmtClass: - case Stmt::ObjCAtSynchronizedStmtClass: - addContext(Parent); - break; - default: - break; - } - } - - addContext(S); -} - -void EdgeBuilder::addContext(const Stmt *S) { - if (!S) - return; - - PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.LC); - addContext(L); -} - -void EdgeBuilder::addContext(const PathDiagnosticLocation &L) { - while (!CLocs.empty()) { - const PathDiagnosticLocation &TopContextLoc = CLocs.back(); - - // Is the top location context the same as the one for the new location? - if (TopContextLoc == L) - return; - - if (containsLocation(TopContextLoc, L)) { - CLocs.push_back(L); - return; - } - - // Context does not contain the location. Flush it. - popLocation(); - } - - CLocs.push_back(L); -} - // Cone-of-influence: support the reverse propagation of "interesting" symbols // and values by tracing interesting calculations backwards through evaluated // expressions along a path. This is probably overly complicated, but the idea @@ -1431,211 +1089,6 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { return isContainedByStmt(PM, LoopBody, S); } -/// Generate extensive diagnostics for statement associated with node \p N, -/// and write it into \p PD. -static void generateExtensiveDiagnosticsForNode( - const ExplodedNode *N, - PathDiagnosticBuilder &PDB, - LocationContextMap &LCM, - EdgeBuilder &EB, - StackDiagVector &CallStack, - PathDiagnostic &PD, - InterestingExprs &IE) { - const ExplodedNode *NextNode = N->getFirstPred(); - ProgramPoint P = N->getLocation(); - const SourceManager& SM = PDB.getSourceManager(); - - if (Optional PS = P.getAs()) { - if (const Expr *Ex = PS->getStmtAs()) - reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, - N->getState().get(), Ex, - N->getLocationContext()); - return; - } else if (Optional CE = P.getAs()) { - const Stmt *S = CE->getCalleeContext()->getCallSite(); - if (const auto *Ex = dyn_cast_or_null(S)) { - reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, - N->getState().get(), Ex, - N->getLocationContext()); - } - - auto C = PathDiagnosticCallPiece::construct(N, *CE, SM); - LCM[&C->path] = CE->getCalleeContext(); - - EB.addEdge(C->callReturn, /*AlwaysAdd=*/true, /*IsPostJump=*/true); - EB.flushLocations(); - - auto *P = C.get(); - PD.getActivePath().push_front(std::move(C)); - PD.pushActivePath(&P->path); - CallStack.push_back(StackDiagPair(P, N)); - return; - } else if (Optional CE = P.getAs()) { - // Pop the call hierarchy if we are done walking the contents - // of a function call. - - // Add an edge to the start of the function. - const Decl *D = CE->getCalleeContext()->getDecl(); - PathDiagnosticLocation pos = - PathDiagnosticLocation::createBegin(D, SM); - EB.addEdge(pos); - - // Flush all locations, and pop the active path. - bool VisitedEntireCall = PD.isWithinCall(); - EB.flushLocations(); - PD.popActivePath(); - PDB.LC = N->getLocationContext(); - - // Either we just added a bunch of stuff to the top-level path, or - // we have a previous CallExitEnd. If the former, it means that the - // path terminated within a function call. We must then take the - // current contents of the active path and place it within - // a new PathDiagnosticCallPiece. - PathDiagnosticCallPiece *C; - if (VisitedEntireCall) { - C = cast(PD.getActivePath().front().get()); - } else { - const Decl *Caller = CE->getLocationContext()->getDecl(); - C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); - LCM[&C->path] = CE->getCalleeContext(); - } - - C->setCallee(*CE, SM); - EB.addContext(C->getLocation()); - - if (!CallStack.empty()) { - assert(CallStack.back().first == C); - CallStack.pop_back(); - } - return; - } - - // Note that is important that we update the LocationContext - // after looking at CallExits. CallExit basically adds an - // edge in the *caller*, so we don't want to update the LocationContext - // too soon. - PDB.LC = N->getLocationContext(); - - if (Optional BE = P.getAs()) { - // Does this represent entering a call? If so, look at propagating - // interesting symbols across call boundaries. - if (NextNode) { - const LocationContext *CallerCtx = NextNode->getLocationContext(); - const LocationContext *CalleeCtx = PDB.LC; - if (CallerCtx != CalleeCtx) { - reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, - N->getState().get(), - CalleeCtx, CallerCtx); - } - } - - // Are we jumping to the head of a loop? Add a special diagnostic. - if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { - PathDiagnosticLocation L(Loop, SM, PDB.LC); - const CompoundStmt *CS = nullptr; - - if (const auto *FS = dyn_cast(Loop)) - CS = dyn_cast(FS->getBody()); - else if (const auto *WS = dyn_cast(Loop)) - CS = dyn_cast(WS->getBody()); - - auto p = std::make_shared( - L, "Looping back to the head of the loop"); - p->setPrunable(true); - - EB.addEdge(p->getLocation(), true); - PD.getActivePath().push_front(std::move(p)); - - if (CS) { - PathDiagnosticLocation BL = - PathDiagnosticLocation::createEndBrace(CS, SM); - EB.addEdge(BL); - } - } - - const CFGBlock *BSrc = BE->getSrc(); - ParentMap &PM = PDB.getParentMap(); - - if (const Stmt *Term = BSrc->getTerminator()) { - // Are we jumping past the loop body without ever executing the - // loop (because the condition was false)? - if (isLoopJumpPastBody(Term, &*BE) && - !isInLoopBody(PM, - getStmtBeforeCond(PM, - BSrc->getTerminatorCondition(), - N), - Term)) { - PathDiagnosticLocation L(Term, SM, PDB.LC); - auto PE = std::make_shared( - L, "Loop body executed 0 times"); - PE->setPrunable(true); - - EB.addEdge(PE->getLocation(), true); - PD.getActivePath().push_front(std::move(PE)); - } - - // In any case, add the terminator as the current statement - // context for control edges. - EB.addContext(Term); - } - } else if (Optional BE = P.getAs()) { - Optional First = BE->getFirstElement(); - if (Optional S = First ? First->getAs() : None) { - const Stmt *stmt = S->getStmt(); - if (IsControlFlowExpr(stmt)) { - // Add the proper context for '&&', '||', and '?'. - EB.addContext(stmt); - } - else - EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt()); - } - } -} - -//===----------------------------------------------------------------------===// -// Top-level logic for generating extensive path diagnostics. -//===----------------------------------------------------------------------===// - -static bool GenerateExtensivePathDiagnostic( - PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef> visitors) { - EdgeBuilder EB(PD, PDB); - StackDiagVector CallStack; - - InterestingExprs IE; - const ExplodedNode *NextNode = N->pred_empty() ? nullptr : *(N->pred_begin()); - while (NextNode) { - N = NextNode; - NextNode = N->getFirstPred(); - - generateExtensiveDiagnosticsForNode(N, PDB, LCM, EB, CallStack, PD, IE); - - if (!NextNode) - continue; - - // Add pieces from custom visitors. - BugReport *R = PDB.getBugReport(); - llvm::FoldingSet DeduplicationSet; - for (auto &V : visitors) { - if (auto p = V->VisitNode(N, NextNode, PDB, *R)) { - if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) - continue; - - const PathDiagnosticLocation &Loc = p->getLocation(); - EB.addEdge(Loc, true); - updateStackPiecesWithMessage(*p, CallStack); - PD.getActivePath().push_front(std::move(p)); - - if (const Stmt *S = Loc.asStmt()) - EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); - } - } - } - - return PDB.getBugReport()->isValid(); -} - /// Adds a sanitized control-flow diagnostic edge to a path. static void addEdgeToPath(PathPieces &path, PathDiagnosticLocation &PrevLoc, @@ -1679,9 +1132,9 @@ static const char StrLoopRangeEmpty[] = static const char StrLoopCollectionEmpty[] = "Loop body skipped when collection is empty"; -/// Generate alternate-extensive diagnostics for the node \p N, +/// Generate extensive diagnostics for the node \p N, /// and write it into \p PD. -static void generateAlternateExtensiveDiagnosticsForNode(const ExplodedNode *N, +static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, PathDiagnostic &PD, PathDiagnosticLocation &PrevLoc, PathDiagnosticBuilder &PDB, @@ -1894,12 +1347,11 @@ static void generateAlternateExtensiveDiagnosticsForNode(const ExplodedNode *N, } } -static bool GenerateAlternateExtensivePathDiagnostic( +static bool GenerateExtensivePathDiagnostic( PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef> visitors) { BugReport *report = PDB.getBugReport(); - const SourceManager& SM = PDB.getSourceManager(); StackDiagVector CallStack; InterestingExprs IE; @@ -1910,7 +1362,7 @@ static bool GenerateAlternateExtensivePathDiagnostic( N = NextNode; NextNode = N->getFirstPred(); - generateAlternateExtensiveDiagnosticsForNode( + generateExtensivePathDiagnosticForNode( N, PD, PrevLoc, PDB, LCM, CallStack, IE); if (!NextNode) @@ -1935,7 +1387,7 @@ static bool GenerateAlternateExtensivePathDiagnostic( const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); const Decl *D = CalleeLC->getDecl(); addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, SM), + PathDiagnosticLocation::createBegin(D, PDB.getSourceManager()), CalleeLC); return report->isValid(); @@ -3122,13 +2574,6 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); - if (ActiveScheme == PathDiagnosticConsumer::Extensive) { - AnalyzerOptions &options = getAnalyzerOptions(); - if (options.getBooleanOption("path-diagnostics-alternate", true)) { - ActiveScheme = PathDiagnosticConsumer::AlternateExtensive; - } - } - TrimmedGraph TrimG(&getGraph(), errorNodes); ReportGraph ErrorGraph; @@ -3162,7 +2607,10 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // new symbols and regions are interesting, or add other visitors based on // the information they find. If they do, we need to regenerate the path // based on our new report configuration. - do { + int jj=0; + do { // TODO: dump statistics on the MAX number of iterations of this loop. + jj++; + assert(jj<10); // Get a clean copy of all the visitors. for (BugReport::visitor_iterator I = R->visitor_begin(), E = R->visitor_end(); I != E; ++I) @@ -3197,9 +2645,6 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, LCM.clear(); switch (ActiveScheme) { - case PathDiagnosticConsumer::AlternateExtensive: - GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); - break; case PathDiagnosticConsumer::Extensive: GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); break; @@ -3233,7 +2678,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, adjustCallLocations(PD.getMutablePieces()); removePiecesWithInvalidLocations(PD.getMutablePieces()); - if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) { + if (ActiveScheme == PathDiagnosticConsumer::Extensive) { SourceManager &SM = getSourceManager(); // Reduce the number of edges from a very conservative set diff --git a/test/Analysis/Inputs/system-header-simulator-for-nullability.h b/test/Analysis/Inputs/system-header-simulator-for-nullability.h index f99c7ee341..751057dd45 100644 --- a/test/Analysis/Inputs/system-header-simulator-for-nullability.h +++ b/test/Analysis/Inputs/system-header-simulator-for-nullability.h @@ -32,6 +32,7 @@ NSObject @interface NSString : NSObject - (BOOL)isEqualToString : (NSString *)aString; - (NSString *)stringByAppendingString:(NSString *)aString; +- (nullable NSString *)nullableStringByAppendingString:(NSString *)aString; + (NSString * _Nonnull) generateString; + (NSString *) generateImplicitlyNonnullString; + (NSString * _Nullable) generatePossiblyNullString; diff --git a/test/Analysis/MismatchedDeallocator-path-notes.cpp b/test/Analysis/MismatchedDeallocator-path-notes.cpp index 1354386fc8..4e4ffc4242 100644 --- a/test/Analysis/MismatchedDeallocator-path-notes.cpp +++ b/test/Analysis/MismatchedDeallocator-path-notes.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -analyzer-output=plist %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void changePointee(int *p); @@ -131,40 +131,6 @@ void test() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -243,6 +209,40 @@ void test() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line13 // CHECK-NEXT: col3 // CHECK-NEXT: file0 diff --git a/test/Analysis/NewDelete-path-notes.cpp b/test/Analysis/NewDelete-path-notes.cpp index d57f67e719..48c402d25c 100644 --- a/test/Analysis/NewDelete-path-notes.cpp +++ b/test/Analysis/NewDelete-path-notes.cpp @@ -1,6 +1,6 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=text -analyzer-config c++-allocator-inlining=true -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.NewDelete,unix.Malloc -analyzer-output=plist %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void test() { @@ -34,40 +34,6 @@ void test(Odd *odd) { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -105,12 +71,12 @@ void test(Odd *odd) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line7 -// CHECK-NEXT: col12 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line7 -// CHECK-NEXT: col14 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/conditional-path-notes.c b/test/Analysis/conditional-path-notes.c index 0ccf40f4cd..8fc27be391 100644 --- a/test/Analysis/conditional-path-notes.c +++ b/test/Analysis/conditional-path-notes.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=text -verify -// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t +// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t // RUN: FileCheck --input-file=%t %s void testCondOp(int *p) { @@ -271,6 +271,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line10 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -417,6 +451,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 // CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -771,108 +839,6 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -923,6 +889,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line44 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line44 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line44 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line44 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line44 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1069,6 +1069,40 @@ void testNonDiagnosableBranchArithmetic(int a, int b) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line53 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line53 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line53 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line53 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line53 // CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/cxx-for-range.cpp b/test/Analysis/cxx-for-range.cpp index bf3cfbff12..d1a689b62c 100644 --- a/test/Analysis/cxx-for-range.cpp +++ b/test/Analysis/cxx-for-range.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist-multi-file -o %t.plist -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify %s // RUN: FileCheck --input-file=%t.plist %s extern void work(); diff --git a/test/Analysis/diagnostics/deref-track-symbolic-region.c b/test/Analysis/diagnostics/deref-track-symbolic-region.c index 179e736ee1..48c659f2b8 100644 --- a/test/Analysis/diagnostics/deref-track-symbolic-region.c +++ b/test/Analysis/diagnostics/deref-track-symbolic-region.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s struct S { diff --git a/test/Analysis/diagnostics/report-issues-within-main-file.cpp b/test/Analysis/diagnostics/report-issues-within-main-file.cpp index e1dccc8e32..18795d25bd 100644 --- a/test/Analysis/diagnostics/report-issues-within-main-file.cpp +++ b/test/Analysis/diagnostics/report-issues-within-main-file.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file -analyzer-config report-in-main-source-file=true -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-output=plist-multi-file -analyzer-config report-in-main-source-file=true %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s #include "Inputs/include/report-issues-within-main-file.h" @@ -77,6 +77,40 @@ void callInMacroArg() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line49 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line49 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line51 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line51 +// CHECK-NEXT: col23 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -343,6 +377,40 @@ void callInMacroArg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line56 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line56 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line58 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line58 +// CHECK-NEXT: col23 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -532,6 +600,40 @@ void callInMacroArg() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line67 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line67 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line69 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line69 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -721,40 +823,6 @@ void callInMacroArg() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -792,46 +860,12 @@ void callInMacroArg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line6 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line6 -// CHECK-NEXT: col17 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line6 -// CHECK-NEXT: col17 +// CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1542,40 +1576,6 @@ void callInMacroArg() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line44 // CHECK-NEXT: col3 // CHECK-NEXT: file0 diff --git a/test/Analysis/diagnostics/undef-value-caller.c b/test/Analysis/diagnostics/undef-value-caller.c index 4f273bd9a7..60a885afe2 100644 --- a/test/Analysis/diagnostics/undef-value-caller.c +++ b/test/Analysis/diagnostics/undef-value-caller.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -o %t %s // RUN: FileCheck --input-file %t %s #include "undef-value-callee.h" @@ -66,40 +66,6 @@ int test_calling_unimportant_callee(int argc, char *argv[]) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line10 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line10 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line10 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line10 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line11 // CHECK-NEXT: col3 // CHECK-NEXT: file0 diff --git a/test/Analysis/diagnostics/undef-value-param.c b/test/Analysis/diagnostics/undef-value-param.c index 266a33518b..99e31d2e6c 100644 --- a/test/Analysis/diagnostics/undef-value-param.c +++ b/test/Analysis/diagnostics/undef-value-param.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void foo_irrelevant(int c) { @@ -306,6 +306,40 @@ double testPassingParentRegionStruct(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -320,6 +354,40 @@ double testPassingParentRegionStruct(int x) { // CHECK-NEXT: Returning without writing to '*x' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line15 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1057,6 +1125,40 @@ double testPassingParentRegionStruct(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1071,6 +1173,40 @@ double testPassingParentRegionStruct(int x) { // CHECK-NEXT: Returning without writing to 'X->f1' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line54 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: diff --git a/test/Analysis/diagnostics/undef-value-param.m b/test/Analysis/diagnostics/undef-value-param.m index 521fd7b85f..69bc9b991d 100644 --- a/test/Analysis/diagnostics/undef-value-param.m +++ b/test/Analysis/diagnostics/undef-value-param.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s typedef signed char BOOL; @@ -865,6 +865,40 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -879,6 +913,40 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) { // CHECK-NEXT: Returning without writing to '*storeRef' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line72 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: diff --git a/test/Analysis/edges-new.mm b/test/Analysis/edges-new.mm index f310f1bfa1..3e9615b94b 100644 --- a/test/Analysis/edges-new.mm +++ b/test/Analysis/edges-new.mm @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-eagerly-assume -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist -o %t -w %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-eagerly-assume -analyzer-output=plist -o %t -w %s // RUN: FileCheck --input-file %t %s //===----------------------------------------------------------------------===// diff --git a/test/Analysis/inline-plist.c b/test/Analysis/inline-plist.c index 441bb48b10..457fb26642 100644 --- a/test/Analysis/inline-plist.c +++ b/test/Analysis/inline-plist.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s -// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false -o %t +// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference,core.DivideZero -fblocks -analyzer-output=plist -analyzer-config suppress-null-return-paths=false -o %t // RUN: FileCheck -input-file %t %s // @@ -210,40 +210,6 @@ void test_block_arg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line18 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line18 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line18 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line18 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line18 // CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -306,40 +272,6 @@ void test_block_arg() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line27 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line27 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line27 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line27 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -660,40 +592,6 @@ void test_block_arg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col16 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1419,6 +1317,40 @@ void test_block_arg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line70 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line70 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line70 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line70 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line70 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1671,6 +1603,40 @@ void test_block_arg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line78 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line78 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line78 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line78 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line78 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1923,6 +1889,40 @@ void test_block_arg() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line86 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/inline-unique-reports.c b/test/Analysis/inline-unique-reports.c index f827f88deb..0044d14e52 100644 --- a/test/Analysis/inline-unique-reports.c +++ b/test/Analysis/inline-unique-reports.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t > /dev/null 2>&1 +// RUN: %clang_analyze_cc1 %s -analyzer-checker=core.NullDereference -analyzer-output=plist -o %t > /dev/null 2>&1 // RUN: FileCheck -input-file %t %s static inline bug(int *p) { @@ -85,40 +85,6 @@ void test_bug_2() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line15 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line15 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line15 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line15 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.c b/test/Analysis/inlining/eager-reclamation-path-notes.c index 7c0f0ec8f5..a31ab9ed0a 100644 --- a/test/Analysis/inlining/eager-reclamation-path-notes.c +++ b/test/Analysis/inlining/eager-reclamation-path-notes.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void use(int *ptr, int val) { @@ -99,46 +99,12 @@ void testChainedCalls() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line21 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col16 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col16 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col7 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line21 -// CHECK-NEXT: col7 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -398,40 +364,6 @@ void testChainedCalls() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line41 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -538,74 +470,6 @@ void testChainedCalls() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col6 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line33 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: diff --git a/test/Analysis/inlining/eager-reclamation-path-notes.cpp b/test/Analysis/inlining/eager-reclamation-path-notes.cpp index f77a19f996..9a9b01c3bd 100644 --- a/test/Analysis/inlining/eager-reclamation-path-notes.cpp +++ b/test/Analysis/inlining/eager-reclamation-path-notes.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 -analyzer-config suppress-null-return-paths=false %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s typedef struct { diff --git a/test/Analysis/inlining/path-notes.c b/test/Analysis/inlining/path-notes.c index 49ac873f74..15441d4a3c 100644 --- a/test/Analysis/inlining/path-notes.c +++ b/test/Analysis/inlining/path-notes.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config suppress-null-return-paths=false -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void zero(int **p) { @@ -318,6 +318,40 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line14 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1046,40 +1080,6 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1286,12 +1286,12 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line65 -// CHECK-NEXT: col4 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line65 -// CHECK-NEXT: col10 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1593,40 +1593,6 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: Returning from 'getZero' // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line72 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line72 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line72 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line72 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1992,6 +1958,40 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line83 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line83 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line83 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line83 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line83 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2370,6 +2370,40 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line92 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2693,6 +2727,40 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: Passing null pointer value via 1st parameter 'p' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line103 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line103 +// CHECK-NEXT: col20 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line103 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line103 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3155,6 +3223,40 @@ int testBoringCalleeOfInterestingCallee() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line132 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/inlining/path-notes.cpp b/test/Analysis/inlining/path-notes.cpp index 4d0b899e7c..e475399f60 100644 --- a/test/Analysis/inlining/path-notes.cpp +++ b/test/Analysis/inlining/path-notes.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config c++-inlining=destructors -std=c++11 -verify -Wno-tautological-undefined-compare %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 -analyzer-config path-diagnostics-alternate=false %s -o %t.plist -Wno-tautological-undefined-compare +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 %s -o %t.plist -Wno-tautological-undefined-compare // RUN: FileCheck --input-file=%t.plist %s class Foo { @@ -324,40 +324,6 @@ namespace PR17746 { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line31 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line31 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line31 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line31 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line32 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -560,40 +526,6 @@ namespace PR17746 { // CHECK-NEXT: Passing null pointer value via 1st parameter 'p' // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line24 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line24 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line24 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line24 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -671,40 +603,6 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line13 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line13 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line13 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line13 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -901,40 +799,6 @@ namespace PR17746 { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line38 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line38 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line44 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line44 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line44 // CHECK-NEXT: col5 // CHECK-NEXT: file0 @@ -962,40 +826,6 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line46 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line46 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line46 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line46 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1235,6 +1065,40 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line112 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line112 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line112 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line112 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line112 // CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1277,6 +1141,40 @@ namespace PR17746 { // CHECK-NEXT: Calling implicit default constructor for 'Wrapper' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1485,6 +1383,40 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line120 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line120 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line120 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line120 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line120 // CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1527,6 +1459,40 @@ namespace PR17746 { // CHECK-NEXT: Calling implicit copy constructor for 'Wrapper' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1735,12 +1701,12 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col25 +// CHECK-NEXT: col18 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1756,12 +1722,12 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col25 +// CHECK-NEXT: col18 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1811,6 +1777,40 @@ namespace PR17746 { // CHECK-NEXT: Calling defaulted move constructor for 'MovableWrapper' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1989,40 +1989,6 @@ namespace PR17746 { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line133 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line133 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line133 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line133 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line134 // CHECK-NEXT: col5 // CHECK-NEXT: file0 @@ -2129,6 +2095,40 @@ namespace PR17746 { // CHECK-NEXT: Calling implicit copy assignment operator for 'Wrapper' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2272,56 +2272,22 @@ namespace PR17746 { // CHECK-NEXT: descriptionDereference of null pointer (loaded from variable 'globalPtr') // CHECK-NEXT: categoryLogic error // CHECK-NEXT: typeDereference of null pointer -// CHECK-NEXT: check_namecore.NullDereference -// CHECK-NEXT: -// CHECK-NEXT: issue_hash_content_of_line_in_context9484c73e190dfe4b8c6c5bdfad9700c1 -// CHECK-NEXT: issue_context_kindC++ method -// CHECK-NEXT: issue_contextoperator= -// CHECK-NEXT: issue_hash_function_offset1 -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line78 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: path -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line142 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line142 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line142 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line142 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: +// CHECK-NEXT: check_namecore.NullDereference +// CHECK-NEXT: +// CHECK-NEXT: issue_hash_content_of_line_in_context9484c73e190dfe4b8c6c5bdfad9700c1 +// CHECK-NEXT: issue_context_kindC++ method +// CHECK-NEXT: issue_contextoperator= +// CHECK-NEXT: issue_hash_function_offset1 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line78 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges @@ -2331,12 +2297,12 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line142 -// CHECK-NEXT: col20 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line142 -// CHECK-NEXT: col20 +// CHECK-NEXT: col18 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2407,12 +2373,12 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line145 -// CHECK-NEXT: col9 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line145 -// CHECK-NEXT: col12 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2663,40 +2629,6 @@ namespace PR17746 { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line150 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line150 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line150 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line150 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line151 // CHECK-NEXT: col5 // CHECK-NEXT: file0 @@ -2788,6 +2720,40 @@ namespace PR17746 { // CHECK-NEXT: Calling implicit destructor for 'Wrapper' // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line93 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3770,40 +3736,6 @@ namespace PR17746 { // CHECK-NEXT: Passing null pointer value via 1st parameter 'p' // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line205 -// CHECK-NEXT: col23 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line205 -// CHECK-NEXT: col23 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line205 -// CHECK-NEXT: col21 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line205 -// CHECK-NEXT: col21 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3950,6 +3882,40 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line197 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line197 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line197 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line197 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line197 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -4269,6 +4235,40 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line221 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -4561,6 +4561,40 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line243 +// CHECK-NEXT: col2 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line243 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line243 +// CHECK-NEXT: col2 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line243 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line243 // CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -4959,40 +4993,6 @@ namespace PR17746 { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line269 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line269 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line269 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line269 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line269 // CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m index 5bfd41d95a..a372dab6bb 100644 --- a/test/Analysis/inlining/path-notes.m +++ b/test/Analysis/inlining/path-notes.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -analyzer-config path-diagnostics-alternate=false -fblocks %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s typedef struct dispatch_queue_s *dispatch_queue_t; @@ -362,40 +362,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -425,40 +391,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: 'p' not called because the receiver is nil // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line73 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -525,12 +457,12 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line79 -// CHECK-NEXT: col4 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line79 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1513,6 +1445,35 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: 'getPtr' not called because the receiver is nil // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line152 +// CHECK-NEXT: col25 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line152 +// CHECK-NEXT: col25 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line152 +// CHECK-NEXT: col35 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'x' +// CHECK-NEXT: message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'x' +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -1521,12 +1482,12 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line152 -// CHECK-NEXT: col26 +// CHECK-NEXT: col25 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line152 -// CHECK-NEXT: col26 +// CHECK-NEXT: col25 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1534,12 +1495,12 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line152 -// CHECK-NEXT: col25 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line152 -// CHECK-NEXT: col25 +// CHECK-NEXT: col23 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1551,35 +1512,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line152 -// CHECK-NEXT: col25 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line152 -// CHECK-NEXT: col25 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line152 -// CHECK-NEXT: col35 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth0 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Passing null pointer value via 1st parameter 'x' -// CHECK-NEXT: message -// CHECK-NEXT: Passing null pointer value via 1st parameter 'x' -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line152 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1936,40 +1868,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line168 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line168 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line168 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line168 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: line170 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -2047,40 +1945,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: Method returns an instance of NSObject with a +1 retain count // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2130,81 +1994,6 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line170 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col60 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col47 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth0 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Object autoreleased -// CHECK-NEXT: message -// CHECK-NEXT: Object autoreleased -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2217,13 +2006,13 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line175 +// CHECK-NEXT: line170 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col15 +// CHECK-NEXT: line170 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2238,13 +2027,13 @@ void testNullDereferenceInDispatch() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line175 +// CHECK-NEXT: line170 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col15 +// CHECK-NEXT: line170 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c index 513bf77667..ce50758571 100644 --- a/test/Analysis/malloc-plist.c +++ b/test/Analysis/malloc-plist.c @@ -1,5 +1,5 @@ // RUN: rm -f %t -// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -o %t %s // RUN: FileCheck -input-file %t %s typedef __typeof(sizeof(int)) size_t; @@ -311,40 +311,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line12 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line12 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line12 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line12 -// CHECK-NEXT: col23 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -382,12 +348,46 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 -// CHECK-NEXT: col18 +// CHECK-NEXT: col9 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 -// CHECK-NEXT: col23 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line14 +// CHECK-NEXT: col9 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -476,40 +476,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line21 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -547,12 +513,46 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line21 -// CHECK-NEXT: col9 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line21 -// CHECK-NEXT: col14 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line22 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line22 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line22 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -607,40 +607,6 @@ void testMyMalloc() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line26 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line26 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line26 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line26 -// CHECK-NEXT: col23 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -678,12 +644,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line26 -// CHECK-NEXT: col18 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line26 -// CHECK-NEXT: col23 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -704,40 +670,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line28 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line28 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line28 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line28 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -775,12 +707,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line28 -// CHECK-NEXT: col18 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line28 -// CHECK-NEXT: col24 +// CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1106,40 +1038,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line37 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line37 -// CHECK-NEXT: col6 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line37 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line37 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1177,12 +1075,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line37 -// CHECK-NEXT: col13 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line37 -// CHECK-NEXT: col18 +// CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1349,13 +1247,13 @@ void testMyMalloc() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col1 +// CHECK-NEXT: line45 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col1 +// CHECK-NEXT: line45 +// CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1363,14 +1261,82 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col1 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: depth0 +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line45 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line45 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line46 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line46 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line46 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line46 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line47 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line47 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line47 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth0 // CHECK-NEXT: extended_message // CHECK-NEXT: Potential leak of memory pointed to by 'buf' // CHECK-NEXT: message @@ -1508,40 +1474,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line55 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line55 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line55 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line55 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1579,12 +1511,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line55 -// CHECK-NEXT: col10 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line55 -// CHECK-NEXT: col15 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1983,40 +1915,6 @@ void testMyMalloc() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line76 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line76 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line76 -// CHECK-NEXT: col25 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line76 -// CHECK-NEXT: col30 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2054,12 +1952,46 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line76 -// CHECK-NEXT: col25 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line76 -// CHECK-NEXT: col30 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2191,40 +2123,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line69 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line69 -// CHECK-NEXT: col7 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line69 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line69 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2262,12 +2160,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line69 -// CHECK-NEXT: col18 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line69 -// CHECK-NEXT: col24 +// CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2497,6 +2395,40 @@ void testMyMalloc() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line78 // CHECK-NEXT: col5 // CHECK-NEXT: file0 @@ -2566,12 +2498,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line87 -// CHECK-NEXT: col9 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line87 -// CHECK-NEXT: col26 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2579,12 +2511,46 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line87 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col26 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges // CHECK-NEXT: @@ -2656,40 +2622,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2768,6 +2700,40 @@ void testMyMalloc() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line87 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line88 // CHECK-NEXT: col1 // CHECK-NEXT: file0 @@ -2850,40 +2816,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line100 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line100 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line100 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line100 -// CHECK-NEXT: col17 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2921,12 +2853,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line100 -// CHECK-NEXT: col12 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line100 -// CHECK-NEXT: col17 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3103,6 +3035,40 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line102 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line102 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -3199,40 +3165,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3270,12 +3202,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line109 -// CHECK-NEXT: col15 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line109 -// CHECK-NEXT: col20 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3407,40 +3339,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3478,12 +3376,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line120 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line120 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3615,40 +3513,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line128 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line128 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line128 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line128 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3686,12 +3550,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line128 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3823,40 +3687,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line136 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line136 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line136 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line136 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3894,12 +3724,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line136 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line136 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4128,40 +3958,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line145 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line145 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line145 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line145 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4199,12 +3995,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line145 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line145 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4433,40 +4229,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line159 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line159 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line159 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line159 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4504,12 +4266,46 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line159 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line159 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line160 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line160 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line160 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line160 +// CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4641,40 +4437,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col27 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4712,12 +4474,12 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line170 -// CHECK-NEXT: col22 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line170 -// CHECK-NEXT: col27 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4849,40 +4611,6 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line183 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line183 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line183 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line183 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -5086,6 +4814,35 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line192 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line192 +// CHECK-NEXT: col12 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line192 +// CHECK-NEXT: col21 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Memory is allocated +// CHECK-NEXT: message +// CHECK-NEXT: Memory is allocated +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -5106,13 +4863,13 @@ void testMyMalloc() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line192 -// CHECK-NEXT: col12 +// CHECK-NEXT: line193 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line192 -// CHECK-NEXT: col17 +// CHECK-NEXT: line193 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5123,35 +4880,6 @@ void testMyMalloc() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line192 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line192 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line192 -// CHECK-NEXT: col21 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Memory is allocated -// CHECK-NEXT: message -// CHECK-NEXT: Memory is allocated -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: // CHECK-NEXT: line196 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -5357,6 +5085,35 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line204 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line204 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line204 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Memory is allocated +// CHECK-NEXT: message +// CHECK-NEXT: Memory is allocated +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -5377,13 +5134,13 @@ void testMyMalloc() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line204 -// CHECK-NEXT: col9 +// CHECK-NEXT: line205 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line204 -// CHECK-NEXT: col14 +// CHECK-NEXT: line205 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5394,35 +5151,6 @@ void testMyMalloc() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line204 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line204 -// CHECK-NEXT: col9 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line204 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Memory is allocated -// CHECK-NEXT: message -// CHECK-NEXT: Memory is allocated -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: // CHECK-NEXT: line208 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -5514,5 +5242,3 @@ void testMyMalloc() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: diff --git a/test/Analysis/method-call-path-notes.cpp b/test/Analysis/method-call-path-notes.cpp index e6253d4f89..7c93c99bfd 100644 --- a/test/Analysis/method-call-path-notes.cpp +++ b/test/Analysis/method-call-path-notes.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s // Test warning about null or uninitialized pointer values used as instance member diff --git a/test/Analysis/null-deref-path-notes.m b/test/Analysis/null-deref-path-notes.m index 39cf9c79f3..4a68d8f6fb 100644 --- a/test/Analysis/null-deref-path-notes.m +++ b/test/Analysis/null-deref-path-notes.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=text -fblocks -verify -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false -fblocks -Wno-objc-root-class %s -o %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region -analyzer-output=plist-multi-file -fblocks -Wno-objc-root-class %s -o %t // RUN: FileCheck --input-file=%t %s @interface Root { diff --git a/test/Analysis/nullability-notes.m b/test/Analysis/nullability-notes.m index c93aa02c42..8b6e1b02b6 100644 --- a/test/Analysis/nullability-notes.m +++ b/test/Analysis/nullability-notes.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -analyzer-config path-diagnostics-alternate=true -o %t.plist %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -o %t.plist %s // RUN: FileCheck --input-file=%t.plist %s #include "Inputs/system-header-simulator-for-nullability.h" diff --git a/test/Analysis/objc-arc.m b/test/Analysis/objc-arc.m index 4b446abc90..687d63e24e 100644 --- a/test/Analysis/objc-arc.m +++ b/test/Analysis/objc-arc.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-config path-diagnostics-alternate=true -analyzer-output=plist-multi-file -o %t.plist %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc -analyzer-output=plist-multi-file -o %t.plist %s // RUN: FileCheck --input-file=%t.plist %s typedef signed char BOOL; diff --git a/test/Analysis/objc-radar17039661.m b/test/Analysis/objc-radar17039661.m index bfb8ef0230..0d2ddbfc30 100644 --- a/test/Analysis/objc-radar17039661.m +++ b/test/Analysis/objc-radar17039661.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount -fblocks -analyzer-output=plist-multi-file %s -o %t // RUN: FileCheck --input-file=%t %s @class NSString; typedef long NSInteger; @@ -86,6 +86,40 @@ void runTest() { // CHECK: // CHECK: // CHECK: line49 +// CHECK: col3 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line49 +// CHECK: col6 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line49 +// CHECK: col3 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line49 +// CHECK: col6 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line49 // CHECK: col26 // CHECK: file0 // CHECK: @@ -461,40 +495,6 @@ void runTest() { // CHECK: // CHECK: // CHECK: -// CHECK: kindcontrol -// CHECK: edges -// CHECK: -// CHECK: -// CHECK: start -// CHECK: -// CHECK: -// CHECK: line33 -// CHECK: col7 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: line33 -// CHECK: col14 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: end -// CHECK: -// CHECK: -// CHECK: line33 -// CHECK: col30 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: line33 -// CHECK: col30 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: -// CHECK: -// CHECK: -// CHECK: // CHECK: kindevent // CHECK: location // CHECK: @@ -532,12 +532,46 @@ void runTest() { // CHECK: // CHECK: // CHECK: line33 -// CHECK: col30 +// CHECK: col7 // CHECK: file0 // CHECK: // CHECK: // CHECK: line33 -// CHECK: col30 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 // CHECK: file0 // CHECK: // CHECK: @@ -635,40 +669,6 @@ void runTest() { // CHECK: // CHECK: // CHECK: -// CHECK: kindcontrol -// CHECK: edges -// CHECK: -// CHECK: -// CHECK: start -// CHECK: -// CHECK: -// CHECK: line50 -// CHECK: col5 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: line50 -// CHECK: col17 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: end -// CHECK: -// CHECK: -// CHECK: line50 -// CHECK: col21 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: line50 -// CHECK: col21 -// CHECK: file0 -// CHECK: -// CHECK: -// CHECK: -// CHECK: -// CHECK: -// CHECK: // CHECK: kindevent // CHECK: location // CHECK: @@ -710,6 +710,40 @@ void runTest() { // CHECK: Reference count incremented. The object now has a +1 retain count // CHECK: // CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line50 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line50 +// CHECK: col17 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line52 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line52 +// CHECK: col10 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: // CHECK: kindevent // CHECK: location // CHECK: @@ -759,6 +793,40 @@ void runTest() { // CHECK: end // CHECK: // CHECK: +// CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: // CHECK: line37 // CHECK: col7 // CHECK: file0 @@ -1065,6 +1133,40 @@ void runTest() { // CHECK: // CHECK: // CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col7 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line35 +// CHECK: col14 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line35 // CHECK: col33 // CHECK: file0 // CHECK: @@ -1229,5 +1331,3 @@ void runTest() { // CHECK: // CHECK: // CHECK: -// CHECK: -// CHECK: diff --git a/test/Analysis/plist-macros.cpp b/test/Analysis/plist-macros.cpp index 821110e185..53f7a19c13 100644 --- a/test/Analysis/plist-macros.cpp +++ b/test/Analysis/plist-macros.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=ture %s -o %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -analyzer-eagerly-assume -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m index 03f3393af8..1a80a4d5c6 100644 --- a/test/Analysis/plist-output-alternate.m +++ b/test/Analysis/plist-output-alternate.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -fblocks -analyzer-output=plist -o %t %s // RUN: FileCheck --input-file %t %s void test_null_init(void) { @@ -113,6 +113,40 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -259,6 +293,40 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -468,6 +536,40 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -857,6 +959,40 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -927,40 +1063,6 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line36 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1037,6 +1139,40 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1133,40 +1269,6 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line54 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line54 -// CHECK-NEXT: col13 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line54 -// CHECK-NEXT: col23 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line54 -// CHECK-NEXT: col36 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1204,12 +1306,12 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line54 -// CHECK-NEXT: col23 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line54 -// CHECK-NEXT: col36 +// CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1314,12 +1416,12 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col10 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col14 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1335,12 +1437,12 @@ void rdar8331641(int x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col10 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col14 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m index a80ab5c31c..6b39e31e0e 100644 --- a/test/Analysis/plist-output.m +++ b/test/Analysis/plist-output.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t.plist +// RUN: %clang_analyze_cc1 %s -analyzer-checker=osx.cocoa.RetainCount,deadcode.DeadStores,core -analyzer-output=plist -o %t.plist // RUN: FileCheck --input-file=%t.plist %s void test_null_init(void) { @@ -250,6 +250,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -396,6 +430,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line12 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -605,6 +673,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -994,6 +1096,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line31 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1064,40 +1200,6 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line36 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 -// CHECK-NEXT: col24 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line36 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1174,6 +1276,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line38 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1480,6 +1616,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line50 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line50 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line50 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line50 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line50 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1961,12 +2131,12 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line77 -// CHECK-NEXT: col8 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line77 -// CHECK-NEXT: col8 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1974,20 +2144,54 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col8 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col6 -// CHECK-NEXT: file0 +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line77 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line77 @@ -2181,40 +2385,6 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line86 -// CHECK-NEXT: col5 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line86 -// CHECK-NEXT: col6 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line86 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line86 -// CHECK-NEXT: col14 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2252,12 +2422,12 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line86 -// CHECK-NEXT: col14 +// CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line86 -// CHECK-NEXT: col14 +// CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2312,6 +2482,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col28 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -2366,6 +2565,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line96 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line96 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line96 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line96 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line100 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -2443,6 +2676,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: Looping back to the head of the loop // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col28 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -2561,6 +2823,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line98 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line98 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line98 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line98 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line98 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2690,7 +2986,7 @@ int testFoo(Foo *x) { // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line108 -// CHECK-NEXT: col3 +// CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -2698,12 +2994,12 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line108 -// CHECK-NEXT: col3 +// CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line108 -// CHECK-NEXT: col5 +// CHECK-NEXT: col28 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2899,7 +3195,7 @@ int testFoo(Foo *x) { // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line117 -// CHECK-NEXT: col3 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -2907,12 +3203,12 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line117 -// CHECK-NEXT: col3 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line117 -// CHECK-NEXT: col5 +// CHECK-NEXT: col15 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3104,6 +3400,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col28 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -3158,6 +3483,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line127 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line127 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line127 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line127 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line129 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -3235,6 +3594,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: Looping back to the head of the loop // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line126 +// CHECK-NEXT: col28 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -3454,6 +3842,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col23 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -3560,7 +3977,36 @@ int testFoo(Foo *x) { // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line135 -// CHECK-NEXT: col3 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Looping back to the head of the loop +// CHECK-NEXT: message +// CHECK-NEXT: Looping back to the head of the loop +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line135 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -3568,21 +4014,21 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line135 -// CHECK-NEXT: col3 +// CHECK-NEXT: col19 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line135 -// CHECK-NEXT: col5 +// CHECK-NEXT: col23 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: depth0 // CHECK-NEXT: extended_message -// CHECK-NEXT: Looping back to the head of the loop +// CHECK-NEXT: Entering loop body // CHECK-NEXT: message -// CHECK-NEXT: Looping back to the head of the loop +// CHECK-NEXT: Entering loop body // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol @@ -3896,6 +4342,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col23 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -3950,6 +4425,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line143 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line143 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line143 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line143 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line144 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -4027,6 +4536,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: Looping back to the head of the loop // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line141 +// CHECK-NEXT: col23 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -4372,6 +4910,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -4426,6 +4993,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line153 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line153 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line153 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line153 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line154 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -4503,6 +5104,35 @@ int testFoo(Foo *x) { // CHECK-NEXT: Looping back to the head of the loop // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line151 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: message +// CHECK-NEXT: Entering loop body +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -4930,7 +5560,7 @@ int testFoo(Foo *x) { // CHECK-NEXT: location // CHECK-NEXT: // CHECK-NEXT: line160 -// CHECK-NEXT: col3 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: ranges @@ -4938,21 +5568,21 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line160 -// CHECK-NEXT: col3 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line160 -// CHECK-NEXT: col5 +// CHECK-NEXT: col13 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: depth0 // CHECK-NEXT: extended_message -// CHECK-NEXT: Loop body executed 0 times +// CHECK-NEXT: Loop body skipped when collection is empty // CHECK-NEXT: message -// CHECK-NEXT: Loop body executed 0 times +// CHECK-NEXT: Loop body skipped when collection is empty // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindcontrol @@ -5122,6 +5752,40 @@ int testFoo(Foo *x) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line172 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line172 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line172 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line172 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line172 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -5456,40 +6120,6 @@ int testFoo(Foo *x) { // CHECK-NEXT: 'returnsPointer' not called because the receiver is nil // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line194 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line194 -// CHECK-NEXT: col12 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line194 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line194 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: diff --git a/test/Analysis/retain-release-path-notes-gc.m b/test/Analysis/retain-release-path-notes-gc.m index 04f991263c..307aef1a5e 100644 --- a/test/Analysis/retain-release-path-notes-gc.m +++ b/test/Analysis/retain-release-path-notes-gc.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fobjc-gc-only -analyzer-output=plist-multi-file %s -o %t.plist // RUN: FileCheck --input-file=%t.plist %s /*** @@ -79,40 +79,6 @@ void retainReleaseIgnored () { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line43 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -150,12 +116,12 @@ void retainReleaseIgnored () { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line43 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line43 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -225,40 +191,6 @@ void retainReleaseIgnored () { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line48 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line48 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line48 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line48 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -296,12 +228,12 @@ void retainReleaseIgnored () { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line48 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line48 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -671,40 +603,6 @@ void retainReleaseIgnored () { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -742,12 +640,12 @@ void retainReleaseIgnored () { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1042,40 +940,6 @@ void retainReleaseIgnored () { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line66 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line66 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line66 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line66 -// CHECK-NEXT: col36 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1113,12 +977,12 @@ void retainReleaseIgnored () { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line66 -// CHECK-NEXT: col20 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line66 -// CHECK-NEXT: col36 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1229,40 +1093,6 @@ void retainReleaseIgnored () { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col36 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1300,12 +1130,12 @@ void retainReleaseIgnored () { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line71 -// CHECK-NEXT: col20 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line71 -// CHECK-NEXT: col36 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/retain-release-path-notes.m b/test/Analysis/retain-release-path-notes.m index 052d42d2e6..719a4d488c 100644 --- a/test/Analysis/retain-release-path-notes.m +++ b/test/Analysis/retain-release-path-notes.m @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file -analyzer-config path-diagnostics-alternate=false %s -o %t +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=plist-multi-file %s -o %t // RUN: FileCheck --input-file=%t %s /*** @@ -335,40 +335,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line47 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -406,12 +372,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line47 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line47 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -481,40 +447,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line52 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line52 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line52 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line52 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -552,12 +484,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line52 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line52 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -627,40 +559,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line57 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -698,12 +596,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line57 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -998,40 +896,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line65 -// CHECK-NEXT: col31 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1069,12 +933,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line65 -// CHECK-NEXT: col19 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line65 -// CHECK-NEXT: col31 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1219,40 +1083,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line71 -// CHECK-NEXT: col35 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1290,12 +1120,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line71 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line71 -// CHECK-NEXT: col35 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1440,40 +1270,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line77 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1511,12 +1307,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line77 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line77 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1661,40 +1457,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line83 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1732,12 +1494,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line83 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line83 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -1882,40 +1644,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line89 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line89 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line89 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line89 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -1953,12 +1681,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line89 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line89 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2178,40 +1906,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line96 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line96 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line96 -// CHECK-NEXT: col19 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line96 -// CHECK-NEXT: col31 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2249,12 +1943,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line96 -// CHECK-NEXT: col19 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line96 -// CHECK-NEXT: col31 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2399,40 +2093,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line102 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line102 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line102 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line102 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2470,12 +2130,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line102 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line102 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2695,40 +2355,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line109 -// CHECK-NEXT: col35 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2766,12 +2392,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line109 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line109 -// CHECK-NEXT: col35 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -2882,40 +2508,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line114 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line114 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line114 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line114 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2953,12 +2545,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line114 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line114 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3069,40 +2661,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col20 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line120 -// CHECK-NEXT: col32 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3140,12 +2698,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line120 -// CHECK-NEXT: col20 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line120 -// CHECK-NEXT: col32 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3256,40 +2814,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line125 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line125 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line125 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line125 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3327,12 +2851,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line125 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line125 -// CHECK-NEXT: col18 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3443,40 +2967,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line130 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line130 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line130 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line130 -// CHECK-NEXT: col18 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3514,12 +3004,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line130 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line130 -// CHECK-NEXT: col18 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3630,40 +3120,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line135 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line135 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line135 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line135 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3701,12 +3157,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line135 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line135 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -3817,40 +3273,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line140 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line140 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line140 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line140 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -3888,12 +3310,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line140 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line140 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4038,40 +3460,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line170 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4109,12 +3497,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line170 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line170 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4184,40 +3572,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line175 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4255,12 +3609,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line175 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line175 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4330,40 +3684,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line180 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line180 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line180 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line180 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4401,12 +3721,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line180 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line180 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4476,40 +3796,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line185 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line185 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line185 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line185 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -4547,12 +3833,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line185 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line185 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4619,42 +3905,8 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: path -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line190 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line190 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line190 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line190 -// CHECK-NEXT: col15 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location @@ -4693,12 +3945,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line190 -// CHECK-NEXT: col15 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line190 -// CHECK-NEXT: col15 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -4831,40 +4083,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: Method returns an instance of MyObj with a +1 retain count // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -5171,13 +4389,13 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 +// CHECK-NEXT: line232 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5192,13 +4410,13 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line226 -// CHECK-NEXT: col10 +// CHECK-NEXT: line232 +// CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5296,6 +4514,35 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line215 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line215 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line215 +// CHECK-NEXT: col21 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Method returns an instance of MyObj with a +1 retain count +// CHECK-NEXT: message +// CHECK-NEXT: Method returns an instance of MyObj with a +1 retain count +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -5316,13 +4563,13 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line215 -// CHECK-NEXT: col10 +// CHECK-NEXT: line216 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line215 -// CHECK-NEXT: col10 +// CHECK-NEXT: line216 +// CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5333,35 +4580,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line215 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: ranges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line215 -// CHECK-NEXT: col10 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line215 -// CHECK-NEXT: col21 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Method returns an instance of MyObj with a +1 retain count -// CHECK-NEXT: message -// CHECK-NEXT: Method returns an instance of MyObj with a +1 retain count -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: // CHECK-NEXT: line232 // CHECK-NEXT: col10 // CHECK-NEXT: file0 @@ -5408,6 +4626,40 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line237 // CHECK-NEXT: col3 // CHECK-NEXT: file0 @@ -5505,40 +4757,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line247 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line247 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line247 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line247 -// CHECK-NEXT: col38 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -5576,12 +4794,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line247 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line247 -// CHECK-NEXT: col38 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -5801,40 +5019,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line254 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line254 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line254 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line254 -// CHECK-NEXT: col35 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -5872,12 +5056,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line254 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line254 -// CHECK-NEXT: col35 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: @@ -6022,40 +5206,6 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line260 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line260 -// CHECK-NEXT: col11 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line260 -// CHECK-NEXT: col22 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line260 -// CHECK-NEXT: col35 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -6093,12 +5243,12 @@ void CFAutoreleaseUnownedMixed() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line260 -// CHECK-NEXT: col22 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line260 -// CHECK-NEXT: col35 +// CHECK-NEXT: col11 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c index 9126e1bb39..44e7a2e643 100644 --- a/test/Analysis/unix-fns.c +++ b/test/Analysis/unix-fns.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,unix.API,osx.API,optin.portability %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist // RUN: FileCheck --input-file=%t.plist %s // RUN: mkdir -p %t.dir // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,osx.API,optin.portability -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s @@ -700,40 +700,6 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line103 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line103 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindcontrol -// CHECK-NEXT: edges -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: start -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line103 -// CHECK-NEXT: col3 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line103 -// CHECK-NEXT: col4 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: end -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: line103 // CHECK-NEXT: col8 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1786,6 +1752,40 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: 'p' captured by block as a null pointer value // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line221 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2153,6 +2153,40 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line232 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 // CHECK-NEXT: col24 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2195,6 +2229,40 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: 'p' captured by block as a null pointer value // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col24 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line232 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2492,6 +2560,40 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line239 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line239 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line241 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line241 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: @@ -2880,6 +2982,40 @@ void test_inline_dispatch_once_reachable() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line245 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line245 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line245 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line245 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line245 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: -- GitLab From c8e52edcb9b9e92811c1893ef4a14ae1ddd7ac38 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 19:08:00 +0000 Subject: [PATCH 0099/1023] [analyzer] [NFC] Unify Minimal and Extensive diagnostics. Once we removed AlternateExtensive, I've looked closer into the difference between Minimal and Extensive, and turns out, the difference was not that large. Differential Revision: https://reviews.llvm.org/D47756 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334525 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporter.cpp | 529 +++++++++++------------- 1 file changed, 243 insertions(+), 286 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index ace494c349..2f0ecb5d19 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -388,7 +388,7 @@ public: PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { - return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive; + return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Minimal; } bool supportsLogicalOpControlFlow() const { @@ -536,7 +536,7 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { //===----------------------------------------------------------------------===// // "Visitors only" path diagnostic generation algorithm. //===----------------------------------------------------------------------===// -static bool GenerateVisitorsOnlyPathDiagnostic( +static bool generateVisitorsOnlyPathDiagnostics( PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef> visitors) { // All path generation skips the very first node (the error node). @@ -586,99 +586,155 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece &P, static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); -/// Add path diagnostic for statement associated with node \p N -/// to diagnostics \p PD. -/// Precondition: location associated with \p N is a \c BlockEdge. -static void generateMinimalDiagnosticsForBlockEdge(const ExplodedNode *N, - PathDiagnosticBuilder &PDB, - PathDiagnostic &PD) { - const LocationContext *LC = N->getLocationContext(); - SourceManager& SMgr = PDB.getSourceManager(); - BlockEdge BE = N->getLocation().castAs(); - const CFGBlock *Src = BE.getSrc(); - const CFGBlock *Dst = BE.getDst(); - const Stmt *T = Src->getTerminator(); - if (!T) - return; - auto Start = PathDiagnosticLocation::createBegin(T, SMgr, LC); - switch (T->getStmtClass()) { - default: - break; +std::shared_ptr generateDiagForSwitchOP( + const ExplodedNode *N, + const CFGBlock *Dst, + const SourceManager &SM, + const LocationContext *LC, + PathDiagnosticBuilder &PDB, + PathDiagnosticLocation &Start + ) { + // Figure out what case arm we took. + std::string sbuf; + llvm::raw_string_ostream os(sbuf); + PathDiagnosticLocation End; - case Stmt::GotoStmtClass: - case Stmt::IndirectGotoStmtClass: { - const Stmt *S = PathDiagnosticLocation::getNextStmt(N); + if (const Stmt *S = Dst->getLabel()) { + End = PathDiagnosticLocation(S, SM, LC); - if (!S) + switch (S->getStmtClass()) { + default: + os << "No cases match in the switch statement. " + "Control jumps to line " + << End.asLocation().getExpansionLineNumber(); + break; + case Stmt::DefaultStmtClass: + os << "Control jumps to the 'default' case at line " + << End.asLocation().getExpansionLineNumber(); break; - std::string sbuf; - llvm::raw_string_ostream os(sbuf); - const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); + case Stmt::CaseStmtClass: { + os << "Control jumps to 'case "; + const auto *Case = cast(S); + const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); - os << "Control jumps to line " << End.asLocation().getExpansionLineNumber(); - PD.getActivePath().push_front( - std::make_shared(Start, End, os.str())); - break; + // Determine if it is an enum. + bool GetRawInt = true; + + if (const auto *DR = dyn_cast(LHS)) { + // FIXME: Maybe this should be an assertion. Are there cases + // were it is not an EnumConstantDecl? + const auto *D = dyn_cast(DR->getDecl()); + + if (D) { + GetRawInt = false; + os << *D; + } + } + + if (GetRawInt) + os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); + + os << ":' at line " << End.asLocation().getExpansionLineNumber(); + break; + } + } + } else { + os << "'Default' branch taken. "; + End = PDB.ExecutionContinues(os, N); } + return std::make_shared(Start, End, + os.str()); +} - case Stmt::SwitchStmtClass: { - // Figure out what case arm we took. + +std::shared_ptr generateDiagForGotoOP( + const Stmt *S, + PathDiagnosticBuilder &PDB, + PathDiagnosticLocation &Start) { std::string sbuf; llvm::raw_string_ostream os(sbuf); + const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); + os << "Control jumps to line " << End.asLocation().getExpansionLineNumber(); + return std::make_shared(Start, End, os.str()); - if (const Stmt *S = Dst->getLabel()) { - PathDiagnosticLocation End(S, SMgr, LC); +} - switch (S->getStmtClass()) { - default: - os << "No cases match in the switch statement. " - "Control jumps to line " - << End.asLocation().getExpansionLineNumber(); - break; - case Stmt::DefaultStmtClass: - os << "Control jumps to the 'default' case at line " - << End.asLocation().getExpansionLineNumber(); - break; +std::shared_ptr generateDiagForBinaryOP( + const ExplodedNode *N, + const Stmt *T, + const CFGBlock *Src, + const CFGBlock *Dst, + const SourceManager &SM, + PathDiagnosticBuilder &PDB, + const LocationContext *LC) { + const auto *B = cast(T); + std::string sbuf; + llvm::raw_string_ostream os(sbuf); + os << "Left side of '"; + PathDiagnosticLocation Start, End; - case Stmt::CaseStmtClass: { - os << "Control jumps to 'case "; - const auto *Case = cast(S); - const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); + if (B->getOpcode() == BO_LAnd) { + os << "&&" + << "' is "; - // Determine if it is an enum. - bool GetRawInt = true; + if (*(Src->succ_begin() + 1) == Dst) { + os << "false"; + End = PathDiagnosticLocation(B->getLHS(), SM, LC); + Start = + PathDiagnosticLocation::createOperatorLoc(B, SM); + } else { + os << "true"; + Start = PathDiagnosticLocation(B->getLHS(), SM, LC); + End = PDB.ExecutionContinues(N); + } + } else { + assert(B->getOpcode() == BO_LOr); + os << "||" + << "' is "; - if (const auto *DR = dyn_cast(LHS)) { - // FIXME: Maybe this should be an assertion. Are there cases - // were it is not an EnumConstantDecl? - const auto *D = dyn_cast(DR->getDecl()); + if (*(Src->succ_begin() + 1) == Dst) { + os << "false"; + Start = PathDiagnosticLocation(B->getLHS(), SM, LC); + End = PDB.ExecutionContinues(N); + } else { + os << "true"; + End = PathDiagnosticLocation(B->getLHS(), SM, LC); + Start = + PathDiagnosticLocation::createOperatorLoc(B, SM); + } + } + return std::make_shared(Start, End, + os.str()); +} - if (D) { - GetRawInt = false; - os << *D; - } - } +void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE, + const SourceManager &SM, + PathDiagnosticBuilder &PDB, + PathDiagnostic &PD) { + const LocationContext *LC = N->getLocationContext(); + const CFGBlock *Src = BE.getSrc(); + const CFGBlock *Dst = BE.getDst(); + const Stmt *T = Src->getTerminator(); + if (!T) + return; - if (GetRawInt) - os << LHS->EvaluateKnownConstInt(PDB.getASTContext()); + auto Start = PathDiagnosticLocation::createBegin(T, SM, LC); + switch (T->getStmtClass()) { + default: + break; - os << ":' at line " << End.asLocation().getExpansionLineNumber(); - break; - } - } - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } else { - os << "'Default' branch taken. "; - const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } + case Stmt::GotoStmtClass: + case Stmt::IndirectGotoStmtClass: { + if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N)) + PD.getActivePath().push_front(generateDiagForGotoOP(S, PDB, Start)); + break; + } + case Stmt::SwitchStmtClass: { + PD.getActivePath().push_front( + generateDiagForSwitchOP(N, Dst, SM, LC, PDB, Start)); break; } @@ -719,54 +775,9 @@ static void generateMinimalDiagnosticsForBlockEdge(const ExplodedNode *N, if (!PDB.supportsLogicalOpControlFlow()) break; - const auto *B = cast(T); - std::string sbuf; - llvm::raw_string_ostream os(sbuf); - os << "Left side of '"; - - if (B->getOpcode() == BO_LAnd) { - os << "&&" - << "' is "; - - if (*(Src->succ_begin() + 1) == Dst) { - os << "false"; - PathDiagnosticLocation End(B->getLHS(), SMgr, LC); - PathDiagnosticLocation Start = - PathDiagnosticLocation::createOperatorLoc(B, SMgr); - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } else { - os << "true"; - PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); - PathDiagnosticLocation End = PDB.ExecutionContinues(N); - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } - } else { - assert(B->getOpcode() == BO_LOr); - os << "||" - << "' is "; - - if (*(Src->succ_begin() + 1) == Dst) { - os << "false"; - PathDiagnosticLocation Start(B->getLHS(), SMgr, LC); - PathDiagnosticLocation End = PDB.ExecutionContinues(N); - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } else { - os << "true"; - PathDiagnosticLocation End(B->getLHS(), SMgr, LC); - PathDiagnosticLocation Start = - PathDiagnosticLocation::createOperatorLoc(B, SMgr); - PD.getActivePath().push_front( - std::make_shared(Start, End, - os.str())); - } - } - + std::shared_ptr Diag = + generateDiagForBinaryOP(N, T, Src, Dst, SM, PDB, LC); + PD.getActivePath().push_front(Diag); break; } @@ -842,94 +853,6 @@ static void generateMinimalDiagnosticsForBlockEdge(const ExplodedNode *N, } } -/// Generate minimal diagnostics for node \p N, and write it into path -/// diagnostics \p PD. -void generateMinimalDiagnosticsForNode(const ExplodedNode *N, - PathDiagnosticBuilder &PDB, - PathDiagnostic &PD, - LocationContextMap &LCM, - StackDiagVector &CallStack) { - SourceManager &SMgr = PDB.getSourceManager(); - ProgramPoint P = N->getLocation(); - - if (Optional CE = P.getAs()) { - auto C = PathDiagnosticCallPiece::construct(N, *CE, SMgr); - // Record the mapping from call piece to LocationContext. - LCM[&C->path] = CE->getCalleeContext(); - auto *P = C.get(); - PD.getActivePath().push_front(std::move(C)); - PD.pushActivePath(&P->path); - CallStack.push_back(StackDiagPair(P, N)); - } else if (Optional CE = P.getAs()) { - // Flush all locations, and pop the active path. - bool VisitedEntireCall = PD.isWithinCall(); - PD.popActivePath(); - - // Either we just added a bunch of stuff to the top-level path, or - // we have a previous CallExitEnd. If the former, it means that the - // path terminated within a function call. We must then take the - // current contents of the active path and place it within - // a new PathDiagnosticCallPiece. - PathDiagnosticCallPiece *C; - if (VisitedEntireCall) { - C = cast(PD.getActivePath().front().get()); - } else { - const Decl *Caller = CE->getLocationContext()->getDecl(); - C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); - // Record the mapping from call piece to LocationContext. - LCM[&C->path] = CE->getCalleeContext(); - } - - C->setCallee(*CE, SMgr); - if (!CallStack.empty()) { - assert(CallStack.back().first == C); - CallStack.pop_back(); - } - } else if (P.getKind() == ProgramPoint::BlockEdgeKind) { - generateMinimalDiagnosticsForBlockEdge(N, PDB, PD); - } -} - -static bool GenerateMinimalPathDiagnostic( - PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef> visitors) { - const ExplodedNode *NextNode = N->pred_empty() - ? nullptr : *(N->pred_begin()); - StackDiagVector CallStack; - - while (NextNode) { - N = NextNode; - PDB.LC = N->getLocationContext(); - NextNode = N->getFirstPred(); - - generateMinimalDiagnosticsForNode(N, PDB, PD, LCM, CallStack); - - if (NextNode) { - // Add diagnostic pieces from custom visitors. - BugReport *R = PDB.getBugReport(); - llvm::FoldingSet DeduplicationSet; - for (auto &V : visitors) { - if (auto p = V->VisitNode(N, NextNode, PDB, *R)) { - if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) - continue; - - updateStackPiecesWithMessage(*p, CallStack); - PD.getActivePath().push_front(std::move(p)); - } - } - } - } - - if (!PDB.getBugReport()->isValid()) - return false; - - // After constructing the full PathDiagnostic, do a pass over it to compact - // PathDiagnosticPieces that occur within a macro. - CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); - return true; -} - // Cone-of-influence: support the reverse propagation of "interesting" symbols // and values by tracing interesting calculations backwards through evaluated // expressions along a path. This is probably overly complicated, but the idea @@ -1023,16 +946,6 @@ static bool isJumpToFalseBranch(const BlockEdge *BE) { return (*(Src->succ_begin()+1) == BE->getDst()); } -/// Return true if the terminator is a loop and the destination is the -/// false branch. -static bool isLoopJumpPastBody(const Stmt *Term, const BlockEdge *BE) { - if (!isLoop(Term)) - return false; - - // Did we take the false branch? - return isJumpToFalseBranch(BE); -} - static bool isContainedByStmt(ParentMap &PM, const Stmt *S, const Stmt *SubS) { while (SubS) { if (SubS == S) @@ -1132,16 +1045,18 @@ static const char StrLoopRangeEmpty[] = static const char StrLoopCollectionEmpty[] = "Loop body skipped when collection is empty"; -/// Generate extensive diagnostics for the node \p N, +/// Generate diagnostics for the node \p N, /// and write it into \p PD. -static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, +/// \p AddPathEdges Whether diagnostic consumer can generate path arrows +/// showing both row and column. +static void generatePathDiagnosticsForNode(const ExplodedNode *N, PathDiagnostic &PD, PathDiagnosticLocation &PrevLoc, PathDiagnosticBuilder &PDB, LocationContextMap &LCM, StackDiagVector &CallStack, - InterestingExprs &IE) { - const ExplodedNode *NextNode = N->getFirstPred(); + InterestingExprs &IE, + bool AddPathEdges) { ProgramPoint P = N->getLocation(); const SourceManager& SM = PDB.getSourceManager(); @@ -1149,19 +1064,22 @@ static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, // the case that we have not encountered a matching // call exit before this point. This means that the path // terminated within the call itself. - if (Optional CE = P.getAs()) { - // Add an edge to the start of the function. - const StackFrameContext *CalleeLC = CE->getCalleeContext(); - const Decl *D = CalleeLC->getDecl(); - // Add the edge only when the callee has body. We jump to the beginning - // of the *declaration*, however we expect it to be followed by the - // body. This isn't the case for autosynthesized property accessors in - // Objective-C. No need for a similar extra check for CallExit points - // because the exit edge comes from a statement (i.e. return), - // not from declaration. - if (D->hasBody()) - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, SM), CalleeLC); + if (auto CE = P.getAs()) { + + if (AddPathEdges) { + // Add an edge to the start of the function. + const StackFrameContext *CalleeLC = CE->getCalleeContext(); + const Decl *D = CalleeLC->getDecl(); + // Add the edge only when the callee has body. We jump to the beginning + // of the *declaration*, however we expect it to be followed by the + // body. This isn't the case for autosynthesized property accessors in + // Objective-C. No need for a similar extra check for CallExit points + // because the exit edge comes from a statement (i.e. return), + // not from declaration. + if (D->hasBody()) + addEdgeToPath(PD.getActivePath(), PrevLoc, + PathDiagnosticLocation::createBegin(D, SM), CalleeLC); + } // Did we visit an entire call? bool VisitedEntireCall = PD.isWithinCall(); @@ -1169,17 +1087,18 @@ static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, PathDiagnosticCallPiece *C; if (VisitedEntireCall) { - PathDiagnosticPiece *P = PD.getActivePath().front().get(); - C = cast(P); + C = cast(PD.getActivePath().front().get()); } else { const Decl *Caller = CE->getLocationContext()->getDecl(); C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); - // Since we just transferred the path over to the call piece, - // reset the mapping from active to location context. - assert(PD.getActivePath().size() == 1 && - PD.getActivePath().front().get() == C); - LCM[&PD.getActivePath()] = nullptr; + if (AddPathEdges) { + // Since we just transferred the path over to the call piece, + // reset the mapping from active to location context. + assert(PD.getActivePath().size() == 1 && + PD.getActivePath().front().get() == C); + LCM[&PD.getActivePath()] = nullptr; + } // Record the location context mapping for the path within // the call. @@ -1207,43 +1126,53 @@ static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, return; } - // Query the location context here and the previous location - // as processing CallEnter may change the active path. - PDB.LC = N->getLocationContext(); - // Record the mapping from the active path to the location - // context. - assert(!LCM[&PD.getActivePath()] || - LCM[&PD.getActivePath()] == PDB.LC); - LCM[&PD.getActivePath()] = PDB.LC; + if (AddPathEdges) { + // Query the location context here and the previous location + // as processing CallEnter may change the active path. + PDB.LC = N->getLocationContext(); + + // Record the mapping from the active path to the location + // context. + assert(!LCM[&PD.getActivePath()] || LCM[&PD.getActivePath()] == PDB.LC); + LCM[&PD.getActivePath()] = PDB.LC; + } // Have we encountered an exit from a function call? if (Optional CE = P.getAs()) { - const Stmt *S = CE->getCalleeContext()->getCallSite(); - // Propagate the interesting symbols accordingly. - if (const auto *Ex = dyn_cast_or_null(S)) { - reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, - N->getState().get(), Ex, - N->getLocationContext()); - } // We are descending into a call (backwards). Construct // a new call piece to contain the path pieces for that call. auto C = PathDiagnosticCallPiece::construct(N, *CE, SM); - - // Record the location context for this call piece. + // Record the mapping from call piece to LocationContext. LCM[&C->path] = CE->getCalleeContext(); - // Add the edge to the return site. - addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); + if (AddPathEdges) { + const Stmt *S = CE->getCalleeContext()->getCallSite(); + // Propagate the interesting symbols accordingly. + if (const auto *Ex = dyn_cast_or_null(S)) { + reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, + N->getState().get(), Ex, + N->getLocationContext()); + } + // Add the edge to the return site. + addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC); + PrevLoc.invalidate(); + } + auto *P = C.get(); PD.getActivePath().push_front(std::move(C)); - PrevLoc.invalidate(); // Make the contents of the call the active path for now. PD.pushActivePath(&P->path); CallStack.push_back(StackDiagPair(P, N)); - } else if (Optional PS = P.getAs()) { + return; + } + + if (auto PS = P.getAs()) { + if (!AddPathEdges) + return; + // For expressions, make sure we propagate the // interesting symbols correctly. if (const Expr *Ex = PS->getStmtAs()) @@ -1259,13 +1188,20 @@ static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, PathDiagnosticLocation(PS->getStmt(), SM, PDB.LC); addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC); } - } else if (Optional BE = P.getAs()) { + + } else if (auto BE = P.getAs()) { + + if (!AddPathEdges) { + generateMinimalDiagForBlockEdge(N, *BE, SM, PDB, PD); + return; + } + // Does this represent entering a call? If so, look at propagating // interesting symbols across call boundaries. - if (NextNode) { + if (const ExplodedNode *NextNode = N->getFirstPred()) { const LocationContext *CallerCtx = NextNode->getLocationContext(); const LocationContext *CalleeCtx = PDB.LC; - if (CallerCtx != CalleeCtx) { + if (CallerCtx != CalleeCtx && AddPathEdges) { reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, N->getState().get(), CalleeCtx, CallerCtx); @@ -1347,10 +1283,18 @@ static void generateExtensivePathDiagnosticForNode(const ExplodedNode *N, } } -static bool GenerateExtensivePathDiagnostic( +/// There are two path diagnostics generation modes: with adding edges (used +/// for plists) and without (used for HTML and text). +/// When edges are added (\p AddPathEdges), +/// the path is modified to insert artificially generated +/// edges. +/// Otherwise, more detailed diagnostics is emitted for block edges, explaining +/// the transitions in words. +static bool generatePathDiagnostics( PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, - ArrayRef> visitors) { + ArrayRef> visitors, + bool AddPathEdges) { BugReport *report = PDB.getBugReport(); StackDiagVector CallStack; InterestingExprs IE; @@ -1362,8 +1306,8 @@ static bool GenerateExtensivePathDiagnostic( N = NextNode; NextNode = N->getFirstPred(); - generateExtensivePathDiagnosticForNode( - N, PD, PrevLoc, PDB, LCM, CallStack, IE); + generatePathDiagnosticsForNode( + N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); if (!NextNode) continue; @@ -1375,22 +1319,33 @@ static bool GenerateExtensivePathDiagnostic( if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) continue; - addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); + if (AddPathEdges) + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); updateStackPiecesWithMessage(*p, CallStack); PD.getActivePath().push_front(std::move(p)); } } } - // Add an edge to the start of the function. - // We'll prune it out later, but it helps make diagnostics more uniform. - const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); - const Decl *D = CalleeLC->getDecl(); - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, PDB.getSourceManager()), - CalleeLC); + if (AddPathEdges) { + // Add an edge to the start of the function. + // We'll prune it out later, but it helps make diagnostics more uniform. + const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); + const Decl *D = CalleeLC->getDecl(); + addEdgeToPath(PD.getActivePath(), PrevLoc, + PathDiagnosticLocation::createBegin(D, PDB.getSourceManager()), + CalleeLC); + } - return report->isValid(); + if (!report->isValid()) + return false; + + // After constructing the full PathDiagnostic, do a pass over it to compact + // PathDiagnosticPieces that occur within a macro. + if (!AddPathEdges) + CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); + + return true; } static const Stmt *getLocStmt(PathDiagnosticLocation L) { @@ -2646,13 +2601,15 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, switch (ActiveScheme) { case PathDiagnosticConsumer::Extensive: - GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); + generatePathDiagnostics(PD, PDB, N, LCM, visitors, + /*AddPathEdges=*/true); break; case PathDiagnosticConsumer::Minimal: - GenerateMinimalPathDiagnostic(PD, PDB, N, LCM, visitors); + generatePathDiagnostics(PD, PDB, N, LCM, visitors, + /*AddPathEdges=*/false); break; case PathDiagnosticConsumer::None: - GenerateVisitorsOnlyPathDiagnostic(PD, PDB, N, visitors); + generateVisitorsOnlyPathDiagnostics(PD, PDB, N, visitors); break; } -- GitLab From 9cc0ad9b8a752cf7c3eb3b4554651f9b00f4b7d8 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 19:08:17 +0000 Subject: [PATCH 0100/1023] [analyzer] [NFC] Now let's have only one place for diagnostics generation Differential Revision: https://reviews.llvm.org/D47808 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334526 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporter.cpp | 58 +++++++------------------ 1 file changed, 15 insertions(+), 43 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2f0ecb5d19..98c90559e2 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -533,30 +533,6 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { /*allowNestedContexts=*/false); } -//===----------------------------------------------------------------------===// -// "Visitors only" path diagnostic generation algorithm. -//===----------------------------------------------------------------------===// -static bool generateVisitorsOnlyPathDiagnostics( - PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, - ArrayRef> visitors) { - // All path generation skips the very first node (the error node). - // This is because there is special handling for the end-of-path note. - N = N->getFirstPred(); - if (!N) - return true; - - BugReport *R = PDB.getBugReport(); - while (const ExplodedNode *Pred = N->getFirstPred()) { - for (auto &V : visitors) - // Visit all the node pairs, but throw the path pieces away. - V->VisitNode(N, Pred, PDB, *R); - - N = Pred; - } - - return R->isValid(); -} - //===----------------------------------------------------------------------===// // "Minimal" path diagnostic generation algorithm. //===----------------------------------------------------------------------===// @@ -1285,7 +1261,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N, /// There are two path diagnostics generation modes: with adding edges (used /// for plists) and without (used for HTML and text). -/// When edges are added (\p AddPathEdges), +/// When edges are added (\p ActiveScheme is Extensive), /// the path is modified to insert artificially generated /// edges. /// Otherwise, more detailed diagnostics is emitted for block edges, explaining @@ -1294,20 +1270,24 @@ static bool generatePathDiagnostics( PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef> visitors, - bool AddPathEdges) { + PathDiagnosticConsumer::PathGenerationScheme ActiveScheme) { BugReport *report = PDB.getBugReport(); StackDiagVector CallStack; InterestingExprs IE; + bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive); + bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None); - PathDiagnosticLocation PrevLoc = PD.getLocation(); + PathDiagnosticLocation PrevLoc = GenerateDiagnostics ? + PD.getLocation() : PathDiagnosticLocation(); const ExplodedNode *NextNode = N->getFirstPred(); while (NextNode) { N = NextNode; NextNode = N->getFirstPred(); - generatePathDiagnosticsForNode( - N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); + if (GenerateDiagnostics) + generatePathDiagnosticsForNode( + N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); if (!NextNode) continue; @@ -1316,6 +1296,10 @@ static bool generatePathDiagnostics( llvm::FoldingSet DeduplicationSet; for (auto &V : visitors) { if (auto p = V->VisitNode(N, NextNode, PDB, *report)) { + + if (!GenerateDiagnostics) + continue; + if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) continue; @@ -1342,7 +1326,7 @@ static bool generatePathDiagnostics( // After constructing the full PathDiagnostic, do a pass over it to compact // PathDiagnosticPieces that occur within a macro. - if (!AddPathEdges) + if (!AddPathEdges && GenerateDiagnostics) CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); return true; @@ -2599,19 +2583,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // hold onto old mappings. LCM.clear(); - switch (ActiveScheme) { - case PathDiagnosticConsumer::Extensive: - generatePathDiagnostics(PD, PDB, N, LCM, visitors, - /*AddPathEdges=*/true); - break; - case PathDiagnosticConsumer::Minimal: - generatePathDiagnostics(PD, PDB, N, LCM, visitors, - /*AddPathEdges=*/false); - break; - case PathDiagnosticConsumer::None: - generateVisitorsOnlyPathDiagnostics(PD, PDB, N, visitors); - break; - } + generatePathDiagnostics(PD, PDB, N, LCM, visitors, ActiveScheme); // Clean up the visitors we used. visitors.clear(); -- GitLab From 6fc954314a3ab8b4866b2fdc828ccf09889d2c12 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 12 Jun 2018 19:33:15 +0000 Subject: [PATCH 0101/1023] [clang-format] Fix crash while reflowing backslash in comments Summary: The added test case was currently crashing with an assertion: ``` krasimir@krasimir> cat test.cc ~ // How to run: // bbbbb run \ // rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr \ // -- --output_directory="" krasimir@krasimir> ~/work/llvm-build/bin/clang-format test.cc ~ clang-format: /usr/local/google/home/krasimir/work/llvm/tools/clang/lib/Format/WhitespaceManager.cpp:117: void clang::format::WhitespaceManager::calculateLineBreakInformation(): Assertion `PreviousOriginalWhitespaceEndOffset <= OriginalWhitespaceStartOffset' failed. ``` The root cause was that BreakableToken was not considering the case of a reflow between an unescaped newline in a line comment. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48089 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334527 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/BreakableToken.cpp | 45 +++++++++++++++++++++---- unittests/Format/FormatTestComments.cpp | 15 +++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp index f727f8ddf8..cc68f70100 100644 --- a/lib/Format/BreakableToken.cpp +++ b/lib/Format/BreakableToken.cpp @@ -789,16 +789,47 @@ BreakableComment::Split BreakableLineCommentSection::getReflowSplit( void BreakableLineCommentSection::reflow(unsigned LineIndex, WhitespaceManager &Whitespaces) const { - // Reflow happens between tokens. Replace the whitespace between the - // tokens by the empty string. - Whitespaces.replaceWhitespace( - *Tokens[LineIndex], /*Newlines=*/0, /*Spaces=*/0, - /*StartOfTokenColumn=*/StartColumn, /*InPPDirective=*/false); + if (LineIndex > 0 && Tokens[LineIndex] != Tokens[LineIndex - 1]) { + // Reflow happens between tokens. Replace the whitespace between the + // tokens by the empty string. + Whitespaces.replaceWhitespace( + *Tokens[LineIndex], /*Newlines=*/0, /*Spaces=*/0, + /*StartOfTokenColumn=*/StartColumn, /*InPPDirective=*/false); + } else if (LineIndex > 0) { + // In case we're reflowing after the '\' in: + // + // // line comment \ + // // line 2 + // + // the reflow happens inside the single comment token (it is a single line + // comment with an unescaped newline). + // Replace the whitespace between the '\' and '//' with the empty string. + // + // Offset points to after the '\' relative to start of the token. + unsigned Offset = Lines[LineIndex - 1].data() + + Lines[LineIndex - 1].size() - + tokenAt(LineIndex - 1).TokenText.data(); + // WhitespaceLength is the number of chars between the '\' and the '//' on + // the next line. + unsigned WhitespaceLength = + Lines[LineIndex].data() - tokenAt(LineIndex).TokenText.data() - Offset; + Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex], + Offset, + /*ReplaceChars=*/WhitespaceLength, + /*PreviousPostfix=*/"", + /*CurrentPrefix=*/"", + /*InPPDirective=*/false, + /*Newlines=*/0, + /*Spaces=*/0); + + } // Replace the indent and prefix of the token with the reflow prefix. + unsigned Offset = + Lines[LineIndex].data() - tokenAt(LineIndex).TokenText.data(); unsigned WhitespaceLength = - Content[LineIndex].data() - tokenAt(LineIndex).TokenText.data(); + Content[LineIndex].data() - Lines[LineIndex].data(); Whitespaces.replaceWhitespaceInToken(*Tokens[LineIndex], - /*Offset=*/0, + Offset, /*ReplaceChars=*/WhitespaceLength, /*PreviousPostfix=*/"", /*CurrentPrefix=*/ReflowPrefix, diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp index e89f1d9cde..cacd2024fe 100644 --- a/unittests/Format/FormatTestComments.cpp +++ b/unittests/Format/FormatTestComments.cpp @@ -3090,6 +3090,21 @@ TEST_F(FormatTestComments, BreaksBeforeTrailingUnbreakableSequence) { getLLVMStyleWithColumns(23)); } +TEST_F(FormatTestComments, ReflowBackslashCrash) { +// clang-format off + EXPECT_EQ( +"// How to run:\n" +"// bbbbb run \\\n" +"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr\n" +"// \\ -- --output_directory=\"\"", + format( +"// How to run:\n" +"// bbbbb run \\\n" +"// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr \\\n" +"// -- --output_directory=\"\"")); +// clang-format on +} + } // end namespace } // end namespace format } // end namespace clang -- GitLab From c186f2243df5cc5dcb25697639febbf7c5299c68 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Jun 2018 20:00:50 +0000 Subject: [PATCH 0102/1023] [AArch64] Support reserving x20 register Register x20 is a callee-saved register which may be used for other purposes in certain contexts, for example to hold special variables within the kernel. This change adds support for reserving this register both to frontend and backend to make this register usable for these purposes. Differential Revision: https://reviews.llvm.org/D46552 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334531 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangCommandLineReference.rst | 4 ++++ include/clang/Driver/Options.td | 2 ++ lib/Driver/ToolChains/Arch/AArch64.cpp | 3 +++ test/Driver/aarch64-fixed-x20.c | 4 ++++ 4 files changed, 13 insertions(+) create mode 100644 test/Driver/aarch64-fixed-x20.c diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 10fc831bdf..264729dd0f 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -2296,6 +2296,10 @@ AARCH64 Reserve the x18 register (AArch64 only) +.. option:: -ffixed-x20 + +Reserve the x20 register (AArch64 only) + .. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769 Workaround Cortex-A53 erratum 835769 (AArch64 only) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index e5aaeb93de..4c04d33466 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -2004,6 +2004,8 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">, HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">; def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group, HelpText<"Reserve the x18 register (AArch64 only)">; +def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group, + HelpText<"Reserve the x20 register (AArch64 only)">; def msimd128 : Flag<["-"], "msimd128">, Group; def mno_simd128 : Flag<["-"], "mno-simd128">, Group; diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp index ad04aedd09..7bac69687a 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -198,6 +198,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, if (Args.hasArg(options::OPT_ffixed_x18)) Features.push_back("+reserve-x18"); + if (Args.hasArg(options::OPT_ffixed_x20)) + Features.push_back("+reserve-x20"); + if (Args.hasArg(options::OPT_mno_neg_immediates)) Features.push_back("+no-neg-immediates"); } diff --git a/test/Driver/aarch64-fixed-x20.c b/test/Driver/aarch64-fixed-x20.c new file mode 100644 index 0000000000..0be63971a4 --- /dev/null +++ b/test/Driver/aarch64-fixed-x20.c @@ -0,0 +1,4 @@ +// RUN: %clang -target aarch64-none-gnu -ffixed-x20 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s + +// CHECK-FIXED-X20: "-target-feature" "+reserve-x20" -- GitLab From 6fd0941a7def3ea274d3492dfd58122a53a0f7c6 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Jun 2018 20:44:11 +0000 Subject: [PATCH 0103/1023] Work around false -Wmissing-braces warning from old clang which has been fixed in r314838 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334539 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 3d86945a55..81f6943686 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -883,7 +883,7 @@ UbigraphViz::~UbigraphViz() { std::string Ubiviz; if (auto Path = llvm::sys::findProgramByName("ubiviz")) Ubiviz = *Path; - std::array Args = {Ubiviz, Filename}; + std::array Args{{Ubiviz, Filename}}; if (llvm::sys::ExecuteAndWait(Ubiviz, Args, llvm::None, {}, 0, 0, &ErrMsg)) { llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; -- GitLab From adbb1b6dd3017aae49c0c9ad63ff6d5861d2f078 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 20:50:44 +0000 Subject: [PATCH 0104/1023] [analyzer] [NFC] Remove most usages of getEndPath getEndPath is a problematic API, because it's not clear when it's called (hint: not always at the end of the path), it crashes at runtime with more than one non-nullptr returning implementation, and diagnostics internal depend on it being called at some exact place. However, most visitors don't actually need that: all they want is a function consistently called after all nodes are traversed, to perform finalization and to decide whether invalidation is needed. Differential Revision: https://reviews.llvm.org/D48042 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334540 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/BugReporterVisitors.h | 16 ++++++---- lib/StaticAnalyzer/Core/BugReporter.cpp | 10 ++++-- .../Core/BugReporterVisitors.cpp | 31 +++++++++---------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 80a6763783..9662d91fea 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -73,12 +73,17 @@ public: VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) = 0; + /// Last function called on the visitor, no further calls to VisitNode + /// would follow. + virtual void finalizeVisitor(BugReporterContext &BRC, + const ExplodedNode *EndPathNode, + BugReport &BR); + /// Provide custom definition for the final diagnostic piece on the /// path - the piece, which is displayed before the path is expanded. /// - /// If returns NULL the default implementation will be used. - /// Also note that at most one visitor of a BugReport should generate a - /// non-NULL end of path diagnostic piece. + /// NOTE that this function can be implemented on at most one used visitor, + /// and otherwise it crahes at runtime. virtual std::unique_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); @@ -268,9 +273,8 @@ public: return nullptr; } - std::unique_ptr getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) override; + void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, + BugReport &BR) override; }; /// When a region containing undefined value or '0' value is passed diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 98c90559e2..22185d2d03 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1270,7 +1270,9 @@ static bool generatePathDiagnostics( PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, LocationContextMap &LCM, ArrayRef> visitors, + BugReport *R, PathDiagnosticConsumer::PathGenerationScheme ActiveScheme) { + const ExplodedNode *LastNode = N; BugReport *report = PDB.getBugReport(); StackDiagVector CallStack; InterestingExprs IE; @@ -1289,8 +1291,12 @@ static bool generatePathDiagnostics( generatePathDiagnosticsForNode( N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); - if (!NextNode) + if (!NextNode) { + for (auto &V : visitors) { + V->finalizeVisitor(PDB, LastNode, *R); + } continue; + } // Add pieces from custom visitors. llvm::FoldingSet DeduplicationSet; @@ -2583,7 +2589,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // hold onto old mappings. LCM.clear(); - generatePathDiagnostics(PD, PDB, N, LCM, visitors, ActiveScheme); + generatePathDiagnostics(PD, PDB, N, LCM, visitors, R, ActiveScheme); // Clean up the visitors we used. visitors.clear(); diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index fe1a711a82..75126c6c37 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -181,6 +181,11 @@ BugReporterVisitor::getEndPath(BugReporterContext &BRC, return nullptr; } +void +BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC, + const ExplodedNode *EndPathNode, + BugReport &BR) {}; + std::unique_ptr BugReporterVisitor::getDefaultEndPath( BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { PathDiagnosticLocation L = @@ -866,12 +871,10 @@ public: llvm_unreachable("Invalid visit mode!"); } - std::unique_ptr getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) override { + void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, + BugReport &BR) override { if (EnableNullFPSuppression) BR.markInvalid(ReturnVisitor::getTag(), StackFrame); - return nullptr; } }; @@ -2144,10 +2147,8 @@ bool ConditionBRVisitor::isPieceMessageGeneric( Piece->getString() == GenericFalseMessage; } -std::unique_ptr -LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) { +void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor( + BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { // Here we suppress false positives coming from system headers. This list is // based on known issues. ExprEngine &Eng = BRC.getBugReporter().getEngine(); @@ -2161,7 +2162,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // TR1, Boost, or llvm/ADT. if (Options.shouldSuppressFromCXXStandardLibrary()) { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } else { // If the complete 'std' suppression is not enabled, suppress reports // from the 'std' namespace that are known to produce false positives. @@ -2173,7 +2174,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, const CXXRecordDecl *CD = MD->getParent(); if (CD->getName() == "list") { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } } @@ -2183,7 +2184,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, const CXXRecordDecl *CD = MD->getParent(); if (CD->getName() == "__independent_bits_engine") { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } } @@ -2202,7 +2203,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // data structure. if (CD->getName() == "basic_string") { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } // The analyzer issues a false positive on @@ -2210,7 +2211,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // because it does not reason properly about temporary destructors. if (CD->getName() == "shared_ptr") { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } } } @@ -2224,11 +2225,9 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, Loc = Loc.getSpellingLoc(); if (SM.getFilename(Loc).endswith("sys/queue.h")) { BR.markInvalid(getTag(), nullptr); - return nullptr; + return; } } - - return nullptr; } std::shared_ptr -- GitLab From eee461ae16d7dbbc8aa5adc44c3fae12191b6133 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 20:51:01 +0000 Subject: [PATCH 0105/1023] [analyzer] [NFC] Move ::dump methods from BugReporter.cpp to PathDiagnostics.cpp BugReporter.cpp is already severely overloaded, and those dump methods are on PathDiagnostics and should belong in the corresponding implementation file. Differential Revision: https://reviews.llvm.org/D48035 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334541 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/PathDiagnostic.h | 6 + lib/StaticAnalyzer/Core/BugReporter.cpp | 123 +++--------------- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 81 ++++++++++++ 3 files changed, 106 insertions(+), 104 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 54920e2d22..244cbfea9e 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -296,6 +296,12 @@ public: } const Stmt *asStmt() const { assert(isValid()); return S; } + const Stmt *getStmtOrNull() const { + if (!isValid()) + return nullptr; + return asStmt(); + } + const Decl *asDecl() const { assert(isValid()); return D; } bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 22185d2d03..9e4ba81a97 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1338,12 +1338,6 @@ static bool generatePathDiagnostics( return true; } -static const Stmt *getLocStmt(PathDiagnosticLocation L) { - if (!L.isValid()) - return nullptr; - return L.asStmt(); -} - static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { if (!S) return nullptr; @@ -1448,7 +1442,7 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM, // This is important for nested logical expressions (||, &&, ?:) where we // want to show all the levels of context. while (true) { - const Stmt *Dst = getLocStmt(Piece->getEndLocation()); + const Stmt *Dst = Piece->getEndLocation().getStmtOrNull(); // We are looking at an edge. Is the destination within a larger // expression? @@ -1471,9 +1465,11 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM, auto *PrevPiece = dyn_cast(Prev->get()); if (PrevPiece) { - if (const Stmt *PrevSrc = getLocStmt(PrevPiece->getStartLocation())) { + if (const Stmt *PrevSrc = + PrevPiece->getStartLocation().getStmtOrNull()) { const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM); - if (PrevSrcParent == getStmtParent(getLocStmt(DstContext), PM)) { + if (PrevSrcParent == + getStmtParent(DstContext.getStmtOrNull(), PM)) { PrevPiece->setEndLocation(DstContext); break; } @@ -1509,8 +1505,8 @@ static void simplifySimpleBranches(PathPieces &pieces) { if (!PieceI) continue; - const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); - const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); + const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull(); + const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull(); if (!s1Start || !s1End) continue; @@ -1543,8 +1539,8 @@ static void simplifySimpleBranches(PathPieces &pieces) { if (!PieceNextI) continue; - const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); - const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); + const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull(); + const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull(); if (!s2Start || !s2End || s1End != s2Start) continue; @@ -1634,8 +1630,8 @@ static void removeContextCycles(PathPieces &Path, SourceManager &SM, continue; } - const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); - const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); + const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull(); + const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull(); PathPieces::iterator NextI = I; ++NextI; if (NextI == E) @@ -1658,8 +1654,8 @@ static void removeContextCycles(PathPieces &Path, SourceManager &SM, } } - const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); - const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); + const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull(); + const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull(); if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) { const size_t MAX_SHORT_LINE_LENGTH = 80; @@ -1702,8 +1698,8 @@ static void removePunyEdges(PathPieces &path, SourceManager &SM, if (!PieceI) continue; - const Stmt *start = getLocStmt(PieceI->getStartLocation()); - const Stmt *end = getLocStmt(PieceI->getEndLocation()); + const Stmt *start = PieceI->getStartLocation().getStmtOrNull(); + const Stmt *end = PieceI->getEndLocation().getStmtOrNull(); if (!start || !end) continue; @@ -1794,8 +1790,8 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM, continue; } - const Stmt *s1Start = getLocStmt(PieceI->getStartLocation()); - const Stmt *s1End = getLocStmt(PieceI->getEndLocation()); + const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull(); + const Stmt *s1End = PieceI->getEndLocation().getStmtOrNull(); const Stmt *level1 = getStmtParent(s1Start, PM); const Stmt *level2 = getStmtParent(s1End, PM); @@ -1810,8 +1806,8 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM, continue; } - const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation()); - const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation()); + const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull(); + const Stmt *s2End = PieceNextI->getEndLocation().getStmtOrNull(); const Stmt *level3 = getStmtParent(s2Start, PM); const Stmt *level4 = getStmtParent(s2End, PM); @@ -3090,84 +3086,3 @@ BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name, BT = new BugType(CheckName, name, category); return BT; } - -LLVM_DUMP_METHOD void PathPieces::dump() const { - unsigned index = 0; - for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) { - llvm::errs() << "[" << index++ << "] "; - (*I)->dump(); - llvm::errs() << "\n"; - } -} - -LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const { - llvm::errs() << "CALL\n--------------\n"; - - if (const Stmt *SLoc = getLocStmt(getLocation())) - SLoc->dump(); - else if (const auto *ND = dyn_cast(getCallee())) - llvm::errs() << *ND << "\n"; - else - getLocation().dump(); -} - -LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const { - llvm::errs() << "EVENT\n--------------\n"; - llvm::errs() << getString() << "\n"; - llvm::errs() << " ---- at ----\n"; - getLocation().dump(); -} - -LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const { - llvm::errs() << "CONTROL\n--------------\n"; - getStartLocation().dump(); - llvm::errs() << " ---- to ----\n"; - getEndLocation().dump(); -} - -LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const { - llvm::errs() << "MACRO\n--------------\n"; - // FIXME: Print which macro is being invoked. -} - -LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const { - llvm::errs() << "NOTE\n--------------\n"; - llvm::errs() << getString() << "\n"; - llvm::errs() << " ---- at ----\n"; - getLocation().dump(); -} - -LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const { - if (!isValid()) { - llvm::errs() << "\n"; - return; - } - - switch (K) { - case RangeK: - // FIXME: actually print the range. - llvm::errs() << "\n"; - break; - case SingleLocK: - asLocation().dump(); - llvm::errs() << "\n"; - break; - case StmtK: - if (S) - S->dump(); - else - llvm::errs() << "\n"; - break; - case DeclK: - if (const auto *ND = dyn_cast_or_null(D)) - llvm::errs() << *ND << "\n"; - else if (isa(D)) - // FIXME: Make this nicer. - llvm::errs() << "\n"; - else if (D) - llvm::errs() << "\n"; - else - llvm::errs() << "\n"; - break; - } -} diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 4da966f644..95a7f33ce8 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -1321,3 +1321,84 @@ std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE, return os.str(); } + +LLVM_DUMP_METHOD void PathPieces::dump() const { + unsigned index = 0; + for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) { + llvm::errs() << "[" << index++ << "] "; + (*I)->dump(); + llvm::errs() << "\n"; + } +} + +LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const { + llvm::errs() << "CALL\n--------------\n"; + + if (const Stmt *SLoc = getLocation().getStmtOrNull()) + SLoc->dump(); + else if (const auto *ND = dyn_cast_or_null(getCallee())) + llvm::errs() << *ND << "\n"; + else + getLocation().dump(); +} + +LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const { + llvm::errs() << "EVENT\n--------------\n"; + llvm::errs() << getString() << "\n"; + llvm::errs() << " ---- at ----\n"; + getLocation().dump(); +} + +LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const { + llvm::errs() << "CONTROL\n--------------\n"; + getStartLocation().dump(); + llvm::errs() << " ---- to ----\n"; + getEndLocation().dump(); +} + +LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const { + llvm::errs() << "MACRO\n--------------\n"; + // FIXME: Print which macro is being invoked. +} + +LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const { + llvm::errs() << "NOTE\n--------------\n"; + llvm::errs() << getString() << "\n"; + llvm::errs() << " ---- at ----\n"; + getLocation().dump(); +} + +LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const { + if (!isValid()) { + llvm::errs() << "\n"; + return; + } + + switch (K) { + case RangeK: + // FIXME: actually print the range. + llvm::errs() << "\n"; + break; + case SingleLocK: + asLocation().dump(); + llvm::errs() << "\n"; + break; + case StmtK: + if (S) + S->dump(); + else + llvm::errs() << "\n"; + break; + case DeclK: + if (const auto *ND = dyn_cast_or_null(D)) + llvm::errs() << *ND << "\n"; + else if (isa(D)) + // FIXME: Make this nicer. + llvm::errs() << "\n"; + else if (D) + llvm::errs() << "\n"; + else + llvm::errs() << "\n"; + break; + } +} -- GitLab From f564a73a09421017a258348591ce726ab46eb553 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 20:51:19 +0000 Subject: [PATCH 0106/1023] [analyzer] [NFC] Remove "removeInvalidation" from visitor API removeInvalidation is a very problematic API, as it makes suppression order-dependent. Moreover, it was used only once, and could be rewritten in a much cleaner way. Differential Revision: https://reviews.llvm.org/D48045 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334542 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/Core/BugReporter/BugReporter.h | 7 ------- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 5 +++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 2f04a3b0fc..67d2dedc15 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -253,13 +253,6 @@ public: void markInvalid(const void *Tag, const void *Data) { Invalidations.insert(std::make_pair(Tag, Data)); } - - /// Reverses the effects of a previous invalidation. - /// - /// \sa markInvalid - void removeInvalidation(const void *Tag, const void *Data) { - Invalidations.erase(std::make_pair(Tag, Data)); - } /// Return the canonical declaration, be it a method or class, where /// this issue semantically occurred. diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 75126c6c37..3cac6cb328 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -616,6 +616,7 @@ class ReturnVisitor : public BugReporterVisitorImpl { } Mode = Initial; bool EnableNullFPSuppression; + bool ShouldInvalidate = true; public: ReturnVisitor(const StackFrameContext *Frame, bool Suppressed) @@ -845,7 +846,7 @@ public: if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true, EnableNullFPSuppression)) - BR.removeInvalidation(ReturnVisitor::getTag(), StackFrame); + ShouldInvalidate = false; // If we /can't/ track the null pointer, we should err on the side of // false negatives, and continue towards marking this report invalid. @@ -873,7 +874,7 @@ public: void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) override { - if (EnableNullFPSuppression) + if (EnableNullFPSuppression && ShouldInvalidate) BR.markInvalid(ReturnVisitor::getTag(), StackFrame); } }; -- GitLab From 08956eb168014e72aed6dff54dcdd5607a52aa5e Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Tue, 12 Jun 2018 21:27:36 +0000 Subject: [PATCH 0107/1023] [CMake][Darwin] Match cxx-headers -> cxx_headers libcxx target rename. This was changed in r334477. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334550 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Apple-stage2.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake index c7f3f04b42..3b80b5f407 100644 --- a/cmake/caches/Apple-stage2.cmake +++ b/cmake/caches/Apple-stage2.cmake @@ -61,7 +61,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS LTO clang-format clang-headers - cxx-headers + cxx_headers ${LLVM_TOOLCHAIN_TOOLS} CACHE STRING "") -- GitLab From e4b014451ae7dceacbfb5d0d4b4c8beb34f48158 Mon Sep 17 00:00:00 2001 From: Matthew Voss Date: Tue, 12 Jun 2018 22:22:35 +0000 Subject: [PATCH 0108/1023] [analyzer] Ensure that loop widening does not invalidate references Loop widening can invalidate a reference. If the analyzer attempts to visit the destructor to a non-existent reference, it will crash. This patch ensures that the reference is preserved. https://reviews.llvm.org/D47044 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334554 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/LoopWidening.cpp | 19 +++++++++++++++++++ .../loop-widening-preserve-reference-type.cpp | 14 ++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/Analysis/loop-widening-preserve-reference-type.cpp diff --git a/lib/StaticAnalyzer/Core/LoopWidening.cpp b/lib/StaticAnalyzer/Core/LoopWidening.cpp index a609aa96d7..fa14f7a18f 100644 --- a/lib/StaticAnalyzer/Core/LoopWidening.cpp +++ b/lib/StaticAnalyzer/Core/LoopWidening.cpp @@ -14,10 +14,16 @@ /// //===----------------------------------------------------------------------===// +#include "clang/AST/AST.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h" using namespace clang; using namespace ento; +using namespace clang::ast_matchers; + +const auto MatchRef = "matchref"; /// Return the loops condition Stmt or NULL if LoopStmt is not a loop static const Expr *getLoopCondition(const Stmt *LoopStmt) { @@ -49,6 +55,7 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, // TODO Nested loops are currently widened as a result of the invalidation // being so inprecise. When the invalidation is improved, the handling // of nested loops will also need to be improved. + ASTContext &ASTCtx = LCtx->getAnalysisDeclContext()->getASTContext(); const StackFrameContext *STC = LCtx->getCurrentStackFrame(); MemRegionManager &MRMgr = PrevState->getStateManager().getRegionManager(); const MemRegion *Regions[] = {MRMgr.getStackLocalsRegion(STC), @@ -60,6 +67,18 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, RegionAndSymbolInvalidationTraits::TK_EntireMemSpace); } + // References should not be invalidated. + auto Matches = match(findAll(stmt(hasDescendant(varDecl(hasType(referenceType())).bind(MatchRef)))), + *LCtx->getDecl()->getBody(), ASTCtx); + for (BoundNodes Match : Matches) { + const VarDecl *VD = Match.getNodeAs(MatchRef); + assert(VD); + const VarRegion *VarMem = MRMgr.getVarRegion(VD, LCtx); + ITraits.setTrait(VarMem, + RegionAndSymbolInvalidationTraits::TK_PreserveContents); + } + + // 'this' pointer is not an lvalue, we should not invalidate it. If the loop // is located in a method, constructor or destructor, the value of 'this' // pointer shoule remain unchanged. diff --git a/test/Analysis/loop-widening-preserve-reference-type.cpp b/test/Analysis/loop-widening-preserve-reference-type.cpp new file mode 100644 index 0000000000..b5746d1fe7 --- /dev/null +++ b/test/Analysis/loop-widening-preserve-reference-type.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s + +void clang_analyzer_eval(int); + +struct A { + ~A() {} +}; +struct B : public A {}; + +void invalid_type_region_access() { + const A &x = B(); + for (int i = 0; i < 10; ++i) { } + clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}} +} // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} -- GitLab From b28c0c543c93e5ada9127947a0adc91c8fd00331 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 12 Jun 2018 23:53:54 +0000 Subject: [PATCH 0109/1023] [analyzer] Do not crash in the visitor when the function is given more arguments than it has parameters rdar://40335545 Differential Revision: https://reviews.llvm.org/D48107 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334560 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 +- .../diagnostics/no-store-func-path-notes.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 3cac6cb328..fceb3f094c 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -286,7 +286,7 @@ public: } ArrayRef parameters = getCallParameters(Call); - for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) { + for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) { const ParmVarDecl *PVD = parameters[I]; SVal S = Call->getArgSVal(I); unsigned IndirectionLevel = 1; diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp index a704c14c25..b96dc4cf2a 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp +++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp @@ -145,3 +145,18 @@ int usepointerreference() { return s.x; // expected-warning{{Undefined or garbage value returned to caller}} // expected-note@-1{{Undefined or garbage value returned to caller}} } + +void *has_no_argument_and_returns_null(void) { + return 0; +} + +void rdar40335545() { + int local; // expected-note{{}} + void (*takes_int_ptr_argument)(int *) = (void (*)(int*))has_no_argument_and_returns_null; + + takes_int_ptr_argument(&local); // no-crash + + int useLocal = local; //expected-warning{{}} + //expected-note@-1{{}} + (void)useLocal; +} -- GitLab From 078d5aacfa9d385b8689cec8f0e6f60e38db89ce Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 12 Jun 2018 23:58:59 +0000 Subject: [PATCH 0110/1023] [CUDA][HIP] Allow CUDA __global__ functions to have amdgpu kernel attributes There are HIP applications e.g. Tensorflow 1.3 using amdgpu kernel attributes, however currently they are only allowed on OpenCL kernel functions. This patch will allow amdgpu kernel attributes to be applied to CUDA/HIP __global__ functions. Differential Revision: https://reviews.llvm.org/D47958 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334561 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 +- lib/Sema/SemaDeclAttr.cpp | 34 ++++++------ test/CodeGenCUDA/amdgpu-kernel-attrs.cu | 37 +++++++++++++ test/SemaCUDA/amdgpu-attrs.cu | 62 ++++++---------------- test/SemaOpenCL/invalid-kernel-attrs.cl | 8 +-- 5 files changed, 76 insertions(+), 67 deletions(-) create mode 100644 test/CodeGenCUDA/amdgpu-kernel-attrs.cu diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f0ea769f91..8fb30ff4e4 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8435,7 +8435,7 @@ def err_reference_pipe_type : Error < "pipes packet types cannot be of reference type">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; def err_opencl_kernel_attr : - Error<"attribute %0 can only be applied to a kernel function">; + Error<"attribute %0 can only be applied to an OpenCL kernel function">; def err_opencl_return_value_with_address_space : Error< "return value cannot be qualified with address space">; def err_opencl_constant_no_init : Error< diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e4532a7e67..779192b865 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6468,25 +6468,27 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } else if (const auto *A = D->getAttr()) { Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); - } else if (const auto *A = D->getAttr()) { - Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) - << A << ExpectedKernelFunction; - D->setInvalidDecl(); } else if (const auto *A = D->getAttr()) { Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; D->setInvalidDecl(); + } else if (!D->hasAttr()) { + if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << ExpectedKernelFunction; + D->setInvalidDecl(); + } else if (const auto *A = D->getAttr()) { + Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) + << A << ExpectedKernelFunction; + D->setInvalidDecl(); + } } } } diff --git a/test/CodeGenCUDA/amdgpu-kernel-attrs.cu b/test/CodeGenCUDA/amdgpu-kernel-attrs.cu new file mode 100644 index 0000000000..70eb9091d8 --- /dev/null +++ b/test/CodeGenCUDA/amdgpu-kernel-attrs.cu @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa \ +// RUN: -fcuda-is-device -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple nvptx \ +// RUN: -fcuda-is-device -emit-llvm -o - %s | FileCheck %s \ +// RUN: -check-prefix=NAMD +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \ +// RUN: -verify -o - %s | FileCheck -check-prefix=NAMD %s + +#include "Inputs/cuda.h" + +__attribute__((amdgpu_flat_work_group_size(32, 64))) // expected-no-diagnostics +__global__ void flat_work_group_size_32_64() { +// CHECK: define amdgpu_kernel void @_Z26flat_work_group_size_32_64v() [[FLAT_WORK_GROUP_SIZE_32_64:#[0-9]+]] +} +__attribute__((amdgpu_waves_per_eu(2))) // expected-no-diagnostics +__global__ void waves_per_eu_2() { +// CHECK: define amdgpu_kernel void @_Z14waves_per_eu_2v() [[WAVES_PER_EU_2:#[0-9]+]] +} +__attribute__((amdgpu_num_sgpr(32))) // expected-no-diagnostics +__global__ void num_sgpr_32() { +// CHECK: define amdgpu_kernel void @_Z11num_sgpr_32v() [[NUM_SGPR_32:#[0-9]+]] +} +__attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics +__global__ void num_vgpr_64() { +// CHECK: define amdgpu_kernel void @_Z11num_vgpr_64v() [[NUM_VGPR_64:#[0-9]+]] +} + +// Make sure this is silently accepted on other targets. +// NAMD-NOT: "amdgpu-flat-work-group-size" +// NAMD-NOT: "amdgpu-waves-per-eu" +// NAMD-NOT: "amdgpu-num-vgpr" +// NAMD-NOT: "amdgpu-num-sgpr" + +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" +// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" diff --git a/test/SemaCUDA/amdgpu-attrs.cu b/test/SemaCUDA/amdgpu-attrs.cu index 8755972686..63abda9eea 100644 --- a/test/SemaCUDA/amdgpu-attrs.cu +++ b/test/SemaCUDA/amdgpu-attrs.cu @@ -1,110 +1,80 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s - #include "Inputs/cuda.h" -// expected-error@+2 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64))) __global__ void flat_work_group_size_32_64() {} -// expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2))) __global__ void waves_per_eu_2() {} -// expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2, 4))) __global__ void waves_per_eu_2_4() {} -// expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_num_sgpr(32))) __global__ void num_sgpr_32() {} -// expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_num_vgpr(64))) __global__ void num_vgpr_64() {} -// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2))) __global__ void flat_work_group_size_32_64_waves_per_eu_2() {} -// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4() {} -// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_sgpr(32))) __global__ void flat_work_group_size_32_64_num_sgpr_32() {} -// expected-error@+3 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_num_vgpr_64() {} -// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32))) __global__ void waves_per_eu_2_num_sgpr_32() {} -// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64))) __global__ void waves_per_eu_2_num_vgpr_64() {} -// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32))) __global__ void waves_per_eu_2_4_num_sgpr_32() {} -// expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64))) __global__ void waves_per_eu_2_4_num_vgpr_64() {} -// expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) __global__ void num_sgpr_32_num_vgpr_64() {} - -// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32() {} -// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_num_vgpr_64() {} -// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32() {} -// expected-error@+4 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_vgpr_64() {} - -// expected-error@+5 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+4 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_64() {} -// expected-error@+5 {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}} -// fixme-expected-error@+4 {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}} -// fixme-expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}} -// fixme-expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}} __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {} + +// expected-error@+2{{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel function}} +__attribute__((reqd_work_group_size(32, 64, 64))) +__global__ void reqd_work_group_size_32_64_64() {} + +// expected-error@+2{{attribute 'work_group_size_hint' can only be applied to an OpenCL kernel function}} +__attribute__((work_group_size_hint(2, 2, 2))) +__global__ void work_group_size_hint_2_2_2() {} + +// expected-error@+2{{attribute 'vec_type_hint' can only be applied to an OpenCL kernel function}} +__attribute__((vec_type_hint(int))) +__global__ void vec_type_hint_int() {} + +// expected-error@+2{{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel function}} +__attribute__((intel_reqd_sub_group_size(64))) +__global__ void intel_reqd_sub_group_size_64() {} diff --git a/test/SemaOpenCL/invalid-kernel-attrs.cl b/test/SemaOpenCL/invalid-kernel-attrs.cl index 1f1359ccee..a19a989f41 100644 --- a/test/SemaOpenCL/invalid-kernel-attrs.cl +++ b/test/SemaOpenCL/invalid-kernel-attrs.cl @@ -14,11 +14,11 @@ kernel __attribute__((work_group_size_hint(8,16,32,4))) void kernel6() {} //expe kernel __attribute__((work_group_size_hint(1,2,3))) __attribute__((work_group_size_hint(3,2,1))) void kernel7() {} //expected-warning{{attribute 'work_group_size_hint' is already applied with different parameters}} -__attribute__((reqd_work_group_size(8,16,32))) void kernel8(){} // expected-error {{attribute 'reqd_work_group_size' can only be applied to a kernel}} +__attribute__((reqd_work_group_size(8,16,32))) void kernel8(){} // expected-error {{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel}} -__attribute__((work_group_size_hint(8,16,32))) void kernel9(){} // expected-error {{attribute 'work_group_size_hint' can only be applied to a kernel}} +__attribute__((work_group_size_hint(8,16,32))) void kernel9(){} // expected-error {{attribute 'work_group_size_hint' can only be applied to an OpenCL kernel}} -__attribute__((vec_type_hint(char))) void kernel10(){} // expected-error {{attribute 'vec_type_hint' can only be applied to a kernel}} +__attribute__((vec_type_hint(char))) void kernel10(){} // expected-error {{attribute 'vec_type_hint' can only be applied to an OpenCL kernel}} constant int foo1 __attribute__((reqd_work_group_size(8,16,32))) = 0; // expected-error {{'reqd_work_group_size' attribute only applies to functions}} @@ -34,6 +34,6 @@ kernel __attribute__((reqd_work_group_size(1,2,0))) void kernel11(){} // expecte kernel __attribute__((reqd_work_group_size(1,0,2))) void kernel12(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}} kernel __attribute__((reqd_work_group_size(0,1,2))) void kernel13(){} // expected-error {{'reqd_work_group_size' attribute must be greater than 0}} -__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to a kernel}} +__attribute__((intel_reqd_sub_group_size(8))) void kernel14(){} // expected-error {{attribute 'intel_reqd_sub_group_size' can only be applied to an OpenCL kernel}} kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15(){} // expected-error {{'intel_reqd_sub_group_size' attribute must be greater than 0}} kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel16() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}} -- GitLab From 00eb2b47bef2f7c89fed207aea90bdc5e53dfecc Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 13 Jun 2018 02:06:28 +0000 Subject: [PATCH 0111/1023] Fix crash emitting transparent list initializer for a large aggregate. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334565 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprAgg.cpp | 2 ++ test/CodeGenCXX/value-init.cpp | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 41e32a9d60..d350a86a11 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -1673,6 +1673,8 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // If this is an initlist expr, sum up the size of sizes of the (present) // elements. If this is something weird, assume the whole thing is non-zero. const InitListExpr *ILE = dyn_cast(E); + while (ILE && ILE->isTransparent()) + ILE = dyn_cast(ILE->getInit(0)); if (!ILE || !CGF.getTypes().isZeroInitializable(ILE->getType())) return CGF.getContext().getTypeSizeInChars(E->getType()); diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index 348cbf7815..8d76fc5346 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98 +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX17 struct A { virtual ~A(); @@ -114,13 +115,15 @@ void f() { // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NOT: call void @llvm.memset.p0i8.i64 - // CHECK: call void @_ZN6PR98015Test2C1Ev + // CHECK-CXX98: call void @_ZN6PR98015Test2C1Ev + // CHECK-CXX17: call void @_ZN6PR98014TestC1Ev // CHECK-NOT: call void @_ZN6PR98015Test2C1Ev Test2 empty2[3] = {}; // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NOT: call void @llvm.memset.p0i8.i64 - // CHECK: call void @_ZN6PR98015Test3C1Ev + // CHECK-CXX98: call void @_ZN6PR98015Test3C1Ev + // CHECK-CXX17: call void @_ZN6PR98014TestC2Ev // CHECK-NOT: call void @llvm.memset.p0i8.i64 // CHECK-NOT: call void @_ZN6PR98015Test3C1Ev Test3 empty3[3] = {}; @@ -222,7 +225,7 @@ namespace test6 { // CHECK: [[CUR:%.*]] = phi [20 x [[A]]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] // Inner loop. - // CHECK-NEXT: [[IBEGIN:%.*]] = getelementptr inbounds [20 x [[A]]], [20 x [[A]]]* [[CUR]], i32 0, i32 0 + // CHECK-NEXT: [[IBEGIN:%.*]] = getelementptr inbounds [20 x [[A]]], [20 x [[A]]]* [[CUR]], i{{32|64}} 0, i{{32|64}} 0 // CHECK-NEXT: [[IEND:%.*]] = getelementptr inbounds [[A]], [[A]]* [[IBEGIN]], i64 20 // CHECK-NEXT: br label // CHECK: [[ICUR:%.*]] = phi [[A]]* [ [[IBEGIN]], {{%.*}} ], [ [[INEXT:%.*]], {{%.*}} ] @@ -327,3 +330,12 @@ int explicitly_defaulted() { // CHECK: call void @llvm.memset.p0i8.i64 // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev // CHECK-NEXT: ret void + +#if __cplusplus >= 201103L +namespace transparent_init_list { + struct optional_assign_base {}; + struct optional_data_dtor_base { char dummy_[24]; }; + struct optional : optional_data_dtor_base, optional_assign_base {}; + optional f(optional a) { return {optional(a)}; } +} +#endif -- GitLab From 2d49a17bf49641c2d71bc4c35f9494746b014682 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 13 Jun 2018 05:26:23 +0000 Subject: [PATCH 0112/1023] [Sema] When the address of a member function is used as a template argument, use the context in which it is used for checking its accessibility. This fixes PR32898. rdar://problem/33737747 Differential Revision: https://reviews.llvm.org/D36918 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334569 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 10 +++++-- test/SemaCXX/access.cpp | 47 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 87968362e0..fd4197ce2a 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -3803,10 +3803,16 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return Result; } + // Capture the context in which the function call is made. This is the context + // that is needed when the accessibility of template arguments is checked. + DeclContext *CallingCtx = CurContext; + return FinishTemplateArgumentDeduction( FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info, - &OriginalCallArgs, PartialOverloading, - [&]() { return CheckNonDependent(ParamTypesForArgChecking); }); + &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() { + ContextRAII SavedContext(*this, CallingCtx); + return CheckNonDependent(ParamTypesForArgChecking); + }); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 29a58a1388..74c5f27751 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -169,3 +169,50 @@ namespace ThisLambdaIsNotMyFriend { } void bar() { foo(); } } + +namespace OverloadedMemberFunctionPointer { + template + void func0() {} + + template + void func1() {} + + template + void func2(void(*fn)()) {} // expected-note 2 {{candidate function template not viable: no overload of 'func}} + + class C { + private: + friend void friendFunc(); + void overloadedMethod(); + protected: + void overloadedMethod(int); + public: + void overloadedMethod(int, int); + void method() { + func2(&func0); + func2(&func1); + } + }; + + void friendFunc() { + func2(&func0); + func2(&func1); + } + + void nonFriendFunc() { + func2(&func0); // expected-error {{no matching function for call to 'func2'}} + func2(&func1); // expected-error {{no matching function for call to 'func2'}} + } + + // r325321 caused an assertion failure when the following code was compiled. + class A { + template static bool foo1() { return true; } + + public: + void init(bool c) { + if (c) { + auto f = foo1; + } + } + }; +} -- GitLab From 05aca69b3064cfed12e6ecf3449cc9d938719a73 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 13 Jun 2018 06:33:59 +0000 Subject: [PATCH 0113/1023] Remove extraneous semicolon. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334573 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index fceb3f094c..4765db0741 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -184,7 +184,7 @@ BugReporterVisitor::getEndPath(BugReporterContext &BRC, void BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR) {}; + BugReport &BR) {} std::unique_ptr BugReporterVisitor::getDefaultEndPath( BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { -- GitLab From 577e6ca1350766a0b505f8c9c4c5cee9c1370dcb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 13 Jun 2018 06:48:40 +0000 Subject: [PATCH 0114/1023] crash-report-modules.m: Shorten path length to make Windows bot happy git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334574 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-report-modules.m | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index f5cf76e2a9..73b1e9f04b 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -1,12 +1,15 @@ -// RUN: rm -rf %t -// RUN: mkdir -p %t/i %t/m %t +// FIXME: Instead of %T/crmdir, it would be nice to just use %t, but the +// filename ran into path length limits for the rm command on some Windows +// bots. +// RUN: rm -rf %T/crmdir +// RUN: mkdir -p %T/crmdir/i %T/crmdir/m -// RUN: env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ -// RUN: not %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ -// RUN: -fmodules -fmodules-cache-path=%t/m/ -DFOO=BAR 2>&1 | FileCheck %s +// RUN: env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%T/crmdir TEMP=%T/crmdir TMP=%T/crmdir \ +// RUN: not %clang -fsyntax-only %s -I %S/Inputs/module -isysroot %/t/i/ \ +// RUN: -fmodules -fmodules-cache-path=%T/crmdir/m/ -DFOO=BAR 2>&1 | FileCheck %s -// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-report-*.m -// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-report-*.sh +// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %T/crmdir/crash-report-*.m +// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %T/crmdir/crash-report-*.sh // REQUIRES: crash-recovery @import simple; -- GitLab From 46c05521ad97b165353fa285cd56d51bcb4a1327 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Jun 2018 07:19:28 +0000 Subject: [PATCH 0115/1023] [X86] Remove masking from avx512vbmi2 concat and shift by immediate builtins. Use select builtins instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334577 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 36 +-- lib/Headers/avx512vbmi2intrin.h | 152 +++++-------- lib/Headers/avx512vlvbmi2intrin.h | 302 ++++++++++---------------- lib/Sema/SemaChecking.cpp | 36 +-- test/CodeGen/avx512vbmi2-builtins.c | 48 ++-- test/CodeGen/avx512vlvbmi2-builtins.c | 96 +++++--- test/Sema/builtins-x86.c | 72 +++--- 7 files changed, 326 insertions(+), 416 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 6a3016bcd3..06f56c7d05 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1238,15 +1238,15 @@ TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128, "V8sV8sV8sV8s", "nc", "avx512vl,a TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256, "V16sV16sV16sV16s", "nc", "avx512vl,avx512bw") TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512, "V32sV32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpshldd128_mask, "V4iV4iV4iIiV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd256_mask, "V8iV8iV8iIiV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd512_mask, "V16iV16iV16iIiV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw128_mask, "V8sV8sV8sIiV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw256_mask, "V16sV16sV16sIiV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw512_mask, "V32sV32sV32sIiV32sUi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd128, "V4iV4iV4iIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd256, "V8iV8iV8iIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd512, "V16iV16iV16iIi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "nc", "avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl,avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl,avx512vbmi2") @@ -1286,15 +1286,15 @@ TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "nc", "avx512 TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd128_mask, "V4iV4iV4iIiV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd256_mask, "V8iV8iV8iIiV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd512_mask, "V16iV16iV16iIiV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw128_mask, "V8sV8sV8sIiV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw256_mask, "V16sV16sV16sIiV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw512_mask, "V32sV32sV32sIiV32sUi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd512, "V16iV16iV16iIi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw128, "V8sV8sV8sIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw256, "V16sV16sV16sIi", "nc", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw512, "V32sV32sV32sIi", "nc", "avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") diff --git a/lib/Headers/avx512vbmi2intrin.h b/lib/Headers/avx512vbmi2intrin.h index e0ada4c16f..01a75a70bb 100644 --- a/lib/Headers/avx512vbmi2intrin.h +++ b/lib/Headers/avx512vbmi2intrin.h @@ -142,131 +142,89 @@ _mm512_maskz_expandloadu_epi8(__mmask64 __U, void const *__P) __U); } +#define _mm512_shldi_epi64(A, B, I) \ + (__m512i)__builtin_ia32_vpshldq512((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(I)) + #define _mm512_mask_shldi_epi64(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)(__m512i)(S), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_shldi_epi64((A), (B), (I)), \ + (__v8di)(__m512i)(S)) #define _mm512_maskz_shldi_epi64(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_shldi_epi64((A), (B), (I)), \ + (__v8di)_mm512_setzero_si512()) -#define _mm512_shldi_epi64(A, B, I) \ - (__m512i)__builtin_ia32_vpshldq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)_mm512_undefined_epi32(), \ - (__mmask8)-1) +#define _mm512_shldi_epi32(A, B, I) \ + (__m512i)__builtin_ia32_vpshldd512((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B), (int)(I)) #define _mm512_mask_shldi_epi32(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)(__m512i)(S), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_shldi_epi32((A), (B), (I)), \ + (__v16si)(__m512i)(S)) #define _mm512_maskz_shldi_epi32(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_shldi_epi32((A), (B), (I)), \ + (__v16si)_mm512_setzero_si512()) -#define _mm512_shldi_epi32(A, B, I) \ - (__m512i)__builtin_ia32_vpshldd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)_mm512_undefined_epi32(), \ - (__mmask16)-1) +#define _mm512_shldi_epi16(A, B, I) \ + (__m512i)__builtin_ia32_vpshldw512((__v32hi)(__m512i)(A), \ + (__v32hi)(__m512i)(B), (int)(I)) #define _mm512_mask_shldi_epi16(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)(__m512i)(S), \ - (__mmask32)(U)) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_shldi_epi16((A), (B), (I)), \ + (__v32hi)(__m512i)(S)) #define _mm512_maskz_shldi_epi16(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshldw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)_mm512_setzero_si512(), \ - (__mmask32)(U)) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_shldi_epi16((A), (B), (I)), \ + (__v32hi)_mm512_setzero_si512()) -#define _mm512_shldi_epi16(A, B, I) \ - (__m512i)__builtin_ia32_vpshldw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)_mm512_undefined_epi32(), \ - (__mmask32)-1) +#define _mm512_shrdi_epi64(A, B, I) \ + (__m512i)__builtin_ia32_vpshrdq512((__v8di)(__m512i)(A), \ + (__v8di)(__m512i)(B), (int)(I)) #define _mm512_mask_shrdi_epi64(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)(__m512i)(S), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_shrdi_epi64((A), (B), (I)), \ + (__v8di)(__m512i)(S)) #define _mm512_maskz_shrdi_epi64(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_shrdi_epi64((A), (B), (I)), \ + (__v8di)_mm512_setzero_si512()) -#define _mm512_shrdi_epi64(A, B, I) \ - (__m512i)__builtin_ia32_vpshrdq512_mask((__v8di)(__m512i)(A), \ - (__v8di)(__m512i)(B), \ - (int)(I), \ - (__v8di)_mm512_undefined_epi32(), \ - (__mmask8)-1) +#define _mm512_shrdi_epi32(A, B, I) \ + (__m512i)__builtin_ia32_vpshrdd512((__v16si)(__m512i)(A), \ + (__v16si)(__m512i)(B), (int)(I)) #define _mm512_mask_shrdi_epi32(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)(__m512i)(S), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_shrdi_epi32((A), (B), (I)), \ + (__v16si)(__m512i)(S)) #define _mm512_maskz_shrdi_epi32(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_shrdi_epi32((A), (B), (I)), \ + (__v16si)_mm512_setzero_si512()) -#define _mm512_shrdi_epi32(A, B, I) \ - (__m512i)__builtin_ia32_vpshrdd512_mask((__v16si)(__m512i)(A), \ - (__v16si)(__m512i)(B), \ - (int)(I), \ - (__v16si)_mm512_undefined_epi32(), \ - (__mmask16)-1) +#define _mm512_shrdi_epi16(A, B, I) \ + (__m512i)__builtin_ia32_vpshrdw512((__v32hi)(__m512i)(A), \ + (__v32hi)(__m512i)(B), (int)(I)) #define _mm512_mask_shrdi_epi16(S, U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)(__m512i)(S), \ - (__mmask32)(U)) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_shrdi_epi16((A), (B), (I)), \ + (__v32hi)(__m512i)(S)) #define _mm512_maskz_shrdi_epi16(U, A, B, I) \ - (__m512i)__builtin_ia32_vpshrdw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)_mm512_setzero_si512(), \ - (__mmask32)(U)) - -#define _mm512_shrdi_epi16(A, B, I) \ - (__m512i)__builtin_ia32_vpshrdw512_mask((__v32hi)(__m512i)(A), \ - (__v32hi)(__m512i)(B), \ - (int)(I), \ - (__v32hi)_mm512_undefined_epi32(), \ - (__mmask32)-1) + (__m512i)__builtin_ia32_selectw_512((__mmask32)(U), \ + (__v32hi)_mm512_shrdi_epi16((A), (B), (I)), \ + (__v32hi)_mm512_setzero_si512()) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_shldv_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) diff --git a/lib/Headers/avx512vlvbmi2intrin.h b/lib/Headers/avx512vlvbmi2intrin.h index 6dde1e9643..38ef9b0f84 100644 --- a/lib/Headers/avx512vlvbmi2intrin.h +++ b/lib/Headers/avx512vlvbmi2intrin.h @@ -251,257 +251,173 @@ _mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P) __U); } +#define _mm256_shldi_epi64(A, B, I) \ + (__m256i)__builtin_ia32_vpshldq256((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), (int)(I)) + #define _mm256_mask_shldi_epi64(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)(__m256i)(S), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ + (__v4di)_mm256_shldi_epi64((A), (B), (I)), \ + (__v4di)(__m256i)(S)) #define _mm256_maskz_shldi_epi64(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ + (__v4di)_mm256_shldi_epi64((A), (B), (I)), \ + (__v4di)_mm256_setzero_si256()) -#define _mm256_shldi_epi64(A, B, I) \ - (__m256i)__builtin_ia32_vpshldq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)_mm256_undefined_si256(), \ - (__mmask8)-1) +#define _mm_shldi_epi64(A, B, I) \ + (__m128i)__builtin_ia32_vpshldq128((__v2di)(__m128i)(A), \ + (__v2di)(__m128i)(B), (int)(I)) #define _mm_mask_shldi_epi64(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ + (__v2di)_mm_shldi_epi64((A), (B), (I)), \ + (__v2di)(__m128i)(S)) #define _mm_maskz_shldi_epi64(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ + (__v2di)_mm_shldi_epi64((A), (B), (I)), \ + (__v2di)_mm_setzero_si128()) -#define _mm_shldi_epi64(A, B, I) \ - (__m128i)__builtin_ia32_vpshldq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)_mm_undefined_si128(), \ - (__mmask8)-1) +#define _mm256_shldi_epi32(A, B, I) \ + (__m256i)__builtin_ia32_vpshldd256((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B), (int)(I)) #define _mm256_mask_shldi_epi32(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)(__m256i)(S), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ + (__v8si)_mm256_shldi_epi32((A), (B), (I)), \ + (__v8si)(__m256i)(S)) #define _mm256_maskz_shldi_epi32(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ + (__v8si)_mm256_shldi_epi32((A), (B), (I)), \ + (__v8si)_mm256_setzero_si256()) -#define _mm256_shldi_epi32(A, B, I) \ - (__m256i)__builtin_ia32_vpshldd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)_mm256_undefined_si256(), \ - (__mmask8)-1) +#define _mm_shldi_epi32(A, B, I) \ + (__m128i)__builtin_ia32_vpshldd128((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B), (int)(I)) #define _mm_mask_shldi_epi32(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ + (__v4si)_mm_shldi_epi32((A), (B), (I)), \ + (__v4si)(__m128i)(S)) #define _mm_maskz_shldi_epi32(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ + (__v4si)_mm_shldi_epi32((A), (B), (I)), \ + (__v4si)_mm_setzero_si128()) -#define _mm_shldi_epi32(A, B, I) \ - (__m128i)__builtin_ia32_vpshldd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)_mm_undefined_si128(), \ - (__mmask8)-1) +#define _mm256_shldi_epi16(A, B, I) \ + (__m256i)__builtin_ia32_vpshldw256((__v16hi)(__m256i)(A), \ + (__v16hi)(__m256i)(B), (int)(I)) #define _mm256_mask_shldi_epi16(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)(__m256i)(S), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_shldi_epi16((A), (B), (I)), \ + (__v16hi)(__m256i)(S)) #define _mm256_maskz_shldi_epi16(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshldw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)_mm256_setzero_si256(), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_shldi_epi16((A), (B), (I)), \ + (__v16hi)_mm256_setzero_si256()) -#define _mm256_shldi_epi16(A, B, I) \ - (__m256i)__builtin_ia32_vpshldw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)_mm256_undefined_si256(), \ - (__mmask16)-1) +#define _mm_shldi_epi16(A, B, I) \ + (__m128i)__builtin_ia32_vpshldw128((__v8hi)(__m128i)(A), \ + (__v8hi)(__m128i)(B), (int)(I)) #define _mm_mask_shldi_epi16(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_shldi_epi16((A), (B), (I)), \ + (__v8hi)(__m128i)(S)) #define _mm_maskz_shldi_epi16(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshldw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_shldi_epi16((A), (B), (I)), \ + (__v8hi)_mm_setzero_si128()) -#define _mm_shldi_epi16(A, B, I) \ - (__m128i)__builtin_ia32_vpshldw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)_mm_undefined_si128(), \ - (__mmask8)-1) +#define _mm256_shrdi_epi64(A, B, I) \ + (__m256i)__builtin_ia32_vpshrdq256((__v4di)(__m256i)(A), \ + (__v4di)(__m256i)(B), (int)(I)) #define _mm256_mask_shrdi_epi64(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)(__m256i)(S), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ + (__v4di)_mm256_shrdi_epi64((A), (B), (I)), \ + (__v4di)(__m256i)(S)) #define _mm256_maskz_shrdi_epi64(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ + (__v4di)_mm256_shrdi_epi64((A), (B), (I)), \ + (__v4di)_mm256_setzero_si256()) -#define _mm256_shrdi_epi64(A, B, I) \ - (__m256i)__builtin_ia32_vpshrdq256_mask((__v4di)(__m256i)(A), \ - (__v4di)(__m256i)(B), \ - (int)(I), \ - (__v4di)_mm256_undefined_si256(), \ - (__mmask8)-1) +#define _mm_shrdi_epi64(A, B, I) \ + (__m128i)__builtin_ia32_vpshrdq128((__v2di)(__m128i)(A), \ + (__v2di)(__m128i)(B), (int)(I)) #define _mm_mask_shrdi_epi64(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ + (__v2di)_mm_shrdi_epi64((A), (B), (I)), \ + (__v2di)(__m128i)(S)) #define _mm_maskz_shrdi_epi64(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \ + (__v2di)_mm_shrdi_epi64((A), (B), (I)), \ + (__v2di)_mm_setzero_si128()) -#define _mm_shrdi_epi64(A, B, I) \ - (__m128i)__builtin_ia32_vpshrdq128_mask((__v2di)(__m128i)(A), \ - (__v2di)(__m128i)(B), \ - (int)(I), \ - (__v2di)_mm_undefined_si128(), \ - (__mmask8)-1) +#define _mm256_shrdi_epi32(A, B, I) \ + (__m256i)__builtin_ia32_vpshrdd256((__v8si)(__m256i)(A), \ + (__v8si)(__m256i)(B), (int)(I)) #define _mm256_mask_shrdi_epi32(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)(__m256i)(S), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ + (__v8si)_mm256_shrdi_epi32((A), (B), (I)), \ + (__v8si)(__m256i)(S)) #define _mm256_maskz_shrdi_epi32(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)(U)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ + (__v8si)_mm256_shrdi_epi32((A), (B), (I)), \ + (__v8si)_mm256_setzero_si256()) -#define _mm256_shrdi_epi32(A, B, I) \ - (__m256i)__builtin_ia32_vpshrdd256_mask((__v8si)(__m256i)(A), \ - (__v8si)(__m256i)(B), \ - (int)(I), \ - (__v8si)_mm256_undefined_si256(), \ - (__mmask8)-1) +#define _mm_shrdi_epi32(A, B, I) \ + (__m128i)__builtin_ia32_vpshrdd128((__v4si)(__m128i)(A), \ + (__v4si)(__m128i)(B), (int)(I)) #define _mm_mask_shrdi_epi32(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ + (__v4si)_mm_shrdi_epi32((A), (B), (I)), \ + (__v4si)(__m128i)(S)) #define _mm_maskz_shrdi_epi32(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \ + (__v4si)_mm_shrdi_epi32((A), (B), (I)), \ + (__v4si)_mm_setzero_si128()) -#define _mm_shrdi_epi32(A, B, I) \ - (__m128i)__builtin_ia32_vpshrdd128_mask((__v4si)(__m128i)(A), \ - (__v4si)(__m128i)(B), \ - (int)(I), \ - (__v4si)_mm_undefined_si128(), \ - (__mmask8)-1) +#define _mm256_shrdi_epi16(A, B, I) \ + (__m256i)__builtin_ia32_vpshrdw256((__v16hi)(__m256i)(A), \ + (__v16hi)(__m256i)(B), (int)(I)) #define _mm256_mask_shrdi_epi16(S, U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)(__m256i)(S), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_shrdi_epi16((A), (B), (I)), \ + (__v16hi)(__m256i)(S)) #define _mm256_maskz_shrdi_epi16(U, A, B, I) \ - (__m256i)__builtin_ia32_vpshrdw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)_mm256_setzero_si256(), \ - (__mmask16)(U)) + (__m256i)__builtin_ia32_selectw_256((__mmask16)(U), \ + (__v16hi)_mm256_shrdi_epi16((A), (B), (I)), \ + (__v16hi)_mm256_setzero_si256()) -#define _mm256_shrdi_epi16(A, B, I) \ - (__m256i)__builtin_ia32_vpshrdw256_mask((__v16hi)(__m256i)(A), \ - (__v16hi)(__m256i)(B), \ - (int)(I), \ - (__v16hi)_mm256_undefined_si256(), \ - (__mmask16)-1) +#define _mm_shrdi_epi16(A, B, I) \ + (__m128i)__builtin_ia32_vpshrdw128((__v8hi)(__m128i)(A), \ + (__v8hi)(__m128i)(B), (int)(I)) #define _mm_mask_shrdi_epi16(S, U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)(__m128i)(S), \ - (__mmask8)(U)) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_shrdi_epi16((A), (B), (I)), \ + (__v8hi)(__m128i)(S)) #define _mm_maskz_shrdi_epi16(U, A, B, I) \ - (__m128i)__builtin_ia32_vpshrdw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)_mm_setzero_si128(), \ - (__mmask8)(U)) - -#define _mm_shrdi_epi16(A, B, I) \ - (__m128i)__builtin_ia32_vpshrdw128_mask((__v8hi)(__m128i)(A), \ - (__v8hi)(__m128i)(B), \ - (int)(I), \ - (__v8hi)_mm_undefined_si128(), \ - (__mmask8)-1) + (__m128i)__builtin_ia32_selectw_128((__mmask8)(U), \ + (__v8hi)_mm_shrdi_epi16((A), (B), (I)), \ + (__v8hi)_mm_setzero_si128()) static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index d5945ef6f6..6a1cbdf621 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2841,24 +2841,24 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_dbpsadbw128: case X86::BI__builtin_ia32_dbpsadbw256: case X86::BI__builtin_ia32_dbpsadbw512: - case X86::BI__builtin_ia32_vpshldd128_mask: - case X86::BI__builtin_ia32_vpshldd256_mask: - case X86::BI__builtin_ia32_vpshldd512_mask: - case X86::BI__builtin_ia32_vpshldq128_mask: - case X86::BI__builtin_ia32_vpshldq256_mask: - case X86::BI__builtin_ia32_vpshldq512_mask: - case X86::BI__builtin_ia32_vpshldw128_mask: - case X86::BI__builtin_ia32_vpshldw256_mask: - case X86::BI__builtin_ia32_vpshldw512_mask: - case X86::BI__builtin_ia32_vpshrdd128_mask: - case X86::BI__builtin_ia32_vpshrdd256_mask: - case X86::BI__builtin_ia32_vpshrdd512_mask: - case X86::BI__builtin_ia32_vpshrdq128_mask: - case X86::BI__builtin_ia32_vpshrdq256_mask: - case X86::BI__builtin_ia32_vpshrdq512_mask: - case X86::BI__builtin_ia32_vpshrdw128_mask: - case X86::BI__builtin_ia32_vpshrdw256_mask: - case X86::BI__builtin_ia32_vpshrdw512_mask: + case X86::BI__builtin_ia32_vpshldd128: + case X86::BI__builtin_ia32_vpshldd256: + case X86::BI__builtin_ia32_vpshldd512: + case X86::BI__builtin_ia32_vpshldq128: + case X86::BI__builtin_ia32_vpshldq256: + case X86::BI__builtin_ia32_vpshldq512: + case X86::BI__builtin_ia32_vpshldw128: + case X86::BI__builtin_ia32_vpshldw256: + case X86::BI__builtin_ia32_vpshldw512: + case X86::BI__builtin_ia32_vpshrdd128: + case X86::BI__builtin_ia32_vpshrdd256: + case X86::BI__builtin_ia32_vpshrdd512: + case X86::BI__builtin_ia32_vpshrdq128: + case X86::BI__builtin_ia32_vpshrdq256: + case X86::BI__builtin_ia32_vpshrdq512: + case X86::BI__builtin_ia32_vpshrdw128: + case X86::BI__builtin_ia32_vpshrdw256: + case X86::BI__builtin_ia32_vpshrdw512: i = 2; l = 0; u = 255; break; case X86::BI__builtin_ia32_fixupimmpd512_mask: diff --git a/test/CodeGen/avx512vbmi2-builtins.c b/test/CodeGen/avx512vbmi2-builtins.c index 6d20f9d2ee..db4abdba45 100644 --- a/test/CodeGen/avx512vbmi2-builtins.c +++ b/test/CodeGen/avx512vbmi2-builtins.c @@ -88,109 +88,121 @@ __m512i test_mm512_maskz_expandloadu_epi8(__mmask64 __U, void const* __P) { __m512i test_mm512_mask_shldi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.512 + // CHECK: @llvm.x86.avx512.vpshld.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_shldi_epi64(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shldi_epi64(__mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.512 + // CHECK: @llvm.x86.avx512.vpshld.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_shldi_epi64(__U, __A, __B, 63); } __m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.512 + // CHECK: @llvm.x86.avx512.vpshld.q.512 return _mm512_shldi_epi64(__A, __B, 31); } __m512i test_mm512_mask_shldi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.512 + // CHECK: @llvm.x86.avx512.vpshld.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_shldi_epi32(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shldi_epi32(__mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.512 + // CHECK: @llvm.x86.avx512.vpshld.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_shldi_epi32(__U, __A, __B, 63); } __m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.512 + // CHECK: @llvm.x86.avx512.vpshld.d.512 return _mm512_shldi_epi32(__A, __B, 31); } __m512i test_mm512_mask_shldi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.512 + // CHECK: @llvm.x86.avx512.vpshld.w.512 + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_shldi_epi16(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shldi_epi16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.512 + // CHECK: @llvm.x86.avx512.vpshld.w.512 + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_shldi_epi16(__U, __A, __B, 63); } __m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.512 + // CHECK: @llvm.x86.avx512.vpshld.w.512 return _mm512_shldi_epi16(__A, __B, 31); } __m512i test_mm512_mask_shrdi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512 + // CHECK: @llvm.x86.avx512.vpshrd.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_shrdi_epi64(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shrdi_epi64(__mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512 + // CHECK: @llvm.x86.avx512.vpshrd.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_shrdi_epi64(__U, __A, __B, 63); } __m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.512 + // CHECK: @llvm.x86.avx512.vpshrd.q.512 return _mm512_shrdi_epi64(__A, __B, 31); } __m512i test_mm512_mask_shrdi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512 + // CHECK: @llvm.x86.avx512.vpshrd.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_shrdi_epi32(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shrdi_epi32(__mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512 + // CHECK: @llvm.x86.avx512.vpshrd.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_shrdi_epi32(__U, __A, __B, 63); } __m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.512 + // CHECK: @llvm.x86.avx512.vpshrd.d.512 return _mm512_shrdi_epi32(__A, __B, 31); } __m512i test_mm512_mask_shrdi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512 + // CHECK: @llvm.x86.avx512.vpshrd.w.512 + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_mask_shrdi_epi16(__S, __U, __A, __B, 127); } __m512i test_mm512_maskz_shrdi_epi16(__mmask32 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512 + // CHECK: @llvm.x86.avx512.vpshrd.w.512 + // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}} return _mm512_maskz_shrdi_epi16(__U, __A, __B, 63); } __m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.512 + // CHECK: @llvm.x86.avx512.vpshrd.w.512 return _mm512_shrdi_epi16(__A, __B, 31); } diff --git a/test/CodeGen/avx512vlvbmi2-builtins.c b/test/CodeGen/avx512vlvbmi2-builtins.c index 8ae0ab7da7..aceb97616d 100644 --- a/test/CodeGen/avx512vlvbmi2-builtins.c +++ b/test/CodeGen/avx512vlvbmi2-builtins.c @@ -172,217 +172,241 @@ __m256i test_mm256_maskz_expandloadu_epi8(__mmask32 __U, void const* __P) { __m256i test_mm256_mask_shldi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.256 + // CHECK: @llvm.x86.avx512.vpshld.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_shldi_epi64(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shldi_epi64(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.256 + // CHECK: @llvm.x86.avx512.vpshld.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_shldi_epi64(__U, __A, __B, 63); } __m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.256 + // CHECK: @llvm.x86.avx512.vpshld.q.256 return _mm256_shldi_epi64(__A, __B, 31); } __m128i test_mm_mask_shldi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.128 + // CHECK: @llvm.x86.avx512.vpshld.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_shldi_epi64(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shldi_epi64(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.128 + // CHECK: @llvm.x86.avx512.vpshld.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_shldi_epi64(__U, __A, __B, 63); } __m128i test_mm_shldi_epi64(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shldi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshld.q.128 + // CHECK: @llvm.x86.avx512.vpshld.q.128 return _mm_shldi_epi64(__A, __B, 31); } __m256i test_mm256_mask_shldi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.256 + // CHECK: @llvm.x86.avx512.vpshld.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_shldi_epi32(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shldi_epi32(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.256 + // CHECK: @llvm.x86.avx512.vpshld.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_shldi_epi32(__U, __A, __B, 63); } __m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.256 + // CHECK: @llvm.x86.avx512.vpshld.d.256 return _mm256_shldi_epi32(__A, __B, 31); } __m128i test_mm_mask_shldi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.128 + // CHECK: @llvm.x86.avx512.vpshld.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_shldi_epi32(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shldi_epi32(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.128 + // CHECK: @llvm.x86.avx512.vpshld.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_shldi_epi32(__U, __A, __B, 63); } __m128i test_mm_shldi_epi32(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shldi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshld.d.128 + // CHECK: @llvm.x86.avx512.vpshld.d.128 return _mm_shldi_epi32(__A, __B, 31); } __m256i test_mm256_mask_shldi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.256 + // CHECK: @llvm.x86.avx512.vpshld.w.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shldi_epi16(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shldi_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.256 + // CHECK: @llvm.x86.avx512.vpshld.w.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_shldi_epi16(__U, __A, __B, 63); } __m256i test_mm256_shldi_epi16(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.256 + // CHECK: @llvm.x86.avx512.vpshld.w.256 return _mm256_shldi_epi16(__A, __B, 31); } __m128i test_mm_mask_shldi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.128 + // CHECK: @llvm.x86.avx512.vpshld.w.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shldi_epi16(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shldi_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.128 + // CHECK: @llvm.x86.avx512.vpshld.w.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shldi_epi16(__U, __A, __B, 63); } __m128i test_mm_shldi_epi16(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shldi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshld.w.128 + // CHECK: @llvm.x86.avx512.vpshld.w.128 return _mm_shldi_epi16(__A, __B, 31); } __m256i test_mm256_mask_shrdi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256 + // CHECK: @llvm.x86.avx512.vpshrd.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_shrdi_epi64(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shrdi_epi64(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256 + // CHECK: @llvm.x86.avx512.vpshrd.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_shrdi_epi64(__U, __A, __B, 63); } __m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.256 + // CHECK: @llvm.x86.avx512.vpshrd.q.256 return _mm256_shrdi_epi64(__A, __B, 31); } __m128i test_mm_mask_shrdi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128 + // CHECK: @llvm.x86.avx512.vpshrd.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_shrdi_epi64(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shrdi_epi64(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128 + // CHECK: @llvm.x86.avx512.vpshrd.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_shrdi_epi64(__U, __A, __B, 63); } __m128i test_mm_shrdi_epi64(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shrdi_epi64 - // CHECK: @llvm.x86.avx512.mask.vpshrd.q.128 + // CHECK: @llvm.x86.avx512.vpshrd.q.128 return _mm_shrdi_epi64(__A, __B, 31); } __m256i test_mm256_mask_shrdi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256 + // CHECK: @llvm.x86.avx512.vpshrd.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_shrdi_epi32(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shrdi_epi32(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256 + // CHECK: @llvm.x86.avx512.vpshrd.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_shrdi_epi32(__U, __A, __B, 63); } __m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.256 + // CHECK: @llvm.x86.avx512.vpshrd.d.256 return _mm256_shrdi_epi32(__A, __B, 31); } __m128i test_mm_mask_shrdi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128 + // CHECK: @llvm.x86.avx512.vpshrd.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_shrdi_epi32(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shrdi_epi32(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128 + // CHECK: @llvm.x86.avx512.vpshrd.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_shrdi_epi32(__U, __A, __B, 63); } __m128i test_mm_shrdi_epi32(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shrdi_epi32 - // CHECK: @llvm.x86.avx512.mask.vpshrd.d.128 + // CHECK: @llvm.x86.avx512.vpshrd.d.128 return _mm_shrdi_epi32(__A, __B, 31); } __m256i test_mm256_mask_shrdi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256 + // CHECK: @llvm.x86.avx512.vpshrd.w.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shrdi_epi16(__S, __U, __A, __B, 127); } __m256i test_mm256_maskz_shrdi_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256 + // CHECK: @llvm.x86.avx512.vpshrd.w.256 + // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_shrdi_epi16(__U, __A, __B, 63); } __m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.256 + // CHECK: @llvm.x86.avx512.vpshrd.w.256 return _mm256_shrdi_epi16(__A, __B, 31); } __m128i test_mm_mask_shrdi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128 + // CHECK: @llvm.x86.avx512.vpshrd.w.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shrdi_epi16(__S, __U, __A, __B, 127); } __m128i test_mm_maskz_shrdi_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128 + // CHECK: @llvm.x86.avx512.vpshrd.w.128 + // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shrdi_epi16(__U, __A, __B, 63); } __m128i test_mm_shrdi_epi16(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_shrdi_epi16 - // CHECK: @llvm.x86.avx512.mask.vpshrd.w.128 + // CHECK: @llvm.x86.avx512.vpshrd.w.128 return _mm_shrdi_epi16(__A, __B, 31); } diff --git a/test/Sema/builtins-x86.c b/test/Sema/builtins-x86.c index ad9e00779e..e96caf2d79 100644 --- a/test/Sema/builtins-x86.c +++ b/test/Sema/builtins-x86.c @@ -93,74 +93,74 @@ __m512 _mm512_mask_prefetch_i32gather_ps_2(__m512i index, __mmask16 mask, int co return __builtin_ia32_gatherpfdps(mask, index, addr, 1, 1); // expected-error {{argument should be a value from 2 to 3}} } -__m512i test_mm512_mask_shldi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshldq512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshldq512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m512i test_mm512_mask_shldi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshldd512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshldd512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m512i test_mm512_mask_shldi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshldw512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshldw512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m512i test_mm512_mask_shrdi_epi64(__m512i __S, __mmask8 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdq512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshrdq512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m512i test_mm512_mask_shrdi_epi32(__m512i __S, __mmask16 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdd512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshrdd512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m512i test_mm512_mask_shrdi_epi16(__m512i __S, __mmask32 __U, __m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdw512_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) { + return __builtin_ia32_vpshrdw512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shldi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshldq256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) { + return __builtin_ia32_vpshldq256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shldi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshldq128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shldi_epi64( __m128i __A, __m128i __B) { + return __builtin_ia32_vpshldq128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shldi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshldd256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) { + return __builtin_ia32_vpshldd256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shldi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshldd128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shldi_epi32(__m128i __A, __m128i __B) { + return __builtin_ia32_vpshldd128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shldi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshldw256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shldi_epi16( __m256i __A, __m256i __B) { + return __builtin_ia32_vpshldw256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shldi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshldw128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shldi_epi16(__m128i __A, __m128i __B) { + return __builtin_ia32_vpshldw128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shrdi_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdq256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) { + return __builtin_ia32_vpshrdq256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shrdi_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdq128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shrdi_epi64(__m128i __A, __m128i __B) { + return __builtin_ia32_vpshrdq128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shrdi_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdd256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) { + return __builtin_ia32_vpshrdd256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shrdi_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdd128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shrdi_epi32(__m128i __A, __m128i __B) { + return __builtin_ia32_vpshrdd128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m256i test_mm256_mask_shrdi_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdw256_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) { + return __builtin_ia32_vpshrdw256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -__m128i test_mm128_mask_shrdi_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdw128_mask(__A, __B, 1024, __S, __U); // expected-error {{argument should be a value from 0 to 255}} +__m128i test_mm128_shrdi_epi16(__m128i __A, __m128i __B) { + return __builtin_ia32_vpshrdw128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} } -- GitLab From 85ffa9bd6b859e0aab115e6985678252669e8e65 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 13 Jun 2018 12:37:08 +0000 Subject: [PATCH 0116/1023] [libclang] Optionally add code completion results for arrow instead of dot Follow up for D41537 - libclang part. Differential Revision: https://reviews.llvm.org/D46862 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334593 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 90 ++++++++++++++++++++++- include/clang/Sema/CodeCompleteConsumer.h | 37 +++++----- test/Index/complete-arrow-dot.cpp | 54 ++++++++++++++ tools/c-index-test/c-index-test.c | 50 +++++++++++-- tools/libclang/CIndex.cpp | 36 +++++++++ tools/libclang/CIndexCodeCompletion.cpp | 57 +++++++++++++- tools/libclang/libclang.exports | 27 ++++--- 7 files changed, 310 insertions(+), 41 deletions(-) create mode 100644 test/Index/complete-arrow-dot.cpp diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 0973783a45..4afcd2b1e3 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 48 +#define CINDEX_VERSION_MINOR 49 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -1327,7 +1327,7 @@ enum CXTranslationUnit_Flags { CXTranslationUnit_SingleFileParse = 0x400, /** - * \brief Used in combination with CXTranslationUnit_SkipFunctionBodies to + * Used in combination with CXTranslationUnit_SkipFunctionBodies to * constrain the skipping of function bodies to the preamble. * * The function bodies of the main file are not skipped. @@ -4748,6 +4748,20 @@ typedef struct { void *ptr_data; } CXToken; +/** + * Get the raw lexical token starting with the given location. + * + * \param TU the translation unit whose text is being tokenized. + * + * \param Location the source location with which the token starts. + * + * \returns The token starting with the given location or NULL if no such token + * exist. The returned pointer must be freed with clang_disposeTokens before the + * translation unit is destroyed. + */ +CINDEX_LINKAGE CXToken *clang_getToken(CXTranslationUnit TU, + CXSourceLocation Location); + /** * Determine the kind of the given token. */ @@ -5243,6 +5257,70 @@ typedef struct { unsigned NumResults; } CXCodeCompleteResults; +/** + * Retrieve the number of fix-its for the given completion index. + * + * Calling this makes sense only if CXCodeComplete_IncludeCompletionsWithFixIts + * option was set. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \return The number of fix-its which must be applied before the completion at + * completion_index can be applied + */ +CINDEX_LINKAGE unsigned +clang_getCompletionNumFixIts(CXCodeCompleteResults *results, + unsigned completion_index); + +/** + * Fix-its that *must* be applied before inserting the text for the + * corresponding completion. + * + * By default, clang_codeCompleteAt() only returns completions with empty + * fix-its. Extra completions with non-empty fix-its should be explicitly + * requested by setting CXCodeComplete_IncludeCompletionsWithFixIts. + * + * For the clients to be able to compute position of the cursor after applying + * fix-its, the following conditions are guaranteed to hold for + * replacement_range of the stored fix-its: + * - Ranges in the fix-its are guaranteed to never contain the completion + * point (or identifier under completion point, if any) inside them, except + * at the start or at the end of the range. + * - If a fix-it range starts or ends with completion point (or starts or + * ends after the identifier under completion point), it will contain at + * least one character. It allows to unambiguously recompute completion + * point after applying the fix-it. + * + * The intuition is that provided fix-its change code around the identifier we + * complete, but are not allowed to touch the identifier itself or the + * completion point. One example of completions with corrections are the ones + * replacing '.' with '->' and vice versa: + * + * std::unique_ptr> vec_ptr; + * In 'vec_ptr.^', one of the completions is 'push_back', it requires + * replacing '.' with '->'. + * In 'vec_ptr->^', one of the completions is 'release', it requires + * replacing '->' with '.'. + * + * \param results The structure keeping all completion results + * + * \param completion_index The index of the completion + * + * \param fixit_index The index of the fix-it for the completion at + * completion_index + * + * \param replacement_range The fix-it range that must be replaced before the + * completion at completion_index can be applied + * + * \returns The fix-it string that must replace the code at replacement_range + * before the completion at completion_index can be applied + */ +CINDEX_LINKAGE CXString clang_getCompletionFixIt( + CXCodeCompleteResults *results, unsigned completion_index, + unsigned fixit_index, CXSourceRange *replacement_range); + /** * Flags that can be passed to \c clang_codeCompleteAt() to * modify its behavior. @@ -5274,7 +5352,13 @@ enum CXCodeComplete_Flags { * defined in the preamble. There's no guarantee any particular entity is * omitted. This may be useful if the headers are indexed externally. */ - CXCodeComplete_SkipPreamble = 0x08 + CXCodeComplete_SkipPreamble = 0x08, + + /** + * Whether to include completions with small + * fix-its, e.g. change '.' to '->' on member access, etc. + */ + CXCodeComplete_IncludeCompletionsWithFixIts = 0x10 }; /** diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index a94c6d568d..86e52f404c 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -783,30 +783,33 @@ public: /// The availability of this result. CXAvailabilityKind Availability = CXAvailability_Available; - /// FixIts that *must* be applied before inserting the text for the - /// corresponding completion item. + /// Fix-its that *must* be applied before inserting the text for the + /// corresponding completion. /// - /// Completion items with non-empty fixits will not be returned by default, - /// they should be explicitly requested by setting - /// CompletionOptions::IncludeFixIts. For the editors to be able to - /// compute position of the cursor for the completion item itself, the - /// following conditions are guaranteed to hold for RemoveRange of the stored - /// fixits: - /// - Ranges in the fixits are guaranteed to never contain the completion + /// By default, CodeCompletionBuilder only returns completions with empty + /// fix-its. Extra completions with non-empty fix-its should be explicitly + /// requested by setting CompletionOptions::IncludeFixIts. + /// + /// For the clients to be able to compute position of the cursor after + /// applying fix-its, the following conditions are guaranteed to hold for + /// RemoveRange of the stored fix-its: + /// - Ranges in the fix-its are guaranteed to never contain the completion /// point (or identifier under completion point, if any) inside them, except /// at the start or at the end of the range. - /// - If a fixit range starts or ends with completion point (or starts or + /// - If a fix-it range starts or ends with completion point (or starts or /// ends after the identifier under completion point), it will contain at /// least one character. It allows to unambiguously recompute completion - /// point after applying the fixit. - /// The intuition is that provided fixits change code around the identifier we - /// complete, but are not allowed to touch the identifier itself or the - /// completion point. One example of completion items with corrections are the - /// ones replacing '.' with '->' and vice versa: + /// point after applying the fix-it. + /// + /// The intuition is that provided fix-its change code around the identifier + /// we complete, but are not allowed to touch the identifier itself or the + /// completion point. One example of completions with corrections are the ones + /// replacing '.' with '->' and vice versa: + /// /// std::unique_ptr> vec_ptr; - /// In 'vec_ptr.^', one of completion items is 'push_back', it requires + /// In 'vec_ptr.^', one of the completions is 'push_back', it requires /// replacing '.' with '->'. - /// In 'vec_ptr->^', one of completion items is 'release', it requires + /// In 'vec_ptr->^', one of the completions is 'release', it requires /// replacing '->' with '.'. std::vector FixIts; diff --git a/test/Index/complete-arrow-dot.cpp b/test/Index/complete-arrow-dot.cpp new file mode 100644 index 0000000000..fb5efbe6e6 --- /dev/null +++ b/test/Index/complete-arrow-dot.cpp @@ -0,0 +1,54 @@ +struct X { + void doSomething(); + + int field; +}; + +void X::doSomething() { + // RUN: c-index-test -code-completion-at=%s:10:8 %s | FileCheck %s + // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:10:8 %s | FileCheck -check-prefix=CHECK-WITH-CORRECTION %s + this.; +} + +void doSomething() { + // RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT %s + // RUN: env CINDEXTEST_COMPLETION_INCLUDE_FIXITS=1 c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-ARROW-TO-DOT-WITH-CORRECTION %s + X x; + x-> +} + +// CHECK-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK: Completion contexts: +// CHECK-NEXT: Dot member access + +// CHECK-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-WITH-CORRECTION-NEXT: Completion contexts: +// CHECK-WITH-CORRECTION-NEXT: Dot member access + +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-NOT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT: Completion contexts: +// CHECK-ARROW-TO-DOT-NEXT: Unknown + +// CHECK-ARROW-TO-DOT-WITH-CORRECTION: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: FieldDecl:{ResultType int}{TypedText field} (35) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder X &&}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: StructDecl:{TypedText X}{Text ::} (75) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: CXXDestructor:{ResultType void}{TypedText ~X}{LeftParen (}{RightParen )} (79) (requires fix-it:{{.*}} +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Completion contexts: +// CHECK-ARROW-TO-DOT-WITH-CORRECTION-NEXT: Arrow member access diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index e86a20b55b..50fea5ba8b 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -2270,8 +2270,33 @@ static void print_completion_string(CXCompletionString completion_string, } -static void print_completion_result(CXCompletionResult *completion_result, +static void print_line_column(CXSourceLocation location, FILE *file) { + unsigned line, column; + clang_getExpansionLocation(location, NULL, &line, &column, NULL); + fprintf(file, "%d:%d", line, column); +} + +static void print_token_range(CXTranslationUnit translation_unit, + CXSourceLocation start, FILE *file) { + CXToken *token = clang_getToken(translation_unit, start); + + fprintf(file, "{"); + if (token != NULL) { + CXSourceRange token_range = clang_getTokenExtent(translation_unit, *token); + print_line_column(clang_getRangeStart(token_range), file); + fprintf(file, "-"); + print_line_column(clang_getRangeEnd(token_range), file); + clang_disposeTokens(translation_unit, token, 1); + } + + fprintf(file, "}"); +} + +static void print_completion_result(CXTranslationUnit translation_unit, + CXCodeCompleteResults *completion_results, + unsigned index, FILE *file) { + CXCompletionResult *completion_result = completion_results->Results + index; CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind); unsigned annotationCount; enum CXCursorKind ParentKind; @@ -2339,7 +2364,20 @@ static void print_completion_result(CXCompletionResult *completion_result, fprintf(file, "(brief comment: %s)", BriefCommentCString); } clang_disposeString(BriefComment); - + + unsigned i; + for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); + ++i) { + CXSourceRange correction_range; + CXString FixIt = clang_getCompletionFixIt(completion_results, index, i, + &correction_range); + fprintf(file, " (requires fix-it: "); + print_token_range(translation_unit, clang_getRangeStart(correction_range), + file); + fprintf(file, " to \"%s\")", clang_getCString(FixIt)); + clang_disposeString(FixIt); + } + fprintf(file, "\n"); } @@ -2438,6 +2476,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { completionOptions |= CXCodeComplete_IncludeBriefComments; if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE")) completionOptions |= CXCodeComplete_SkipPreamble; + if (getenv("CINDEXTEST_COMPLETION_INCLUDE_FIXITS")) + completionOptions |= CXCodeComplete_IncludeCompletionsWithFixIts; if (timing_only) input += strlen("-code-completion-timing="); @@ -2502,7 +2542,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { clang_sortCodeCompletionResults(results->Results, results->NumResults); for (i = 0; i != n; ++i) - print_completion_result(results->Results + i, stdout); + print_completion_result(TU, results, i, stdout); } n = clang_codeCompleteGetNumDiagnostics(results); for (i = 0; i != n; ++i) { @@ -4402,10 +4442,10 @@ static void printLocation(CXSourceLocation L) { CXFile File; CXString FileName; unsigned line, column, offset; - + clang_getExpansionLocation(L, &File, &line, &column, &offset); FileName = clang_getFileName(File); - + fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column); clang_disposeString(FileName); } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 32f6ca994b..1c291d7332 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -6652,6 +6652,42 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range, } while (Lex.getBufferLocation() < EffectiveBufferEnd); } +CXToken *clang_getToken(CXTranslationUnit TU, CXSourceLocation Location) { + LOG_FUNC_SECTION { + *Log << TU << ' ' << Location; + } + + if (isNotUsableTU(TU)) { + LOG_BAD_TU(TU); + return NULL; + } + + ASTUnit *CXXUnit = cxtu::getASTUnit(TU); + if (!CXXUnit) + return NULL; + + SourceLocation Begin = cxloc::translateSourceLocation(Location); + if (Begin.isInvalid()) + return NULL; + SourceManager &SM = CXXUnit->getSourceManager(); + std::pair DecomposedEnd = SM.getDecomposedLoc(Begin); + DecomposedEnd.second += Lexer::MeasureTokenLength(Begin, SM, CXXUnit->getLangOpts()); + + SourceLocation End = SM.getComposedLoc(DecomposedEnd.first, DecomposedEnd.second); + + SmallVector CXTokens; + getTokens(CXXUnit, SourceRange(Begin, End), CXTokens); + + if (CXTokens.empty()) + return NULL; + + CXTokens.resize(1); + CXToken *Token = static_cast(llvm::safe_malloc(sizeof(CXToken))); + + memmove(Token, CXTokens.data(), sizeof(CXToken)); + return Token; +} + void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXToken **Tokens, unsigned *NumTokens) { LOG_FUNC_SECTION { diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 73f8da1e1b..f49f9763c3 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -16,6 +16,7 @@ #include "CIndexDiagnostic.h" #include "CLog.h" #include "CXCursor.h" +#include "CXSourceLocation.h" #include "CXString.h" #include "CXTranslationUnit.h" #include "clang/AST/Decl.h" @@ -302,10 +303,53 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// A string containing the Objective-C selector entered thus far for a /// message send. std::string Selector; + + /// Vector of fix-its for each completion result that *must* be applied + /// before that result for the corresponding completion item. + std::vector> FixItsVector; }; } // end anonymous namespace +unsigned clang_getCompletionNumFixIts(CXCodeCompleteResults *results, + unsigned completion_index) { + AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results; + + if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) + return 0; + + return static_cast(allocated_results->FixItsVector[completion_index].size()); +} + +CXString clang_getCompletionFixIt(CXCodeCompleteResults *results, + unsigned completion_index, + unsigned fixit_index, + CXSourceRange *replacement_range) { + AllocatedCXCodeCompleteResults *allocated_results = (AllocatedCXCodeCompleteResults *)results; + + if (!allocated_results || allocated_results->FixItsVector.size() <= completion_index) { + if (replacement_range) + *replacement_range = clang_getNullRange(); + return cxstring::createNull(); + } + + ArrayRef FixIts = allocated_results->FixItsVector[completion_index]; + if (FixIts.size() <= fixit_index) { + if (replacement_range) + *replacement_range = clang_getNullRange(); + return cxstring::createNull(); + } + + const FixItHint &FixIt = FixIts[fixit_index]; + if (replacement_range) { + *replacement_range = cxloc::translateSourceRange( + *allocated_results->SourceMgr, allocated_results->LangOpts, + FixIt.RemoveRange); + } + + return cxstring::createRef(FixIt.CodeToInsert.c_str()); +} + /// Tracks the number of code-completion result objects that are /// currently active. /// @@ -531,8 +575,10 @@ namespace { CodeCompletionResult *Results, unsigned NumResults) override { StoredResults.reserve(StoredResults.size() + NumResults); + if (includeFixIts()) + AllocatedResults.FixItsVector.reserve(NumResults); for (unsigned I = 0; I != NumResults; ++I) { - CodeCompletionString *StoredCompletion + CodeCompletionString *StoredCompletion = Results[I].CreateCodeCompletionString(S, Context, getAllocator(), getCodeCompletionTUInfo(), includeBriefComments()); @@ -541,8 +587,10 @@ namespace { R.CursorKind = Results[I].CursorKind; R.CompletionString = StoredCompletion; StoredResults.push_back(R); + if (includeFixIts()) + AllocatedResults.FixItsVector.emplace_back(std::move(Results[I].FixIts)); } - + enum CodeCompletionContext::Kind contextKind = Context.getKind(); AllocatedResults.ContextKind = contextKind; @@ -644,13 +692,13 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; bool SkipPreamble = options & CXCodeComplete_SkipPreamble; + bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts; #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); #endif #endif - bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr; if (cxtu::isNotUsableTU(TU)) { @@ -691,6 +739,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; Opts.LoadExternal = !SkipPreamble; + Opts.IncludeFixIts = IncludeFixIts; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion. @@ -964,7 +1013,7 @@ namespace { = (CodeCompletionString *)XR.CompletionString; CodeCompletionString *Y = (CodeCompletionString *)YR.CompletionString; - + SmallString<256> XBuffer; StringRef XText = GetTypedName(X, XBuffer); SmallString<256> YBuffer; diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 222598dcd9..a185bc7845 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -168,12 +168,14 @@ clang_getClangVersion clang_getCompletionAnnotation clang_getCompletionAvailability clang_getCompletionBriefComment -clang_getCompletionChunkCompletionString -clang_getCompletionChunkKind -clang_getCompletionChunkText -clang_getCompletionNumAnnotations -clang_getCompletionParent -clang_getCompletionPriority +clang_getCompletionChunkCompletionString +clang_getCompletionChunkKind +clang_getCompletionChunkText +clang_getCompletionNumFixIts +clang_getCompletionFixIt +clang_getCompletionNumAnnotations +clang_getCompletionParent +clang_getCompletionPriority clang_getCursor clang_getCursorAvailability clang_getCursorCompletionString @@ -257,12 +259,13 @@ clang_getRemappingsFromFileList clang_getResultType clang_getSkippedRanges clang_getSpecializedCursorTemplate -clang_getSpellingLocation -clang_getTUResourceUsageName -clang_getTemplateCursorKind -clang_getTokenExtent -clang_getTokenKind -clang_getTokenLocation +clang_getSpellingLocation +clang_getTUResourceUsageName +clang_getTemplateCursorKind +clang_getToken +clang_getTokenExtent +clang_getTokenKind +clang_getTokenLocation clang_getTokenSpelling clang_getTranslationUnitCursor clang_getTranslationUnitSpelling -- GitLab From 79be246d396dc27a00ba7cbdfe032945c6908b5c Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 13 Jun 2018 13:25:11 +0000 Subject: [PATCH 0117/1023] Correct behavior of __builtin_*_overflow and constexpr. Enable these builtins to be called across a lambda boundary with captureless const/constexpr, as brought up by Eli here: https://reviews.llvm.org/D48040 Differential Revision: https://reviews.llvm.org/D48053 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334597 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 30 +++++++++++++++++++++--------- test/SemaCXX/builtins-overflow.cpp | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 test/SemaCXX/builtins-overflow.cpp diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6a1cbdf621..dfe4373f33 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -197,30 +197,42 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { // First two arguments should be integers. for (unsigned I = 0; I < 2; ++I) { - Expr *Arg = TheCall->getArg(I); - QualType Ty = Arg->getType(); + ExprResult Arg = TheCall->getArg(I); + QualType Ty = Arg.get()->getType(); if (!Ty->isIntegerType()) { - S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int) - << Ty << Arg->getSourceRange(); + S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int) + << Ty << Arg.get()->getSourceRange(); return true; } + InitializedEntity Entity = InitializedEntity::InitializeParameter( + S.getASTContext(), Ty, /*consume*/ false); + Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return true; + TheCall->setArg(I, Arg.get()); } // Third argument should be a pointer to a non-const integer. // IRGen correctly handles volatile, restrict, and address spaces, and // the other qualifiers aren't possible. { - Expr *Arg = TheCall->getArg(2); - QualType Ty = Arg->getType(); + ExprResult Arg = TheCall->getArg(2); + QualType Ty = Arg.get()->getType(); const auto *PtrTy = Ty->getAs(); if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() && !PtrTy->getPointeeType().isConstQualified())) { - S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int) - << Ty << Arg->getSourceRange(); + S.Diag(Arg.get()->getLocStart(), + diag::err_overflow_builtin_must_be_ptr_int) + << Ty << Arg.get()->getSourceRange(); return true; } + InitializedEntity Entity = InitializedEntity::InitializeParameter( + S.getASTContext(), Ty, /*consume*/ false); + Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return true; + TheCall->setArg(2, Arg.get()); } - return false; } diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp new file mode 100644 index 0000000000..9054cce257 --- /dev/null +++ b/test/SemaCXX/builtins-overflow.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s +// expected-no-diagnostics + +int a() { + const int x = 3; + static int z; + constexpr int *y = &z; + return []() { return __builtin_sub_overflow((int)x, (int)x, (int *)y); }(); +} +int a2() { + const int x = 3; + static int z; + constexpr int *y = &z; + return []() { return __builtin_sub_overflow(x, x, y); }(); +} -- GitLab From 1452597f76a7028d9782dc8cff4d08fc5eb3c945 Mon Sep 17 00:00:00 2001 From: Piotr Padlewski Date: Wed, 13 Jun 2018 13:55:42 +0000 Subject: [PATCH 0118/1023] Add -fforce-emit-vtables Summary: In many cases we can't devirtualize because definition of vtable is not present. Most of the time it is caused by inline virtual function not beeing emitted. Forcing emitting of vtable adds a reference of these inline virtual functions. Note that GCC was always doing it. Reviewers: rjmccall, rsmith, amharc, kuhar Subscribers: llvm-commits, cfe-commits Differential Revision: https://reviews.llvm.org/D47108 Co-authored-by: Krzysztof Pszeniczny git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334600 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangCommandLineReference.rst | 6 + docs/ReleaseNotes.rst | 6 + docs/UsersManual.rst | 6 + include/clang/Basic/LangOptions.def | 2 + include/clang/Driver/Options.td | 5 + include/clang/Frontend/CodeGenOptions.def | 4 + lib/CodeGen/ItaniumCXXABI.cpp | 14 +- lib/Driver/ToolChains/Clang.cpp | 4 + lib/Frontend/CompilerInvocation.cpp | 4 + lib/Sema/SemaDeclCXX.cpp | 6 + .../vtable-available-externally.cpp | 128 ++++++++++++++++++ 11 files changed, 182 insertions(+), 3 deletions(-) diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 264729dd0f..513128119e 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -1934,6 +1934,12 @@ Set the default symbol visibility for all global declarations Enables whole-program vtable optimization. Requires -flto +.. option:: -fforce-emit-vtables, -fno-force-emit-vtables + +In order to improve devirtualization, forces emitting of vtables even in +modules where it isn't necessary. It causes more inline virtual functions +to be emitted. + .. option:: -fwrapv, -fno-wrapv Treat signed integer overflow as two's complement diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 8414555464..15ae73e859 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -112,6 +112,12 @@ New Compiler Flags 'no-strict' option, Clang attempts to match the overflowing behavior of the target's native float-to-int conversion instructions. +- :option: `-fforce-emit-vtables` and `-fno-force-emit-vtables`. + + In order to improve devirtualization, forces emitting of vtables even in + modules where it isn't necessary. It causes more inline virtual functions + to be emitted. + - ... Deprecated Compiler Flags diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index 9778b1654d..b1c286193c 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -1269,6 +1269,12 @@ are listed below. devirtualization and virtual constant propagation, for classes with :doc:`hidden LTO visibility `. Requires ``-flto``. +.. option:: -fforce-emit-vtables + + In order to improve devirtualization, forces emitting of vtables even in + modules where it isn't necessary. It causes more inline virtual functions + to be emitted. + .. option:: -fno-assume-sane-operator-new Don't assume that the C++'s new operator is sane. diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 6bd8958e36..f9246bd893 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -293,6 +293,8 @@ LANGOPT(XRayAlwaysEmitTypedEvents, 1, 0, "controls whether to always emit intrinsic calls to " "__xray_typedevent(...) builtin.") +LANGOPT(ForceEmitVTables, 1, 0, "whether to emit all vtables") + BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 4c04d33466..cd02a5ab5b 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1688,6 +1688,11 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group; def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group, Flags<[CoreOption]>; +def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group, + Flags<[CC1Option]>, + HelpText<"Emits more virtual tables to improve devirtualization">; +def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group, + Flags<[CoreOption]>; def fwrapv : Flag<["-"], "fwrapv">, Group, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags<[CC1Option]>, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index c2dd7e4358..019425d194 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -332,6 +332,10 @@ CODEGENOPT(NoPLT, 1, 0) /// Whether to embed source in DWARF debug line section. CODEGENOPT(EmbedSource, 1, 0) +/// Whether to emit all vtables +CODEGENOPT(ForceEmitVTables, 1, 0) + + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index d84a10c6ba..6ac7d29752 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1707,11 +1707,19 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { if (CGM.getLangOpts().AppleKext) return false; - // If we don't have any not emitted inline virtual function, and if vtable is - // not hidden, then we are safe to emit available_externally copy of vtable. + // If the vtable is hidden then it is not safe to emit an available_externally + // copy of vtable. + if (isVTableHidden(RD)) + return false; + + if (CGM.getCodeGenOpts().ForceEmitVTables) + return true; + + // If we don't have any not emitted inline virtual function then we are safe + // to emit an available_externally copy of vtable. // FIXME we can still emit a copy of the vtable if we // can emit definition of the inline functions. - return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD); + return !hasAnyUnusedVirtualInlineFunction(RD); } static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 3eee463bb1..d392f68897 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3472,6 +3472,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_vtable_pointers, false)) CmdArgs.push_back("-fstrict-vtable-pointers"); + if (Args.hasFlag(options::OPT_fforce_emit_vtables, + options::OPT_fno_force_emit_vtables, + false)) + CmdArgs.push_back("-fforce-emit-vtables"); if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, options::OPT_fno_optimize_sibling_calls)) CmdArgs.push_back("-mdisable-tail-calls"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index a959cdb234..2aa74c38e2 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -719,6 +719,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return); Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers); + Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); @@ -2735,6 +2736,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.getAllArgValues(OPT_fxray_never_instrument); Opts.XRayAttrListFiles = Args.getAllArgValues(OPT_fxray_attr_list); + // -fforce-emit-vtables + Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables); + // -fallow-editor-placeholders Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 55517fc3f6..f5e4821092 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6125,6 +6125,12 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { Record->setParamDestroyedInCallee(true); else if (Record->hasNonTrivialDestructor()) Record->setParamDestroyedInCallee(CanPass); + + if (getLangOpts().ForceEmitVTables) { + // If we want to emit all the vtables, we need to mark it as used. This + // is especially required for cases like vtable assumption loads. + MarkVTableUsed(Record->getInnerLocStart(), Record); + } } /// Look up the special member function that would be called by a special diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index 0e7e8b4a32..b52527d36c 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,6 +217,7 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -221,6 +226,7 @@ void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,6 +243,7 @@ struct B : A { // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function @@ -245,6 +252,8 @@ struct C : A { // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ void g() { namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ namespace Test13 { // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ namespace Test16 { // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ namespace Test17 { // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); @@ -418,3 +438,111 @@ void testcaseB() { } } // namespace Test17 + +namespace Test18 { +// Here vtable will be only emitted because it is referenced by assume-load +// after the Derived construction. +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test187DerivedE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN6Test187DerivedE {{.*}} @_ZN6Test184Base3funEv {{.*}} @_ZN6Test184BaseD2Ev {{.*}} @_ZN6Test187DerivedD0Ev +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test187DerivedD0Ev +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test184BaseD2Ev +// CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN6Test184Base3funEv +// CHECK-FORCE-EMIT-DAG: @_ZTIN6Test187DerivedE = linkonce_odr constant + +struct Base { + virtual int fun() { return 42; } + virtual ~Base() { } +}; + +struct Derived : Base { + Derived(); +}; + +int foo() { + Derived *der = new Derived(); + return der->fun(); +} +} + +namespace TestTemplates { + +// CHECK-FORCE-EMIT-DAG: @_ZTVN13TestTemplates8TemplateIiEE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN13TestTemplates8TemplateIiEE {{.*}} @_ZN13TestTemplates8TemplateIiE3fooEi {{.*}}@_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi {{.*}}@_ZN13TestTemplates8TemplateIiED1Ev {{.*}}@_ZN13TestTemplates8TemplateIiED0Ev +// CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi + +template +struct Template { + Template(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates8TemplateIiE22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~Template(); +}; + + +struct NonTemplate { + typedef int T; + NonTemplate(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates11NonTemplate22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~NonTemplate(); +}; + +// CHECK-FORCE-EMIT-DAG: @_ZTVN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiEE = linkonce_odr {{.*}} @_ZTIN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiEE {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE3fooEi {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE22thisShouldBeEmittedTooEi {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiED1Ev {{.*}} @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiED0Ev + +struct OuterNonTemplate { + template + struct NestedTemplateInNonTemplate { + NestedTemplateInNonTemplate(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates16OuterNonTemplate27NestedTemplateInNonTemplateIiE22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~NestedTemplateInNonTemplate(); + }; + + struct NestedNonTemplateInNonTemplate { + typedef int T; + NestedNonTemplateInNonTemplate(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates16OuterNonTemplate30NestedNonTemplateInNonTemplate22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~NestedNonTemplateInNonTemplate(); + }; +}; + +template +struct OuterTemplate { + template + struct NestedTemplateInTemplate { + NestedTemplateInTemplate(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates13OuterTemplateIlE24NestedTemplateInTemplateIiE22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~NestedTemplateInTemplate(); + }; + + struct NestedNonTemplateInTemplate { + typedef int T; + NestedNonTemplateInTemplate(); + virtual T foo(T val); + // CHECK-FORCE-EMIT-DAG: define linkonce_odr i32 @_ZN13TestTemplates13OuterTemplateIlE27NestedNonTemplateInTemplate22thisShouldBeEmittedTooEi + virtual T thisShouldBeEmittedToo(T val) { return val; } + virtual ~NestedNonTemplateInTemplate(); + }; +}; + +template +int use() { + T *ptr = new T(); + return ptr->foo(42); +} + +void test() { + use >(); + use::NestedTemplateInTemplate >(); + use >(); + + use(); + use::NestedNonTemplateInTemplate>(); + use(); +} +} -- GitLab From 0438a55db90f05d85dc75089a6fe1da021e50911 Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Wed, 13 Jun 2018 16:00:39 +0000 Subject: [PATCH 0119/1023] [libclang] Make c-index-test.c ISO C90 compliant. Fixes a build bot breakage caused by r334593. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334612 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/c-index-test/c-index-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 50fea5ba8b..dd1652e32c 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -2304,6 +2304,7 @@ static void print_completion_result(CXTranslationUnit translation_unit, CXString BriefComment; CXString Annotation; const char *BriefCommentCString; + unsigned i; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -2365,7 +2366,6 @@ static void print_completion_result(CXTranslationUnit translation_unit, } clang_disposeString(BriefComment); - unsigned i; for (i = 0; i < clang_getCompletionNumFixIts(completion_results, index); ++i) { CXSourceRange correction_range; -- GitLab From 9d8fe3e8b1bb18c53710eaf1929c4b4a74323af5 Mon Sep 17 00:00:00 2001 From: Stefan Pintilie Date: Wed, 13 Jun 2018 16:05:05 +0000 Subject: [PATCH 0120/1023] [PowerPC] The __float128 type should only be available on Power9 Diasble the use of the type __float128 for PPC machines older than Power9. The use of -mfloat128 for PPC machine older than Power9 will result in an error. Differential Revision: https://reviews.llvm.org/D48088 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334613 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/PPC.cpp | 115 +++++----------------- lib/Basic/Targets/PPC.h | 104 ++++++++++++++----- test/Driver/ppc-f128-support-check.c | 20 ++++ test/Preprocessor/init.c | 2 +- test/Sema/float128-ld-incompatibility.cpp | 2 +- 5 files changed, 127 insertions(+), 116 deletions(-) create mode 100644 test/Driver/ppc-f128-support-check.c diff --git a/lib/Basic/Targets/PPC.cpp b/lib/Basic/Targets/PPC.cpp index 36be14a6cb..b4eb3b1b97 100644 --- a/lib/Basic/Targets/PPC.cpp +++ b/lib/Basic/Targets/PPC.cpp @@ -15,7 +15,6 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" -#include "llvm/ADT/StringSwitch.h" using namespace clang; using namespace clang::targets; @@ -116,111 +115,37 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64)) Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16"); - // CPU identification. - ArchDefineTypes defs = - (ArchDefineTypes)llvm::StringSwitch(CPU) - .Case("440", ArchDefineName) - .Case("450", ArchDefineName | ArchDefine440) - .Case("601", ArchDefineName) - .Case("602", ArchDefineName | ArchDefinePpcgr) - .Case("603", ArchDefineName | ArchDefinePpcgr) - .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) - .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) - .Case("604", ArchDefineName | ArchDefinePpcgr) - .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr) - .Case("620", ArchDefineName | ArchDefinePpcgr) - .Case("630", ArchDefineName | ArchDefinePpcgr) - .Case("7400", ArchDefineName | ArchDefinePpcgr) - .Case("7450", ArchDefineName | ArchDefinePpcgr) - .Case("750", ArchDefineName | ArchDefinePpcgr) - .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("a2", ArchDefineA2) - .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q) - .Case("pwr3", ArchDefinePpcgr) - .Case("pwr4", ArchDefineName | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr5", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("pwr5x", ArchDefineName | ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr6", ArchDefineName | ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr6x", ArchDefineName | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("pwr7", ArchDefineName | ArchDefinePwr6x | ArchDefinePwr6 | - ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr8", ArchDefineName | ArchDefinePwr7 | ArchDefinePwr6x | - ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("pwr9", ArchDefineName | ArchDefinePwr8 | ArchDefinePwr7 | - ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power3", ArchDefinePpcgr) - .Case("power4", ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power5", ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power5x", ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power6", ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power6x", ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power7", ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 | - ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - .Case("power8", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x | - ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Case("power9", ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | - ArchDefinePwr6x | ArchDefinePwr6 | - ArchDefinePwr5x | ArchDefinePwr5 | - ArchDefinePwr4 | ArchDefinePpcgr | - ArchDefinePpcsq) - // powerpc64le automatically defaults to at least power8. - .Case("ppc64le", ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x | - ArchDefinePwr6 | ArchDefinePwr5x | - ArchDefinePwr5 | ArchDefinePwr4 | - ArchDefinePpcgr | ArchDefinePpcsq) - .Default(ArchDefineNone); - - if (defs & ArchDefineName) + if (ArchDefs & ArchDefineName) Builder.defineMacro(Twine("_ARCH_", StringRef(CPU).upper())); - if (defs & ArchDefinePpcgr) + if (ArchDefs & ArchDefinePpcgr) Builder.defineMacro("_ARCH_PPCGR"); - if (defs & ArchDefinePpcsq) + if (ArchDefs & ArchDefinePpcsq) Builder.defineMacro("_ARCH_PPCSQ"); - if (defs & ArchDefine440) + if (ArchDefs & ArchDefine440) Builder.defineMacro("_ARCH_440"); - if (defs & ArchDefine603) + if (ArchDefs & ArchDefine603) Builder.defineMacro("_ARCH_603"); - if (defs & ArchDefine604) + if (ArchDefs & ArchDefine604) Builder.defineMacro("_ARCH_604"); - if (defs & ArchDefinePwr4) + if (ArchDefs & ArchDefinePwr4) Builder.defineMacro("_ARCH_PWR4"); - if (defs & ArchDefinePwr5) + if (ArchDefs & ArchDefinePwr5) Builder.defineMacro("_ARCH_PWR5"); - if (defs & ArchDefinePwr5x) + if (ArchDefs & ArchDefinePwr5x) Builder.defineMacro("_ARCH_PWR5X"); - if (defs & ArchDefinePwr6) + if (ArchDefs & ArchDefinePwr6) Builder.defineMacro("_ARCH_PWR6"); - if (defs & ArchDefinePwr6x) + if (ArchDefs & ArchDefinePwr6x) Builder.defineMacro("_ARCH_PWR6X"); - if (defs & ArchDefinePwr7) + if (ArchDefs & ArchDefinePwr7) Builder.defineMacro("_ARCH_PWR7"); - if (defs & ArchDefinePwr8) + if (ArchDefs & ArchDefinePwr8) Builder.defineMacro("_ARCH_PWR8"); - if (defs & ArchDefinePwr9) + if (ArchDefs & ArchDefinePwr9) Builder.defineMacro("_ARCH_PWR9"); - if (defs & ArchDefineA2) + if (ArchDefs & ArchDefineA2) Builder.defineMacro("_ARCH_A2"); - if (defs & ArchDefineA2q) { + if (ArchDefs & ArchDefineA2q) { Builder.defineMacro("_ARCH_A2Q"); Builder.defineMacro("_ARCH_QP"); } @@ -384,6 +309,14 @@ bool PPCTargetInfo::initFeatureMap( if (!ppcUserFeaturesCheck(Diags, FeaturesVec)) return false; + if (!(ArchDefs & ArchDefinePwr9) && (ArchDefs & ArchDefinePpcgr) && + std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") != + FeaturesVec.end()) { + // We have __float128 on PPC but not power 9 and above. + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" << CPU; + return false; + } + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } diff --git a/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h index 9ea100f0a1..70d0f1c2cd 100644 --- a/lib/Basic/Targets/PPC.h +++ b/lib/Basic/Targets/PPC.h @@ -18,6 +18,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -25,6 +26,30 @@ namespace targets { // PPC abstract base class class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { + + /// Flags for architecture specific defines. + typedef enum { + ArchDefineNone = 0, + ArchDefineName = 1 << 0, // is substituted for arch name. + ArchDefinePpcgr = 1 << 1, + ArchDefinePpcsq = 1 << 2, + ArchDefine440 = 1 << 3, + ArchDefine603 = 1 << 4, + ArchDefine604 = 1 << 5, + ArchDefinePwr4 = 1 << 6, + ArchDefinePwr5 = 1 << 7, + ArchDefinePwr5x = 1 << 8, + ArchDefinePwr6 = 1 << 9, + ArchDefinePwr6x = 1 << 10, + ArchDefinePwr7 = 1 << 11, + ArchDefinePwr8 = 1 << 12, + ArchDefinePwr9 = 1 << 13, + ArchDefineA2 = 1 << 14, + ArchDefineA2q = 1 << 15 + } ArchDefineTypes; + + + ArchDefineTypes ArchDefs; static const Builtin::Info BuiltinInfo[]; static const char *const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; @@ -50,34 +75,13 @@ public: : TargetInfo(Triple), HasAltivec(false), HasVSX(false), HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false), HasBPERMD(false), HasExtDiv(false), - HasP9Vector(false) { + HasP9Vector(false), ArchDefs(ArchDefineNone) { SuitableAlign = 128; SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); } - /// Flags for architecture specific defines. - typedef enum { - ArchDefineNone = 0, - ArchDefineName = 1 << 0, // is substituted for arch name. - ArchDefinePpcgr = 1 << 1, - ArchDefinePpcsq = 1 << 2, - ArchDefine440 = 1 << 3, - ArchDefine603 = 1 << 4, - ArchDefine604 = 1 << 5, - ArchDefinePwr4 = 1 << 6, - ArchDefinePwr5 = 1 << 7, - ArchDefinePwr5x = 1 << 8, - ArchDefinePwr6 = 1 << 9, - ArchDefinePwr6x = 1 << 10, - ArchDefinePwr7 = 1 << 11, - ArchDefinePwr8 = 1 << 12, - ArchDefinePwr9 = 1 << 13, - ArchDefineA2 = 1 << 14, - ArchDefineA2q = 1 << 15 - } ArchDefineTypes; - // Set the language option for altivec based on our value. void adjust(LangOptions &Opts) override; @@ -90,8 +94,62 @@ public: bool setCPU(const std::string &Name) override { bool CPUKnown = isValidCPUName(Name); - if (CPUKnown) + if (CPUKnown) { CPU = Name; + + // CPU identification. + ArchDefs = + (ArchDefineTypes)llvm::StringSwitch(CPU) + .Case("440", ArchDefineName) + .Case("450", ArchDefineName | ArchDefine440) + .Case("601", ArchDefineName) + .Case("602", ArchDefineName | ArchDefinePpcgr) + .Case("603", ArchDefineName | ArchDefinePpcgr) + .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) + .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) + .Case("604", ArchDefineName | ArchDefinePpcgr) + .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr) + .Case("620", ArchDefineName | ArchDefinePpcgr) + .Case("630", ArchDefineName | ArchDefinePpcgr) + .Case("7400", ArchDefineName | ArchDefinePpcgr) + .Case("7450", ArchDefineName | ArchDefinePpcgr) + .Case("750", ArchDefineName | ArchDefinePpcgr) + .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | + ArchDefinePpcsq) + .Case("a2", ArchDefineA2) + .Case("a2q", ArchDefineName | ArchDefineA2 | ArchDefineA2q) + .Cases("power3", "pwr3", ArchDefinePpcgr) + .Cases("power4", "pwr4", + ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) + .Cases("power5", "pwr5", + ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | + ArchDefinePpcsq) + .Cases("power5x", "pwr5x", + ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | + ArchDefinePpcgr | ArchDefinePpcsq) + .Cases("power6", "pwr6", + ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | + ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) + .Cases("power6x", "pwr6x", + ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | + ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | + ArchDefinePpcsq) + .Cases("power7", "pwr7", + ArchDefinePwr7 | ArchDefinePwr6x | ArchDefinePwr6 | + ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | + ArchDefinePpcgr | ArchDefinePpcsq) + // powerpc64le automatically defaults to at least power8. + .Cases("power8", "pwr8", "ppc64le", + ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6x | + ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | + ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) + .Cases("power9", "pwr9", + ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | + ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | + ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | + ArchDefinePpcsq) + .Default(ArchDefineNone); + } return CPUKnown; } diff --git a/test/Driver/ppc-f128-support-check.c b/test/Driver/ppc-f128-support-check.c new file mode 100644 index 0000000000..2474890561 --- /dev/null +++ b/test/Driver/ppc-f128-support-check.c @@ -0,0 +1,20 @@ +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=power9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 + +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr8 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mcpu=pwr7 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 +// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ +// RUN: -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 + +#ifdef __FLOAT128__ +static_assert(false, "__float128 enabled"); +#endif + +// HASF128: __float128 enabled +// HASF128-NOT: option '-mfloat128' cannot be specified with +// NOF128: option '-mfloat128' cannot be specified with + diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c index 4adbcfce2e..6dedf26a24 100644 --- a/test/Preprocessor/init.c +++ b/test/Preprocessor/init.c @@ -6370,7 +6370,7 @@ // PPCPOWER9:#define _ARCH_PWR7 1 // PPCPOWER9:#define _ARCH_PWR9 1 // -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s // PPC-FLOAT128:#define __FLOAT128__ 1 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-LINUX %s diff --git a/test/Sema/float128-ld-incompatibility.cpp b/test/Sema/float128-ld-incompatibility.cpp index 13f5b6d5d1..369b14a87e 100644 --- a/test/Sema/float128-ld-incompatibility.cpp +++ b/test/Sema/float128-ld-incompatibility.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \ -// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 \ +// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 \ // RUN: -target-feature +float128 %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -Wno-parentheses %s -- GitLab From add093f497fe5510806fe5a81086198885995740 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Wed, 13 Jun 2018 16:45:12 +0000 Subject: [PATCH 0121/1023] [Basic] Fix -Wreorder warning Just use field initializers that don't suffer from this problem git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334619 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/PPC.h | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h index 70d0f1c2cd..d5ccdd1b11 100644 --- a/lib/Basic/Targets/PPC.h +++ b/lib/Basic/Targets/PPC.h @@ -49,33 +49,30 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { } ArchDefineTypes; - ArchDefineTypes ArchDefs; + ArchDefineTypes ArchDefs = ArchDefineNone; static const Builtin::Info BuiltinInfo[]; static const char *const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; std::string CPU; // Target cpu features. - bool HasAltivec; - bool HasVSX; - bool HasP8Vector; - bool HasP8Crypto; - bool HasDirectMove; - bool HasQPX; - bool HasHTM; - bool HasBPERMD; - bool HasExtDiv; - bool HasP9Vector; + bool HasAltivec = false; + bool HasVSX = false; + bool HasP8Vector = false; + bool HasP8Crypto = false; + bool HasDirectMove = false; + bool HasQPX = false; + bool HasHTM = false; + bool HasBPERMD = false; + bool HasExtDiv = false; + bool HasP9Vector = false; protected: std::string ABI; public: PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &) - : TargetInfo(Triple), HasAltivec(false), HasVSX(false), - HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), - HasQPX(false), HasHTM(false), HasBPERMD(false), HasExtDiv(false), - HasP9Vector(false), ArchDefs(ArchDefineNone) { + : TargetInfo(Triple) { SuitableAlign = 128; SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; -- GitLab From 4b0cada1baa6ea14bc9d253f0545c24c3f08a422 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 13 Jun 2018 17:54:52 +0000 Subject: [PATCH 0122/1023] [CodeGen] make nan builtins pure rather than const (PR37778) https://bugs.llvm.org/show_bug.cgi?id=37778 ...shows a miscompile resulting from marking nan builtins as 'const'. The nan libcalls/builtins take a pointer argument: http://www.cplusplus.com/reference/cmath/nan-function/ ...and the chars dereferenced by that arg are used to fill in the NaN constant payload bits. "const" means that the pointer argument isn't dereferenced. That's translated to "readnone" in LLVM. "pure" means that the pointer argument may be dereferenced. That's translated to "readonly" in LLVM. This change prevents the IR optimizer from killing the lead-up to the nan call here: double a() { char buf[4]; buf[0] = buf[1] = buf[2] = '9'; buf[3] = '\0'; return __builtin_nan(buf); } ...the optimizer isn't currently able to simplify this to a constant as we might hope, but this patch should solve the miscompile. Differential Revision: https://reviews.llvm.org/D48134 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334628 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 16 +++++++------- test/CodeGen/math-builtins.c | 36 +++++++++++++++++--------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 6f39c16302..dd0730f961 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -137,14 +137,14 @@ BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "ncF") -BUILTIN(__builtin_nanf, "fcC*" , "ncF") -BUILTIN(__builtin_nanl, "LdcC*", "ncF") -BUILTIN(__builtin_nanf128, "LLdcC*", "ncF") -BUILTIN(__builtin_nans, "dcC*" , "ncF") -BUILTIN(__builtin_nansf, "fcC*" , "ncF") -BUILTIN(__builtin_nansl, "LdcC*", "ncF") -BUILTIN(__builtin_nansf128, "LLdcC*", "ncF") +BUILTIN(__builtin_nan, "dcC*" , "FnU") +BUILTIN(__builtin_nanf, "fcC*" , "FnU") +BUILTIN(__builtin_nanl, "LdcC*", "FnU") +BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") +BUILTIN(__builtin_nans, "dcC*" , "FnU") +BUILTIN(__builtin_nansf, "fcC*" , "FnU") +BUILTIN(__builtin_nansl, "LdcC*", "FnU") +BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") diff --git a/test/CodeGen/math-builtins.c b/test/CodeGen/math-builtins.c index 4be8981ec3..82f049bdd1 100644 --- a/test/CodeGen/math-builtins.c +++ b/test/CodeGen/math-builtins.c @@ -90,25 +90,25 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c); -// NO__ERRNO: declare double @nan(i8*) [[READNONE]] -// NO__ERRNO: declare float @nanf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] -// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// NO__ERRNO: declare float @nanf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]] __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c); -// NO__ERRNO: declare double @nans(i8*) [[READNONE]] -// NO__ERRNO: declare float @nansf(i8*) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] -// HAS_ERRNO: declare double @nans(i8*) [[READNONE]] -// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] -// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] +// NO__ERRNO: declare double @nans(i8*) [[PURE]] +// NO__ERRNO: declare float @nansf(i8*) [[PURE]] +// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]] +// HAS_ERRNO: declare double @nans(i8*) [[PURE]] +// HAS_ERRNO: declare float @nansf(i8*) [[PURE]] +// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]] +// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]] __builtin_pow(f,f); __builtin_powf(f,f); __builtin_powl(f,f); @@ -188,7 +188,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // NO__ERRNO: declare double @cbrt(double) [[READNONE]] // NO__ERRNO: declare float @cbrtf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cbrt(double) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare float @cbrtf(float) [[READNONE]] // HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] @@ -581,9 +581,11 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -- GitLab From c162fd122637b96d175ca1a3039c461a56809dd1 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 13 Jun 2018 18:32:19 +0000 Subject: [PATCH 0123/1023] [analyzer] Fix offset overflow check in MemRegion rdar://39593879 https://bugs.llvm.org/show_bug.cgi?id=37142 Differential Revision: https://reviews.llvm.org/D48139 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/MemRegion.cpp | 50 +++++---------------------- test/Analysis/region_store_overflow.c | 7 +++- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 5dfe3c95b9..9507ea0e08 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -41,6 +41,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CheckedArithmetic.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -1181,38 +1182,8 @@ const SymbolicRegion *MemRegion::getSymbolicBase() const { return nullptr; } -/// Perform a given operation on two integers, return whether it overflows. -/// Optionally write the resulting output into \p Res. -static bool checkedOp( - int64_t LHS, - int64_t RHS, - std::function Op, - int64_t *Res = nullptr) { - llvm::APInt ALHS(/*BitSize=*/64, LHS, /*Signed=*/true); - llvm::APInt ARHS(/*BitSize=*/64, RHS, /*Signed=*/true); - bool Overflow; - llvm::APInt Out = Op(&ALHS, ARHS, Overflow); - if (!Overflow && Res) - *Res = Out.getSExtValue(); - return Overflow; -} - -static bool checkedAdd( - int64_t LHS, - int64_t RHS, - int64_t *Res=nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov, Res); -} - -static bool checkedMul( - int64_t LHS, - int64_t RHS, - int64_t *Res=nullptr) { - return checkedOp(LHS, RHS, &llvm::APInt::smul_ov, Res); -} - RegionRawOffset ElementRegion::getAsArrayOffset() const { - CharUnits offset = CharUnits::Zero(); + int64_t offset = 0; const ElementRegion *ER = this; const MemRegion *superR = nullptr; ASTContext &C = getContext(); @@ -1224,7 +1195,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { // FIXME: generalize to symbolic offsets. SVal index = ER->getIndex(); - if (Optional CI = index.getAs()) { + if (auto CI = index.getAs()) { // Update the offset. int64_t i = CI->getValue().getSExtValue(); @@ -1237,20 +1208,15 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { break; } - CharUnits size = C.getTypeSizeInChars(elemType); - - int64_t Mult; - bool Overflow = checkedAdd(i, size.getQuantity(), &Mult); - if (!Overflow) - Overflow = checkedMul(Mult, offset.getQuantity()); - if (Overflow) { + int64_t size = C.getTypeSizeInChars(elemType).getQuantity(); + if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) { + offset = *NewOffset; + } else { LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: " << "offset overflowing, returning unknown\n"); return nullptr; } - - offset += (i * size); } // Go to the next ElementRegion (if any). @@ -1262,7 +1228,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { } assert(superR && "super region cannot be NULL"); - return RegionRawOffset(superR, offset); + return RegionRawOffset(superR, CharUnits::fromQuantity(offset)); } /// Returns true if \p Base is an immediate base class of \p Child diff --git a/test/Analysis/region_store_overflow.c b/test/Analysis/region_store_overflow.c index 6401b83636..505965301b 100644 --- a/test/Analysis/region_store_overflow.c +++ b/test/Analysis/region_store_overflow.c @@ -1,6 +1,5 @@ // RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -verify %s -// expected-no-diagnostics int **h; int overflow_in_memregion(long j) { for (int l = 0;; ++l) { @@ -9,3 +8,9 @@ int overflow_in_memregion(long j) { } return 0; } + +void rdar39593879(long long *d) { + long e, f; + e = f = d[1]; // no-crash + for (; d[e];) f-- > 0; // expected-warning{{relational comparison result unused}}; +} -- GitLab From b23a0ab08abfaf3f7a49f0be4d023ad0758094f3 Mon Sep 17 00:00:00 2001 From: Mandeep Singh Grang Date: Wed, 13 Jun 2018 18:49:35 +0000 Subject: [PATCH 0124/1023] [COFF] Add ARM64 intrinsics: __yield, __wfe, __wfi, __sev, __sevl Summary: These intrinsics result in hint instructions. They are provided here for MSVC ARM64 compatibility. Reviewers: mstorsjo, compnerd, javed.absar Reviewed By: mstorsjo Subscribers: kristof.beyls, chrib, cfe-commits Differential Revision: https://reviews.llvm.org/D48132 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334639 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsAArch64.def | 6 ++++ lib/CodeGen/CGBuiltin.cpp | 5 ++++ test/CodeGen/arm64-microsoft-intrinsics.c | 35 +++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index f902accfa6..af336ae1f5 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -65,9 +65,15 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) // MSVC intrinsics for volatile but non-acquire/release loads and stores LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 9325839794..3c4184d8f3 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -6362,18 +6362,23 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, HintID = 0; break; case AArch64::BI__builtin_arm_yield: + case AArch64::BI__yield: HintID = 1; break; case AArch64::BI__builtin_arm_wfe: + case AArch64::BI__wfe: HintID = 2; break; case AArch64::BI__builtin_arm_wfi: + case AArch64::BI__wfi: HintID = 3; break; case AArch64::BI__builtin_arm_sev: + case AArch64::BI__sev: HintID = 4; break; case AArch64::BI__builtin_arm_sevl: + case AArch64::BI__sevl: HintID = 5; break; } diff --git a/test/CodeGen/arm64-microsoft-intrinsics.c b/test/CodeGen/arm64-microsoft-intrinsics.c index ff802e7f9b..2dbf1f9ea0 100644 --- a/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/test/CodeGen/arm64-microsoft-intrinsics.c @@ -24,3 +24,38 @@ void check__isb(void) { // CHECK-MSVC: @llvm.aarch64.isb(i32 0) // CHECK-LINUX: error: implicit declaration of function '__isb' + +void check__yield(void) { + __yield(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 1) +// CHECK-LINUX: error: implicit declaration of function '__yield' + +void check__wfe(void) { + __wfe(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 2) +// CHECK-LINUX: error: implicit declaration of function '__wfe' + +void check__wfi(void) { + __wfi(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 3) +// CHECK-LINUX: error: implicit declaration of function '__wfi' + +void check__sev(void) { + __sev(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 4) +// CHECK-LINUX: error: implicit declaration of function '__sev' + +void check__sevl(void) { + __sevl(); +} + +// CHECK-MSVC: @llvm.aarch64.hint(i32 5) +// CHECK-LINUX: error: implicit declaration of function '__sevl' -- GitLab From 95bd40ecc7abf3667f7b7f7768dce43839d879fb Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 13 Jun 2018 20:43:27 +0000 Subject: [PATCH 0125/1023] Implement constexpr __builtin_*_overflow As requested here:https://bugs.llvm.org/show_bug.cgi?id=37633 permit the __builtin_*_overflow builtins in constexpr functions. Differential Revision: https://reviews.llvm.org/D48040 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334650 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 118 +++++++++++++++++++++++++++++ test/SemaCXX/builtins-overflow.cpp | 84 ++++++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 590ebba997..028834e79b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -8155,6 +8155,124 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BIomp_is_initial_device: // We can decide statically which value the runtime would return if called. return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + case Builtin::BI__builtin_sadd_overflow: + case Builtin::BI__builtin_uadd_overflow: + case Builtin::BI__builtin_uaddl_overflow: + case Builtin::BI__builtin_uaddll_overflow: + case Builtin::BI__builtin_usub_overflow: + case Builtin::BI__builtin_usubl_overflow: + case Builtin::BI__builtin_usubll_overflow: + case Builtin::BI__builtin_umul_overflow: + case Builtin::BI__builtin_umull_overflow: + case Builtin::BI__builtin_umulll_overflow: + case Builtin::BI__builtin_saddl_overflow: + case Builtin::BI__builtin_saddll_overflow: + case Builtin::BI__builtin_ssub_overflow: + case Builtin::BI__builtin_ssubl_overflow: + case Builtin::BI__builtin_ssubll_overflow: + case Builtin::BI__builtin_smul_overflow: + case Builtin::BI__builtin_smull_overflow: + case Builtin::BI__builtin_smulll_overflow: { + LValue ResultLValue; + APSInt LHS, RHS; + + QualType ResultType = E->getArg(2)->getType()->getPointeeType(); + if (!EvaluateInteger(E->getArg(0), LHS, Info) || + !EvaluateInteger(E->getArg(1), RHS, Info) || + !EvaluatePointer(E->getArg(2), ResultLValue, Info)) + return false; + + APSInt Result; + bool DidOverflow = false; + + // If the types don't have to match, enlarge all 3 to the largest of them. + if (BuiltinOp == Builtin::BI__builtin_add_overflow || + BuiltinOp == Builtin::BI__builtin_sub_overflow || + BuiltinOp == Builtin::BI__builtin_mul_overflow) { + bool IsSigned = LHS.isSigned() || RHS.isSigned() || + ResultType->isSignedIntegerOrEnumerationType(); + bool AllSigned = LHS.isSigned() && RHS.isSigned() && + ResultType->isSignedIntegerOrEnumerationType(); + uint64_t LHSSize = LHS.getBitWidth(); + uint64_t RHSSize = RHS.getBitWidth(); + uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType); + uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); + + // Add an additional bit if the signedness isn't uniformly agreed to. We + // could do this ONLY if there is a signed and an unsigned that both have + // MaxBits, but the code to check that is pretty nasty. The issue will be + // caught in the shrink-to-result later anyway. + if (IsSigned && !AllSigned) + ++MaxBits; + + LHS = APSInt(IsSigned ? LHS.sextOrSelf(MaxBits) : LHS.zextOrSelf(MaxBits), + !IsSigned); + RHS = APSInt(IsSigned ? RHS.sextOrSelf(MaxBits) : RHS.zextOrSelf(MaxBits), + !IsSigned); + Result = APSInt(MaxBits, !IsSigned); + } + + // Find largest int. + switch (BuiltinOp) { + default: + llvm_unreachable("Invalid value for BuiltinOp"); + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sadd_overflow: + case Builtin::BI__builtin_saddl_overflow: + case Builtin::BI__builtin_saddll_overflow: + case Builtin::BI__builtin_uadd_overflow: + case Builtin::BI__builtin_uaddl_overflow: + case Builtin::BI__builtin_uaddll_overflow: + Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow) + : LHS.uadd_ov(RHS, DidOverflow); + break; + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_ssub_overflow: + case Builtin::BI__builtin_ssubl_overflow: + case Builtin::BI__builtin_ssubll_overflow: + case Builtin::BI__builtin_usub_overflow: + case Builtin::BI__builtin_usubl_overflow: + case Builtin::BI__builtin_usubll_overflow: + Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow) + : LHS.usub_ov(RHS, DidOverflow); + break; + case Builtin::BI__builtin_mul_overflow: + case Builtin::BI__builtin_smul_overflow: + case Builtin::BI__builtin_smull_overflow: + case Builtin::BI__builtin_smulll_overflow: + case Builtin::BI__builtin_umul_overflow: + case Builtin::BI__builtin_umull_overflow: + case Builtin::BI__builtin_umulll_overflow: + Result = LHS.isSigned() ? LHS.smul_ov(RHS, DidOverflow) + : LHS.umul_ov(RHS, DidOverflow); + break; + } + + // In the case where multiple sizes are allowed, truncate and see if + // the values are the same. + if (BuiltinOp == Builtin::BI__builtin_add_overflow || + BuiltinOp == Builtin::BI__builtin_sub_overflow || + BuiltinOp == Builtin::BI__builtin_mul_overflow) { + // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead, + // since it will give us the behavior of a TruncOrSelf in the case where + // its parameter <= its size. We previously set Result to be at least the + // type-size of the result, so getTypeSize(ResultType) <= Result.BitWidth + // will work exactly like TruncOrSelf. + APSInt Temp = Result.extOrTrunc(Info.Ctx.getTypeSize(ResultType)); + Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType()); + + if (!APSInt::isSameValue(Temp, Result)) + DidOverflow = true; + Result = Temp; + } + + APValue APV{Result}; + handleAssignment(Info, E, ResultLValue, ResultType, APV); + return Success(DidOverflow, E); + } } } diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp index 9054cce257..8cd28341e4 100644 --- a/test/SemaCXX/builtins-overflow.cpp +++ b/test/SemaCXX/builtins-overflow.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s // expected-no-diagnostics +#include + int a() { const int x = 3; static int z; @@ -13,3 +15,85 @@ int a2() { constexpr int *y = &z; return []() { return __builtin_sub_overflow(x, x, y); }(); } + +template +struct Result { + bool B; + T Value; + constexpr bool operator==(const Result &Other) { + return B == Other.B && Value == Other.Value; + } +}; + + +template +constexpr Result add(LHS &&lhs, RHS &&rhs) { + RET sum{}; + bool b = __builtin_add_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(add(static_cast(120), static_cast(10)) == Result{false, 130}); +static_assert(add(static_cast(120), static_cast(10)) == Result{true, -126}); +static_assert(add(INT_MAX, INT_MAX) == Result{false, static_cast(INT_MAX) * 2u}); +static_assert(add(static_cast(INT_MAX), 1u) == Result{true, INT_MIN}); + +static_assert(add(17, 22) == Result{false, 39}); +static_assert(add(INT_MAX - 22, 24) == Result{true, INT_MIN + 1}); +static_assert(add(INT_MIN + 22, -23) == Result{true, INT_MAX}); + +template +constexpr Result sub(LHS &&lhs, RHS &&rhs) { + RET sum{}; + bool b = __builtin_sub_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(sub(static_cast(0),static_cast(1)) == Result{true, UCHAR_MAX}); +static_assert(sub(static_cast(0),static_cast(1)) == Result{false, -1}); +static_assert(sub(static_cast(0),static_cast(1)) == Result{true, USHRT_MAX}); + +static_assert(sub(17,22) == Result{false, -5}); +static_assert(sub(INT_MAX - 22, -23) == Result{true, INT_MIN}); +static_assert(sub(INT_MIN + 22, 23) == Result{true, INT_MAX}); + +template +constexpr Result mul(LHS &&lhs, RHS &&rhs) { + RET sum{}; + bool b = __builtin_mul_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(mul(17,22) == Result{false, 374}); +static_assert(mul(INT_MAX / 22, 23) == Result{true, -2049870757}); +static_assert(mul(INT_MIN / 22, -23) == Result{true, -2049870757}); + +constexpr Result sadd(int lhs, int rhs) { + int sum{}; + bool b = __builtin_sadd_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(sadd(17,22) == Result{false, 39}); +static_assert(sadd(INT_MAX - 22, 23) == Result{true, INT_MIN}); +static_assert(sadd(INT_MIN + 22, -23) == Result{true, INT_MAX}); + +constexpr Result ssub(int lhs, int rhs) { + int sum{}; + bool b = __builtin_ssub_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(ssub(17,22) == Result{false, -5}); +static_assert(ssub(INT_MAX - 22, -23) == Result{true, INT_MIN}); +static_assert(ssub(INT_MIN + 22, 23) == Result{true, INT_MAX}); + +constexpr Result smul(int lhs, int rhs) { + int sum{}; + bool b = __builtin_smul_overflow(lhs, rhs, &sum); + return {b, sum}; +} + +static_assert(smul(17,22) == Result{false, 374}); +static_assert(smul(INT_MAX / 22, 23) == Result{true, -2049870757}); +static_assert(smul(INT_MIN / 22, -23) == Result{true, -2049870757}); -- GitLab From 54984ffdefff42ccd702cc99f91c5e37d08b4302 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 13 Jun 2018 20:47:12 +0000 Subject: [PATCH 0126/1023] Simplify test from r334650 No reason to have the 'bool' as an intermediary value, simply use the fact that curley braces enforce eval order. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334652 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/builtins-overflow.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/test/SemaCXX/builtins-overflow.cpp b/test/SemaCXX/builtins-overflow.cpp index 8cd28341e4..65733c0c15 100644 --- a/test/SemaCXX/builtins-overflow.cpp +++ b/test/SemaCXX/builtins-overflow.cpp @@ -29,8 +29,7 @@ struct Result { template constexpr Result add(LHS &&lhs, RHS &&rhs) { RET sum{}; - bool b = __builtin_add_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_add_overflow(lhs, rhs, &sum), sum}; } static_assert(add(static_cast(120), static_cast(10)) == Result{false, 130}); @@ -45,8 +44,7 @@ static_assert(add(INT_MIN + 22, -23) == Result{true, INT_MAX}); template constexpr Result sub(LHS &&lhs, RHS &&rhs) { RET sum{}; - bool b = __builtin_sub_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_sub_overflow(lhs, rhs, &sum), sum}; } static_assert(sub(static_cast(0),static_cast(1)) == Result{true, UCHAR_MAX}); @@ -60,8 +58,7 @@ static_assert(sub(INT_MIN + 22, 23) == Result{true, INT_MAX}); template constexpr Result mul(LHS &&lhs, RHS &&rhs) { RET sum{}; - bool b = __builtin_mul_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_mul_overflow(lhs, rhs, &sum), sum}; } static_assert(mul(17,22) == Result{false, 374}); @@ -70,8 +67,7 @@ static_assert(mul(INT_MIN / 22, -23) == Result{true, -2049870757}); constexpr Result sadd(int lhs, int rhs) { int sum{}; - bool b = __builtin_sadd_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_sadd_overflow(lhs, rhs, &sum), sum}; } static_assert(sadd(17,22) == Result{false, 39}); @@ -80,8 +76,7 @@ static_assert(sadd(INT_MIN + 22, -23) == Result{true, INT_MAX}); constexpr Result ssub(int lhs, int rhs) { int sum{}; - bool b = __builtin_ssub_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_ssub_overflow(lhs, rhs, &sum), sum}; } static_assert(ssub(17,22) == Result{false, -5}); @@ -90,8 +85,7 @@ static_assert(ssub(INT_MIN + 22, 23) == Result{true, INT_MAX}); constexpr Result smul(int lhs, int rhs) { int sum{}; - bool b = __builtin_smul_overflow(lhs, rhs, &sum); - return {b, sum}; + return {__builtin_smul_overflow(lhs, rhs, &sum), sum}; } static_assert(smul(17,22) == Result{false, 374}); -- GitLab From d23eb76fcccaf326c6b869b8ea69153df610d0c1 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 13 Jun 2018 23:18:26 +0000 Subject: [PATCH 0127/1023] docs: Correct some misstatements in the control flow integrity docs. These were true at one point but haven't been true for a long time. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334669 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ControlFlowIntegrity.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index 35b03a0e63..5e837db731 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -104,10 +104,10 @@ dynamic type; that is, the dynamic type of the called object must be a derived class of the static type of the object used to make the call. This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``. -For this scheme to work, all translation units containing the definition -of a virtual member function (whether inline or not), other than members -of :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-vcall`` enabled and be statically linked into the program. +For this scheme to work, all translation units containing the definition of +a virtual member function (whether inline or not), other than members of +:ref:`blacklisted ` types, must be compiled with ``-flto`` +or ``-flto=thin`` enabled and be statically linked into the program. Performance ----------- @@ -152,9 +152,9 @@ functions may be :ref:`blacklisted `. For this scheme to work, all translation units containing the definition of a virtual member function (whether inline or not), other than members -of :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-derived-cast`` or ``-fsanitize=cfi-unrelated-cast`` enabled -and be statically linked into the program. +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. Non-Virtual Member Function Call Checking ========================================= @@ -168,8 +168,9 @@ polymorphic class type. This CFI scheme can be enabled on its own using For this scheme to work, all translation units containing the definition of a virtual member function (whether inline or not), other than members -of :ref:`blacklisted ` types, must be compiled with -``-fsanitize=cfi-nvcall`` enabled and be statically linked into the program. +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. .. _cfi-strictness: -- GitLab From ccfb6ba23ab4ecfa58c1f0abf126b588b048580a Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 13 Jun 2018 23:21:02 +0000 Subject: [PATCH 0128/1023] docs: Add a missing LTO visibility reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334671 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ControlFlowIntegrity.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index 5e837db731..6b397befdd 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -104,10 +104,11 @@ dynamic type; that is, the dynamic type of the called object must be a derived class of the static type of the object used to make the call. This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``. -For this scheme to work, all translation units containing the definition of -a virtual member function (whether inline or not), other than members of -:ref:`blacklisted ` types, must be compiled with ``-flto`` -or ``-flto=thin`` enabled and be statically linked into the program. +For this scheme to work, all translation units containing the definition +of a virtual member function (whether inline or not), other than members +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. Performance ----------- -- GitLab From 1ac05da6ec0f2d100e0889a333a3258c2afa1545 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 14 Jun 2018 00:03:41 +0000 Subject: [PATCH 0129/1023] Driver: De-duplicate some code. NFCI. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334673 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index d392f68897..a5943de993 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3501,8 +3501,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); - if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as, - IsIntegratedAssemblerDefault)) + if (!getToolChain().useIntegratedAs()) CmdArgs.push_back("-no-integrated-as"); if (Args.hasArg(options::OPT_fdebug_pass_structure)) { -- GitLab From b878dfda35d801834e4d97f3088b51b86acc73e2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 14 Jun 2018 00:05:28 +0000 Subject: [PATCH 0130/1023] [www] Update cxx_status page for Rapperswil motions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334674 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/cxx_status.html | 51 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/www/cxx_status.html b/www/cxx_status.html index 63dc13ee33..dfd05575e3 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -844,10 +844,14 @@ as the draft C++2a standard evolves. Clang 6 - __VA_OPT__ for preprocessor comma elision + __VA_OPT__ for preprocessor comma elision P0306R4 Clang 6 + + P1042R1 + Partial + Designated initializers P0329R4 @@ -883,13 +887,16 @@ as the draft C++2a standard evolves. No - Consistent comparison (operator<=>) + Consistent comparison (operator<=>) P0515R3 - Partial + Partial P0905R1 + + P1120R0 + Access checking on specializations P0692R1 @@ -926,6 +933,42 @@ as the draft C++2a standard evolves. P0780R2 No + + + Class types as non-type template parameters + P0732R2 + No + + + Destroying operator delete + P0722R3 + Clang 6 + + + Virtual function calls in constant expressions + P1064R0 + No + + + Prohibit aggregates with user-declared constructors + P1008R1 + No + + + Contracts + P0542R5 + No + + + Feature test macros + P0941R2 + (see below) + + + explicit(bool) + P0892R2 + No + @@ -958,7 +1001,7 @@ and library features that are not part of standard C++.

Compiler flag Available in Clang? - + SD-6: SG10 feature test recommendations SD-6 N/A -- GitLab From 7652941f0aa0811a7ac205a74d3413a4e1ae08a4 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 14 Jun 2018 00:40:20 +0000 Subject: [PATCH 0131/1023] P0096R5, P0941R2: Update to match latest feature test macro specification. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334677 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Frontend/InitPreprocessor.cpp | 102 ++++++++++++++++-------------- test/Lexer/cxx-features.cpp | 31 ++++++--- www/cxx_status.html | 25 +++++--- 3 files changed, 91 insertions(+), 67 deletions(-) diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 6fbc810ca5..e3f4f92b9d 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -487,82 +487,86 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, MacroBuilder &Builder) { // C++98 features. if (LangOpts.RTTI) - Builder.defineMacro("__cpp_rtti", "199711"); + Builder.defineMacro("__cpp_rtti", "199711L"); if (LangOpts.CXXExceptions) - Builder.defineMacro("__cpp_exceptions", "199711"); + Builder.defineMacro("__cpp_exceptions", "199711L"); // C++11 features. if (LangOpts.CPlusPlus11) { - Builder.defineMacro("__cpp_unicode_characters", "200704"); - Builder.defineMacro("__cpp_raw_strings", "200710"); - Builder.defineMacro("__cpp_unicode_literals", "200710"); - Builder.defineMacro("__cpp_user_defined_literals", "200809"); - Builder.defineMacro("__cpp_lambdas", "200907"); + Builder.defineMacro("__cpp_unicode_characters", "200704L"); + Builder.defineMacro("__cpp_raw_strings", "200710L"); + Builder.defineMacro("__cpp_unicode_literals", "200710L"); + Builder.defineMacro("__cpp_user_defined_literals", "200809L"); + Builder.defineMacro("__cpp_lambdas", "200907L"); Builder.defineMacro("__cpp_constexpr", - LangOpts.CPlusPlus17 ? "201603" : - LangOpts.CPlusPlus14 ? "201304" : "200704"); + LangOpts.CPlusPlus17 ? "201603L" : + LangOpts.CPlusPlus14 ? "201304L" : "200704"); Builder.defineMacro("__cpp_range_based_for", - LangOpts.CPlusPlus17 ? "201603" : "200907"); + LangOpts.CPlusPlus17 ? "201603L" : "200907"); Builder.defineMacro("__cpp_static_assert", - LangOpts.CPlusPlus17 ? "201411" : "200410"); - Builder.defineMacro("__cpp_decltype", "200707"); - Builder.defineMacro("__cpp_attributes", "200809"); - Builder.defineMacro("__cpp_rvalue_references", "200610"); - Builder.defineMacro("__cpp_variadic_templates", "200704"); - Builder.defineMacro("__cpp_initializer_lists", "200806"); - Builder.defineMacro("__cpp_delegating_constructors", "200604"); - Builder.defineMacro("__cpp_nsdmi", "200809"); - Builder.defineMacro("__cpp_inheriting_constructors", "201511"); - Builder.defineMacro("__cpp_ref_qualifiers", "200710"); - Builder.defineMacro("__cpp_alias_templates", "200704"); + LangOpts.CPlusPlus17 ? "201411L" : "200410"); + Builder.defineMacro("__cpp_decltype", "200707L"); + Builder.defineMacro("__cpp_attributes", "200809L"); + Builder.defineMacro("__cpp_rvalue_references", "200610L"); + Builder.defineMacro("__cpp_variadic_templates", "200704L"); + Builder.defineMacro("__cpp_initializer_lists", "200806L"); + Builder.defineMacro("__cpp_delegating_constructors", "200604L"); + Builder.defineMacro("__cpp_nsdmi", "200809L"); + Builder.defineMacro("__cpp_inheriting_constructors", "201511L"); + Builder.defineMacro("__cpp_ref_qualifiers", "200710L"); + Builder.defineMacro("__cpp_alias_templates", "200704L"); } if (LangOpts.ThreadsafeStatics) - Builder.defineMacro("__cpp_threadsafe_static_init", "200806"); + Builder.defineMacro("__cpp_threadsafe_static_init", "200806L"); // C++14 features. if (LangOpts.CPlusPlus14) { - Builder.defineMacro("__cpp_binary_literals", "201304"); - Builder.defineMacro("__cpp_digit_separators", "201309"); - Builder.defineMacro("__cpp_init_captures", "201304"); - Builder.defineMacro("__cpp_generic_lambdas", "201304"); - Builder.defineMacro("__cpp_decltype_auto", "201304"); - Builder.defineMacro("__cpp_return_type_deduction", "201304"); - Builder.defineMacro("__cpp_aggregate_nsdmi", "201304"); - Builder.defineMacro("__cpp_variable_templates", "201304"); + Builder.defineMacro("__cpp_binary_literals", "201304L"); + Builder.defineMacro("__cpp_digit_separators", "201309L"); + Builder.defineMacro("__cpp_init_captures", "201304L"); + Builder.defineMacro("__cpp_generic_lambdas", "201304L"); + Builder.defineMacro("__cpp_decltype_auto", "201304L"); + Builder.defineMacro("__cpp_return_type_deduction", "201304L"); + Builder.defineMacro("__cpp_aggregate_nsdmi", "201304L"); + Builder.defineMacro("__cpp_variable_templates", "201304L"); } if (LangOpts.SizedDeallocation) - Builder.defineMacro("__cpp_sized_deallocation", "201309"); + Builder.defineMacro("__cpp_sized_deallocation", "201309L"); // C++17 features. if (LangOpts.CPlusPlus17) { - Builder.defineMacro("__cpp_hex_float", "201603"); - Builder.defineMacro("__cpp_inline_variables", "201606"); - Builder.defineMacro("__cpp_noexcept_function_type", "201510"); - Builder.defineMacro("__cpp_capture_star_this", "201603"); - Builder.defineMacro("__cpp_if_constexpr", "201606"); - Builder.defineMacro("__cpp_deduction_guides", "201703"); - Builder.defineMacro("__cpp_template_auto", "201606"); - Builder.defineMacro("__cpp_namespace_attributes", "201411"); - Builder.defineMacro("__cpp_enumerator_attributes", "201411"); - Builder.defineMacro("__cpp_nested_namespace_definitions", "201411"); - Builder.defineMacro("__cpp_variadic_using", "201611"); - Builder.defineMacro("__cpp_aggregate_bases", "201603"); - Builder.defineMacro("__cpp_structured_bindings", "201606"); - Builder.defineMacro("__cpp_nontype_template_args", "201411"); - Builder.defineMacro("__cpp_fold_expressions", "201603"); + Builder.defineMacro("__cpp_hex_float", "201603L"); + Builder.defineMacro("__cpp_inline_variables", "201606L"); + Builder.defineMacro("__cpp_noexcept_function_type", "201510L"); + Builder.defineMacro("__cpp_capture_star_this", "201603L"); + Builder.defineMacro("__cpp_if_constexpr", "201606L"); + Builder.defineMacro("__cpp_deduction_guides", "201703L"); + Builder.defineMacro("__cpp_template_auto", "201606L"); // (old name) + Builder.defineMacro("__cpp_namespace_attributes", "201411L"); + Builder.defineMacro("__cpp_enumerator_attributes", "201411L"); + Builder.defineMacro("__cpp_nested_namespace_definitions", "201411L"); + Builder.defineMacro("__cpp_variadic_using", "201611L"); + Builder.defineMacro("__cpp_aggregate_bases", "201603L"); + Builder.defineMacro("__cpp_structured_bindings", "201606L"); + Builder.defineMacro("__cpp_nontype_template_args", "201411L"); + Builder.defineMacro("__cpp_fold_expressions", "201603L"); + Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L"); + Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L"); } if (LangOpts.AlignedAllocation) - Builder.defineMacro("__cpp_aligned_new", "201606"); + Builder.defineMacro("__cpp_aligned_new", "201606L"); + if (LangOpts.RelaxedTemplateTemplateArgs) + Builder.defineMacro("__cpp_template_template_args", "201611L"); // TS features. if (LangOpts.ConceptsTS) - Builder.defineMacro("__cpp_experimental_concepts", "1"); + Builder.defineMacro("__cpp_experimental_concepts", "1L"); if (LangOpts.CoroutinesTS) Builder.defineMacro("__cpp_coroutines", "201703L"); // Potential future breaking changes. if (LangOpts.Char8) - Builder.defineMacro("__cpp_char8_t", "201803"); + Builder.defineMacro("__cpp_char8_t", "201803L"); } static void InitializePredefinedMacros(const TargetInfo &TI, diff --git a/test/Lexer/cxx-features.cpp b/test/Lexer/cxx-features.cpp index a0058511eb..772fa26e96 100644 --- a/test/Lexer/cxx-features.cpp +++ b/test/Lexer/cxx-features.cpp @@ -1,9 +1,11 @@ // RUN: %clang_cc1 -std=c++98 -fcxx-exceptions -verify %s // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -verify %s -// RUN: %clang_cc1 -std=c++1y -fcxx-exceptions -fsized-deallocation -verify %s // RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -verify %s +// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fsized-deallocation -verify %s +// +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -frelaxed-template-template-args -DRELAXED_TEMPLATE_TEMPLATE_ARGS=1 -verify %s +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s // RUN: %clang_cc1 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS -fsized-deallocation // RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify -fsized-deallocation %s // RUN: %clang_cc1 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify -fsized-deallocation %s @@ -12,13 +14,13 @@ // FIXME using `defined` in a macro has undefined behavior. #if __cplusplus < 201103L -#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98 +#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98 #elif __cplusplus < 201402L -#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11 +#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11 #elif __cplusplus < 201406L -#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14 +#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14 #else -#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z +#define check(macro, cxx98, cxx11, cxx14, cxx17) cxx17 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx17 #endif // --- C++17 features --- @@ -35,6 +37,10 @@ #error "wrong value for __cpp_aligned_new" #endif +#if check(guaranteed_copy_elision, 0, 0, 0, 201606) +#error "wrong value for __cpp_guaranteed_copy_elision" +#endif + #if check(noexcept_function_type, 0, 0, 0, 201510) #error "wrong value for __cpp_noexcept_function_type" #endif @@ -61,6 +67,12 @@ #error "wrong value for __cpp_deduction_guides" #endif +#if check(nontype_template_parameter_auto, 0, 0, 0, 201606) +#error "wrong value for __cpp_nontype_template_parameter_auto" +#endif + +// This is the old name (from P0096R4) for +// __cpp_nontype_template_parameter_auto #if check(template_auto, 0, 0, 0, 201606) #error "wrong value for __cpp_template_auto" #endif @@ -75,6 +87,7 @@ #error "wrong value for __cpp_enumerator_attributes" #endif +// This is an old name (from P0096R4), now removed from SD-6. #if check(nested_namespace_definitions, 0, 0, 0, 201411) #error "wrong value for __cpp_nested_namespace_definitions" #endif @@ -97,7 +110,9 @@ #error "wrong value for __cpp_nontype_template_args" #endif -#if check(template_template_args, 0, 0, 0, 0) // FIXME: should be 201611 when feature is enabled +#if defined(RELAXED_TEMPLATE_TEMPLATE_ARGS) \ + ? check(template_template_args, 0, 0, 0, 201611) \ + : check(template_template_args, 0, 0, 0, 0) #error "wrong value for __cpp_template_template_args" #endif diff --git a/www/cxx_status.html b/www/cxx_status.html index dfd05575e3..b935e72186 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -962,7 +962,7 @@ as the draft C++2a standard evolves. Feature test macros P0941R2 - (see below) + (see below) explicit(bool) @@ -1002,9 +1002,9 @@ and library features that are not part of standard C++.

Available in Clang? - SD-6: SG10 feature test recommendations - SD-6 - N/A + SD-6: SG10 feature test recommendations + SD-6 + N/A Clang 3.4 (N3745)
@@ -1024,6 +1024,11 @@ and library features that are not part of standard C++.

Clang 5 (P0096R4) + + + SVN (P0096R5) + + y + // / + // A-->iptr->(int value) + // \ + // ->bptr + // + // From this we'll construct a vector of fieldchains, where each fieldchain + // represents an uninitialized field. An uninitialized field may be a + // primitive object, a member pointer, a pointer, a pointee or a union without + // a single initialized field. + // In the above example, for the default constructor call we'll end up with + // these fieldchains: + // + // this->b.x + // this->iptr (pointee uninit) + // this->bptr (pointer uninit) + // + // We'll traverse each node of the above graph with the appropiate one of + // these methods: + + /// This method checks a region of a union object, and returns true if no + /// field is initialized within the region. + bool isUnionUninit(const TypedValueRegion *R); + + /// This method checks a region of a non-union object, and returns true if + /// an uninitialized field is found within the region. + bool isNonUnionUninit(const TypedValueRegion *R, FieldChainInfo LocalChain); + + /// This method checks a region of a pointer or reference object, and returns + /// true if the ptr/ref object itself or any field within the pointee's region + /// is uninitialized. + bool isPointerOrReferenceUninit(const FieldRegion *FR, + FieldChainInfo LocalChain); + + /// This method checks a region of MemberPointerType, and returns true if the + /// the pointer is uninitialized. + bool isMemberPointerUninit(const FieldRegion *FR, FieldChainInfo LocalChain); + + /// This method returns true if the value of a primitive object is + /// uninitialized. + bool isPrimitiveUninit(const SVal &V); + + // Note that we don't have a method for arrays -- the elements of an array are + // often left uninitialized intentionally even when it is of a C++ record + // type, so we'll assume that an array is always initialized. + // TODO: Add a support for nonloc::LocAsInteger. +}; + +// Utility function declarations. + +/// Returns the object that was constructed by CtorDecl, or None if that isn't +/// possible. +Optional +getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context); + +/// Checks whether the constructor under checking is called by another +/// constructor. +bool isCalledByConstructor(const CheckerContext &Context); + +/// Returns whether FD can be (transitively) dereferenced to a void pointer type +/// (void*, void**, ...). The type of the region behind a void pointer isn't +/// known, and thus FD can not be analyzed. +bool isVoidPointer(const FieldDecl *FD); + +/// Returns true if T is a primitive type. We'll call a type primitive if it's +/// either a BuiltinType or an EnumeralType. +bool isPrimitiveType(const QualType &T) { + return T->isBuiltinType() || T->isEnumeralType(); +} + +} // end of anonymous namespace + +//===----------------------------------------------------------------------===// +// Methods for UninitializedObjectChecker. +//===----------------------------------------------------------------------===// + +void UninitializedObjectChecker::checkEndFunction( + CheckerContext &Context) const { + + const auto *CtorDecl = dyn_cast_or_null( + Context.getLocationContext()->getDecl()); + if (!CtorDecl) + return; + + if (!CtorDecl->isUserProvided()) + return; + + if (CtorDecl->getParent()->isUnion()) + return; + + // This avoids essentially the same error being reported multiple times. + if (isCalledByConstructor(Context)) + return; + + Optional Object = getObjectVal(CtorDecl, Context); + if (!Object) + return; + + FindUninitializedFields F(Context.getState(), Object->getRegion(), + IsPedantic); + + const UninitFieldSet &UninitFields = F.getUninitFields(); + + if (UninitFields.empty()) + return; + + // There are uninitialized fields in the record. + + ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState()); + if (!Node) + return; + + PathDiagnosticLocation LocUsedForUniqueing; + const Stmt *CallSite = Context.getStackFrame()->getCallSite(); + if (CallSite) + LocUsedForUniqueing = PathDiagnosticLocation::createBegin( + CallSite, Context.getSourceManager(), Node->getLocationContext()); + + SmallString<100> WarningBuf; + llvm::raw_svector_ostream WarningOS(WarningBuf); + WarningOS << UninitFields.size() << " uninitialized field" + << (UninitFields.size() == 1 ? "" : "s") + << " at the end of the constructor call"; + + auto Report = llvm::make_unique( + *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing, + Node->getLocationContext()->getDecl()); + + // TODO: As of now, one warning is emitted per constructor call, and the + // uninitialized fields are listed in notes. Until there's a better support + // for notes avaible, a note-less version of this checker should be + // implemented. + for (const auto &FieldChain : UninitFields) { + SmallString<200> NoteBuf; + llvm::raw_svector_ostream NoteOS(NoteBuf); + + if (FieldChain.isPointer()) { + if (FieldChain.isDereferenced()) + NoteOS << "uninitialized pointee 'this->"; + else + NoteOS << "uninitialized pointer 'this->"; + } else + NoteOS << "uninitialized field 'this->"; + FieldChain.print(NoteOS); + NoteOS << "'"; + + Report->addNote(NoteOS.str(), + PathDiagnosticLocation::create(FieldChain.getEndOfChain(), + Context.getSourceManager())); + } + + Context.emitReport(std::move(Report)); +} + +//===----------------------------------------------------------------------===// +// Methods for FindUninitializedFields. +//===----------------------------------------------------------------------===// + +FindUninitializedFields::FindUninitializedFields( + ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic) + : State(State), ObjectR(R), IsPedantic(IsPedantic) {} + +const UninitFieldSet &FindUninitializedFields::getUninitFields() { + isNonUnionUninit(ObjectR, FieldChainInfo()); + + if (!IsPedantic && !IsAnyFieldInitialized) + UninitFields.clear(); + + return UninitFields; +} + +bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) { + if (State->getStateManager().getContext().getSourceManager().isInSystemHeader( + Chain.getEndOfChain()->getLocation())) + return false; + + return UninitFields.insert(Chain).second; +} + +bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, + FieldChainInfo LocalChain) { + assert(R->getValueType()->isRecordType() && + !R->getValueType()->isUnionType() && + "This method only checks non-union record objects!"); + + const RecordDecl *RD = + R->getValueType()->getAs()->getDecl()->getDefinition(); + assert(RD && "Referred record has no definition"); + + bool ContainsUninitField = false; + + // Are all of this non-union's fields initialized? + for (const FieldDecl *I : RD->fields()) { + + const auto FieldVal = + State->getLValue(I, loc::MemRegionVal(R)).castAs(); + const auto *FR = FieldVal.getRegionAs(); + QualType T = I->getType(); + + // If LocalChain already contains FR, then we encountered a cyclic + // reference. In this case, region FR is already under checking at an + // earlier node in the directed tree. + if (LocalChain.contains(FR)) + return false; + + if (T->isStructureOrClassType()) { + if (isNonUnionUninit(FR, {LocalChain, FR})) + ContainsUninitField = true; + continue; + } + + if (T->isUnionType()) { + if (isUnionUninit(FR)) { + if (addFieldToUninits({LocalChain, FR})) + ContainsUninitField = true; + } else + IsAnyFieldInitialized = true; + continue; + } + + if (T->isArrayType()) { + IsAnyFieldInitialized = true; + continue; + } + + if (T->isMemberPointerType()) { + if (isMemberPointerUninit(FR, LocalChain)) + ContainsUninitField = true; + continue; + } + + // If this is a pointer or reference type. + if (T->isPointerType() || T->isReferenceType()) { + if (isPointerOrReferenceUninit(FR, LocalChain)) + ContainsUninitField = true; + continue; + } + + assert(isPrimitiveType(T) && "Non-primitive type! " + "At this point FR must be primitive!"); + + SVal V = State->getSVal(FieldVal); + + if (isPrimitiveUninit(V)) { + if (addFieldToUninits({LocalChain, FR})) + ContainsUninitField = true; + } + } + + // Checking bases. + // FIXME: As of now, because of `isCalledByConstructor`, objects whose type + // is a descendant of another type will emit warnings for uninitalized + // inherited members. + // This is not the only way to analyze bases of an object -- if we didn't + // filter them out, and didn't analyze the bases, this checker would run for + // each base of the object in order of base initailization and in theory would + // find every uninitalized field. This approach could also make handling + // diamond inheritances more easily. + // + // This rule (that a descendant type's cunstructor is responsible for + // initializing inherited data members) is not obvious, and should it should + // be. + const auto *CXXRD = dyn_cast(RD); + if (!CXXRD) + return ContainsUninitField; + + for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) { + const auto *BaseRegion = State->getLValue(BaseSpec, R) + .castAs() + .getRegionAs(); + + if (isNonUnionUninit(BaseRegion, LocalChain)) + ContainsUninitField = true; + } + + return ContainsUninitField; +} + +bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) { + assert(R->getValueType()->isUnionType() && + "This method only checks union objects!"); + // TODO: Implement support for union fields. + return false; +} + +// Note that pointers/references don't contain fields themselves, so in this +// function we won't add anything to LocalChain. +bool FindUninitializedFields::isPointerOrReferenceUninit( + const FieldRegion *FR, FieldChainInfo LocalChain) { + + assert((FR->getDecl()->getType()->isPointerType() || + FR->getDecl()->getType()->isReferenceType()) && + "This method only checks pointer/reference objects!"); + + SVal V = State->getSVal(FR); + + if (V.isUnknown() || V.isZeroConstant()) { + IsAnyFieldInitialized = true; + return false; + } + + if (V.isUndef()) { + return addFieldToUninits({LocalChain, FR}); + } + + const FieldDecl *FD = FR->getDecl(); + + // TODO: The dynamic type of a void pointer may be retrieved with + // `getDynamicTypeInfo`. + if (isVoidPointer(FD)) { + IsAnyFieldInitialized = true; + return false; + } + + assert(V.getAs() && "V should be Loc at this point!"); + + // At this point the pointer itself is initialized and points to a valid + // location, we'll now check the pointee. + SVal DerefdV = State->getSVal(V.castAs()); + + // TODO: Dereferencing should be done according to the dynamic type. + while (Optional L = DerefdV.getAs()) { + DerefdV = State->getSVal(*L); + } + + // If V is a pointer pointing to a record type. + if (Optional RecordV = + DerefdV.getAs()) { + + const TypedValueRegion *R = RecordV->getRegion(); + + // We can't reason about symbolic regions, assume its initialized. + // Note that this also avoids a potential infinite recursion, because + // constructors for list-like classes are checked without being called, and + // the Static Analyzer will construct a symbolic region for Node *next; or + // similar code snippets. + if (R->getSymbolicBase()) { + IsAnyFieldInitialized = true; + return false; + } + + const QualType T = R->getValueType(); + + if (T->isStructureOrClassType()) + return isNonUnionUninit(R, {LocalChain, FR}); + + if (T->isUnionType()) { + if (isUnionUninit(R)) { + return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); + } else { + IsAnyFieldInitialized = true; + return false; + } + } + + if (T->isArrayType()) { + IsAnyFieldInitialized = true; + return false; + } + + llvm_unreachable("All cases are handled!"); + } + + // TODO: If possible, it should be asserted that the DerefdV at this point is + // primitive. + + if (isPrimitiveUninit(DerefdV)) + return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); + + IsAnyFieldInitialized = true; + return false; +} + +bool FindUninitializedFields::isMemberPointerUninit(const FieldRegion *FR, + FieldChainInfo LocalChain) { + assert(FR->getDecl()->getType()->isMemberPointerType() && + "This function only checks regions that hold MemberPointerTypes!"); + // TODO: Implement support for MemberPointerTypes. + return false; +} + +bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) { + if (V.isUndef()) + return true; + + IsAnyFieldInitialized = true; + return false; +} + +//===----------------------------------------------------------------------===// +// Methods for FieldChainInfo. +//===----------------------------------------------------------------------===// + +FieldChainInfo::FieldChainInfo(const FieldChainInfo &Other, + const FieldRegion *FR, const bool IsDereferenced) + : FieldChainInfo(Other, IsDereferenced) { + assert(!contains(FR) && "Can't add a field that is already a part of the " + "fieldchain! Is this a cyclic reference?"); + Chain = Factory.add(FR, Other.Chain); +} + +bool FieldChainInfo::isPointer() const { + assert(!Chain.isEmpty() && "Empty fieldchain!"); + return (*Chain.begin())->getDecl()->getType()->isPointerType(); +} + +bool FieldChainInfo::isDereferenced() const { + assert(isPointer() && "Only pointers may or may not be dereferenced!"); + return IsDereferenced; +} + +const FieldDecl *FieldChainInfo::getEndOfChain() const { + assert(!Chain.isEmpty() && "Empty fieldchain!"); + return (*Chain.begin())->getDecl(); +} + +// TODO: This function constructs an incorrect fieldchain string in the +// following case: +// +// struct Base { int x; }; +// struct D1 : Base {}; struct D2 : Base {}; +// +// struct MostDerived : D1, D2 { +// MostDerived() {} +// } +// +// A call to MostDerived::MostDerived() will cause two notes that say +// "uninitialized field 'this->x'", but we can't refer to 'x' directly, +// we need an explicit namespace resolution whether the uninit field was +// 'D1::x' or 'D2::x'. +// +// TODO: If a field in the fieldchain is a captured lambda parameter, this +// function constructs an empty string for it: +// +// template struct A { +// Callable c; +// A(const Callable &c, int) : c(c) {} +// }; +// +// int b; // say that this isn't zero initialized +// auto alwaysTrue = [&b](int a) { return true; }; +// +// A call with these parameters: A::A(alwaysTrue, int()) +// will emit a note with the message "uninitialized field: 'this->c.'". If +// possible, the lambda parameter name should be retrieved or be replaced with a +// "" or something similar. +void FieldChainInfo::print(llvm::raw_ostream &Out) const { + if (Chain.isEmpty()) + return; + + const llvm::ImmutableListImpl *L = + Chain.getInternalPointer(); + printTail(Out, L->getTail()); + Out << L->getHead()->getDecl()->getNameAsString(); +} + +void FieldChainInfo::printTail( + llvm::raw_ostream &Out, + const llvm::ImmutableListImpl *L) { + if (!L) + return; + + printTail(Out, L->getTail()); + const FieldDecl *Field = L->getHead()->getDecl(); + Out << Field->getNameAsString(); + Out << (Field->getType()->isPointerType() ? "->" : "."); +} + +//===----------------------------------------------------------------------===// +// Utility functions. +//===----------------------------------------------------------------------===// + +namespace { + +bool isVoidPointer(const FieldDecl *FD) { + QualType T = FD->getType(); + + while (!T.isNull()) { + if (T->isVoidPointerType()) + return true; + T = T->getPointeeType(); + } + return false; +} + +Optional +getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) { + + Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(), + Context.getStackFrame()); + // Getting the value for 'this'. + SVal This = Context.getState()->getSVal(ThisLoc); + + // Getting the value for '*this'. + SVal Object = Context.getState()->getSVal(This.castAs()); + + return Object.getAs(); +} + +// TODO: We should also check that if the constructor was called by another +// constructor, whether those two are in any relation to one another. In it's +// current state, this introduces some false negatives. +bool isCalledByConstructor(const CheckerContext &Context) { + const LocationContext *LC = Context.getLocationContext()->getParent(); + + while (LC) { + if (isa(LC->getDecl())) + return true; + + LC = LC->getParent(); + } + return false; +} + +} // end of anonymous namespace + +void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { + auto Chk = Mgr.registerChecker(); + Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption( + "Pedantic", /*DefaultVal*/ false, Chk); +} diff --git a/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h b/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h new file mode 100644 index 0000000000..2397824fc9 --- /dev/null +++ b/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h @@ -0,0 +1,18 @@ +// Like the compiler, the static analyzer treats some functions differently if +// they come from a system header -- for example, it is assumed that system +// functions do not arbitrarily free() their parameters, and that some bugs +// found in system headers cannot be fixed by the user and should be +// suppressed. + +#pragma clang system_header + +struct RecordInSystemHeader { + int a; + int b; +}; + +template +struct ContainerInSystemHeader { + T &t; + ContainerInSystemHeader(T& t) : t(t) {} +}; diff --git a/test/Analysis/cxx-uninitialized-object-inheritance.cpp b/test/Analysis/cxx-uninitialized-object-inheritance.cpp new file mode 100644 index 0000000000..3b048b759e --- /dev/null +++ b/test/Analysis/cxx-uninitialized-object-inheritance.cpp @@ -0,0 +1,775 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -verify %s + +//===----------------------------------------------------------------------===// +// Non-polymorphic inheritance tests +//===----------------------------------------------------------------------===// + +class NonPolymorphicLeft1 { + int x; + +protected: + int y; + +public: + NonPolymorphicLeft1() = default; + NonPolymorphicLeft1(int) : x(1) {} +}; + +class NonPolymorphicInheritanceTest1 : public NonPolymorphicLeft1 { + int z; + +public: + NonPolymorphicInheritanceTest1() + : NonPolymorphicLeft1(int{}) { + y = 2; + z = 3; + // All good! + } +}; + +void fNonPolymorphicInheritanceTest1() { + NonPolymorphicInheritanceTest1(); +} + +class NonPolymorphicBaseClass2 { + int x; // expected-note{{uninitialized field 'this->x'}} +protected: + int y; + +public: + NonPolymorphicBaseClass2() = default; + NonPolymorphicBaseClass2(int) : x(4) {} +}; + +class NonPolymorphicInheritanceTest2 : public NonPolymorphicBaseClass2 { + int z; + +public: + NonPolymorphicInheritanceTest2() { + y = 5; + z = 6; // expected-warning{{1 uninitialized field}} + } +}; + +void fNonPolymorphicInheritanceTest2() { + NonPolymorphicInheritanceTest2(); +} + +class NonPolymorphicBaseClass3 { + int x; + +protected: + int y; // expected-note{{uninitialized field 'this->y'}} +public: + NonPolymorphicBaseClass3() = default; + NonPolymorphicBaseClass3(int) : x(7) {} +}; + +class NonPolymorphicInheritanceTest3 : public NonPolymorphicBaseClass3 { + int z; + +public: + NonPolymorphicInheritanceTest3() + : NonPolymorphicBaseClass3(int{}) { + z = 8; // expected-warning{{1 uninitialized field}} + } +}; + +void fNonPolymorphicInheritanceTest3() { + NonPolymorphicInheritanceTest3(); +} + +class NonPolymorphicBaseClass4 { + int x; + +protected: + int y; + +public: + NonPolymorphicBaseClass4() = default; + NonPolymorphicBaseClass4(int) : x(9) {} +}; + +class NonPolymorphicInheritanceTest4 : public NonPolymorphicBaseClass4 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + NonPolymorphicInheritanceTest4() + : NonPolymorphicBaseClass4(int{}) { + y = 10; // expected-warning{{1 uninitialized field}} + } +}; + +void fNonPolymorphicInheritanceTest4() { + NonPolymorphicInheritanceTest4(); +} + +//===----------------------------------------------------------------------===// +// Polymorphic inheritance tests +//===----------------------------------------------------------------------===// + +class PolymorphicLeft1 { + int x; + +protected: + int y; + +public: + virtual ~PolymorphicLeft1() = default; + PolymorphicLeft1() = default; + PolymorphicLeft1(int) : x(11) {} +}; + +class PolymorphicInheritanceTest1 : public PolymorphicLeft1 { + int z; + +public: + PolymorphicInheritanceTest1() + : PolymorphicLeft1(int{}) { + y = 12; + z = 13; + // All good! + } +}; + +void fPolymorphicInheritanceTest1() { + PolymorphicInheritanceTest1(); +} + +class PolymorphicRight1 { + int x; // expected-note{{uninitialized field 'this->x'}} +protected: + int y; + +public: + virtual ~PolymorphicRight1() = default; + PolymorphicRight1() = default; + PolymorphicRight1(int) : x(14) {} +}; + +class PolymorphicInheritanceTest2 : public PolymorphicRight1 { + int z; + +public: + PolymorphicInheritanceTest2() { + y = 15; + z = 16; // expected-warning{{1 uninitialized field}} + } +}; + +void fPolymorphicInheritanceTest2() { + PolymorphicInheritanceTest2(); +} + +class PolymorphicBaseClass3 { + int x; + +protected: + int y; // expected-note{{uninitialized field 'this->y'}} +public: + virtual ~PolymorphicBaseClass3() = default; + PolymorphicBaseClass3() = default; + PolymorphicBaseClass3(int) : x(17) {} +}; + +class PolymorphicInheritanceTest3 : public PolymorphicBaseClass3 { + int z; + +public: + PolymorphicInheritanceTest3() + : PolymorphicBaseClass3(int{}) { + z = 18; // expected-warning{{1 uninitialized field}} + } +}; + +void fPolymorphicInheritanceTest3() { + PolymorphicInheritanceTest3(); +} + +class PolymorphicBaseClass4 { + int x; + +protected: + int y; + +public: + virtual ~PolymorphicBaseClass4() = default; + PolymorphicBaseClass4() = default; + PolymorphicBaseClass4(int) : x(19) {} +}; + +class PolymorphicInheritanceTest4 : public PolymorphicBaseClass4 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + PolymorphicInheritanceTest4() + : PolymorphicBaseClass4(int{}) { + y = 20; // expected-warning{{1 uninitialized field}} + } +}; + +void fPolymorphicInheritanceTest4() { + PolymorphicInheritanceTest4(); +} + +//===----------------------------------------------------------------------===// +// Virtual inheritance tests +//===----------------------------------------------------------------------===// + +class VirtualPolymorphicLeft1 { + int x; + +protected: + int y; + +public: + virtual ~VirtualPolymorphicLeft1() = default; + VirtualPolymorphicLeft1() = default; + VirtualPolymorphicLeft1(int) : x(21) {} +}; + +class VirtualInheritanceTest1 : virtual public VirtualPolymorphicLeft1 { + int z; + +public: + VirtualInheritanceTest1() + : VirtualPolymorphicLeft1(int()) { + y = 22; + z = 23; + // All good! + } +}; + +void fVirtualInheritanceTest1() { + VirtualInheritanceTest1(); +} + +class VirtualPolymorphicRight1 { + int x; // expected-note{{uninitialized field 'this->x'}} +protected: + int y; + +public: + virtual ~VirtualPolymorphicRight1() = default; + VirtualPolymorphicRight1() = default; + VirtualPolymorphicRight1(int) : x(24) {} +}; + +class VirtualInheritanceTest2 : virtual public VirtualPolymorphicRight1 { + int z; + +public: + VirtualInheritanceTest2() { + y = 25; + z = 26; // expected-warning{{1 uninitialized field}} + } +}; + +void fVirtualInheritanceTest2() { + VirtualInheritanceTest2(); +} + +class VirtualPolymorphicBaseClass3 { + int x; + +protected: + int y; // expected-note{{uninitialized field 'this->y'}} +public: + virtual ~VirtualPolymorphicBaseClass3() = default; + VirtualPolymorphicBaseClass3() = default; + VirtualPolymorphicBaseClass3(int) : x(27) {} +}; + +class VirtualInheritanceTest3 : virtual public VirtualPolymorphicBaseClass3 { + int z; + +public: + VirtualInheritanceTest3() + : VirtualPolymorphicBaseClass3(int{}) { + z = 28; // expected-warning{{1 uninitialized field}} + } +}; + +void fVirtualInheritanceTest3() { + VirtualInheritanceTest3(); +} + +//===----------------------------------------------------------------------===// +// Multiple inheritance tests +//===----------------------------------------------------------------------===// + +/* + Left Right + \ / + \ / + \ / + MultipleInheritanceTest +*/ + +struct Left1 { + int x; + Left1() = default; + Left1(int) : x(29) {} +}; +struct Right1 { + int y; + Right1() = default; + Right1(int) : y(30) {} +}; + +class MultipleInheritanceTest1 : public Left1, public Right1 { + int z; + +public: + MultipleInheritanceTest1() + : Left1(int{}), + Right1(char{}) { + z = 31; + // All good! + } + + MultipleInheritanceTest1(int) + : Left1(int{}) { + y = 32; + z = 33; + // All good! + } + + MultipleInheritanceTest1(int, int) + : Right1(char{}) { + x = 34; + z = 35; + // All good! + } +}; + +void fMultipleInheritanceTest1() { + MultipleInheritanceTest1(); + MultipleInheritanceTest1(int()); + MultipleInheritanceTest1(int(), int()); +} + +struct Left2 { + int x; + Left2() = default; + Left2(int) : x(36) {} +}; +struct Right2 { + int y; // expected-note{{uninitialized field 'this->y'}} + Right2() = default; + Right2(int) : y(37) {} +}; + +class MultipleInheritanceTest2 : public Left2, public Right2 { + int z; + +public: + MultipleInheritanceTest2() + : Left2(int{}) { + z = 38; // expected-warning{{1 uninitialized field}} + } +}; + +void fMultipleInheritanceTest2() { + MultipleInheritanceTest2(); +} + +struct Left3 { + int x; // expected-note{{uninitialized field 'this->x'}} + Left3() = default; + Left3(int) : x(39) {} +}; +struct Right3 { + int y; + Right3() = default; + Right3(int) : y(40) {} +}; + +class MultipleInheritanceTest3 : public Left3, public Right3 { + int z; + +public: + MultipleInheritanceTest3() + : Right3(char{}) { + z = 41; // expected-warning{{1 uninitialized field}} + } +}; + +void fMultipleInheritanceTest3() { + MultipleInheritanceTest3(); +} + +struct Left4 { + int x; + Left4() = default; + Left4(int) : x(42) {} +}; +struct Right4 { + int y; + Right4() = default; + Right4(int) : y(43) {} +}; + +class MultipleInheritanceTest4 : public Left4, public Right4 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + MultipleInheritanceTest4() + : Left4(int{}), + Right4(char{}) { // expected-warning{{1 uninitialized field}} + } +}; + +void fMultipleInheritanceTest4() { + MultipleInheritanceTest4(); +} + +struct Left5 { + int x; + Left5() = default; + Left5(int) : x(44) {} +}; +struct Right5 { + int y; // expected-note{{uninitialized field 'this->y'}} + Right5() = default; + Right5(int) : y(45) {} +}; + +class MultipleInheritanceTest5 : public Left5, public Right5 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + MultipleInheritanceTest5() // expected-warning{{2 uninitialized fields}} + : Left5(int{}) { + } +}; + +void fMultipleInheritanceTest5() { + MultipleInheritanceTest5(); +} + +//===----------------------------------------------------------------------===// +// Non-virtual diamond inheritance tests +//===----------------------------------------------------------------------===// + +/* + NonVirtualBase NonVirtualBase + | | + | | + | | + First Second + \ / + \ / + \ / + NonVirtualDiamondInheritanceTest +*/ + +struct NonVirtualBase1 { + int x; + NonVirtualBase1() = default; + NonVirtualBase1(int) : x(46) {} +}; +struct First1 : public NonVirtualBase1 { + First1() = default; + First1(int) : NonVirtualBase1(int{}) {} +}; +struct Second1 : public NonVirtualBase1 { + Second1() = default; + Second1(int) : NonVirtualBase1(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest1 : public First1, public Second1 { + int z; + +public: + NonVirtualDiamondInheritanceTest1() + : First1(int{}), + Second1(int{}) { + z = 47; + // All good! + } + + NonVirtualDiamondInheritanceTest1(int) + : First1(int{}) { + Second1::x = 48; + z = 49; + // All good! + } + + NonVirtualDiamondInheritanceTest1(int, int) + : Second1(int{}) { + First1::x = 50; + z = 51; + // All good! + } +}; + +void fNonVirtualDiamondInheritanceTest1() { + NonVirtualDiamondInheritanceTest1(); + NonVirtualDiamondInheritanceTest1(int()); + NonVirtualDiamondInheritanceTest1(int(), int()); +} + +struct NonVirtualBase2 { + int x; // expected-note{{uninitialized field 'this->x'}} + NonVirtualBase2() = default; + NonVirtualBase2(int) : x(52) {} +}; +struct First2 : public NonVirtualBase2 { + First2() = default; + First2(int) : NonVirtualBase2(int{}) {} +}; +struct Second2 : public NonVirtualBase2 { + Second2() = default; + Second2(int) : NonVirtualBase2(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest2 : public First2, public Second2 { + int z; + +public: + NonVirtualDiamondInheritanceTest2() + : First2(int{}) { + z = 53; // expected-warning{{1 uninitialized field}} + } +}; + +void fNonVirtualDiamondInheritanceTest2() { + NonVirtualDiamondInheritanceTest2(); +} + +struct NonVirtualBase3 { + int x; // expected-note{{uninitialized field 'this->x'}} + NonVirtualBase3() = default; + NonVirtualBase3(int) : x(54) {} +}; +struct First3 : public NonVirtualBase3 { + First3() = default; + First3(int) : NonVirtualBase3(int{}) {} +}; +struct Second3 : public NonVirtualBase3 { + Second3() = default; + Second3(int) : NonVirtualBase3(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest3 : public First3, public Second3 { + int z; + +public: + NonVirtualDiamondInheritanceTest3() + : Second3(int{}) { + z = 55; // expected-warning{{1 uninitialized field}} + } +}; + +void fNonVirtualDiamondInheritanceTest3() { + NonVirtualDiamondInheritanceTest3(); +} + +struct NonVirtualBase4 { + int x; // expected-note{{uninitialized field 'this->x'}} + // expected-note@-1{{uninitialized field 'this->x'}} + NonVirtualBase4() = default; + NonVirtualBase4(int) : x(56) {} +}; +struct First4 : public NonVirtualBase4 { + First4() = default; + First4(int) : NonVirtualBase4(int{}) {} +}; +struct Second4 : public NonVirtualBase4 { + Second4() = default; + Second4(int) : NonVirtualBase4(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest4 : public First4, public Second4 { + int z; + +public: + NonVirtualDiamondInheritanceTest4() { + z = 57; // expected-warning{{2 uninitialized fields}} + } +}; + +void fNonVirtualDiamondInheritanceTest4() { + NonVirtualDiamondInheritanceTest4(); +} + +struct NonVirtualBase5 { + int x; + NonVirtualBase5() = default; + NonVirtualBase5(int) : x(58) {} +}; +struct First5 : public NonVirtualBase5 { + First5() = default; + First5(int) : NonVirtualBase5(int{}) {} +}; +struct Second5 : public NonVirtualBase5 { + Second5() = default; + Second5(int) : NonVirtualBase5(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest5 : public First5, public Second5 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + NonVirtualDiamondInheritanceTest5() + : First5(int{}), + Second5(int{}) { // expected-warning{{1 uninitialized field}} + } +}; + +void fNonVirtualDiamondInheritanceTest5() { + NonVirtualDiamondInheritanceTest5(); +} + +struct NonVirtualBase6 { + int x; // expected-note{{uninitialized field 'this->x'}} + NonVirtualBase6() = default; + NonVirtualBase6(int) : x(59) {} +}; +struct First6 : public NonVirtualBase6 { + First6() = default; + First6(int) : NonVirtualBase6(int{}) {} +}; +struct Second6 : public NonVirtualBase6 { + Second6() = default; + Second6(int) : NonVirtualBase6(int{}) {} +}; + +class NonVirtualDiamondInheritanceTest6 : public First6, public Second6 { + int z; // expected-note{{uninitialized field 'this->z'}} + +public: + NonVirtualDiamondInheritanceTest6() // expected-warning{{2 uninitialized fields}} + : First6(int{}) { + // 'z' and 'Second::x' unintialized + } +}; + +void fNonVirtualDiamondInheritanceTest6() { + NonVirtualDiamondInheritanceTest6(); +} + +//===----------------------------------------------------------------------===// +// Virtual diamond inheritance tests +//===----------------------------------------------------------------------===// + +/* + VirtualBase + / \ + / \ + / \ + VirtualFirst VirtualSecond + \ / + \ / + \ / + VirtualDiamondInheritanceTest +*/ + +struct VirtualBase1 { + int x; + VirtualBase1() = default; + VirtualBase1(int) : x(60) {} +}; +struct VirtualFirst1 : virtual public VirtualBase1 { + VirtualFirst1() = default; + VirtualFirst1(int) : VirtualBase1(int{}) {} + VirtualFirst1(int, int) { x = 61; } +}; +struct VirtualSecond1 : virtual public VirtualBase1 { + VirtualSecond1() = default; + VirtualSecond1(int) : VirtualBase1(int{}) {} + VirtualSecond1(int, int) { x = 62; } +}; + +class VirtualDiamondInheritanceTest1 : public VirtualFirst1, public VirtualSecond1 { + +public: + VirtualDiamondInheritanceTest1() { + x = 0; + // All good! + } + + VirtualDiamondInheritanceTest1(int) + : VirtualFirst1(int{}, int{}), + VirtualSecond1(int{}, int{}) { + // All good! + } + + VirtualDiamondInheritanceTest1(int, int) + : VirtualFirst1(int{}, int{}) { + // All good! + } +}; + +void fVirtualDiamondInheritanceTest1() { + VirtualDiamondInheritanceTest1(); + VirtualDiamondInheritanceTest1(int()); + VirtualDiamondInheritanceTest1(int(), int()); +} + +struct VirtualBase2 { + int x; // expected-note{{uninitialized field 'this->x'}} + VirtualBase2() = default; + VirtualBase2(int) : x(63) {} +}; +struct VirtualFirst2 : virtual public VirtualBase2 { + VirtualFirst2() = default; + VirtualFirst2(int) : VirtualBase2(int{}) {} + VirtualFirst2(int, int) { x = 64; } +}; +struct VirtualSecond2 : virtual public VirtualBase2 { + VirtualSecond2() = default; + VirtualSecond2(int) : VirtualBase2(int{}) {} + VirtualSecond2(int, int) { x = 65; } +}; + +class VirtualDiamondInheritanceTest2 : public VirtualFirst2, public VirtualSecond2 { + +public: + VirtualDiamondInheritanceTest2() // expected-warning{{1 uninitialized field}} + : VirtualFirst2(int{}) { + // From the N4659 C++ Standard Working Draft: + // + // (15.6.2.7) + // [...] A 'mem-initializer' where the 'mem-initializer-id' denotes a + // virtual base class is ignored during execution of a constructor of any + // class that is not the most derived class. + // + // This means that Left1::x will not be initialized, because in both + // VirtualFirst::VirtualFirst(int) and VirtualSecond::VirtualSecond(int) + // the constructor delegation to Left1::Left1(int) will be + // ignored. + } +}; + +void fVirtualDiamondInheritanceTest2() { + VirtualDiamondInheritanceTest2(); +} + +struct VirtualBase3 { + int x; // expected-note{{uninitialized field 'this->x'}} + VirtualBase3() = default; + VirtualBase3(int) : x(66) {} +}; +struct VirtualFirst3 : virtual public VirtualBase3 { + VirtualFirst3() = default; + VirtualFirst3(int) : VirtualBase3(int{}) {} + VirtualFirst3(int, int) { x = 67; } +}; +struct VirtualSecond3 : virtual public VirtualBase3 { + VirtualSecond3() = default; + VirtualSecond3(int) : VirtualBase3(int{}) {} + VirtualSecond3(int, int) { x = 68; } +}; + +class VirtualDiamondInheritanceTest3 : public VirtualFirst3, public VirtualSecond3 { + +public: + VirtualDiamondInheritanceTest3() // expected-warning{{1 uninitialized field}} + : VirtualFirst3(int{}) {} +}; + +void fVirtualDiamondInheritanceTest3() { + VirtualDiamondInheritanceTest3(); +} diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp new file mode 100644 index 0000000000..e6c0b91a62 --- /dev/null +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -0,0 +1,699 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s + +//===----------------------------------------------------------------------===// +// Concrete location tests. +//===----------------------------------------------------------------------===// + +struct ConcreteIntLocTest { + int *ptr; + + ConcreteIntLocTest() : ptr(reinterpret_cast(0xDEADBEEF)) {} +}; + +void fConcreteIntLocTest() { + ConcreteIntLocTest(); +} + +//===----------------------------------------------------------------------===// +// Null pointer tests. +//===----------------------------------------------------------------------===// + +class NullPtrTest { + struct RecordType { + int x; + int y; + }; + + float *fptr = nullptr; + int *ptr; + RecordType *recPtr; + +public: + NullPtrTest() : ptr(nullptr), recPtr(nullptr) { + // All good! + } +}; + +void fNullPtrTest() { + NullPtrTest(); +} + +//===----------------------------------------------------------------------===// +// Heap pointer tests. +//===----------------------------------------------------------------------===// + +class HeapPointerTest1 { + struct RecordType { + // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}} + int x; // no-note + // TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}} + int y; // no-note + }; + // TODO: we'd expect the note: {{uninitialized pointee 'this->fptr'}} + float *fptr = new float; // no-note + // TODO: we'd expect the note: {{uninitialized pointee 'this->ptr'}} + int *ptr; // no-note + RecordType *recPtr; + +public: + // TODO: we'd expect the warning: {{4 uninitialized fields}} + HeapPointerTest1() : ptr(new int), recPtr(new RecordType) { // no-note + } +}; + +void fHeapPointerTest1() { + HeapPointerTest1(); +} + +class HeapPointerTest2 { + struct RecordType { + int x; + int y; + }; + + float *fptr = new float(); // initializes to 0 + int *ptr; + RecordType *recPtr; + +public: + HeapPointerTest2() : ptr(new int{25}), recPtr(new RecordType{26, 27}) { + // All good! + } +}; + +void fHeapPointerTest2() { + HeapPointerTest2(); +} + +//===----------------------------------------------------------------------===// +// Stack pointer tests. +//===----------------------------------------------------------------------===// + +class StackPointerTest1 { +public: + struct RecordType { + int x; + int y; + }; + +private: + int *ptr; + RecordType *recPtr; + +public: + StackPointerTest1(int *_ptr, StackPointerTest1::RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { + // All good! + } +}; + +void fStackPointerTest1() { + int ok_a = 28; + StackPointerTest1::RecordType ok_rec{29, 30}; + StackPointerTest1(&ok_a, &ok_rec); // 'a', 'rec.x', 'rec.y' uninitialized +} + +#ifdef PEDANTIC +class StackPointerTest2 { +public: + struct RecordType { + int x; // expected-note{{uninitialized field 'this->recPtr->x'}} + int y; // expected-note{{uninitialized field 'this->recPtr->y'}} + }; + +private: + int *ptr; // expected-note{{uninitialized pointee 'this->ptr'}} + RecordType *recPtr; + +public: + StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { // expected-warning{{3 uninitialized fields}} + } +}; + +void fStackPointerTest2() { + int a; + StackPointerTest2::RecordType rec; + StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized +} +#else +class StackPointerTest2 { +public: + struct RecordType { + int x; + int y; + }; + +private: + int *ptr; + RecordType *recPtr; + +public: + StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { + } +}; + +void fStackPointerTest2() { + int a; + StackPointerTest2::RecordType rec; + StackPointerTest2(&a, &rec); // 'a', 'rec.x', 'rec.y' uninitialized +} +#endif // PEDANTIC + +class UninitPointerTest { + struct RecordType { + int x; + int y; + }; + + int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}} + RecordType *recPtr; + +public: + UninitPointerTest() : recPtr(new RecordType{13, 13}) { // expected-warning{{1 uninitialized field}} + } +}; + +void fUninitPointerTest() { + UninitPointerTest(); +} + +struct CharPointerTest { + const char *str; + int dontGetFilteredByNonPedanticMode = 0; + + CharPointerTest() : str("") {} +}; + +void fCharPointerTest() { + CharPointerTest(); +} + +struct CyclicPointerTest { + int *ptr; + CyclicPointerTest() : ptr(reinterpret_cast(&ptr)) {} +}; + +void fCyclicPointerTest() { + CyclicPointerTest(); +} + +//===----------------------------------------------------------------------===// +// Void pointer tests. +//===----------------------------------------------------------------------===// + +// Void pointer tests are mainly no-crash tests. + +void *malloc(int size); + +class VoidPointerTest1 { + void *vptr; + +public: + VoidPointerTest1(void *vptr, char) : vptr(vptr) { + // All good! + } +}; + +void fVoidPointerTest1() { + void *vptr = malloc(sizeof(int)); + VoidPointerTest1(vptr, char()); +} + +class VoidPointerTest2 { + void **vpptr; + +public: + VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) { + // All good! + } +}; + +void fVoidPointerTest2() { + void *vptr = malloc(sizeof(int)); + VoidPointerTest2(&vptr, char()); +} + +class VoidPointerRRefTest1 { + void *&&vptrrref; + +public: + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { + // All good! + } +}; + +void fVoidPointerRRefTest1() { + void *vptr = malloc(sizeof(int)); + VoidPointerRRefTest1(vptr, char()); +} + +class VoidPointerRRefTest2 { + void **&&vpptrrref; + +public: + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { + // All good! + } +}; + +void fVoidPointerRRefTest2() { + void *vptr = malloc(sizeof(int)); + VoidPointerRRefTest2(&vptr, char()); +} + +class VoidPointerLRefTest { + void *&vptrrref; + +public: + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { + // All good! + } +}; + +void fVoidPointerLRefTest() { + void *vptr = malloc(sizeof(int)); + VoidPointerLRefTest(vptr, char()); +} + +struct CyclicVoidPointerTest { + void *vptr; // no-crash + + CyclicVoidPointerTest() : vptr(&vptr) {} + +}; + +void fCyclicVoidPointerTest() { + CyclicVoidPointerTest(); +} + +//===----------------------------------------------------------------------===// +// Multipointer tests. +//===----------------------------------------------------------------------===// + +#ifdef PEDANTIC +class MultiPointerTest1 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}} + +public: + MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}} + } +}; + +void fMultiPointerTest1() { + MultiPointerTest1::RecordType *p1; + MultiPointerTest1::RecordType **mptr = &p1; + MultiPointerTest1(mptr, int()); // '*mptr' uninitialized +} +#else +class MultiPointerTest1 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType **mptr; + +public: + MultiPointerTest1(RecordType **p, int) : mptr(p) {} +}; + +void fMultiPointerTest1() { + MultiPointerTest1::RecordType *p1; + MultiPointerTest1::RecordType **mptr = &p1; + MultiPointerTest1(mptr, int()); // '*mptr' uninitialized +} +#endif // PEDANTIC + +#ifdef PEDANTIC +class MultiPointerTest2 { +public: + struct RecordType { + int x; // expected-note{{uninitialized field 'this->mptr->x'}} + int y; // expected-note{{uninitialized field 'this->mptr->y'}} + }; + +private: + RecordType **mptr; + +public: + MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}} + } +}; + +void fMultiPointerTest2() { + MultiPointerTest2::RecordType i; + MultiPointerTest2::RecordType *p1 = &i; + MultiPointerTest2::RecordType **mptr = &p1; + MultiPointerTest2(mptr, int()); // '**mptr' uninitialized +} +#else +class MultiPointerTest2 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType **mptr; + +public: + MultiPointerTest2(RecordType **p, int) : mptr(p) { + } +}; + +void fMultiPointerTest2() { + MultiPointerTest2::RecordType i; + MultiPointerTest2::RecordType *p1 = &i; + MultiPointerTest2::RecordType **mptr = &p1; + MultiPointerTest2(mptr, int()); // '**mptr' uninitialized +} +#endif // PEDANTIC + +class MultiPointerTest3 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType **mptr; + +public: + MultiPointerTest3(RecordType **p, int) : mptr(p) { + // All good! + } +}; + +void fMultiPointerTest3() { + MultiPointerTest3::RecordType i{31, 32}; + MultiPointerTest3::RecordType *p1 = &i; + MultiPointerTest3::RecordType **mptr = &p1; + MultiPointerTest3(mptr, int()); // '**mptr' uninitialized +} + +//===----------------------------------------------------------------------===// +// Member pointer tests. +//===----------------------------------------------------------------------===// + +struct UsefulFunctions { + int a, b; + + void print() {} + void dump() {} +}; + +#ifdef PEDANTIC +struct PointerToMemberFunctionTest1 { + // TODO: we'd expect the note {{uninitialized field 'this->f'}} + void (UsefulFunctions::*f)(void); // no-note + PointerToMemberFunctionTest1() {} +}; + +void fPointerToMemberFunctionTest1() { + // TODO: we'd expect the warning {{1 uninitialized field}} + PointerToMemberFunctionTest1(); // no-warning +} + +struct PointerToMemberFunctionTest2 { + void (UsefulFunctions::*f)(void); + PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) { + // All good! + } +}; + +void fPointerToMemberFunctionTest2() { + void (UsefulFunctions::*f)(void) = &UsefulFunctions::print; + PointerToMemberFunctionTest2 a(f); +} + +struct MultiPointerToMemberFunctionTest1 { + void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}} + MultiPointerToMemberFunctionTest1() {} +}; + +void fMultiPointerToMemberFunctionTest1() { + MultiPointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}} +} + +struct MultiPointerToMemberFunctionTest2 { + void (UsefulFunctions::**f)(void); + MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) { + // All good! + } +}; + +void fMultiPointerToMemberFunctionTest2() { + void (UsefulFunctions::*f)(void) = &UsefulFunctions::print; + MultiPointerToMemberFunctionTest2 a(&f); +} + +struct PointerToMemberDataTest1 { + // TODO: we'd expect the note {{uninitialized field 'this->f'}} + int UsefulFunctions::*d; // no-note + PointerToMemberDataTest1() {} +}; + +void fPointerToMemberDataTest1() { + // TODO: we'd expect the warning {{1 uninitialized field}} + PointerToMemberDataTest1(); // no-warning +} + +struct PointerToMemberDataTest2 { + int UsefulFunctions::*d; + PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) { + // All good! + } +}; + +void fPointerToMemberDataTest2() { + int UsefulFunctions::*d = &UsefulFunctions::a; + PointerToMemberDataTest2 a(d); +} + +struct MultiPointerToMemberDataTest1 { + int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}} + MultiPointerToMemberDataTest1() {} +}; + +void fMultiPointerToMemberDataTest1() { + MultiPointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}} +} + +struct MultiPointerToMemberDataTest2 { + int UsefulFunctions::**d; + MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) { + // All good! + } +}; + +void fMultiPointerToMemberDataTest2() { + int UsefulFunctions::*d = &UsefulFunctions::a; + MultiPointerToMemberDataTest2 a(&d); +} +#endif // PEDANTIC + +//===----------------------------------------------------------------------===// +// Tests for list-like records. +//===----------------------------------------------------------------------===// + +class ListTest1 { +public: + struct Node { + Node *next = nullptr; // no crash + int i; + }; + +private: + Node *head = nullptr; + +public: + ListTest1() { + // All good! + } +}; + +void fListTest1() { + ListTest1(); +} + +class ListTest2 { +public: + struct Node { + Node *next = nullptr; + int i; // expected-note{{uninitialized field 'this->head->i'}} + }; + +private: + Node *head = nullptr; + +public: + ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}} + } +}; + +void fListTest2() { + ListTest2::Node n; + ListTest2(&n, int()); +} + +class CyclicList { +public: + struct Node { + Node *next = nullptr; + int i; // expected-note{{uninitialized field 'this->head->i'}} + }; + +private: + Node *head = nullptr; + +public: + CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}} + } +}; + +void fCyclicList() { + /* + n3 + / \ + this -- n1 -- n2 + */ + + CyclicList::Node n1; + CyclicList::Node n2; + n2.next = &n1; + n2.i = 50; + CyclicList::Node n3; + n3.next = &n2; + n3.i = 50; + n1.next = &n3; + // note that n1.i is uninitialized + CyclicList(&n1, int()); +} + +//===----------------------------------------------------------------------===// +// Tests for classes containing references. +//===----------------------------------------------------------------------===// + +class ReferenceTest1 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType &lref; + RecordType &&rref; + +public: + ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast(rref)) { + // All good! + } +}; + +void fReferenceTest1() { + ReferenceTest1::RecordType d{33, 34}; + ReferenceTest1(d, d); +} + +#ifdef PEDANTIC +class ReferenceTest2 { +public: + struct RecordType { + int x; // expected-note{{uninitialized field 'this->lref.x'}} + int y; // expected-note{{uninitialized field 'this->lref.y'}} + }; + +private: + RecordType &lref; + RecordType &&rref; + +public: + ReferenceTest2(RecordType &lref, RecordType &rref) + : lref(lref), rref(static_cast(rref)) { // expected-warning{{2 uninitialized fields}} + } +}; + +void fReferenceTest2() { + ReferenceTest2::RecordType c; + ReferenceTest2(c, c); +} +#else +class ReferenceTest2 { +public: + struct RecordType { + int x; + int y; + }; + +private: + RecordType &lref; + RecordType &&rref; + +public: + ReferenceTest2(RecordType &lref, RecordType &rref) + : lref(lref), rref(static_cast(rref)) { + } +}; + +void fReferenceTest2() { + ReferenceTest2::RecordType c; + ReferenceTest2(c, c); +} +#endif // PEDANTIC + +class ReferenceTest3 { +public: + struct RecordType { + int x; // expected-note{{uninitialized field 'this->lref.x'}} + int y; // expected-note{{uninitialized field 'this->lref.y'}} + }; + +private: + RecordType &lref; + RecordType &&rref; + +public: + ReferenceTest3(RecordType &lref, RecordType &rref) + : lref(lref), rref(static_cast(rref)) { // expected-warning{{2 uninitialized fields}} + } +}; + +void fReferenceTest3() { + ReferenceTest3::RecordType c, d{35, 36}; + ReferenceTest3(c, d); +} + +class ReferenceTest4 { +public: + struct RecordType { + int x; // expected-note{{uninitialized field 'this->rref.x'}} + int y; // expected-note{{uninitialized field 'this->rref.y'}} + }; + +private: + RecordType &lref; + RecordType &&rref; + +public: + ReferenceTest4(RecordType &lref, RecordType &rref) + : lref(lref), rref(static_cast(rref)) { // expected-warning{{2 uninitialized fields}} + } +}; + +void fReferenceTest5() { + ReferenceTest4::RecordType c, d{37, 38}; + ReferenceTest4(d, c); +} diff --git a/test/Analysis/cxx-uninitialized-object.cpp b/test/Analysis/cxx-uninitialized-object.cpp new file mode 100644 index 0000000000..617ac78f40 --- /dev/null +++ b/test/Analysis/cxx-uninitialized-object.cpp @@ -0,0 +1,1058 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s + +//===----------------------------------------------------------------------===// +// Default constructor test. +//===----------------------------------------------------------------------===// + +class CompilerGeneratedConstructorTest { + int a, b, c, d, e, f, g, h, i, j; + +public: + CompilerGeneratedConstructorTest() = default; +}; + +void fCompilerGeneratedConstructorTest() { + CompilerGeneratedConstructorTest(); +} + +#ifdef PEDANTIC +class DefaultConstructorTest { + int a; // expected-note{{uninitialized field 'this->a'}} + +public: + DefaultConstructorTest(); +}; + +DefaultConstructorTest::DefaultConstructorTest() = default; + +void fDefaultConstructorTest() { + DefaultConstructorTest(); // expected-warning{{1 uninitialized field}} +} +#else +class DefaultConstructorTest { + int a; + +public: + DefaultConstructorTest(); +}; + +DefaultConstructorTest::DefaultConstructorTest() = default; + +void fDefaultConstructorTest() { + DefaultConstructorTest(); +} +#endif // PEDANTIC + +//===----------------------------------------------------------------------===// +// Initializer list test. +//===----------------------------------------------------------------------===// + +class InitListTest1 { + int a; + int b; + +public: + InitListTest1() + : a(1), + b(2) { + // All good! + } +}; + +void fInitListTest1() { + InitListTest1(); +} + +class InitListTest2 { + int a; + int b; // expected-note{{uninitialized field 'this->b'}} + +public: + InitListTest2() + : a(3) {} // expected-warning{{1 uninitialized field}} +}; + +void fInitListTest2() { + InitListTest2(); +} + +class InitListTest3 { + int a; // expected-note{{uninitialized field 'this->a'}} + int b; + +public: + InitListTest3() + : b(4) {} // expected-warning{{1 uninitialized field}} +}; + +void fInitListTest3() { + InitListTest3(); +} + +//===----------------------------------------------------------------------===// +// Constructor body test. +//===----------------------------------------------------------------------===// + +class CtorBodyTest1 { + int a, b; + +public: + CtorBodyTest1() { + a = 5; + b = 6; + // All good! + } +}; + +void fCtorBodyTest1() { + CtorBodyTest1(); +} + +class CtorBodyTest2 { + int a; + int b; // expected-note{{uninitialized field 'this->b'}} + +public: + CtorBodyTest2() { + a = 7; // expected-warning{{1 uninitialized field}} + } +}; + +void fCtorBodyTest2() { + CtorBodyTest2(); +} + +class CtorBodyTest3 { + int a; // expected-note{{uninitialized field 'this->a'}} + int b; + +public: + CtorBodyTest3() { + b = 8; // expected-warning{{1 uninitialized field}} + } +}; + +void fCtorBodyTest3() { + CtorBodyTest3(); +} + +#ifdef PEDANTIC +class CtorBodyTest4 { + int a; // expected-note{{uninitialized field 'this->a'}} + int b; // expected-note{{uninitialized field 'this->b'}} + +public: + CtorBodyTest4() {} +}; + +void fCtorBodyTest4() { + CtorBodyTest4(); // expected-warning{{2 uninitialized fields}} +} +#else +class CtorBodyTest4 { + int a; + int b; + +public: + CtorBodyTest4() {} +}; + +void fCtorBodyTest4() { + CtorBodyTest4(); +} +#endif + +//===----------------------------------------------------------------------===// +// Constructor delegation test. +//===----------------------------------------------------------------------===// + +class CtorDelegationTest1 { + int a; + int b; + +public: + CtorDelegationTest1(int) + : a(9) { + // leaves 'b' unintialized, but we'll never check this function + } + + CtorDelegationTest1() + : CtorDelegationTest1(int{}) { // Initializing 'a' + b = 10; + // All good! + } +}; + +void fCtorDelegationTest1() { + CtorDelegationTest1(); +} + +class CtorDelegationTest2 { + int a; // expected-note{{uninitialized field 'this->a'}} + int b; + +public: + CtorDelegationTest2(int) + : b(11) { + // leaves 'a' unintialized, but we'll never check this function + } + + CtorDelegationTest2() + : CtorDelegationTest2(int{}) { // expected-warning{{1 uninitialized field}} + } +}; + +void fCtorDelegationTest2() { + CtorDelegationTest2(); +} + +//===----------------------------------------------------------------------===// +// Tests for classes containing records. +//===----------------------------------------------------------------------===// + +class ContainsRecordTest1 { + struct RecordType { + int x; + int y; + } rec; + int c, d; + +public: + ContainsRecordTest1() + : rec({12, 13}), + c(14), + d(15) { + // All good! + } +}; + +void fContainsRecordTest1() { + ContainsRecordTest1(); +} + +class ContainsRecordTest2 { + struct RecordType { + int x; + int y; // expected-note{{uninitialized field 'this->rec.y'}} + } rec; + int c, d; + +public: + ContainsRecordTest2() + : c(16), + d(17) { + rec.x = 18; // expected-warning{{1 uninitialized field}} + } +}; + +void fContainsRecordTest2() { + ContainsRecordTest2(); +} + +class ContainsRecordTest3 { + struct RecordType { + int x; // expected-note{{uninitialized field 'this->rec.x'}} + int y; // expected-note{{uninitialized field 'this->rec.y'}} + } rec; + int c, d; + +public: + ContainsRecordTest3() + : c(19), + d(20) { // expected-warning{{2 uninitialized fields}} + } +}; + +void fContainsRecordTest3() { + ContainsRecordTest3(); +} + +class ContainsRecordTest4 { + struct RecordType { + int x; // expected-note{{uninitialized field 'this->rec.x'}} + int y; // expected-note{{uninitialized field 'this->rec.y'}} + } rec; + int c, d; // expected-note{{uninitialized field 'this->d'}} + +public: + ContainsRecordTest4() + : c(19) { // expected-warning{{3 uninitialized fields}} + } +}; + +void fContainsRecordTest4() { + ContainsRecordTest4(); +} + +//===----------------------------------------------------------------------===// +// Tests for template classes. +//===----------------------------------------------------------------------===// + +template +class IntTemplateClassTest1 { + T t; + int b; + +public: + IntTemplateClassTest1(T i) { + b = 21; + t = i; + // All good! + } +}; + +void fIntTemplateClassTest1() { + IntTemplateClassTest1(22); +} + +template +class IntTemplateClassTest2 { + T t; // expected-note{{uninitialized field 'this->t'}} + int b; + +public: + IntTemplateClassTest2() { + b = 23; // expected-warning{{1 uninitialized field}} + } +}; + +void fIntTemplateClassTest2() { + IntTemplateClassTest2(); +} + +struct Record { + int x; // expected-note{{uninitialized field 'this->t.x'}} + int y; // expected-note{{uninitialized field 'this->t.y'}} +}; + +template +class RecordTemplateClassTest { + T t; + int b; + +public: + RecordTemplateClassTest() { + b = 24; // expected-warning{{2 uninitialized fields}} + } +}; + +void fRecordTemplateClassTest() { + RecordTemplateClassTest(); +} + +//===----------------------------------------------------------------------===// +// Tests involving functions with unknown implementations. +//===----------------------------------------------------------------------===// + +template +void mayInitialize(T &); + +template +void wontInitialize(const T &); + +class PassingToUnknownFunctionTest1 { + int a, b; + +public: + PassingToUnknownFunctionTest1() { + mayInitialize(a); + mayInitialize(b); + // All good! + } + + PassingToUnknownFunctionTest1(int) { + mayInitialize(a); + // All good! + } + + PassingToUnknownFunctionTest1(int, int) { + mayInitialize(*this); + // All good! + } +}; + +void fPassingToUnknownFunctionTest1() { + PassingToUnknownFunctionTest1(); + PassingToUnknownFunctionTest1(int()); + PassingToUnknownFunctionTest1(int(), int()); +} + +class PassingToUnknownFunctionTest2 { + int a; // expected-note{{uninitialized field 'this->a'}} + int b; + +public: + PassingToUnknownFunctionTest2() { + wontInitialize(a); + b = 4; // expected-warning{{1 uninitialized field}} + } +}; + +void fPassingToUnknownFunctionTest2() { + PassingToUnknownFunctionTest2(); +} + +//===----------------------------------------------------------------------===// +// Tests for classes containing unions. +//===----------------------------------------------------------------------===// + +// FIXME: As of writing this checker, there is no good support for union types +// in the Static Analyzer. Here is non-exhaustive list of cases. +// Note that the rules for unions are different in C and C++. +// http://lists.llvm.org/pipermail/cfe-dev/2017-March/052910.html + +class ContainsSimpleUnionTest1 { + union SimpleUnion { + float uf; + int ui; + char uc; + } u; + +public: + ContainsSimpleUnionTest1() { + u.uf = 3.14; + // All good! + } +}; + +void fContainsSimpleUnionTest1() { + ContainsSimpleUnionTest1(); +} + +class ContainsSimpleUnionTest2 { + union SimpleUnion { + float uf; + int ui; + char uc; + // TODO: we'd expect the note: {{uninitialized field 'this->u'}} + } u; // no-note + +public: + ContainsSimpleUnionTest2() {} +}; + +void fContainsSimpleUnionTest2() { + // TODO: we'd expect the warning: {{1 uninitialized field}} + ContainsSimpleUnionTest2(); // no-warning +} + +class UnionPointerTest1 { +public: + union SimpleUnion { + float uf; + int ui; + char uc; + }; + +private: + SimpleUnion *uptr; + +public: + UnionPointerTest1(SimpleUnion *uptr, int) : uptr(uptr) { + // All good! + } +}; + +void fUnionPointerTest1() { + UnionPointerTest1::SimpleUnion u; + u.uf = 41; + UnionPointerTest1(&u, int()); +} + +class UnionPointerTest2 { +public: + union SimpleUnion { + float uf; + int ui; + char uc; + }; + +private: + // TODO: we'd expect the note: {{uninitialized field 'this->uptr'}} + SimpleUnion *uptr; // no-note + +public: + UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} +}; + +void fUnionPointerTest2() { + UnionPointerTest2::SimpleUnion u; + // TODO: we'd expect the warning: {{1 uninitialized field}} + UnionPointerTest2(&u, int()); // no-warning +} + +class ContainsUnionWithRecordTest1 { + union UnionWithRecord { + struct RecordType { + int x; + int y; + } us; + double ud; + long ul; + + UnionWithRecord(){}; + } u; + +public: + ContainsUnionWithRecordTest1() { + u.ud = 3.14; + // All good! + } +}; + +void fContainsUnionWithRecordTest1() { + ContainsUnionWithRecordTest1(); +} + +class ContainsUnionWithRecordTest2 { + union UnionWithRecord { + struct RecordType { + int x; + int y; + } us; + double ud; + long ul; + + UnionWithRecord(){}; + } u; + +public: + ContainsUnionWithRecordTest2() { + u.us = UnionWithRecord::RecordType{42, 43}; + // All good! + } +}; + +void fContainsUnionWithRecordTest2() { + ContainsUnionWithRecordTest1(); +} + +class ContainsUnionWithRecordTest3 { + union UnionWithRecord { + struct RecordType { + int x; + int y; + } us; + double ud; + long ul; + + UnionWithRecord(){}; + // TODO: we'd expect the note: {{uninitialized field 'this->u'}} + } u; // no-note + +public: + ContainsUnionWithRecordTest3() { + UnionWithRecord::RecordType rec; + rec.x = 44; + // TODO: we'd expect the warning: {{1 uninitialized field}} + u.us = rec; // no-warning + } +}; + +void fContainsUnionWithRecordTest3() { + ContainsUnionWithRecordTest3(); +} + +class ContainsUnionWithSimpleUnionTest1 { + union UnionWithSimpleUnion { + union SimpleUnion { + float uf; + int ui; + char uc; + } usu; + long ul; + unsigned uu; + } u; + +public: + ContainsUnionWithSimpleUnionTest1() { + u.usu.ui = 5; + // All good! + } +}; + +void fContainsUnionWithSimpleUnionTest1() { + ContainsUnionWithSimpleUnionTest1(); +} + +class ContainsUnionWithSimpleUnionTest2 { + union UnionWithSimpleUnion { + union SimpleUnion { + float uf; + int ui; + char uc; + } usu; + long ul; + unsigned uu; + // TODO: we'd expect the note: {{uninitialized field 'this->u'}} + } u; // no-note + +public: + ContainsUnionWithSimpleUnionTest2() {} +}; + +void fContainsUnionWithSimpleUnionTest2() { + // TODO: we'd expect the warning: {{1 uninitialized field}} + ContainsUnionWithSimpleUnionTest2(); // no-warning +} + +//===----------------------------------------------------------------------===// +// Zero initialization tests. +//===----------------------------------------------------------------------===// + +struct GlobalVariableTest { + int i; + + GlobalVariableTest() {} +}; + +GlobalVariableTest gvt; // no-warning + +//===----------------------------------------------------------------------===// +// Copy and move constructor tests. +//===----------------------------------------------------------------------===// + +template +void funcToSquelchCompilerWarnings(const T &t); + +#ifdef PEDANTIC +struct CopyConstructorTest { + int i; // expected-note{{uninitialized field 'this->i'}} + + CopyConstructorTest() : i(1337) {} + CopyConstructorTest(const CopyConstructorTest &other) {} +}; + +void fCopyConstructorTest() { + CopyConstructorTest cct; + CopyConstructorTest copy = cct; // expected-warning{{1 uninitialized field}} + funcToSquelchCompilerWarnings(copy); +} +#else +struct CopyConstructorTest { + int i; + + CopyConstructorTest() : i(1337) {} + CopyConstructorTest(const CopyConstructorTest &other) {} +}; + +void fCopyConstructorTest() { + CopyConstructorTest cct; + CopyConstructorTest copy = cct; + funcToSquelchCompilerWarnings(copy); +} +#endif // PEDANTIC + +struct MoveConstructorTest { + // TODO: we'd expect the note: {{uninitialized field 'this->i'}} + int i; // no-note + + MoveConstructorTest() : i(1337) {} + MoveConstructorTest(const CopyConstructorTest &other) = delete; + MoveConstructorTest(const CopyConstructorTest &&other) {} +}; + +void fMoveConstructorTest() { + MoveConstructorTest cct; + // TODO: we'd expect the warning: {{1 uninitialized field}} + MoveConstructorTest copy(static_cast(cct)); // no-warning + funcToSquelchCompilerWarnings(copy); +} + +//===----------------------------------------------------------------------===// +// Array tests. +//===----------------------------------------------------------------------===// + +struct IntArrayTest { + int arr[256]; + + IntArrayTest() { + // All good! + } +}; + +void fIntArrayTest() { + IntArrayTest(); +} + +struct RecordTypeArrayTest { + struct RecordType { + int x, y; + } arr[256]; + + RecordTypeArrayTest() { + // All good! + } +}; + +void fRecordTypeArrayTest() { + RecordTypeArrayTest(); +} + +template +class CharArrayPointerTest { + T *t; // no-crash + +public: + CharArrayPointerTest(T *t, int) : t(t) {} +}; + +void fCharArrayPointerTest() { + char str[16] = "012345678912345"; + CharArrayPointerTest(&str, int()); +} + +//===----------------------------------------------------------------------===// +// Memset tests. +//===----------------------------------------------------------------------===// + +struct MemsetTest1 { + int a, b, c; + + MemsetTest1() { + __builtin_memset(this, 0, sizeof(decltype(*this))); + } +}; + +void fMemsetTest1() { + MemsetTest1(); +} + +struct MemsetTest2 { + int a; + + MemsetTest2() { + __builtin_memset(&a, 0, sizeof(int)); + } +}; + +void fMemsetTest2() { + MemsetTest2(); +} + +//===----------------------------------------------------------------------===// +// Lambda tests. +//===----------------------------------------------------------------------===// + +template +struct LambdaTest1 { + Callable functor; + + LambdaTest1(const Callable &functor, int) : functor(functor) { + // All good! + } +}; + +void fLambdaTest1() { + auto isEven = [](int a) { return a % 2 == 0; }; + LambdaTest1(isEven, int()); +} + +#ifdef PEDANTIC +template +struct LambdaTest2 { + Callable functor; + + LambdaTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}} +}; + +void fLambdaTest2() { + int b; + auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.'}} + LambdaTest2(equals, int()); +} +#else +template +struct LambdaTest2 { + Callable functor; + + LambdaTest2(const Callable &functor, int) : functor(functor) {} +}; + +void fLambdaTest2() { + int b; + auto equals = [&b](int a) { return a == b; }; + LambdaTest2(equals, int()); +} +#endif //PEDANTIC + +#ifdef PEDANTIC +namespace LT3Detail { + +struct RecordType { + int x; // expected-note{{uninitialized field 'this->functor..x'}} + int y; // expected-note{{uninitialized field 'this->functor..y'}} +}; + +} // namespace LT3Detail +template +struct LambdaTest3 { + Callable functor; + + LambdaTest3(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized fields}} +}; + +void fLambdaTest3() { + LT3Detail::RecordType rec1; + auto equals = [&rec1](LT3Detail::RecordType rec2) { + return rec1.x == rec2.x; + }; + LambdaTest3(equals, int()); +} +#else +namespace LT3Detail { + +struct RecordType { + int x; + int y; +}; + +} // namespace LT3Detail +template +struct LambdaTest3 { + Callable functor; + + LambdaTest3(const Callable &functor, int) : functor(functor) {} +}; + +void fLambdaTest3() { + LT3Detail::RecordType rec1; + auto equals = [&rec1](LT3Detail::RecordType rec2) { + return rec1.x == rec2.x; + }; + LambdaTest3(equals, int()); +} +#endif //PEDANTIC + +//===----------------------------------------------------------------------===// +// System header tests. +//===----------------------------------------------------------------------===// + +#include "Inputs/system-header-simulator-for-cxx-uninitialized-object.h" + +struct SystemHeaderTest1 { + RecordInSystemHeader rec; // defined in the system header simulator + + SystemHeaderTest1() { + // All good! + } +}; + +void fSystemHeaderTest1() { + SystemHeaderTest1(); +} + +#ifdef PEDANTIC +struct SystemHeaderTest2 { + struct RecordType { + int x; // expected-note{{uninitialized field 'this->container.t.x}} + int y; // expected-note{{uninitialized field 'this->container.t.y}} + }; + ContainerInSystemHeader container; + + SystemHeaderTest2(RecordType &rec, int) : container(rec) {} // expected-warning{{2 uninitialized fields}} +}; + +void fSystemHeaderTest2() { + SystemHeaderTest2::RecordType rec; + SystemHeaderTest2(rec, int()); +} +#else +struct SystemHeaderTest2 { + struct RecordType { + int x; + int y; + }; + ContainerInSystemHeader container; + + SystemHeaderTest2(RecordType &rec, int) : container(rec) {} +}; + +void fSystemHeaderTest2() { + SystemHeaderTest2::RecordType rec; + SystemHeaderTest2(rec, int()); +} +#endif //PEDANTIC + +//===----------------------------------------------------------------------===// +// Incomplete type tests. +//===----------------------------------------------------------------------===// + +struct IncompleteTypeTest1 { + struct RecordType; + // no-crash + RecordType *recptr; // expected-note{{uninitialized pointer 'this->recptr}} + int dontGetFilteredByNonPedanticMode = 0; + + IncompleteTypeTest1() {} // expected-warning{{1 uninitialized field}} +}; + +void fIncompleteTypeTest1() { + IncompleteTypeTest1(); +} + +struct IncompleteTypeTest2 { + struct RecordType; + RecordType *recptr; // no-crash + int dontGetFilteredByNonPedanticMode = 0; + + RecordType *recordTypeFactory(); + + IncompleteTypeTest2() : recptr(recordTypeFactory()) {} +}; + +void fIncompleteTypeTest2() { + IncompleteTypeTest2(); +} + +struct IncompleteTypeTest3 { + struct RecordType; + RecordType &recref; // no-crash + int dontGetFilteredByNonPedanticMode = 0; + + RecordType &recordTypeFactory(); + + IncompleteTypeTest3() : recref(recordTypeFactory()) {} +}; + +void fIncompleteTypeTest3() { + IncompleteTypeTest3(); +} + +//===----------------------------------------------------------------------===// +// Builtin type or enumeration type related tests. +//===----------------------------------------------------------------------===// + +struct IntegralTypeTest { + int a; // expected-note{{uninitialized field 'this->a'}} + int dontGetFilteredByNonPedanticMode = 0; + + IntegralTypeTest() {} // expected-warning{{1 uninitialized field}} +}; + +void fIntegralTypeTest() { + IntegralTypeTest(); +} + +struct FloatingTypeTest { + float a; // expected-note{{uninitialized field 'this->a'}} + int dontGetFilteredByNonPedanticMode = 0; + + FloatingTypeTest() {} // expected-warning{{1 uninitialized field}} +}; + +void fFloatingTypeTest() { + FloatingTypeTest(); +} + +struct NullptrTypeTypeTest { + decltype(nullptr) a; // expected-note{{uninitialized field 'this->a'}} + int dontGetFilteredByNonPedanticMode = 0; + + NullptrTypeTypeTest() {} // expected-warning{{1 uninitialized field}} +}; + +void fNullptrTypeTypeTest() { + NullptrTypeTypeTest(); +} + +struct EnumTest { + enum Enum { + A, + B + } enum1; // expected-note{{uninitialized field 'this->enum1'}} + enum class Enum2 { + A, + B + } enum2; // expected-note{{uninitialized field 'this->enum2'}} + int dontGetFilteredByNonPedanticMode = 0; + + EnumTest() {} // expected-warning{{2 uninitialized fields}} +}; + +void fEnumTest() { + EnumTest(); +} + +//===----------------------------------------------------------------------===// +// Tests for constructor calls within another cunstructor, without the two +// records being in any relation. +//===----------------------------------------------------------------------===// + +void halt() __attribute__((__noreturn__)); +void assert(int b) { + if (!b) + halt(); +} + +// While a singleton would make more sense as a static variable, that would zero +// initialize all of its fields, hence the not too practical implementation. +struct Singleton { + // TODO: we'd expect the note: {{uninitialized field 'this->i'}} + int i; // no-note + + Singleton() { + assert(!isInstantiated); + // TODO: we'd expect the warning: {{1 uninitialized field}} + isInstantiated = true; // no-warning + } + + ~Singleton() { + isInstantiated = false; + } + + static bool isInstantiated; +}; + +bool Singleton::isInstantiated = false; + +struct SingletonTest { + int dontGetFilteredByNonPedanticMode = 0; + + SingletonTest() { + Singleton(); + } +}; + +void fSingletonTest() { + SingletonTest(); +} + +//===----------------------------------------------------------------------===// +// C++11 member initializer tests. +//===----------------------------------------------------------------------===// + +struct CXX11MemberInitTest1 { + int a = 3; + int b; + CXX11MemberInitTest1() : b(2) { + // All good! + } +}; + +void fCXX11MemberInitTest1() { + CXX11MemberInitTest1(); +} + +struct CXX11MemberInitTest2 { + struct RecordType { + // TODO: we'd expect the note: {{uninitialized field 'this->rec.a'}} + int a; // no-note + // TODO: we'd expect the note: {{uninitialized field 'this->rec.b'}} + int b; // no-note + + RecordType(int) {} + }; + + RecordType rec = RecordType(int()); + int dontGetFilteredByNonPedanticMode = 0; + + CXX11MemberInitTest2() {} +}; + +void fCXX11MemberInitTest2() { + // TODO: we'd expect the warning: {{2 uninitializeds field}} + CXX11MemberInitTest2(); // no-warning +} -- GitLab From 261aad80c8b0592f57fbda1244a44295ad2bfeb3 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Mon, 18 Jun 2018 12:22:17 +0000 Subject: [PATCH 0168/1023] Update copyright year to 2018. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334936 91177308-0d34-0410-b5e6-96231b3b80d8 --- LICENSE.TXT | 2 +- tools/clang-format-vs/ClangFormat/license.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.TXT b/LICENSE.TXT index b452ca2efd..547f6a4893 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -4,7 +4,7 @@ LLVM Release License University of Illinois/NCSA Open Source License -Copyright (c) 2007-2016 University of Illinois at Urbana-Champaign. +Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: diff --git a/tools/clang-format-vs/ClangFormat/license.txt b/tools/clang-format-vs/ClangFormat/license.txt index 9966c8123f..76aa2afdf8 100644 --- a/tools/clang-format-vs/ClangFormat/license.txt +++ b/tools/clang-format-vs/ClangFormat/license.txt @@ -4,7 +4,7 @@ LLVM Release License University of Illinois/NCSA Open Source License -Copyright (c) 2007-2017 University of Illinois at Urbana-Champaign. +Copyright (c) 2007-2018 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: -- GitLab From 6ec623490af2011ba3f67cd31ce045d581e452b5 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 18 Jun 2018 17:11:45 +0000 Subject: [PATCH 0169/1023] [OPENMP, NVPTX] Emit simple reduction if requested. If simple reduction is requested, use the simple reduction instead of the runtime functions calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334962 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 6 ++++++ test/OpenMP/nvptx_target_simd_codegen.cpp | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 785ed56760..9452bdea4c 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -3163,6 +3163,12 @@ void CGOpenMPRuntimeNVPTX::emitReduction( assert((TeamsReduction || ParallelReduction || SimdReduction) && "Invalid reduction selection in emitReduction."); + if (Options.SimpleReduction) { + CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, + ReductionOps, Options); + return; + } + ASTContext &C = CGM.getContext(); // 1. Build a list of reduction variables. diff --git a/test/OpenMP/nvptx_target_simd_codegen.cpp b/test/OpenMP/nvptx_target_simd_codegen.cpp index 5f307d8835..89ea173add 100644 --- a/test/OpenMP/nvptx_target_simd_codegen.cpp +++ b/test/OpenMP/nvptx_target_simd_codegen.cpp @@ -78,9 +78,8 @@ int bar(int n){ // CHECK: call void @__kmpc_kernel_init(i32 %{{.+}}, i16 1) // CHECK-NOT: call void @__kmpc_for_static_init // CHECK-NOT: call void @__kmpc_for_static_fini -// CHECK: [[RES:%.+]] = call i32 @__kmpc_nvptx_simd_reduce_nowait(i32 %{{.+}}, i32 1, i{{64|32}} {{8|4}}, i8* %{{.+}}, void (i8*, i16, i16, i16)* @{{.+}}, void (i8*, i32)* @{{.+}}) -// CHECK: switch i32 [[RES]] -// CHECK: call void @__kmpc_nvptx_end_reduce_nowait(i32 %{{.+}}) +// CHECK-NOT: call i32 @__kmpc_nvptx_simd_reduce_nowait( +// CHECK-NOT: call void @__kmpc_nvptx_end_reduce_nowait( // CHECK: call void @__kmpc_kernel_deinit(i16 1) // CHECK: ret void -- GitLab From 111922d4a2589e470b612788433b846eb7c1bbee Mon Sep 17 00:00:00 2001 From: Tomasz Krupa Date: Mon, 18 Jun 2018 17:57:05 +0000 Subject: [PATCH 0170/1023] Fix a bug introduced by rL334850 Summary: All *_sqrt_round_s[s|d] intrinsics should execute a square root on zeroth element from B (Ops[1]) and insert in to A (Ops[0]), not the other way around. Reviewers: itaraban, craig.topper Reviewed By: craig.topper Subscribers: craig.topper, cfe-commits Differential Revision: https://reviews.llvm.org/D48288 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334964 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 7b0ea22f94..739f2341d9 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9907,7 +9907,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Intrinsic::x86_avx512_mask_sqrt_ss; return Builder.CreateCall(CGM.getIntrinsic(IID), Ops); } - Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); + Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0); Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType()); Value *Src = Builder.CreateExtractElement(Ops[2], (uint64_t)0); int MaskSize = Ops[3]->getType()->getScalarSizeInBits(); @@ -9915,7 +9915,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *Mask = Builder.CreateBitCast(Ops[3], MaskTy); Mask = Builder.CreateExtractElement(Mask, (uint64_t)0); A = Builder.CreateSelect(Mask, Builder.CreateCall(F, {A}), Src); - return Builder.CreateInsertElement(Ops[1], A, (uint64_t)0); + return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0); } case X86::BI__builtin_ia32_sqrtpd256: case X86::BI__builtin_ia32_sqrtpd: -- GitLab From 46ac88f786ba30c569c8ab179716d97e020ad2ad Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 18 Jun 2018 17:59:03 +0000 Subject: [PATCH 0171/1023] [analyzer] Remove accidentally committed lines. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334965 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporter.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 9e4ba81a97..94d08b4935 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2548,10 +2548,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // new symbols and regions are interesting, or add other visitors based on // the information they find. If they do, we need to regenerate the path // based on our new report configuration. - int jj=0; - do { // TODO: dump statistics on the MAX number of iterations of this loop. - jj++; - assert(jj<10); + do { // Get a clean copy of all the visitors. for (BugReport::visitor_iterator I = R->visitor_begin(), E = R->visitor_end(); I != E; ++I) -- GitLab From ec4717bda81827af455efa04c367c168cf1f221c Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 18 Jun 2018 18:50:35 +0000 Subject: [PATCH 0172/1023] Don't let test/Driver/no-canonical-prefixes.c form a symlink cycle the second time it runs. The test makes %t.fake a symlink to %t.real by running `ln -sf %t.real %t.fake`. If %t.fake already is a symlink to %t.real when this runs (e.g. if the test has run before), then this effectively becomes `ln -sf %t.real %t.real`, symlinking the directory to itself. At least on my mac, this leads to the directory containing itself. As fix, just remove %t.fake before creating the symlink. To clean up build dirs on bots, also remove %t.real for a while. https://reviews.llvm.org/D48224 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334972 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/no-canonical-prefixes.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Driver/no-canonical-prefixes.c b/test/Driver/no-canonical-prefixes.c index 7bc76be22d..8b9e04410e 100644 --- a/test/Driver/no-canonical-prefixes.c +++ b/test/Driver/no-canonical-prefixes.c @@ -1,9 +1,14 @@ // Due to ln -sf: // REQUIRES: shell +// RUN: rm -rf %t.real // RUN: mkdir -p %t.real // RUN: cd %t.real // RUN: ln -sf %clang test-clang // RUN: cd .. +// Important to remove %t.fake: If it already is a symlink to %t.real when +// `ln -sf %t.real %t.fake` runs, then that would symlink %t.real to itself, +// forming a cycle. +// RUN: rm -rf %t.fake // RUN: ln -sf %t.real %t.fake // RUN: cd %t.fake // RUN: ./test-clang -v -S %s 2>&1 | FileCheck --check-prefix=CANONICAL %s -- GitLab From e614f166bb3e789f37ea24d0de743658ce85165c Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 18 Jun 2018 20:58:54 +0000 Subject: [PATCH 0173/1023] IRgen: Mark aliases of ctors and dtors as unnamed_addr. This is not only semantically correct but ensures that they will not be marked as address-significant once D48155 lands. Differential Revision: https://reviews.llvm.org/D48206 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334982 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXX.cpp | 16 +++++----------- lib/CodeGen/CodeGenModule.h | 1 - lib/CodeGen/ItaniumCXXABI.cpp | 3 +++ test/CodeGenCXX/constructor-alias.cpp | 2 +- test/CodeGenCXX/ctor-dtor-alias.cpp | 12 ++++++------ test/CodeGenCXX/destructors.cpp | 12 ++++++------ test/CodeGenCXX/dllexport-alias.cpp | 4 ++-- test/CodeGenCXX/dllexport.cpp | 2 +- .../CodeGenCXX/microsoft-abi-structors-alias.cpp | 2 +- test/CodeGenCXX/virtual-bases.cpp | 2 +- test/CodeGenCXX/virtual-destructor-calls.cpp | 6 +++--- 11 files changed, 29 insertions(+), 33 deletions(-) diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index cde4c9b96f..475f17b77d 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -109,17 +109,8 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { D->getType()->getAs()->getCallConv()) return true; - return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), - GlobalDecl(BaseD, Dtor_Base)); -} - -/// Try to emit a definition as a global alias for another definition. -/// If \p InEveryTU is true, we know that an equivalent alias can be produced -/// in every translation unit. -bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, - GlobalDecl TargetDecl) { - if (!getCodeGenOpts().CXXCtorDtorAliases) - return true; + GlobalDecl AliasDecl(D, Dtor_Base); + GlobalDecl TargetDecl(BaseD, Dtor_Base); // The alias will use the linkage of the referent. If we can't // support aliases with that linkage, fail. @@ -193,6 +184,9 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "", Aliasee, &getModule()); + // Destructors are always unnamed_addr. + Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + // Switch any previous uses to the alias. if (Entry) { assert(Entry->getType() == AliasType && diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 89823982ac..bf22ad246c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -1193,7 +1193,6 @@ public: /// are emitted lazily. void EmitGlobal(GlobalDecl D); - bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); llvm::GlobalValue *GetGlobalValue(StringRef Ref); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index b79e51f3ae..d855afab22 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -3693,6 +3693,9 @@ static void emitConstructorDestructorAlias(CodeGenModule &CGM, // Create the alias with no name. auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee); + // Constructors and destructors are always unnamed_addr. + Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + // Switch any previous uses to the alias. if (Entry) { assert(Entry->getType() == Aliasee->getType() && diff --git a/test/CodeGenCXX/constructor-alias.cpp b/test/CodeGenCXX/constructor-alias.cpp index 8359bb90a0..ee2e57b711 100644 --- a/test/CodeGenCXX/constructor-alias.cpp +++ b/test/CodeGenCXX/constructor-alias.cpp @@ -9,4 +9,4 @@ struct B { B::B() { } -// CHECK: @_ZN1BC1Ev = alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev +// CHECK: @_ZN1BC1Ev = unnamed_addr alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index d72c5b48b3..89244cc105 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -14,8 +14,8 @@ namespace test1 { // Test that we produce the appropriate comdats when creating aliases to // weak_odr constructors and destructors. -// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev -// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev +// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev // CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) // CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) @@ -141,7 +141,7 @@ namespace test7 { namespace test8 { // Test that we replace ~zed with ~bar which is an alias to ~foo. - // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev + // CHECK4: @_ZN5test83barD2Ev = unnamed_addr alias {{.*}} @_ZN5test83fooD2Ev // CHECK4: define internal void @__cxx_global_var_init.5() // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev struct foo { @@ -232,8 +232,8 @@ struct foo : public bar { ~foo(); }; foo::~foo() {} -// CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev -// CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev +// CHECK6: @_ZN6test113fooD2Ev = unnamed_addr alias {{.*}} @_ZN6test113barD2Ev +// CHECK6: @_ZN6test113fooD1Ev = unnamed_addr alias {{.*}} @_ZN6test113fooD2Ev } namespace test12 { @@ -243,6 +243,6 @@ struct foo { }; template class foo<1>; -// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr alias {{.*}} @_ZN6test123fooILi1EED2Ev +// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr unnamed_addr alias {{.*}} @_ZN6test123fooILi1EED2Ev // CHECK6: define weak_odr void @_ZN6test123fooILi1EED2Ev({{.*}}) {{.*}} comdat($_ZN6test123fooILi1EED5Ev) } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 180e82de9f..ba8333b00d 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -96,7 +96,7 @@ namespace test0 { // complete destructor alias tested above -// CHECK2-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev // CHECK2-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr // CHECK2: invoke void @_ZN5test06MemberD1Ev // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] @@ -104,7 +104,7 @@ namespace test0 { // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] // In C++11, the destructors are often known not to throw. -// CHECK2v11-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2v11-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev // CHECK2v11-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr // CHECK2v11: call void @_ZN5test06MemberD1Ev // CHECK2v11: call void @_ZN5test04BaseD2Ev @@ -153,15 +153,15 @@ namespace test1 { struct M : A { ~M(); }; M::~M() {} - // CHECK3: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11MD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct N : A, Empty { ~N(); }; N::~N() {} - // CHECK3: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11ND2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct O : Empty, A { ~O(); }; O::~O() {} - // CHECK3: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11OD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct P : NonEmpty, A { ~P(); }; P::~P() {} // CHECK3-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr @@ -174,7 +174,7 @@ namespace test1 { struct S : A { ~S(); int x; }; S::~S() {} - // CHECK4: @_ZN5test11SD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev + // CHECK4: @_ZN5test11SD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev struct T : A { ~T(); B x; }; T::~T() {} // CHECK4-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr diff --git a/test/CodeGenCXX/dllexport-alias.cpp b/test/CodeGenCXX/dllexport-alias.cpp index 65f2946b7b..7eec9cf783 100644 --- a/test/CodeGenCXX/dllexport-alias.cpp +++ b/test/CodeGenCXX/dllexport-alias.cpp @@ -14,5 +14,5 @@ A::A() {} A::~A() {} -// CHECK: @_ZN1AC1Ev = dso_local dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AC2Ev -// CHECK: @_ZN1AD1Ev = dso_local dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AD2Ev +// CHECK: @_ZN1AC1Ev = dso_local dllexport unnamed_addr alias void (%class.A*), void (%class.A*)* @_ZN1AC2Ev +// CHECK: @_ZN1AD1Ev = dso_local dllexport unnamed_addr alias void (%class.A*), void (%class.A*)* @_ZN1AD2Ev diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index b867662e09..3921144e86 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -641,7 +641,7 @@ namespace UseDtorAlias { A::~A() { } B::~B() { } // Emit a alias definition of B's constructor. - // M32-DAG: @"??1B@UseDtorAlias@@QAE@XZ" = dso_local dllexport alias {{.*}} @"??1A@UseDtorAlias@@QAE@XZ" + // M32-DAG: @"??1B@UseDtorAlias@@QAE@XZ" = dso_local dllexport unnamed_addr alias {{.*}} @"??1A@UseDtorAlias@@QAE@XZ" } struct __declspec(dllexport) DefaultedCtorsDtors { diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp index 1aa089324d..38f7b4c8b5 100644 --- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp @@ -22,7 +22,7 @@ B::~B() {} void foo() { B b; } -// CHECK-DAG: @"??1B@test2@@UAE@XZ" = dso_local alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*) +// CHECK-DAG: @"??1B@test2@@UAE@XZ" = dso_local unnamed_addr alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*) } namespace test3 { diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 18d4bf0cde..259b1c157b 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -4,7 +4,7 @@ struct A { A(); }; -// CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev +// CHECK: @_ZN1AC1Ev = unnamed_addr alias {{.*}} @_ZN1AC2Ev // CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr A::A() { } diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index 2e63daac31..10d82367fd 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -14,11 +14,11 @@ struct B : A { }; // Complete dtor: just an alias because there are no virtual bases. -// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev +// CHECK: @_ZN1BD1Ev = unnamed_addr alias {{.*}} @_ZN1BD2Ev // (aliases from C) -// CHECK: @_ZN1CD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN1BD2Ev -// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev +// CHECK: @_ZN1CD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN1BD2Ev +// CHECK: @_ZN1CD1Ev = unnamed_addr alias {{.*}} @_ZN1CD2Ev // Base dtor: actually calls A's base dtor. // CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr -- GitLab From b93627660685bf26a05c6a429a2d330805b160af Mon Sep 17 00:00:00 2001 From: Taiju Tsuiki Date: Tue, 19 Jun 2018 04:39:07 +0000 Subject: [PATCH 0174/1023] Update NRVO logic to support early return (Attempt 2) Summary: This is the second attempt of r333500 (Update NRVO logic to support early return). The previous one was reverted for a miscompilation for an incorrect NRVO set up on templates such as: ``` struct Foo {}; template T bar() { T t; if (false) return T(); return t; } ``` Where, `t` is marked as non-NRVO variable before its instantiation. However, while its instantiation, it's left an NRVO candidate, turned into an NRVO variable later. Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47586 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335019 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 20 ++- include/clang/Sema/Scope.h | 22 +--- lib/Sema/Scope.cpp | 24 ++-- lib/Sema/SemaDecl.cpp | 33 +++-- lib/Sema/SemaExpr.cpp | 10 +- lib/Sema/SemaStmt.cpp | 9 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +- lib/Serialization/ASTReaderDecl.cpp | 2 +- lib/Serialization/ASTWriterDecl.cpp | 4 +- test/CodeGenCXX/nrvo-noopt.cpp | 58 +++++++++ test/CodeGenCXX/nrvo.cpp | 51 ++++++-- test/SemaCXX/nrvo-ast.cpp | 153 +++++++++++++++++++++++ 12 files changed, 307 insertions(+), 84 deletions(-) create mode 100644 test/CodeGenCXX/nrvo-noopt.cpp create mode 100644 test/SemaCXX/nrvo-ast.cpp diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index c10ca9e967..0a0b2c16c0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -879,6 +879,12 @@ protected: DAK_Normal }; + enum NRVOMode { + NRVO_Candidate, + NRVO_Disabled, + NRVO_Enabled, + }; + class ParmVarDeclBitfields { friend class ASTDeclReader; friend class ParmVarDecl; @@ -931,7 +937,7 @@ protected: /// Whether this local variable could be allocated in the return /// slot of its function, enabling the named return value optimization /// (NRVO). - unsigned NRVOVariable : 1; + unsigned NRVOMode : 2; /// Whether this variable is the for-range-declaration in a C++0x /// for-range statement. @@ -1319,12 +1325,20 @@ public: /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. + NRVOMode getNRVOMode() const { + if (isa(this)) + return NRVO_Disabled; + return static_cast(NonParmVarDeclBits.NRVOMode); + } + bool isNRVOCandidate() const { + return isa(this) ? false : NonParmVarDeclBits.NRVOMode == NRVO_Candidate; + } bool isNRVOVariable() const { - return isa(this) ? false : NonParmVarDeclBits.NRVOVariable; + return isa(this) ? false : NonParmVarDeclBits.NRVOMode == NRVO_Enabled; } void setNRVOVariable(bool NRVO) { assert(!isa(this)); - NonParmVarDeclBits.NRVOVariable = NRVO; + NonParmVarDeclBits.NRVOMode = NRVO ? NRVO_Enabled : NRVO_Disabled; } /// Determine whether this variable is the for-range-declaration in diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index a3379ff34f..298c5461ad 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -201,10 +201,6 @@ private: /// Used to determine if errors occurred in this scope. DiagnosticErrorTrap ErrorTrap; - /// A lattice consisting of undefined, a single NRVO candidate variable in - /// this scope, or over-defined. The bit is true when over-defined. - llvm::PointerIntPair NRVO; - void setFlags(Scope *Parent, unsigned F); public: @@ -466,23 +462,7 @@ public: UsingDirectives.end()); } - void addNRVOCandidate(VarDecl *VD) { - if (NRVO.getInt()) - return; - if (NRVO.getPointer() == nullptr) { - NRVO.setPointer(VD); - return; - } - if (NRVO.getPointer() != VD) - setNoNRVO(); - } - - void setNoNRVO() { - NRVO.setInt(true); - NRVO.setPointer(nullptr); - } - - void mergeNRVOIntoParent(); + void setNRVOCandidate(VarDecl *Candidate); /// Init - This is used by the parser to implement scope caching. void Init(Scope *parent, unsigned flags); diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp index eae5a328bf..5a46ba26d2 100644 --- a/lib/Sema/Scope.cpp +++ b/lib/Sema/Scope.cpp @@ -92,7 +92,6 @@ void Scope::Init(Scope *parent, unsigned flags) { UsingDirectives.clear(); Entity = nullptr; ErrorTrap.reset(); - NRVO.setPointerAndInt(nullptr, 0); } bool Scope::containedInPrototypeScope() const { @@ -119,19 +118,15 @@ void Scope::AddFlags(unsigned FlagsToSet) { Flags |= FlagsToSet; } -void Scope::mergeNRVOIntoParent() { - if (VarDecl *Candidate = NRVO.getPointer()) { - if (isDeclScope(Candidate)) - Candidate->setNRVOVariable(true); +void Scope::setNRVOCandidate(VarDecl *Candidate) { + for (Decl *D : DeclsInScope) { + VarDecl *VD = dyn_cast(D); + if (VD && VD != Candidate && VD->isNRVOCandidate()) + VD->setNRVOVariable(false); } - if (getEntity()) - return; - - if (NRVO.getInt()) - getParent()->setNoNRVO(); - else if (NRVO.getPointer()) - getParent()->addNRVOCandidate(NRVO.getPointer()); + if (Scope *parent = getParent()) + parent->setNRVOCandidate(Candidate); } LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } @@ -191,9 +186,4 @@ void Scope::dumpImpl(raw_ostream &OS) const { OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; - - if (NRVO.getInt()) - OS << "NRVO not allowed\n"; - else if (NRVO.getPointer()) - OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f6faf38c95..4c98ffed71 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1798,8 +1798,6 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { - S->mergeNRVOIntoParent(); - if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && "Scope shouldn't contain decls!"); @@ -12563,21 +12561,24 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, /// optimization. /// /// Each of the variables that is subject to the named return value -/// optimization will be marked as NRVO variables in the AST, and any +/// optimization will be marked as NRVO variable candidates in the AST, and any /// return statement that has a marked NRVO variable as its NRVO candidate can /// use the named return value optimization. /// -/// This function applies a very simplistic algorithm for NRVO: if every return -/// statement in the scope of a variable has the same NRVO candidate, that -/// candidate is an NRVO variable. +/// This function applies a very simplistic algorithm for NRVO: if every +/// reachable return statement in the scope of a variable has the same NRVO +/// candidate, that candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { - ReturnStmt **Returns = Scope->Returns.data(); + for (ReturnStmt *Return : Scope->Returns) { + const VarDecl *Candidate = Return->getNRVOCandidate(); + if (!Candidate) + continue; - for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { - if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) { - if (!NRVOCandidate->isNRVOVariable()) - Returns[I]->setNRVOCandidate(nullptr); - } + if (Candidate->isNRVOCandidate()) + const_cast(Candidate)->setNRVOVariable(true); + + if (!Candidate->isNRVOVariable()) + Return->setNRVOCandidate(nullptr); } } @@ -12712,12 +12713,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, else if (CXXDestructorDecl *Destructor = dyn_cast(FD)) MarkVTableUsed(FD->getLocation(), Destructor->getParent()); - // Try to apply the named return value optimization. We have to check - // if we can do this here because lambdas keep return statements around - // to deduce an implicit return type. - if (FD->getReturnType()->isRecordType() && - (!getLangOpts().CPlusPlus || !FD->isDependentContext())) - computeNRVO(Body, getCurFunction()); + // Try to apply the named return value optimization. + computeNRVO(Body, getCurFunction()); } // GNU warning -Wmissing-prototypes: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index aeedd6b169..220d690695 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -13385,13 +13385,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Body && getCurFunction()->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); - // Try to apply the named return value optimization. We have to check again - // if we can do this, though, because blocks keep return statements around - // to deduce an implicit return type. - if (getLangOpts().CPlusPlus && RetTy->isRecordType() && - !BSI->TheDecl->isDependentContext()) - computeNRVO(Body, BSI); - + // Try to apply the named return value optimization. + computeNRVO(Body, BSI); + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index ccf25ee9eb..04f5114510 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3455,12 +3455,9 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, ExpressionEvaluationContext::DiscardedStatement) return R; - if (VarDecl *VD = - const_cast(cast(R.get())->getNRVOCandidate())) { - CurScope->addNRVOCandidate(VD); - } else { - CurScope->setNoNRVO(); - } + VarDecl *VD = + const_cast(cast(R.get())->getNRVOCandidate()); + CurScope->setNRVOCandidate(VD); CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 68857d972b..7e38dcc795 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -740,12 +740,13 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope, InstantiatingVarTemplate); + bool NRVO = false; if (D->isNRVOVariable()) { QualType ReturnType = cast(DC)->getReturnType(); if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) - Var->setNRVOVariable(true); + NRVO = true; } - + Var->setNRVOVariable(NRVO); Var->setImplicit(D->isImplicit()); return Var; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index a1ce26d27c..699a98ce4f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1326,7 +1326,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = Record.readInt(); VD->NonParmVarDeclBits.ExceptionVar = Record.readInt(); - VD->NonParmVarDeclBits.NRVOVariable = Record.readInt(); + VD->NonParmVarDeclBits.NRVOMode = Record.readInt(); VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt(); VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt(); VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt(); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index cf35a2bc1f..c1f983e5ce 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -918,7 +918,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { if (!isa(D)) { Record.push_back(D->isThisDeclarationADemotedDefinition()); Record.push_back(D->isExceptionVariable()); - Record.push_back(D->isNRVOVariable()); + Record.push_back(D->getNRVOMode()); Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isObjCForDecl()); Record.push_back(D->isARCPseudoStrong()); @@ -2031,7 +2031,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // NRVOMode Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong diff --git a/test/CodeGenCXX/nrvo-noopt.cpp b/test/CodeGenCXX/nrvo-noopt.cpp new file mode 100644 index 0000000000..46da7cd013 --- /dev/null +++ b/test/CodeGenCXX/nrvo-noopt.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +struct X { + X(); + X(X&&); +}; + +// CHECK-LABEL: define void @_Z7test_00b +X test_00(bool b) { + if (b) { + // CHECK-NOT: call void @_ZN1XC1EOS_ + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: br label %return + X x; + return x; + } else { + // CHECK-NOT: call void @_ZN1XC1EOS_ + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: br label %return + X x; + return x; + } +} + +// CHECK-LABEL: define void @_Z7test_01b +X test_01(bool b) { + if (b) { + // CHECK-NOT: call void @_ZN1XC1EOS_ + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: br label %return + X x; + return x; + } + // CHECK-NOT: call void @_ZN1XC1EOS_ + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: br label %return + X x; + return x; +} + +// CHECK-LABEL: define void @_Z7test_02b +X test_02(bool b) { + // CHECK: call void @_ZN1XC1Ev + X x; + + if (b) { + // CHECK-NOT: call void @_ZN1XC1EOS_ + // CHECK: call void @_ZN1XC1Ev + // CHECK-NEXT: br label %return + X y; + return y; + } + + // CHECK-NOT: call void @_ZN1XC1Ev + // CHECK: call void @_ZN1XC1EOS_ + // CHECK-NEXT: br label %return + return x; +} diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 0f359b9c90..1da4308e26 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -130,17 +130,13 @@ X test2(bool B) { } // CHECK-LABEL: define void @_Z5test3b -X test3(bool B) { +X test3(bool B, X x) { // CHECK: tail call {{.*}} @_ZN1XC1Ev - // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ - // CHECK: call {{.*}} @_ZN1XC1Ev - // CHECK: call {{.*}} @_ZN1XC1ERKS_ if (B) { X y; return y; } - // FIXME: we should NRVO this variable too. - X x; + // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ return x; } @@ -191,9 +187,13 @@ X test6() { } // CHECK-LABEL: define void @_Z5test7b +// CHECK-EH-LABEL: define void @_Z5test7b X test7(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret if (b) { X x; return x; @@ -202,10 +202,14 @@ X test7(bool b) { } // CHECK-LABEL: define void @_Z5test8b +// CHECK-EH-LABEL: define void @_Z5test8b X test8(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret - if (b) { + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret +if (b) { X x; return x; } else { @@ -221,4 +225,37 @@ Y test9() { // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev +// CHECK-LABEL: define void @_Z6test10b +X test10(bool B, X x) { + if (B) { + // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ + // CHECK-EH: tail call {{.*}} @_ZN1XC1ERKS_ + return x; + } + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NOT: call {{.*}} @_ZN1XC1ERKS_ + X y; + return y; +} + +// CHECK-LABEL: define {{.*}} void @_Z6test11I1XET_v +// CHECK-EH-LABEL: define {{.*}} void @_Z6test11I1XET_v +template +T test11() { + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NEXT: ret void + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret void + T t; + return t; +} + +void test12() { + test11(); +} + // CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/SemaCXX/nrvo-ast.cpp b/test/SemaCXX/nrvo-ast.cpp new file mode 100644 index 0000000000..63fac006e2 --- /dev/null +++ b/test/SemaCXX/nrvo-ast.cpp @@ -0,0 +1,153 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -ast-dump -o - %s | FileCheck %s + +struct X { + X(); + X(const X&); + X(X&&); +}; + +// CHECK-LABEL: FunctionDecl {{.*}} test_00 +X test_00() { + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + return x; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_01 +X test_01(bool b) { + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + if (b) + return x; + return x; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_02 +X test_02(bool b) { + // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo + X x; + // CHECK-NOT: VarDecl {{.*}} y {{.*}} nrvo + X y; + if (b) + return y; + return x; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_03 +X test_03(bool b) { + if (b) { + // CHECK: VarDecl {{.*}} y {{.*}} nrvo + X y; + return y; + } + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + return x; +} + +extern "C" _Noreturn void exit(int) throw(); + +// CHECK-LABEL: FunctionDecl {{.*}} test_04 +X test_04(bool b) { + { + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + if (b) + return x; + } + exit(1); +} + +void may_throw(); +// CHECK-LABEL: FunctionDecl {{.*}} test_05 +X test_05() { + try { + may_throw(); + return X(); + } catch (X x) { + // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo + return x; + } +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_06 +X test_06() { + // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo + X x __attribute__((aligned(8))); + return x; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_07 +X test_07(bool b) { + if (b) { + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + return x; + } + return X(); +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_08 +X test_08(bool b) { + if (b) { + // CHECK: VarDecl {{.*}} x {{.*}} nrvo + X x; + return x; + } else { + // CHECK: VarDecl {{.*}} y {{.*}} nrvo + X y; + return y; + } +} + +template +struct Y { + Y(); + // CHECK-LABEL: CXXMethodDecl {{.*}} test_09 'Y ()' + // CHECK: VarDecl {{.*}} y 'Y' nrvo + + // CHECK-LABEL: CXXMethodDecl {{.*}} test_09 'Y ()' + // CHECK: VarDecl {{.*}} y 'Y' nrvo + static Y test_09() { + Y y; + return y; + } +}; + +struct Z { + Z(const X&); +}; + +// CHECK-LABEL: FunctionDecl {{.*}} test_10 'A ()' +// CHECK: VarDecl {{.*}} b 'B' nrvo + +// CHECK-LABEL: FunctionDecl {{.*}} test_10 'X ()' +// CHECK: VarDecl {{.*}} b {{.*}} nrvo + +// CHECK-LABEL: FunctionDecl {{.*}} test_10 'Z ()' +// CHECK-NOT: VarDecl {{.*}} b {{.*}} nrvo +template +A test_10() { + B b; + return b; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_11 'A (bool)' +// CHECK-NOT: VarDecl {{.*}} a {{.*}} nrvo + +// CHECK-LABEL: FunctionDecl {{.*}} test_11 'X (bool)' +// CHECK-NOT: VarDecl {{.*}} a {{.*}} nrvo +template +A test_11(bool b) { + A a; + if (b) + return A(); + return a; +} + +void instantiate() { + Y::test_09(); + test_10(); + test_10(); + test_11(true); +} -- GitLab From 485081104cd7d2700ae0c18dd0887cd6251bcfd3 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 19 Jun 2018 05:04:44 +0000 Subject: [PATCH 0175/1023] [Sema] Produce diagnostics for attribute 'trivial_abi' that appears after the closing brace of a class declaration. Merge the two call sites of checkIllFormedTrivialABIStruct and sink it into CheckCompletedCXXClass so that it is called after the attribute has been attached to the CXXRecordDecl. rdar://problem/40873297 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335021 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 11 +++++------ lib/Sema/SemaTemplateInstantiate.cpp | 4 ---- test/SemaObjCXX/attr-trivial-abi.mm | 4 ++++ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e21f380fb7..7a7e0378cf 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6018,6 +6018,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } + // See if trivial_abi has to be dropped. + if (Record->hasAttr()) + checkIllFormedTrivialABIStruct(*Record); + // Set HasTrivialSpecialMemberForCall if the record has attribute // "trivial_abi". bool HasTrivialABI = Record->hasAttr(); @@ -7810,17 +7814,12 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, l->getName(); } - // See if trivial_abi has to be dropped. - auto *RD = dyn_cast(TagDecl); - if (RD && RD->hasAttr()) - checkIllFormedTrivialABIStruct(*RD); - ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( // strict aliasing violation! reinterpret_cast(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(RD); + CheckCompletedCXXClass(dyn_cast_or_null(TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index ebda251c64..2218bdd958 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2123,10 +2123,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, } } - // See if trivial_abi has to be dropped. - if (Instantiation && Instantiation->hasAttr()) - checkIllFormedTrivialABIStruct(*Instantiation); - // Finish checking fields. ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields, SourceLocation(), SourceLocation(), nullptr); diff --git a/test/SemaObjCXX/attr-trivial-abi.mm b/test/SemaObjCXX/attr-trivial-abi.mm index c83a94dcd9..fe8baee473 100644 --- a/test/SemaObjCXX/attr-trivial-abi.mm +++ b/test/SemaObjCXX/attr-trivial-abi.mm @@ -18,6 +18,10 @@ struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' can virtual void m(); }; +struct S3_2 { + virtual void m(); +} __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}} + struct S4 { int a; }; -- GitLab From c16cbd04adda63ff9cf07137d527e6e552495102 Mon Sep 17 00:00:00 2001 From: Taiju Tsuiki Date: Tue, 19 Jun 2018 05:35:30 +0000 Subject: [PATCH 0176/1023] Revert r335019 "Update NRVO logic to support early return (Attempt 2)" git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335022 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 20 +-- include/clang/Sema/Scope.h | 22 +++- lib/Sema/Scope.cpp | 24 ++-- lib/Sema/SemaDecl.cpp | 33 ++--- lib/Sema/SemaExpr.cpp | 10 +- lib/Sema/SemaStmt.cpp | 9 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +- lib/Serialization/ASTReaderDecl.cpp | 2 +- lib/Serialization/ASTWriterDecl.cpp | 4 +- test/CodeGenCXX/nrvo-noopt.cpp | 58 --------- test/CodeGenCXX/nrvo.cpp | 51 ++------ test/SemaCXX/nrvo-ast.cpp | 153 ----------------------- 12 files changed, 84 insertions(+), 307 deletions(-) delete mode 100644 test/CodeGenCXX/nrvo-noopt.cpp delete mode 100644 test/SemaCXX/nrvo-ast.cpp diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0a0b2c16c0..c10ca9e967 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -879,12 +879,6 @@ protected: DAK_Normal }; - enum NRVOMode { - NRVO_Candidate, - NRVO_Disabled, - NRVO_Enabled, - }; - class ParmVarDeclBitfields { friend class ASTDeclReader; friend class ParmVarDecl; @@ -937,7 +931,7 @@ protected: /// Whether this local variable could be allocated in the return /// slot of its function, enabling the named return value optimization /// (NRVO). - unsigned NRVOMode : 2; + unsigned NRVOVariable : 1; /// Whether this variable is the for-range-declaration in a C++0x /// for-range statement. @@ -1325,20 +1319,12 @@ public: /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. - NRVOMode getNRVOMode() const { - if (isa(this)) - return NRVO_Disabled; - return static_cast(NonParmVarDeclBits.NRVOMode); - } - bool isNRVOCandidate() const { - return isa(this) ? false : NonParmVarDeclBits.NRVOMode == NRVO_Candidate; - } bool isNRVOVariable() const { - return isa(this) ? false : NonParmVarDeclBits.NRVOMode == NRVO_Enabled; + return isa(this) ? false : NonParmVarDeclBits.NRVOVariable; } void setNRVOVariable(bool NRVO) { assert(!isa(this)); - NonParmVarDeclBits.NRVOMode = NRVO ? NRVO_Enabled : NRVO_Disabled; + NonParmVarDeclBits.NRVOVariable = NRVO; } /// Determine whether this variable is the for-range-declaration in diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 298c5461ad..a3379ff34f 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -201,6 +201,10 @@ private: /// Used to determine if errors occurred in this scope. DiagnosticErrorTrap ErrorTrap; + /// A lattice consisting of undefined, a single NRVO candidate variable in + /// this scope, or over-defined. The bit is true when over-defined. + llvm::PointerIntPair NRVO; + void setFlags(Scope *Parent, unsigned F); public: @@ -462,7 +466,23 @@ public: UsingDirectives.end()); } - void setNRVOCandidate(VarDecl *Candidate); + void addNRVOCandidate(VarDecl *VD) { + if (NRVO.getInt()) + return; + if (NRVO.getPointer() == nullptr) { + NRVO.setPointer(VD); + return; + } + if (NRVO.getPointer() != VD) + setNoNRVO(); + } + + void setNoNRVO() { + NRVO.setInt(true); + NRVO.setPointer(nullptr); + } + + void mergeNRVOIntoParent(); /// Init - This is used by the parser to implement scope caching. void Init(Scope *parent, unsigned flags); diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp index 5a46ba26d2..eae5a328bf 100644 --- a/lib/Sema/Scope.cpp +++ b/lib/Sema/Scope.cpp @@ -92,6 +92,7 @@ void Scope::Init(Scope *parent, unsigned flags) { UsingDirectives.clear(); Entity = nullptr; ErrorTrap.reset(); + NRVO.setPointerAndInt(nullptr, 0); } bool Scope::containedInPrototypeScope() const { @@ -118,15 +119,19 @@ void Scope::AddFlags(unsigned FlagsToSet) { Flags |= FlagsToSet; } -void Scope::setNRVOCandidate(VarDecl *Candidate) { - for (Decl *D : DeclsInScope) { - VarDecl *VD = dyn_cast(D); - if (VD && VD != Candidate && VD->isNRVOCandidate()) - VD->setNRVOVariable(false); +void Scope::mergeNRVOIntoParent() { + if (VarDecl *Candidate = NRVO.getPointer()) { + if (isDeclScope(Candidate)) + Candidate->setNRVOVariable(true); } - if (Scope *parent = getParent()) - parent->setNRVOCandidate(Candidate); + if (getEntity()) + return; + + if (NRVO.getInt()) + getParent()->setNoNRVO(); + else if (NRVO.getPointer()) + getParent()->addNRVOCandidate(NRVO.getPointer()); } LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } @@ -186,4 +191,9 @@ void Scope::dumpImpl(raw_ostream &OS) const { OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; + + if (NRVO.getInt()) + OS << "NRVO not allowed\n"; + else if (NRVO.getPointer()) + OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4c98ffed71..f6faf38c95 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1798,6 +1798,8 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { + S->mergeNRVOIntoParent(); + if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && "Scope shouldn't contain decls!"); @@ -12561,24 +12563,21 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, /// optimization. /// /// Each of the variables that is subject to the named return value -/// optimization will be marked as NRVO variable candidates in the AST, and any +/// optimization will be marked as NRVO variables in the AST, and any /// return statement that has a marked NRVO variable as its NRVO candidate can /// use the named return value optimization. /// -/// This function applies a very simplistic algorithm for NRVO: if every -/// reachable return statement in the scope of a variable has the same NRVO -/// candidate, that candidate is an NRVO variable. +/// This function applies a very simplistic algorithm for NRVO: if every return +/// statement in the scope of a variable has the same NRVO candidate, that +/// candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { - for (ReturnStmt *Return : Scope->Returns) { - const VarDecl *Candidate = Return->getNRVOCandidate(); - if (!Candidate) - continue; - - if (Candidate->isNRVOCandidate()) - const_cast(Candidate)->setNRVOVariable(true); + ReturnStmt **Returns = Scope->Returns.data(); - if (!Candidate->isNRVOVariable()) - Return->setNRVOCandidate(nullptr); + for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { + if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) { + if (!NRVOCandidate->isNRVOVariable()) + Returns[I]->setNRVOCandidate(nullptr); + } } } @@ -12713,8 +12712,12 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, else if (CXXDestructorDecl *Destructor = dyn_cast(FD)) MarkVTableUsed(FD->getLocation(), Destructor->getParent()); - // Try to apply the named return value optimization. - computeNRVO(Body, getCurFunction()); + // Try to apply the named return value optimization. We have to check + // if we can do this here because lambdas keep return statements around + // to deduce an implicit return type. + if (FD->getReturnType()->isRecordType() && + (!getLangOpts().CPlusPlus || !FD->isDependentContext())) + computeNRVO(Body, getCurFunction()); } // GNU warning -Wmissing-prototypes: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 220d690695..aeedd6b169 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -13385,9 +13385,13 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Body && getCurFunction()->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); - // Try to apply the named return value optimization. - computeNRVO(Body, BSI); - + // Try to apply the named return value optimization. We have to check again + // if we can do this, though, because blocks keep return statements around + // to deduce an implicit return type. + if (getLangOpts().CPlusPlus && RetTy->isRecordType() && + !BSI->TheDecl->isDependentContext()) + computeNRVO(Body, BSI); + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 04f5114510..ccf25ee9eb 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3455,9 +3455,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, ExpressionEvaluationContext::DiscardedStatement) return R; - VarDecl *VD = - const_cast(cast(R.get())->getNRVOCandidate()); - CurScope->setNRVOCandidate(VD); + if (VarDecl *VD = + const_cast(cast(R.get())->getNRVOCandidate())) { + CurScope->addNRVOCandidate(VD); + } else { + CurScope->setNoNRVO(); + } CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7e38dcc795..68857d972b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -740,13 +740,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope, InstantiatingVarTemplate); - bool NRVO = false; if (D->isNRVOVariable()) { QualType ReturnType = cast(DC)->getReturnType(); if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) - NRVO = true; + Var->setNRVOVariable(true); } - Var->setNRVOVariable(NRVO); + Var->setImplicit(D->isImplicit()); return Var; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 699a98ce4f..a1ce26d27c 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1326,7 +1326,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = Record.readInt(); VD->NonParmVarDeclBits.ExceptionVar = Record.readInt(); - VD->NonParmVarDeclBits.NRVOMode = Record.readInt(); + VD->NonParmVarDeclBits.NRVOVariable = Record.readInt(); VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt(); VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt(); VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt(); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index c1f983e5ce..cf35a2bc1f 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -918,7 +918,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { if (!isa(D)) { Record.push_back(D->isThisDeclarationADemotedDefinition()); Record.push_back(D->isExceptionVariable()); - Record.push_back(D->getNRVOMode()); + Record.push_back(D->isNRVOVariable()); Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isObjCForDecl()); Record.push_back(D->isARCPseudoStrong()); @@ -2031,7 +2031,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // NRVOMode + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong diff --git a/test/CodeGenCXX/nrvo-noopt.cpp b/test/CodeGenCXX/nrvo-noopt.cpp deleted file mode 100644 index 46da7cd013..0000000000 --- a/test/CodeGenCXX/nrvo-noopt.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s - -struct X { - X(); - X(X&&); -}; - -// CHECK-LABEL: define void @_Z7test_00b -X test_00(bool b) { - if (b) { - // CHECK-NOT: call void @_ZN1XC1EOS_ - // CHECK: call void @_ZN1XC1Ev - // CHECK-NEXT: br label %return - X x; - return x; - } else { - // CHECK-NOT: call void @_ZN1XC1EOS_ - // CHECK: call void @_ZN1XC1Ev - // CHECK-NEXT: br label %return - X x; - return x; - } -} - -// CHECK-LABEL: define void @_Z7test_01b -X test_01(bool b) { - if (b) { - // CHECK-NOT: call void @_ZN1XC1EOS_ - // CHECK: call void @_ZN1XC1Ev - // CHECK-NEXT: br label %return - X x; - return x; - } - // CHECK-NOT: call void @_ZN1XC1EOS_ - // CHECK: call void @_ZN1XC1Ev - // CHECK-NEXT: br label %return - X x; - return x; -} - -// CHECK-LABEL: define void @_Z7test_02b -X test_02(bool b) { - // CHECK: call void @_ZN1XC1Ev - X x; - - if (b) { - // CHECK-NOT: call void @_ZN1XC1EOS_ - // CHECK: call void @_ZN1XC1Ev - // CHECK-NEXT: br label %return - X y; - return y; - } - - // CHECK-NOT: call void @_ZN1XC1Ev - // CHECK: call void @_ZN1XC1EOS_ - // CHECK-NEXT: br label %return - return x; -} diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 1da4308e26..0f359b9c90 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -130,13 +130,17 @@ X test2(bool B) { } // CHECK-LABEL: define void @_Z5test3b -X test3(bool B, X x) { +X test3(bool B) { // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ + // CHECK: call {{.*}} @_ZN1XC1Ev + // CHECK: call {{.*}} @_ZN1XC1ERKS_ if (B) { X y; return y; } - // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ + // FIXME: we should NRVO this variable too. + X x; return x; } @@ -187,13 +191,9 @@ X test6() { } // CHECK-LABEL: define void @_Z5test7b -// CHECK-EH-LABEL: define void @_Z5test7b X test7(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret - - // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev - // CHECK-EH-NEXT: ret if (b) { X x; return x; @@ -202,14 +202,10 @@ X test7(bool b) { } // CHECK-LABEL: define void @_Z5test8b -// CHECK-EH-LABEL: define void @_Z5test8b X test8(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret - - // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev - // CHECK-EH-NEXT: ret -if (b) { + if (b) { X x; return x; } else { @@ -225,37 +221,4 @@ Y test9() { // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev -// CHECK-LABEL: define void @_Z6test10b -X test10(bool B, X x) { - if (B) { - // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ - // CHECK-EH: tail call {{.*}} @_ZN1XC1ERKS_ - return x; - } - // CHECK: tail call {{.*}} @_ZN1XC1Ev - // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ - - // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev - // CHECK-EH-NOT: call {{.*}} @_ZN1XC1ERKS_ - X y; - return y; -} - -// CHECK-LABEL: define {{.*}} void @_Z6test11I1XET_v -// CHECK-EH-LABEL: define {{.*}} void @_Z6test11I1XET_v -template -T test11() { - // CHECK: tail call {{.*}} @_ZN1XC1Ev - // CHECK-NEXT: ret void - - // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev - // CHECK-EH-NEXT: ret void - T t; - return t; -} - -void test12() { - test11(); -} - // CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/SemaCXX/nrvo-ast.cpp b/test/SemaCXX/nrvo-ast.cpp deleted file mode 100644 index 63fac006e2..0000000000 --- a/test/SemaCXX/nrvo-ast.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -ast-dump -o - %s | FileCheck %s - -struct X { - X(); - X(const X&); - X(X&&); -}; - -// CHECK-LABEL: FunctionDecl {{.*}} test_00 -X test_00() { - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - return x; -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_01 -X test_01(bool b) { - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - if (b) - return x; - return x; -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_02 -X test_02(bool b) { - // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo - X x; - // CHECK-NOT: VarDecl {{.*}} y {{.*}} nrvo - X y; - if (b) - return y; - return x; -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_03 -X test_03(bool b) { - if (b) { - // CHECK: VarDecl {{.*}} y {{.*}} nrvo - X y; - return y; - } - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - return x; -} - -extern "C" _Noreturn void exit(int) throw(); - -// CHECK-LABEL: FunctionDecl {{.*}} test_04 -X test_04(bool b) { - { - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - if (b) - return x; - } - exit(1); -} - -void may_throw(); -// CHECK-LABEL: FunctionDecl {{.*}} test_05 -X test_05() { - try { - may_throw(); - return X(); - } catch (X x) { - // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo - return x; - } -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_06 -X test_06() { - // CHECK-NOT: VarDecl {{.*}} x {{.*}} nrvo - X x __attribute__((aligned(8))); - return x; -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_07 -X test_07(bool b) { - if (b) { - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - return x; - } - return X(); -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_08 -X test_08(bool b) { - if (b) { - // CHECK: VarDecl {{.*}} x {{.*}} nrvo - X x; - return x; - } else { - // CHECK: VarDecl {{.*}} y {{.*}} nrvo - X y; - return y; - } -} - -template -struct Y { - Y(); - // CHECK-LABEL: CXXMethodDecl {{.*}} test_09 'Y ()' - // CHECK: VarDecl {{.*}} y 'Y' nrvo - - // CHECK-LABEL: CXXMethodDecl {{.*}} test_09 'Y ()' - // CHECK: VarDecl {{.*}} y 'Y' nrvo - static Y test_09() { - Y y; - return y; - } -}; - -struct Z { - Z(const X&); -}; - -// CHECK-LABEL: FunctionDecl {{.*}} test_10 'A ()' -// CHECK: VarDecl {{.*}} b 'B' nrvo - -// CHECK-LABEL: FunctionDecl {{.*}} test_10 'X ()' -// CHECK: VarDecl {{.*}} b {{.*}} nrvo - -// CHECK-LABEL: FunctionDecl {{.*}} test_10 'Z ()' -// CHECK-NOT: VarDecl {{.*}} b {{.*}} nrvo -template -A test_10() { - B b; - return b; -} - -// CHECK-LABEL: FunctionDecl {{.*}} test_11 'A (bool)' -// CHECK-NOT: VarDecl {{.*}} a {{.*}} nrvo - -// CHECK-LABEL: FunctionDecl {{.*}} test_11 'X (bool)' -// CHECK-NOT: VarDecl {{.*}} a {{.*}} nrvo -template -A test_11(bool b) { - A a; - if (b) - return A(); - return a; -} - -void instantiate() { - Y::test_09(); - test_10(); - test_10(); - test_11(true); -} -- GitLab From ae1561d38e5ac05f9398bcd6a0acdf65305d8ec9 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Tue, 19 Jun 2018 08:35:02 +0000 Subject: [PATCH 0177/1023] [analyzer] Made a buildbot happy. Since `isPrimitiveType` was only used in an assert, a builbot with `-Werror` and no asserts enabled failed to build it as it was unused. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335030 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index 63e4b817da..a517e81122 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -384,15 +384,17 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, continue; } - assert(isPrimitiveType(T) && "Non-primitive type! " - "At this point FR must be primitive!"); + if (isPrimitiveType(T)) { + SVal V = State->getSVal(FieldVal); - SVal V = State->getSVal(FieldVal); - - if (isPrimitiveUninit(V)) { - if (addFieldToUninits({LocalChain, FR})) - ContainsUninitField = true; + if (isPrimitiveUninit(V)) { + if (addFieldToUninits({LocalChain, FR})) + ContainsUninitField = true; + } + continue; } + + llvm_unreachable("All cases are handled!"); } // Checking bases. -- GitLab From 21630d5d23e01b5eef9f6958c21dfacfce20da02 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 19 Jun 2018 14:36:04 +0000 Subject: [PATCH 0178/1023] Implement semantic checking for __builtin_signbit. r242675 changed the signature for the signbit builtin but did not introduce proper semantic checking to ensure the arguments are as-expected. This patch groups the signbit builtin along with the other fp classification builtins. Fixes PR28172. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335048 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 1625 +++++++++++++++++++------------------ test/Sema/builtins.c | 423 +++++----- 2 files changed, 1039 insertions(+), 1009 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 5530bd8fe7..e18dd056e9 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -772,406 +772,409 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { } // Since return type of reserve_read/write_pipe built-in function is - // reserve_id_t, which is not defined in the builtin def file , we used int - // as return type and need to override the return type of these functions. - Call->setType(S.Context.OCLReserveIDTy); - - return false; -} - -// Performs a semantic analysis on {work_group_/sub_group_ -// /_}commit_{read/write}_pipe -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) - return true; - - if (checkOpenCLPipeArg(S, Call)) - return true; - - // Check reserve_id_t. - if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.OCLReserveIDTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - return false; -} - -// Performs a semantic analysis on the call to built-in Pipe -// Query Functions. -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) - return true; - - if (!Call->getArg(0)->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) - << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); - return true; - } - - return false; -} - -// OpenCL v2.0 s6.13.9 - Address space qualifier functions. -// Performs semantic analysis for the to_global/local/private call. -// \param S Reference to the semantic analyzer. -// \param BuiltinID ID of the builtin function. -// \param Call A pointer to the builtin call. -// \return True if a semantic error has been found, false otherwise. -static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, - CallExpr *Call) { - if (Call->getNumArgs() != 1) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - auto RT = Call->getArg(0)->getType(); - if (!RT->isPointerType() || RT->getPointeeType() - .getAddressSpace() == LangAS::opencl_constant) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) - << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - RT = RT->getPointeeType(); - auto Qual = RT.getQualifiers(); - switch (BuiltinID) { - case Builtin::BIto_global: - Qual.setAddressSpace(LangAS::opencl_global); - break; - case Builtin::BIto_local: - Qual.setAddressSpace(LangAS::opencl_local); - break; - case Builtin::BIto_private: - Qual.setAddressSpace(LangAS::opencl_private); - break; - default: - llvm_unreachable("Invalid builtin function"); - } - Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( - RT.getUnqualifiedType(), Qual))); - - return false; -} - -// Emit an error and return true if the current architecture is not in the list -// of supported architectures. -static bool -CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, - ArrayRef SupportedArchs) { - llvm::Triple::ArchType CurArch = - S.getASTContext().getTargetInfo().getTriple().getArch(); - if (llvm::is_contained(SupportedArchs, CurArch)) - return false; - S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) - << TheCall->getSourceRange(); - return true; -} - -ExprResult -Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, - CallExpr *TheCall) { - ExprResult TheCallResult(TheCall); - - // Find out if any arguments are required to be integer constant expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); - if (Error != ASTContext::GE_None) - ICEArguments = 0; // Don't diagnose previously diagnosed errors. - - // If any arguments are required to be ICE's, check and diagnose. - for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { - // Skip arguments not required to be ICE's. - if ((ICEArguments & (1 << ArgNo)) == 0) continue; - - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) - return true; - ICEArguments &= ~(1 << ArgNo); - } - - switch (BuiltinID) { - case Builtin::BI__builtin___CFStringMakeConstantString: - assert(TheCall->getNumArgs() == 1 && - "Wrong # arguments to builtin CFStringMakeConstantString"); - if (CheckObjCString(TheCall->getArg(0))) - return ExprError(); - break; - case Builtin::BI__builtin_ms_va_start: - case Builtin::BI__builtin_stdarg_start: - case Builtin::BI__builtin_va_start: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - case Builtin::BI__va_start: { - switch (Context.getTargetInfo().getTriple().getArch()) { - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (SemaBuiltinVAStartARMMicrosoft(TheCall)) - return ExprError(); - break; - default: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - } - break; - } - - // The acquire, release, and no fence variants are ARM and AArch64 only. - case Builtin::BI_interlockedbittestandset_acq: - case Builtin::BI_interlockedbittestandset_rel: - case Builtin::BI_interlockedbittestandset_nf: - case Builtin::BI_interlockedbittestandreset_acq: - case Builtin::BI_interlockedbittestandreset_rel: - case Builtin::BI_interlockedbittestandreset_nf: - if (CheckBuiltinTargetSupport( - *this, BuiltinID, TheCall, - {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - // The 64-bit bittest variants are x64, ARM, and AArch64 only. - case Builtin::BI_bittest64: - case Builtin::BI_bittestandcomplement64: - case Builtin::BI_bittestandreset64: - case Builtin::BI_bittestandset64: - case Builtin::BI_interlockedbittestandreset64: - case Builtin::BI_interlockedbittestandset64: - if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, - {llvm::Triple::x86_64, llvm::Triple::arm, - llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - case Builtin::BI__builtin_isgreater: - case Builtin::BI__builtin_isgreaterequal: - case Builtin::BI__builtin_isless: - case Builtin::BI__builtin_islessequal: - case Builtin::BI__builtin_islessgreater: - case Builtin::BI__builtin_isunordered: - if (SemaBuiltinUnorderedCompare(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_fpclassify: - if (SemaBuiltinFPClassification(TheCall, 6)) - return ExprError(); - break; - case Builtin::BI__builtin_isfinite: - case Builtin::BI__builtin_isinf: - case Builtin::BI__builtin_isinf_sign: - case Builtin::BI__builtin_isnan: - case Builtin::BI__builtin_isnormal: - if (SemaBuiltinFPClassification(TheCall, 1)) - return ExprError(); - break; - case Builtin::BI__builtin_shufflevector: - return SemaBuiltinShuffleVector(TheCall); - // TheCall will be freed by the smart pointer here, but that's fine, since - // SemaBuiltinShuffleVector guts it, but then doesn't release it. - case Builtin::BI__builtin_prefetch: - if (SemaBuiltinPrefetch(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_alloca_with_align: - if (SemaBuiltinAllocaWithAlign(TheCall)) - return ExprError(); - break; - case Builtin::BI__assume: - case Builtin::BI__builtin_assume: - if (SemaBuiltinAssume(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_assume_aligned: - if (SemaBuiltinAssumeAligned(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_object_size: - if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) - return ExprError(); - break; - case Builtin::BI__builtin_longjmp: - if (SemaBuiltinLongjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_setjmp: - if (SemaBuiltinSetjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI_setjmp: - case Builtin::BI_setjmpex: - if (checkArgCount(*this, TheCall, 1)) - return true; - break; - case Builtin::BI__builtin_classify_type: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__builtin_constant_p: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__sync_fetch_and_add: - case Builtin::BI__sync_fetch_and_add_1: - case Builtin::BI__sync_fetch_and_add_2: - case Builtin::BI__sync_fetch_and_add_4: - case Builtin::BI__sync_fetch_and_add_8: - case Builtin::BI__sync_fetch_and_add_16: - case Builtin::BI__sync_fetch_and_sub: - case Builtin::BI__sync_fetch_and_sub_1: - case Builtin::BI__sync_fetch_and_sub_2: - case Builtin::BI__sync_fetch_and_sub_4: - case Builtin::BI__sync_fetch_and_sub_8: - case Builtin::BI__sync_fetch_and_sub_16: - case Builtin::BI__sync_fetch_and_or: - case Builtin::BI__sync_fetch_and_or_1: - case Builtin::BI__sync_fetch_and_or_2: - case Builtin::BI__sync_fetch_and_or_4: - case Builtin::BI__sync_fetch_and_or_8: - case Builtin::BI__sync_fetch_and_or_16: - case Builtin::BI__sync_fetch_and_and: - case Builtin::BI__sync_fetch_and_and_1: - case Builtin::BI__sync_fetch_and_and_2: - case Builtin::BI__sync_fetch_and_and_4: - case Builtin::BI__sync_fetch_and_and_8: - case Builtin::BI__sync_fetch_and_and_16: - case Builtin::BI__sync_fetch_and_xor: - case Builtin::BI__sync_fetch_and_xor_1: - case Builtin::BI__sync_fetch_and_xor_2: - case Builtin::BI__sync_fetch_and_xor_4: - case Builtin::BI__sync_fetch_and_xor_8: - case Builtin::BI__sync_fetch_and_xor_16: - case Builtin::BI__sync_fetch_and_nand: - case Builtin::BI__sync_fetch_and_nand_1: - case Builtin::BI__sync_fetch_and_nand_2: - case Builtin::BI__sync_fetch_and_nand_4: - case Builtin::BI__sync_fetch_and_nand_8: - case Builtin::BI__sync_fetch_and_nand_16: - case Builtin::BI__sync_add_and_fetch: - case Builtin::BI__sync_add_and_fetch_1: - case Builtin::BI__sync_add_and_fetch_2: - case Builtin::BI__sync_add_and_fetch_4: - case Builtin::BI__sync_add_and_fetch_8: - case Builtin::BI__sync_add_and_fetch_16: - case Builtin::BI__sync_sub_and_fetch: - case Builtin::BI__sync_sub_and_fetch_1: - case Builtin::BI__sync_sub_and_fetch_2: - case Builtin::BI__sync_sub_and_fetch_4: - case Builtin::BI__sync_sub_and_fetch_8: - case Builtin::BI__sync_sub_and_fetch_16: - case Builtin::BI__sync_and_and_fetch: - case Builtin::BI__sync_and_and_fetch_1: - case Builtin::BI__sync_and_and_fetch_2: - case Builtin::BI__sync_and_and_fetch_4: - case Builtin::BI__sync_and_and_fetch_8: - case Builtin::BI__sync_and_and_fetch_16: - case Builtin::BI__sync_or_and_fetch: - case Builtin::BI__sync_or_and_fetch_1: - case Builtin::BI__sync_or_and_fetch_2: - case Builtin::BI__sync_or_and_fetch_4: - case Builtin::BI__sync_or_and_fetch_8: - case Builtin::BI__sync_or_and_fetch_16: - case Builtin::BI__sync_xor_and_fetch: - case Builtin::BI__sync_xor_and_fetch_1: - case Builtin::BI__sync_xor_and_fetch_2: - case Builtin::BI__sync_xor_and_fetch_4: - case Builtin::BI__sync_xor_and_fetch_8: - case Builtin::BI__sync_xor_and_fetch_16: - case Builtin::BI__sync_nand_and_fetch: - case Builtin::BI__sync_nand_and_fetch_1: - case Builtin::BI__sync_nand_and_fetch_2: - case Builtin::BI__sync_nand_and_fetch_4: - case Builtin::BI__sync_nand_and_fetch_8: - case Builtin::BI__sync_nand_and_fetch_16: - case Builtin::BI__sync_val_compare_and_swap: - case Builtin::BI__sync_val_compare_and_swap_1: - case Builtin::BI__sync_val_compare_and_swap_2: - case Builtin::BI__sync_val_compare_and_swap_4: - case Builtin::BI__sync_val_compare_and_swap_8: - case Builtin::BI__sync_val_compare_and_swap_16: - case Builtin::BI__sync_bool_compare_and_swap: - case Builtin::BI__sync_bool_compare_and_swap_1: - case Builtin::BI__sync_bool_compare_and_swap_2: - case Builtin::BI__sync_bool_compare_and_swap_4: - case Builtin::BI__sync_bool_compare_and_swap_8: - case Builtin::BI__sync_bool_compare_and_swap_16: - case Builtin::BI__sync_lock_test_and_set: - case Builtin::BI__sync_lock_test_and_set_1: - case Builtin::BI__sync_lock_test_and_set_2: - case Builtin::BI__sync_lock_test_and_set_4: - case Builtin::BI__sync_lock_test_and_set_8: - case Builtin::BI__sync_lock_test_and_set_16: - case Builtin::BI__sync_lock_release: - case Builtin::BI__sync_lock_release_1: - case Builtin::BI__sync_lock_release_2: - case Builtin::BI__sync_lock_release_4: - case Builtin::BI__sync_lock_release_8: - case Builtin::BI__sync_lock_release_16: - case Builtin::BI__sync_swap: - case Builtin::BI__sync_swap_1: - case Builtin::BI__sync_swap_2: - case Builtin::BI__sync_swap_4: - case Builtin::BI__sync_swap_8: - case Builtin::BI__sync_swap_16: - return SemaBuiltinAtomicOverloaded(TheCallResult); - case Builtin::BI__builtin_nontemporal_load: - case Builtin::BI__builtin_nontemporal_store: - return SemaBuiltinNontemporalOverloaded(TheCallResult); -#define BUILTIN(ID, TYPE, ATTRS) -#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ - case Builtin::BI##ID: \ - return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); -#include "clang/Basic/Builtins.def" - case Builtin::BI__annotation: - if (SemaBuiltinMSVCAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_annotation: - if (SemaBuiltinAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_addressof: - if (SemaBuiltinAddressof(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_add_overflow: - case Builtin::BI__builtin_sub_overflow: - case Builtin::BI__builtin_mul_overflow: - if (SemaBuiltinOverflow(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_operator_new: - case Builtin::BI__builtin_operator_delete: { - bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; - ExprResult Res = - SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); - if (Res.isInvalid()) - CorrectDelayedTyposInExpr(TheCallResult.get()); - return Res; - } - case Builtin::BI__builtin_dump_struct: { - // We first want to ensure we are called with 2 arguments - if (checkArgCount(*this, TheCall, 2)) - return ExprError(); - // Ensure that the first argument is of type 'struct XX *' - const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); - const QualType PtrArgType = PtrArg->getType(); - if (!PtrArgType->isPointerType() || - !PtrArgType->getPointeeType()->isRecordType()) { - Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) - << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType - << "structure pointer"; - return ExprError(); + // reserve_id_t, which is not defined in the builtin def file , we used int + // as return type and need to override the return type of these functions. + Call->setType(S.Context.OCLReserveIDTy); + + return false; +} + +// Performs a semantic analysis on {work_group_/sub_group_ +// /_}commit_{read/write}_pipe +// \param S Reference to the semantic analyzer. +// \param Call The call to the builtin function to be analyzed. +// \return True if a semantic error was found, false otherwise. +static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 2)) + return true; + + if (checkOpenCLPipeArg(S, Call)) + return true; + + // Check reserve_id_t. + if (!Call->getArg(1)->getType()->isReserveIDT()) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + << Call->getDirectCallee() << S.Context.OCLReserveIDTy + << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); + return true; + } + + return false; +} + +// Performs a semantic analysis on the call to built-in Pipe +// Query Functions. +// \param S Reference to the semantic analyzer. +// \param Call The call to the builtin function to be analyzed. +// \return True if a semantic error was found, false otherwise. +static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 1)) + return true; + + if (!Call->getArg(0)->getType()->isPipeType()) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) + << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); + return true; + } + + return false; +} + +// OpenCL v2.0 s6.13.9 - Address space qualifier functions. +// Performs semantic analysis for the to_global/local/private call. +// \param S Reference to the semantic analyzer. +// \param BuiltinID ID of the builtin function. +// \param Call A pointer to the builtin call. +// \return True if a semantic error has been found, false otherwise. +static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, + CallExpr *Call) { + if (Call->getNumArgs() != 1) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) + << Call->getDirectCallee() << Call->getSourceRange(); + return true; + } + + auto RT = Call->getArg(0)->getType(); + if (!RT->isPointerType() || RT->getPointeeType() + .getAddressSpace() == LangAS::opencl_constant) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) + << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); + return true; + } + + RT = RT->getPointeeType(); + auto Qual = RT.getQualifiers(); + switch (BuiltinID) { + case Builtin::BIto_global: + Qual.setAddressSpace(LangAS::opencl_global); + break; + case Builtin::BIto_local: + Qual.setAddressSpace(LangAS::opencl_local); + break; + case Builtin::BIto_private: + Qual.setAddressSpace(LangAS::opencl_private); + break; + default: + llvm_unreachable("Invalid builtin function"); + } + Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( + RT.getUnqualifiedType(), Qual))); + + return false; +} + +// Emit an error and return true if the current architecture is not in the list +// of supported architectures. +static bool +CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, + ArrayRef SupportedArchs) { + llvm::Triple::ArchType CurArch = + S.getASTContext().getTargetInfo().getTriple().getArch(); + if (llvm::is_contained(SupportedArchs, CurArch)) + return false; + S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) + << TheCall->getSourceRange(); + return true; +} + +ExprResult +Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, + CallExpr *TheCall) { + ExprResult TheCallResult(TheCall); + + // Find out if any arguments are required to be integer constant expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); + if (Error != ASTContext::GE_None) + ICEArguments = 0; // Don't diagnose previously diagnosed errors. + + // If any arguments are required to be ICE's, check and diagnose. + for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { + // Skip arguments not required to be ICE's. + if ((ICEArguments & (1 << ArgNo)) == 0) continue; + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + ICEArguments &= ~(1 << ArgNo); + } + + switch (BuiltinID) { + case Builtin::BI__builtin___CFStringMakeConstantString: + assert(TheCall->getNumArgs() == 1 && + "Wrong # arguments to builtin CFStringMakeConstantString"); + if (CheckObjCString(TheCall->getArg(0))) + return ExprError(); + break; + case Builtin::BI__builtin_ms_va_start: + case Builtin::BI__builtin_stdarg_start: + case Builtin::BI__builtin_va_start: + if (SemaBuiltinVAStart(BuiltinID, TheCall)) + return ExprError(); + break; + case Builtin::BI__va_start: { + switch (Context.getTargetInfo().getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (SemaBuiltinVAStartARMMicrosoft(TheCall)) + return ExprError(); + break; + default: + if (SemaBuiltinVAStart(BuiltinID, TheCall)) + return ExprError(); + break; + } + break; + } + + // The acquire, release, and no fence variants are ARM and AArch64 only. + case Builtin::BI_interlockedbittestandset_acq: + case Builtin::BI_interlockedbittestandset_rel: + case Builtin::BI_interlockedbittestandset_nf: + case Builtin::BI_interlockedbittestandreset_acq: + case Builtin::BI_interlockedbittestandreset_rel: + case Builtin::BI_interlockedbittestandreset_nf: + if (CheckBuiltinTargetSupport( + *this, BuiltinID, TheCall, + {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + + // The 64-bit bittest variants are x64, ARM, and AArch64 only. + case Builtin::BI_bittest64: + case Builtin::BI_bittestandcomplement64: + case Builtin::BI_bittestandreset64: + case Builtin::BI_bittestandset64: + case Builtin::BI_interlockedbittestandreset64: + case Builtin::BI_interlockedbittestandset64: + if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, + {llvm::Triple::x86_64, llvm::Triple::arm, + llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: + if (SemaBuiltinUnorderedCompare(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + return ExprError(); + break; + case Builtin::BI__builtin_isfinite: + case Builtin::BI__builtin_isinf: + case Builtin::BI__builtin_isinf_sign: + case Builtin::BI__builtin_isnan: + case Builtin::BI__builtin_isnormal: + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: + if (SemaBuiltinFPClassification(TheCall, 1)) + return ExprError(); + break; + case Builtin::BI__builtin_shufflevector: + return SemaBuiltinShuffleVector(TheCall); + // TheCall will be freed by the smart pointer here, but that's fine, since + // SemaBuiltinShuffleVector guts it, but then doesn't release it. + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_alloca_with_align: + if (SemaBuiltinAllocaWithAlign(TheCall)) + return ExprError(); + break; + case Builtin::BI__assume: + case Builtin::BI__builtin_assume: + if (SemaBuiltinAssume(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_assume_aligned: + if (SemaBuiltinAssumeAligned(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_object_size: + if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) + return ExprError(); + break; + case Builtin::BI__builtin_longjmp: + if (SemaBuiltinLongjmp(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_setjmp: + if (SemaBuiltinSetjmp(TheCall)) + return ExprError(); + break; + case Builtin::BI_setjmp: + case Builtin::BI_setjmpex: + if (checkArgCount(*this, TheCall, 1)) + return true; + break; + case Builtin::BI__builtin_classify_type: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__builtin_constant_p: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: + case Builtin::BI__sync_fetch_and_nand: + case Builtin::BI__sync_fetch_and_nand_1: + case Builtin::BI__sync_fetch_and_nand_2: + case Builtin::BI__sync_fetch_and_nand_4: + case Builtin::BI__sync_fetch_and_nand_8: + case Builtin::BI__sync_fetch_and_nand_16: + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: + case Builtin::BI__sync_nand_and_fetch: + case Builtin::BI__sync_nand_and_fetch_1: + case Builtin::BI__sync_nand_and_fetch_2: + case Builtin::BI__sync_nand_and_fetch_4: + case Builtin::BI__sync_nand_and_fetch_8: + case Builtin::BI__sync_nand_and_fetch_16: + case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: + case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__builtin_nontemporal_load: + case Builtin::BI__builtin_nontemporal_store: + return SemaBuiltinNontemporalOverloaded(TheCallResult); +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case Builtin::BI##ID: \ + return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); +#include "clang/Basic/Builtins.def" + case Builtin::BI__annotation: + if (SemaBuiltinMSVCAnnotation(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_annotation: + if (SemaBuiltinAnnotation(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_addressof: + if (SemaBuiltinAddressof(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + if (SemaBuiltinOverflow(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: { + bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; + ExprResult Res = + SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); + if (Res.isInvalid()) + CorrectDelayedTyposInExpr(TheCallResult.get()); + return Res; + } + case Builtin::BI__builtin_dump_struct: { + // We first want to ensure we are called with 2 arguments + if (checkArgCount(*this, TheCall, 2)) + return ExprError(); + // Ensure that the first argument is of type 'struct XX *' + const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); + const QualType PtrArgType = PtrArg->getType(); + if (!PtrArgType->isPointerType() || + !PtrArgType->getPointeeType()->isRecordType()) { + Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) + << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType + << "structure pointer"; + return ExprError(); } // Ensure that the second argument is of type 'FunctionType' @@ -4392,415 +4395,419 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, return false; } -/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' -/// for validity. Emit an error and return true on failure; return false -/// on success. -bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { - Expr *Fn = TheCall->getCallee(); - - if (checkVAStartABI(*this, BuiltinID, Fn)) - return true; - - if (TheCall->getNumArgs() > 2) { - Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << Fn->getSourceRange() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - return true; - } - - if (TheCall->getNumArgs() < 2) { - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs(); - } - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, TheCall, 0)) - return true; - - // Check that the current function is variadic, and get its last parameter. - ParmVarDecl *LastParam; - if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam)) - return true; - - // Verify that the second argument to the builtin is the last argument of the - // current function or method. - bool SecondArgIsLastNamedArgument = false; - const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); - - // These are valid if SecondArgIsLastNamedArgument is false after the next - // block. - QualType Type; - SourceLocation ParamLoc; - bool IsCRegister = false; - - if (const DeclRefExpr *DR = dyn_cast(Arg)) { - if (const ParmVarDecl *PV = dyn_cast(DR->getDecl())) { - SecondArgIsLastNamedArgument = PV == LastParam; - - Type = PV->getType(); - ParamLoc = PV->getLocation(); - IsCRegister = - PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; - } - } - - if (!SecondArgIsLastNamedArgument) - Diag(TheCall->getArg(1)->getLocStart(), - diag::warn_second_arg_of_va_start_not_last_named_param); - else if (IsCRegister || Type->isReferenceType() || - Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { - // Promotable integers are UB, but enumerations need a bit of - // extra checking to see what their promotable type actually is. - if (!Type->isPromotableIntegerType()) - return false; - if (!Type->isEnumeralType()) - return true; - const EnumDecl *ED = Type->getAs()->getDecl(); - return !(ED && - Context.typesAreCompatible(ED->getPromotionType(), Type)); - }()) { - unsigned Reason = 0; - if (Type->isReferenceType()) Reason = 1; - else if (IsCRegister) Reason = 2; - Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; - Diag(ParamLoc, diag::note_parameter_type) << Type; - } - - TheCall->setType(Context.VoidTy); - return false; -} - -bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { - // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, - // const char *named_addr); - - Expr *Func = Call->getCallee(); - - if (Call->getNumArgs() < 3) - return Diag(Call->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 3 << Call->getNumArgs(); - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, Call, 0)) - return true; - - // Check that the current function is variadic. - if (checkVAStartIsInVariadicFunction(*this, Func)) - return true; - - // __va_start on Windows does not validate the parameter qualifiers - - const Expr *Arg1 = Call->getArg(1)->IgnoreParens(); - const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr(); - - const Expr *Arg2 = Call->getArg(2)->IgnoreParens(); - const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr(); - - const QualType &ConstCharPtrTy = - Context.getPointerType(Context.CharTy.withConst()); - if (!Arg1Ty->isPointerType() || - Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) - Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg1->getType() << ConstCharPtrTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 2 << Arg1->getType() << ConstCharPtrTy; - - const QualType SizeTy = Context.getSizeType(); - if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) - Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg2->getType() << SizeTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 3 << Arg2->getType() << SizeTy; - - return false; -} - -/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and -/// friends. This is declared to take (...), so we have to check everything. -bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << 2 << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > 2) - return Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - ExprResult OrigArg0 = TheCall->getArg(0); - ExprResult OrigArg1 = TheCall->getArg(1); - - // Do standard promotions between the two arguments, returning their common - // type. - QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); - if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) - return true; - - // Make sure any conversions are pushed back into the call; this is - // type safe since unordered compare builtins are declared as "_Bool - // foo(...)". - TheCall->setArg(0, OrigArg0.get()); - TheCall->setArg(1, OrigArg1.get()); - - if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) - return false; - - // If the common type isn't a real floating type, then the arguments were - // invalid for this operation. - if (Res.isNull() || !Res->isRealFloatingType()) - return Diag(OrigArg0.get()->getLocStart(), - diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0.get()->getType() << OrigArg1.get()->getType() - << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); - - return false; -} - -/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like -/// __builtin_isnan and friends. This is declared to take (...), so we have -/// to check everything. We expect the last argument to be a floating point -/// value. -bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { - if (TheCall->getNumArgs() < NumArgs) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > NumArgs) - return Diag(TheCall->getArg(NumArgs)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - Expr *OrigArg = TheCall->getArg(NumArgs-1); - - if (OrigArg->isTypeDependent()) - return false; - - // This operation requires a non-_Complex floating-point number. - if (!OrigArg->getType()->isRealFloatingType()) - return Diag(OrigArg->getLocStart(), - diag::err_typecheck_call_invalid_unary_fp) - << OrigArg->getType() << OrigArg->getSourceRange(); - - // If this is an implicit conversion from float -> float or double, remove it. - if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { - // Only remove standard FloatCasts, leaving other casts inplace - if (Cast->getCastKind() == CK_FloatingCast) { - Expr *CastArg = Cast->getSubExpr(); - if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && - "promotion from float to either float or double is the only expected cast here"); - Cast->setSubExpr(nullptr); - TheCall->setArg(NumArgs-1, CastArg); - } - } - } - - return false; -} - -// Customized Sema Checking for VSX builtins that have the following signature: -// vector [...] builtinName(vector [...], vector [...], const int); -// Which takes the same type of vectors (any legal vector type) for the first -// two arguments and takes compile time constant for the third argument. -// Example builtins are : -// vector double vec_xxpermdi(vector double, vector double, int); -// vector short vec_xxsldwi(vector short, vector short, int); -bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { - unsigned ExpectedNumArgs = 3; - if (TheCall->getNumArgs() < ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - if (TheCall->getNumArgs() > ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - // Check the third argument is a compile time constant - llvm::APSInt Value; - if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) - return Diag(TheCall->getLocStart(), - diag::err_vsx_builtin_nonconstant_argument) - << 3 /* argument index */ << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(2)->getLocStart(), - TheCall->getArg(2)->getLocEnd()); - - QualType Arg1Ty = TheCall->getArg(0)->getType(); - QualType Arg2Ty = TheCall->getArg(1)->getType(); - - // Check the type of argument 1 and argument 2 are vectors. - SourceLocation BuiltinLoc = TheCall->getLocStart(); - if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || - (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { - return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // Check the first two arguments are the same type. - if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { - return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // When default clang type checking is turned off and the customized type - // checking is used, the returning type of the function must be explicitly - // set. Otherwise it is _Bool by default. - TheCall->setType(Arg1Ty); - - return false; -} - -/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. -// This is declared to take (...), so we have to check everything. -ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); - - // Determine which of the following types of shufflevector we're checking: - // 1) unary, vector mask: (lhs, mask) - // 2) binary, scalar mask: (lhs, rhs, index, ..., index) - QualType resType = TheCall->getArg(0)->getType(); - unsigned numElements = 0; - - if (!TheCall->getArg(0)->isTypeDependent() && - !TheCall->getArg(1)->isTypeDependent()) { - QualType LHSType = TheCall->getArg(0)->getType(); - QualType RHSType = TheCall->getArg(1)->getType(); - - if (!LHSType->isVectorType() || !RHSType->isVectorType()) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - - numElements = LHSType->getAs()->getNumElements(); - unsigned numResElements = TheCall->getNumArgs() - 2; - - // Check to see if we have a call with 2 vector arguments, the unary shuffle - // with mask. If so, verify that RHS is an integer vector type with the - // same number of elts as lhs. - if (TheCall->getNumArgs() == 2) { - if (!RHSType->hasIntegerRepresentation() || - RHSType->getAs()->getNumElements() != numElements) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(1)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (numElements != numResElements) { - QualType eltType = LHSType->getAs()->getElementType(); - resType = Context.getVectorType(eltType, numResElements, - VectorType::GenericVector); - } - } - - for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - continue; - - llvm::APSInt Result(32); - if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_nonconstant_argument) - << TheCall->getArg(i)->getSourceRange()); - - // Allow -1 which will be translated to undef in the IR. - if (Result.isSigned() && Result.isAllOnesValue()) - continue; - - if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_argument_too_large) - << TheCall->getArg(i)->getSourceRange()); - } - - SmallVector exprs; - - for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { - exprs.push_back(TheCall->getArg(i)); - TheCall->setArg(i, nullptr); - } - - return new (Context) ShuffleVectorExpr(Context, exprs, resType, - TheCall->getCallee()->getLocStart(), - TheCall->getRParenLoc()); -} - -/// SemaConvertVectorExpr - Handle __builtin_convertvector -ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc) { - ExprValueKind VK = VK_RValue; - ExprObjectKind OK = OK_Ordinary; - QualType DstTy = TInfo->getType(); - QualType SrcTy = E->getType(); - - if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector) - << E->getSourceRange()); - if (!DstTy->isVectorType() && !DstTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector_type)); - - if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { - unsigned SrcElts = SrcTy->getAs()->getNumElements(); - unsigned DstElts = DstTy->getAs()->getNumElements(); - if (SrcElts != DstElts) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_incompatible_vector) - << E->getSourceRange()); - } - - return new (Context) - ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); -} - -/// SemaBuiltinPrefetch - Handle __builtin_prefetch. -// This is declared to take (const void*, ...) and can take two -// optional constant int args. -bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { - unsigned NumArgs = TheCall->getNumArgs(); - - if (NumArgs > 3) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs - << TheCall->getSourceRange(); - - // Argument 0 is checked for us and the remaining arguments must be - // constant integers. - for (unsigned i = 1; i != NumArgs; ++i) +/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' +/// for validity. Emit an error and return true on failure; return false +/// on success. +bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { + Expr *Fn = TheCall->getCallee(); + + if (checkVAStartABI(*this, BuiltinID, Fn)) + return true; + + if (TheCall->getNumArgs() > 2) { + Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << Fn->getSourceRange() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + return true; + } + + if (TheCall->getNumArgs() < 2) { + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs(); + } + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, TheCall, 0)) + return true; + + // Check that the current function is variadic, and get its last parameter. + ParmVarDecl *LastParam; + if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam)) + return true; + + // Verify that the second argument to the builtin is the last argument of the + // current function or method. + bool SecondArgIsLastNamedArgument = false; + const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); + + // These are valid if SecondArgIsLastNamedArgument is false after the next + // block. + QualType Type; + SourceLocation ParamLoc; + bool IsCRegister = false; + + if (const DeclRefExpr *DR = dyn_cast(Arg)) { + if (const ParmVarDecl *PV = dyn_cast(DR->getDecl())) { + SecondArgIsLastNamedArgument = PV == LastParam; + + Type = PV->getType(); + ParamLoc = PV->getLocation(); + IsCRegister = + PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; + } + } + + if (!SecondArgIsLastNamedArgument) + Diag(TheCall->getArg(1)->getLocStart(), + diag::warn_second_arg_of_va_start_not_last_named_param); + else if (IsCRegister || Type->isReferenceType() || + Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { + // Promotable integers are UB, but enumerations need a bit of + // extra checking to see what their promotable type actually is. + if (!Type->isPromotableIntegerType()) + return false; + if (!Type->isEnumeralType()) + return true; + const EnumDecl *ED = Type->getAs()->getDecl(); + return !(ED && + Context.typesAreCompatible(ED->getPromotionType(), Type)); + }()) { + unsigned Reason = 0; + if (Type->isReferenceType()) Reason = 1; + else if (IsCRegister) Reason = 2; + Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; + Diag(ParamLoc, diag::note_parameter_type) << Type; + } + + TheCall->setType(Context.VoidTy); + return false; +} + +bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { + // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, + // const char *named_addr); + + Expr *Func = Call->getCallee(); + + if (Call->getNumArgs() < 3) + return Diag(Call->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 3 << Call->getNumArgs(); + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, Call, 0)) + return true; + + // Check that the current function is variadic. + if (checkVAStartIsInVariadicFunction(*this, Func)) + return true; + + // __va_start on Windows does not validate the parameter qualifiers + + const Expr *Arg1 = Call->getArg(1)->IgnoreParens(); + const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr(); + + const Expr *Arg2 = Call->getArg(2)->IgnoreParens(); + const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr(); + + const QualType &ConstCharPtrTy = + Context.getPointerType(Context.CharTy.withConst()); + if (!Arg1Ty->isPointerType() || + Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) + Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) + << Arg1->getType() << ConstCharPtrTy + << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ + << 2 << Arg1->getType() << ConstCharPtrTy; + + const QualType SizeTy = Context.getSizeType(); + if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) + Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) + << Arg2->getType() << SizeTy + << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ + << 3 << Arg2->getType() << SizeTy; + + return false; +} + +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and +/// friends. This is declared to take (...), so we have to check everything. +bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << 2 << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > 2) + return Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + ExprResult OrigArg0 = TheCall->getArg(0); + ExprResult OrigArg1 = TheCall->getArg(1); + + // Do standard promotions between the two arguments, returning their common + // type. + QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); + if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) + return true; + + // Make sure any conversions are pushed back into the call; this is + // type safe since unordered compare builtins are declared as "_Bool + // foo(...)". + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); + + if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) + return false; + + // If the common type isn't a real floating type, then the arguments were + // invalid for this operation. + if (Res.isNull() || !Res->isRealFloatingType()) + return Diag(OrigArg0.get()->getLocStart(), + diag::err_typecheck_call_invalid_ordered_compare) + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); + + return false; +} + +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. We expect the last argument to be a floating point +/// value. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { + if (TheCall->getNumArgs() < NumArgs) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > NumArgs) + return Diag(TheCall->getArg(NumArgs)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + Expr *OrigArg = TheCall->getArg(NumArgs-1); + + if (OrigArg->isTypeDependent()) + return false; + + // This operation requires a non-_Complex floating-point number. + if (!OrigArg->getType()->isRealFloatingType()) + return Diag(OrigArg->getLocStart(), + diag::err_typecheck_call_invalid_unary_fp) + << OrigArg->getType() << OrigArg->getSourceRange(); + + // If this is an implicit conversion from float -> float, double, or + // long double, remove it. + if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { + // Only remove standard FloatCasts, leaving other casts inplace + if (Cast->getCastKind() == CK_FloatingCast) { + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert( + (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) && + "promotion from float to either float, double, or long double is " + "the only expected cast here"); + Cast->setSubExpr(nullptr); + TheCall->setArg(NumArgs-1, CastArg); + } + } + } + + return false; +} + +// Customized Sema Checking for VSX builtins that have the following signature: +// vector [...] builtinName(vector [...], vector [...], const int); +// Which takes the same type of vectors (any legal vector type) for the first +// two arguments and takes compile time constant for the third argument. +// Example builtins are : +// vector double vec_xxpermdi(vector double, vector double, int); +// vector short vec_xxsldwi(vector short, vector short, int); +bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { + unsigned ExpectedNumArgs = 3; + if (TheCall->getNumArgs() < ExpectedNumArgs) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() + << TheCall->getSourceRange(); + + if (TheCall->getNumArgs() > ExpectedNumArgs) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() + << TheCall->getSourceRange(); + + // Check the third argument is a compile time constant + llvm::APSInt Value; + if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) + return Diag(TheCall->getLocStart(), + diag::err_vsx_builtin_nonconstant_argument) + << 3 /* argument index */ << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(2)->getLocStart(), + TheCall->getArg(2)->getLocEnd()); + + QualType Arg1Ty = TheCall->getArg(0)->getType(); + QualType Arg2Ty = TheCall->getArg(1)->getType(); + + // Check the type of argument 1 and argument 2 are vectors. + SourceLocation BuiltinLoc = TheCall->getLocStart(); + if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || + (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { + return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + } + + // Check the first two arguments are the same type. + if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { + return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + } + + // When default clang type checking is turned off and the customized type + // checking is used, the returning type of the function must be explicitly + // set. Otherwise it is _Bool by default. + TheCall->setType(Arg1Ty); + + return false; +} + +/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. +// This is declared to take (...), so we have to check everything. +ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return ExprError(Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << TheCall->getSourceRange()); + + // Determine which of the following types of shufflevector we're checking: + // 1) unary, vector mask: (lhs, mask) + // 2) binary, scalar mask: (lhs, rhs, index, ..., index) + QualType resType = TheCall->getArg(0)->getType(); + unsigned numElements = 0; + + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(1)->isTypeDependent()) { + QualType LHSType = TheCall->getArg(0)->getType(); + QualType RHSType = TheCall->getArg(1)->getType(); + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_non_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + + numElements = LHSType->getAs()->getNumElements(); + unsigned numResElements = TheCall->getNumArgs() - 2; + + // Check to see if we have a call with 2 vector arguments, the unary shuffle + // with mask. If so, verify that RHS is an integer vector type with the + // same number of elts as lhs. + if (TheCall->getNumArgs() == 2) { + if (!RHSType->hasIntegerRepresentation() || + RHSType->getAs()->getNumElements() != numElements) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + } else if (numElements != numResElements) { + QualType eltType = LHSType->getAs()->getElementType(); + resType = Context.getVectorType(eltType, numResElements, + VectorType::GenericVector); + } + } + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + continue; + + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); + + // Allow -1 which will be translated to undef in the IR. + if (Result.isSigned() && Result.isAllOnesValue()) + continue; + + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_argument_too_large) + << TheCall->getArg(i)->getSourceRange()); + } + + SmallVector exprs; + + for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { + exprs.push_back(TheCall->getArg(i)); + TheCall->setArg(i, nullptr); + } + + return new (Context) ShuffleVectorExpr(Context, exprs, resType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc()); +} + +/// SemaConvertVectorExpr - Handle __builtin_convertvector +ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = TInfo->getType(); + QualType SrcTy = E->getType(); + + if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector) + << E->getSourceRange()); + if (!DstTy->isVectorType() && !DstTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector_type)); + + if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { + unsigned SrcElts = SrcTy->getAs()->getNumElements(); + unsigned DstElts = DstTy->getAs()->getNumElements(); + if (SrcElts != DstElts) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_incompatible_vector) + << E->getSourceRange()); + } + + return new (Context) + ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); +} + +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned NumArgs = TheCall->getNumArgs(); + + if (NumArgs > 3) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs + << TheCall->getSourceRange(); + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i = 1; i != NumArgs; ++i) if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) return true; diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c index 7e999991f3..893a4459f7 100644 --- a/test/Sema/builtins.c +++ b/test/Sema/builtins.c @@ -53,203 +53,226 @@ void test9(short v) { // overloaded atomics should be declared only once. void test9_1(volatile int* ptr, int val) { - __sync_fetch_and_add_4(ptr, val); -} -void test9_2(volatile int* ptr, int val) { - __sync_fetch_and_add(ptr, val); -} -void test9_3(volatile int* ptr, int val) { - __sync_fetch_and_add_4(ptr, val); - __sync_fetch_and_add(ptr, val); - __sync_fetch_and_add(ptr, val); - __sync_fetch_and_add_4(ptr, val); - __sync_fetch_and_add_4(ptr, val); -} - -void test9_4(volatile int* ptr, int val) { - // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} - __sync_fetch_and_nand(ptr, val); -} - -// rdar://7236819 -void test10(void) __attribute__((noreturn)); - -void test10(void) { - __asm__("int3"); - __builtin_unreachable(); - - // No warning about falling off the end of a noreturn function. -} - -void test11(int X) { - switch (X) { - case __builtin_eh_return_data_regno(0): // constant foldable. - break; - } - - __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} -} - -// PR5062 -void test12(void) __attribute__((__noreturn__)); -void test12(void) { - __builtin_trap(); // no warning because trap is noreturn. -} - -void test_unknown_builtin(int a, int b) { - __builtin_isles(a, b); // expected-error{{use of unknown builtin}} \ - // expected-note{{did you mean '__builtin_isless'?}} -} - -int test13() { - __builtin_eh_return(0, 0); // no warning, eh_return never returns. -} - -// -void test14() { - int old; - old = __sync_fetch_and_min((volatile int *)&old, 1); -} - -// -void test15(const char *s) { - __builtin_printf("string is %s\n", s); -} - -// PR7885 -int test16() { - return __builtin_constant_p() + // expected-error{{too few arguments}} - __builtin_constant_p(1, 2); // expected-error {{too many arguments}} -} - -const int test17_n = 0; -const char test17_c[] = {1, 2, 3, 0}; -const char test17_d[] = {1, 2, 3, 4}; -typedef int __attribute__((vector_size(16))) IntVector; -struct Aggregate { int n; char c; }; -enum Enum { EnumValue1, EnumValue2 }; - -typedef __typeof(sizeof(int)) size_t; -size_t strlen(const char *); - -void test17() { -#define ASSERT(...) { int arr[(__VA_ARGS__) ? 1 : -1]; } -#define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__)) -#define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__)) - - // __builtin_constant_p returns 1 if the argument folds to: - // - an arithmetic constant with value which is known at compile time - T(test17_n); - T(&test17_c[3] - test17_c); - T(3i + 5); // expected-warning {{imaginary constant}} - T(4.2 * 7.6); - T(EnumValue1); - T((enum Enum)(int)EnumValue2); - - // - the address of the first character of a string literal, losslessly cast - // to any type - T("string literal"); - T((double*)"string literal"); - T("string literal" + 0); - T((long)"string literal"); - - // ... and otherwise returns 0. - F("string literal" + 1); - F(&test17_n); - F(test17_c); - F(&test17_c); - F(&test17_d); - F((struct Aggregate){0, 1}); - F((IntVector){0, 1, 2, 3}); - - // Ensure that a technique used in glibc is handled correctly. -#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4) - // FIXME: These are incorrectly treated as ICEs because strlen is treated as - // a builtin. - ASSERT(OPT("abc")); - ASSERT(!OPT("abcd")); - // In these cases, the strlen is non-constant, but the __builtin_constant_p - // is 0: the array size is not an ICE but is foldable. - ASSERT(!OPT(test17_c)); // expected-warning {{folded}} - ASSERT(!OPT(&test17_c[0])); // expected-warning {{folded}} - ASSERT(!OPT((char*)test17_c)); // expected-warning {{folded}} - ASSERT(!OPT(test17_d)); // expected-warning {{folded}} - ASSERT(!OPT(&test17_d[0])); // expected-warning {{folded}} - ASSERT(!OPT((char*)test17_d)); // expected-warning {{folded}} - -#undef OPT -#undef T -#undef F -} - -void test18() { - char src[1024]; - char dst[2048]; - size_t result; - void *ptr; - - ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src), sizeof(dst)); - result = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); - result = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); - - ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src)); // expected-error {{too few arguments to function call}} - ptr = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} - ptr = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} -} - -void no_ms_builtins() { - __assume(1); // expected-warning {{implicit declaration}} - __noop(1); // expected-warning {{implicit declaration}} - __debugbreak(); // expected-warning {{implicit declaration}} -} - -void unavailable() { - __builtin_operator_new(0); // expected-error {{'__builtin_operator_new' is only available in C++}} - __builtin_operator_delete(0); // expected-error {{'__builtin_operator_delete' is only available in C++}} -} - -// rdar://18259539 -size_t strlcpy(char * restrict dst, const char * restrict src, size_t size); -size_t strlcat(char * restrict dst, const char * restrict src, size_t size); - -void Test19(void) -{ - static char b[40]; - static char buf[20]; - - strlcpy(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} \\ - // expected-note {{change size argument to be the size of the destination}} - __builtin___strlcpy_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcpy_chk' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} \ - // expected-warning {{'__builtin___strlcpy_chk' will always overflow destination buffer}} - - strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} - - __builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} \ - // expected-warning {{'__builtin___strlcat_chk' will always overflow destination buffer}} -} - -// rdar://11076881 -char * Test20(char *p, const char *in, unsigned n) -{ - static char buf[10]; - - __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} - - __builtin___memcpy_chk (p, "abcde", n, __builtin_object_size (p, 0)); - - __builtin___memcpy_chk (&buf[5], "abcde", 5, __builtin_object_size (&buf[5], 0)); - - __builtin___memcpy_chk (&buf[5], "abcde", n, __builtin_object_size (&buf[5], 0)); - - __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} - - return buf; -} - -void test21(const int *ptr) { - __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} - __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} -} + __sync_fetch_and_add_4(ptr, val); +} +void test9_2(volatile int* ptr, int val) { + __sync_fetch_and_add(ptr, val); +} +void test9_3(volatile int* ptr, int val) { + __sync_fetch_and_add_4(ptr, val); + __sync_fetch_and_add(ptr, val); + __sync_fetch_and_add(ptr, val); + __sync_fetch_and_add_4(ptr, val); + __sync_fetch_and_add_4(ptr, val); +} + +void test9_4(volatile int* ptr, int val) { + // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} + __sync_fetch_and_nand(ptr, val); +} + +// rdar://7236819 +void test10(void) __attribute__((noreturn)); + +void test10(void) { + __asm__("int3"); + __builtin_unreachable(); + + // No warning about falling off the end of a noreturn function. +} + +void test11(int X) { + switch (X) { + case __builtin_eh_return_data_regno(0): // constant foldable. + break; + } + + __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} +} + +// PR5062 +void test12(void) __attribute__((__noreturn__)); +void test12(void) { + __builtin_trap(); // no warning because trap is noreturn. +} + +void test_unknown_builtin(int a, int b) { + __builtin_isles(a, b); // expected-error{{use of unknown builtin}} \ + // expected-note{{did you mean '__builtin_isless'?}} +} + +int test13() { + __builtin_eh_return(0, 0); // no warning, eh_return never returns. +} + +// +void test14() { + int old; + old = __sync_fetch_and_min((volatile int *)&old, 1); +} + +// +void test15(const char *s) { + __builtin_printf("string is %s\n", s); +} + +// PR7885 +int test16() { + return __builtin_constant_p() + // expected-error{{too few arguments}} + __builtin_constant_p(1, 2); // expected-error {{too many arguments}} +} + +const int test17_n = 0; +const char test17_c[] = {1, 2, 3, 0}; +const char test17_d[] = {1, 2, 3, 4}; +typedef int __attribute__((vector_size(16))) IntVector; +struct Aggregate { int n; char c; }; +enum Enum { EnumValue1, EnumValue2 }; + +typedef __typeof(sizeof(int)) size_t; +size_t strlen(const char *); + +void test17() { +#define ASSERT(...) { int arr[(__VA_ARGS__) ? 1 : -1]; } +#define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__)) +#define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__)) + + // __builtin_constant_p returns 1 if the argument folds to: + // - an arithmetic constant with value which is known at compile time + T(test17_n); + T(&test17_c[3] - test17_c); + T(3i + 5); // expected-warning {{imaginary constant}} + T(4.2 * 7.6); + T(EnumValue1); + T((enum Enum)(int)EnumValue2); + + // - the address of the first character of a string literal, losslessly cast + // to any type + T("string literal"); + T((double*)"string literal"); + T("string literal" + 0); + T((long)"string literal"); + + // ... and otherwise returns 0. + F("string literal" + 1); + F(&test17_n); + F(test17_c); + F(&test17_c); + F(&test17_d); + F((struct Aggregate){0, 1}); + F((IntVector){0, 1, 2, 3}); + + // Ensure that a technique used in glibc is handled correctly. +#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4) + // FIXME: These are incorrectly treated as ICEs because strlen is treated as + // a builtin. + ASSERT(OPT("abc")); + ASSERT(!OPT("abcd")); + // In these cases, the strlen is non-constant, but the __builtin_constant_p + // is 0: the array size is not an ICE but is foldable. + ASSERT(!OPT(test17_c)); // expected-warning {{folded}} + ASSERT(!OPT(&test17_c[0])); // expected-warning {{folded}} + ASSERT(!OPT((char*)test17_c)); // expected-warning {{folded}} + ASSERT(!OPT(test17_d)); // expected-warning {{folded}} + ASSERT(!OPT(&test17_d[0])); // expected-warning {{folded}} + ASSERT(!OPT((char*)test17_d)); // expected-warning {{folded}} + +#undef OPT +#undef T +#undef F +} + +void test18() { + char src[1024]; + char dst[2048]; + size_t result; + void *ptr; + + ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src), sizeof(dst)); + result = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); + result = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); + + ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src)); // expected-error {{too few arguments to function call}} + ptr = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} + ptr = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} +} + +void no_ms_builtins() { + __assume(1); // expected-warning {{implicit declaration}} + __noop(1); // expected-warning {{implicit declaration}} + __debugbreak(); // expected-warning {{implicit declaration}} +} + +void unavailable() { + __builtin_operator_new(0); // expected-error {{'__builtin_operator_new' is only available in C++}} + __builtin_operator_delete(0); // expected-error {{'__builtin_operator_delete' is only available in C++}} +} + +// rdar://18259539 +size_t strlcpy(char * restrict dst, const char * restrict src, size_t size); +size_t strlcat(char * restrict dst, const char * restrict src, size_t size); + +void Test19(void) +{ + static char b[40]; + static char buf[20]; + + strlcpy(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} \\ + // expected-note {{change size argument to be the size of the destination}} + __builtin___strlcpy_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcpy_chk' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} \ + // expected-warning {{'__builtin___strlcpy_chk' will always overflow destination buffer}} + + strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} + + __builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} \ + // expected-warning {{'__builtin___strlcat_chk' will always overflow destination buffer}} +} + +// rdar://11076881 +char * Test20(char *p, const char *in, unsigned n) +{ + static char buf[10]; + + __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} + + __builtin___memcpy_chk (p, "abcde", n, __builtin_object_size (p, 0)); + + __builtin___memcpy_chk (&buf[5], "abcde", 5, __builtin_object_size (&buf[5], 0)); + + __builtin___memcpy_chk (&buf[5], "abcde", n, __builtin_object_size (&buf[5], 0)); + + __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} + + return buf; +} + +void test21(const int *ptr) { + __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} + __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} +} + +void test22(void) { + (void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbit(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}} + (void)__builtin_signbit(1.0); + (void)__builtin_signbit(1.0f); + (void)__builtin_signbit(1.0L); + + (void)__builtin_signbitf(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitf(1); + (void)__builtin_signbitf(1.0); + (void)__builtin_signbitf(1.0f); + (void)__builtin_signbitf(1.0L); + + (void)__builtin_signbitl(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitl(1); + (void)__builtin_signbitl(1.0); + (void)__builtin_signbitl(1.0f); + (void)__builtin_signbitl(1.0L); +} -- GitLab From ac1b00383a6afe8c89fa814906e9ed8187157f49 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 19 Jun 2018 14:53:20 +0000 Subject: [PATCH 0179/1023] Reverting due to line ending changes; will reapply after addressing that. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335049 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 1625 ++++++++++++++++++------------------- test/Sema/builtins.c | 423 +++++----- 2 files changed, 1009 insertions(+), 1039 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index e18dd056e9..5530bd8fe7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -772,409 +772,406 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { } // Since return type of reserve_read/write_pipe built-in function is - // reserve_id_t, which is not defined in the builtin def file , we used int - // as return type and need to override the return type of these functions. - Call->setType(S.Context.OCLReserveIDTy); - - return false; -} - -// Performs a semantic analysis on {work_group_/sub_group_ -// /_}commit_{read/write}_pipe -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) - return true; - - if (checkOpenCLPipeArg(S, Call)) - return true; - - // Check reserve_id_t. - if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.OCLReserveIDTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - return false; -} - -// Performs a semantic analysis on the call to built-in Pipe -// Query Functions. -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) - return true; - - if (!Call->getArg(0)->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) - << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); - return true; - } - - return false; -} - -// OpenCL v2.0 s6.13.9 - Address space qualifier functions. -// Performs semantic analysis for the to_global/local/private call. -// \param S Reference to the semantic analyzer. -// \param BuiltinID ID of the builtin function. -// \param Call A pointer to the builtin call. -// \return True if a semantic error has been found, false otherwise. -static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, - CallExpr *Call) { - if (Call->getNumArgs() != 1) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - auto RT = Call->getArg(0)->getType(); - if (!RT->isPointerType() || RT->getPointeeType() - .getAddressSpace() == LangAS::opencl_constant) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) - << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - RT = RT->getPointeeType(); - auto Qual = RT.getQualifiers(); - switch (BuiltinID) { - case Builtin::BIto_global: - Qual.setAddressSpace(LangAS::opencl_global); - break; - case Builtin::BIto_local: - Qual.setAddressSpace(LangAS::opencl_local); - break; - case Builtin::BIto_private: - Qual.setAddressSpace(LangAS::opencl_private); - break; - default: - llvm_unreachable("Invalid builtin function"); - } - Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( - RT.getUnqualifiedType(), Qual))); - - return false; -} - -// Emit an error and return true if the current architecture is not in the list -// of supported architectures. -static bool -CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, - ArrayRef SupportedArchs) { - llvm::Triple::ArchType CurArch = - S.getASTContext().getTargetInfo().getTriple().getArch(); - if (llvm::is_contained(SupportedArchs, CurArch)) - return false; - S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) - << TheCall->getSourceRange(); - return true; -} - -ExprResult -Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, - CallExpr *TheCall) { - ExprResult TheCallResult(TheCall); - - // Find out if any arguments are required to be integer constant expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); - if (Error != ASTContext::GE_None) - ICEArguments = 0; // Don't diagnose previously diagnosed errors. - - // If any arguments are required to be ICE's, check and diagnose. - for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { - // Skip arguments not required to be ICE's. - if ((ICEArguments & (1 << ArgNo)) == 0) continue; - - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) - return true; - ICEArguments &= ~(1 << ArgNo); - } - - switch (BuiltinID) { - case Builtin::BI__builtin___CFStringMakeConstantString: - assert(TheCall->getNumArgs() == 1 && - "Wrong # arguments to builtin CFStringMakeConstantString"); - if (CheckObjCString(TheCall->getArg(0))) - return ExprError(); - break; - case Builtin::BI__builtin_ms_va_start: - case Builtin::BI__builtin_stdarg_start: - case Builtin::BI__builtin_va_start: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - case Builtin::BI__va_start: { - switch (Context.getTargetInfo().getTriple().getArch()) { - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (SemaBuiltinVAStartARMMicrosoft(TheCall)) - return ExprError(); - break; - default: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - } - break; - } - - // The acquire, release, and no fence variants are ARM and AArch64 only. - case Builtin::BI_interlockedbittestandset_acq: - case Builtin::BI_interlockedbittestandset_rel: - case Builtin::BI_interlockedbittestandset_nf: - case Builtin::BI_interlockedbittestandreset_acq: - case Builtin::BI_interlockedbittestandreset_rel: - case Builtin::BI_interlockedbittestandreset_nf: - if (CheckBuiltinTargetSupport( - *this, BuiltinID, TheCall, - {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - // The 64-bit bittest variants are x64, ARM, and AArch64 only. - case Builtin::BI_bittest64: - case Builtin::BI_bittestandcomplement64: - case Builtin::BI_bittestandreset64: - case Builtin::BI_bittestandset64: - case Builtin::BI_interlockedbittestandreset64: - case Builtin::BI_interlockedbittestandset64: - if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, - {llvm::Triple::x86_64, llvm::Triple::arm, - llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - case Builtin::BI__builtin_isgreater: - case Builtin::BI__builtin_isgreaterequal: - case Builtin::BI__builtin_isless: - case Builtin::BI__builtin_islessequal: - case Builtin::BI__builtin_islessgreater: - case Builtin::BI__builtin_isunordered: - if (SemaBuiltinUnorderedCompare(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_fpclassify: - if (SemaBuiltinFPClassification(TheCall, 6)) - return ExprError(); - break; - case Builtin::BI__builtin_isfinite: - case Builtin::BI__builtin_isinf: - case Builtin::BI__builtin_isinf_sign: - case Builtin::BI__builtin_isnan: - case Builtin::BI__builtin_isnormal: - case Builtin::BI__builtin_signbit: - case Builtin::BI__builtin_signbitf: - case Builtin::BI__builtin_signbitl: - if (SemaBuiltinFPClassification(TheCall, 1)) - return ExprError(); - break; - case Builtin::BI__builtin_shufflevector: - return SemaBuiltinShuffleVector(TheCall); - // TheCall will be freed by the smart pointer here, but that's fine, since - // SemaBuiltinShuffleVector guts it, but then doesn't release it. - case Builtin::BI__builtin_prefetch: - if (SemaBuiltinPrefetch(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_alloca_with_align: - if (SemaBuiltinAllocaWithAlign(TheCall)) - return ExprError(); - break; - case Builtin::BI__assume: - case Builtin::BI__builtin_assume: - if (SemaBuiltinAssume(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_assume_aligned: - if (SemaBuiltinAssumeAligned(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_object_size: - if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) - return ExprError(); - break; - case Builtin::BI__builtin_longjmp: - if (SemaBuiltinLongjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_setjmp: - if (SemaBuiltinSetjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI_setjmp: - case Builtin::BI_setjmpex: - if (checkArgCount(*this, TheCall, 1)) - return true; - break; - case Builtin::BI__builtin_classify_type: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__builtin_constant_p: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__sync_fetch_and_add: - case Builtin::BI__sync_fetch_and_add_1: - case Builtin::BI__sync_fetch_and_add_2: - case Builtin::BI__sync_fetch_and_add_4: - case Builtin::BI__sync_fetch_and_add_8: - case Builtin::BI__sync_fetch_and_add_16: - case Builtin::BI__sync_fetch_and_sub: - case Builtin::BI__sync_fetch_and_sub_1: - case Builtin::BI__sync_fetch_and_sub_2: - case Builtin::BI__sync_fetch_and_sub_4: - case Builtin::BI__sync_fetch_and_sub_8: - case Builtin::BI__sync_fetch_and_sub_16: - case Builtin::BI__sync_fetch_and_or: - case Builtin::BI__sync_fetch_and_or_1: - case Builtin::BI__sync_fetch_and_or_2: - case Builtin::BI__sync_fetch_and_or_4: - case Builtin::BI__sync_fetch_and_or_8: - case Builtin::BI__sync_fetch_and_or_16: - case Builtin::BI__sync_fetch_and_and: - case Builtin::BI__sync_fetch_and_and_1: - case Builtin::BI__sync_fetch_and_and_2: - case Builtin::BI__sync_fetch_and_and_4: - case Builtin::BI__sync_fetch_and_and_8: - case Builtin::BI__sync_fetch_and_and_16: - case Builtin::BI__sync_fetch_and_xor: - case Builtin::BI__sync_fetch_and_xor_1: - case Builtin::BI__sync_fetch_and_xor_2: - case Builtin::BI__sync_fetch_and_xor_4: - case Builtin::BI__sync_fetch_and_xor_8: - case Builtin::BI__sync_fetch_and_xor_16: - case Builtin::BI__sync_fetch_and_nand: - case Builtin::BI__sync_fetch_and_nand_1: - case Builtin::BI__sync_fetch_and_nand_2: - case Builtin::BI__sync_fetch_and_nand_4: - case Builtin::BI__sync_fetch_and_nand_8: - case Builtin::BI__sync_fetch_and_nand_16: - case Builtin::BI__sync_add_and_fetch: - case Builtin::BI__sync_add_and_fetch_1: - case Builtin::BI__sync_add_and_fetch_2: - case Builtin::BI__sync_add_and_fetch_4: - case Builtin::BI__sync_add_and_fetch_8: - case Builtin::BI__sync_add_and_fetch_16: - case Builtin::BI__sync_sub_and_fetch: - case Builtin::BI__sync_sub_and_fetch_1: - case Builtin::BI__sync_sub_and_fetch_2: - case Builtin::BI__sync_sub_and_fetch_4: - case Builtin::BI__sync_sub_and_fetch_8: - case Builtin::BI__sync_sub_and_fetch_16: - case Builtin::BI__sync_and_and_fetch: - case Builtin::BI__sync_and_and_fetch_1: - case Builtin::BI__sync_and_and_fetch_2: - case Builtin::BI__sync_and_and_fetch_4: - case Builtin::BI__sync_and_and_fetch_8: - case Builtin::BI__sync_and_and_fetch_16: - case Builtin::BI__sync_or_and_fetch: - case Builtin::BI__sync_or_and_fetch_1: - case Builtin::BI__sync_or_and_fetch_2: - case Builtin::BI__sync_or_and_fetch_4: - case Builtin::BI__sync_or_and_fetch_8: - case Builtin::BI__sync_or_and_fetch_16: - case Builtin::BI__sync_xor_and_fetch: - case Builtin::BI__sync_xor_and_fetch_1: - case Builtin::BI__sync_xor_and_fetch_2: - case Builtin::BI__sync_xor_and_fetch_4: - case Builtin::BI__sync_xor_and_fetch_8: - case Builtin::BI__sync_xor_and_fetch_16: - case Builtin::BI__sync_nand_and_fetch: - case Builtin::BI__sync_nand_and_fetch_1: - case Builtin::BI__sync_nand_and_fetch_2: - case Builtin::BI__sync_nand_and_fetch_4: - case Builtin::BI__sync_nand_and_fetch_8: - case Builtin::BI__sync_nand_and_fetch_16: - case Builtin::BI__sync_val_compare_and_swap: - case Builtin::BI__sync_val_compare_and_swap_1: - case Builtin::BI__sync_val_compare_and_swap_2: - case Builtin::BI__sync_val_compare_and_swap_4: - case Builtin::BI__sync_val_compare_and_swap_8: - case Builtin::BI__sync_val_compare_and_swap_16: - case Builtin::BI__sync_bool_compare_and_swap: - case Builtin::BI__sync_bool_compare_and_swap_1: - case Builtin::BI__sync_bool_compare_and_swap_2: - case Builtin::BI__sync_bool_compare_and_swap_4: - case Builtin::BI__sync_bool_compare_and_swap_8: - case Builtin::BI__sync_bool_compare_and_swap_16: - case Builtin::BI__sync_lock_test_and_set: - case Builtin::BI__sync_lock_test_and_set_1: - case Builtin::BI__sync_lock_test_and_set_2: - case Builtin::BI__sync_lock_test_and_set_4: - case Builtin::BI__sync_lock_test_and_set_8: - case Builtin::BI__sync_lock_test_and_set_16: - case Builtin::BI__sync_lock_release: - case Builtin::BI__sync_lock_release_1: - case Builtin::BI__sync_lock_release_2: - case Builtin::BI__sync_lock_release_4: - case Builtin::BI__sync_lock_release_8: - case Builtin::BI__sync_lock_release_16: - case Builtin::BI__sync_swap: - case Builtin::BI__sync_swap_1: - case Builtin::BI__sync_swap_2: - case Builtin::BI__sync_swap_4: - case Builtin::BI__sync_swap_8: - case Builtin::BI__sync_swap_16: - return SemaBuiltinAtomicOverloaded(TheCallResult); - case Builtin::BI__builtin_nontemporal_load: - case Builtin::BI__builtin_nontemporal_store: - return SemaBuiltinNontemporalOverloaded(TheCallResult); -#define BUILTIN(ID, TYPE, ATTRS) -#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ - case Builtin::BI##ID: \ - return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); -#include "clang/Basic/Builtins.def" - case Builtin::BI__annotation: - if (SemaBuiltinMSVCAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_annotation: - if (SemaBuiltinAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_addressof: - if (SemaBuiltinAddressof(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_add_overflow: - case Builtin::BI__builtin_sub_overflow: - case Builtin::BI__builtin_mul_overflow: - if (SemaBuiltinOverflow(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_operator_new: - case Builtin::BI__builtin_operator_delete: { - bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; - ExprResult Res = - SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); - if (Res.isInvalid()) - CorrectDelayedTyposInExpr(TheCallResult.get()); - return Res; - } - case Builtin::BI__builtin_dump_struct: { - // We first want to ensure we are called with 2 arguments - if (checkArgCount(*this, TheCall, 2)) - return ExprError(); - // Ensure that the first argument is of type 'struct XX *' - const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); - const QualType PtrArgType = PtrArg->getType(); - if (!PtrArgType->isPointerType() || - !PtrArgType->getPointeeType()->isRecordType()) { - Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) - << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType - << "structure pointer"; - return ExprError(); + // reserve_id_t, which is not defined in the builtin def file , we used int + // as return type and need to override the return type of these functions. + Call->setType(S.Context.OCLReserveIDTy); + + return false; +} + +// Performs a semantic analysis on {work_group_/sub_group_ +// /_}commit_{read/write}_pipe +// \param S Reference to the semantic analyzer. +// \param Call The call to the builtin function to be analyzed. +// \return True if a semantic error was found, false otherwise. +static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 2)) + return true; + + if (checkOpenCLPipeArg(S, Call)) + return true; + + // Check reserve_id_t. + if (!Call->getArg(1)->getType()->isReserveIDT()) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) + << Call->getDirectCallee() << S.Context.OCLReserveIDTy + << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); + return true; + } + + return false; +} + +// Performs a semantic analysis on the call to built-in Pipe +// Query Functions. +// \param S Reference to the semantic analyzer. +// \param Call The call to the builtin function to be analyzed. +// \return True if a semantic error was found, false otherwise. +static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 1)) + return true; + + if (!Call->getArg(0)->getType()->isPipeType()) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) + << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); + return true; + } + + return false; +} + +// OpenCL v2.0 s6.13.9 - Address space qualifier functions. +// Performs semantic analysis for the to_global/local/private call. +// \param S Reference to the semantic analyzer. +// \param BuiltinID ID of the builtin function. +// \param Call A pointer to the builtin call. +// \return True if a semantic error has been found, false otherwise. +static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, + CallExpr *Call) { + if (Call->getNumArgs() != 1) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) + << Call->getDirectCallee() << Call->getSourceRange(); + return true; + } + + auto RT = Call->getArg(0)->getType(); + if (!RT->isPointerType() || RT->getPointeeType() + .getAddressSpace() == LangAS::opencl_constant) { + S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) + << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); + return true; + } + + RT = RT->getPointeeType(); + auto Qual = RT.getQualifiers(); + switch (BuiltinID) { + case Builtin::BIto_global: + Qual.setAddressSpace(LangAS::opencl_global); + break; + case Builtin::BIto_local: + Qual.setAddressSpace(LangAS::opencl_local); + break; + case Builtin::BIto_private: + Qual.setAddressSpace(LangAS::opencl_private); + break; + default: + llvm_unreachable("Invalid builtin function"); + } + Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( + RT.getUnqualifiedType(), Qual))); + + return false; +} + +// Emit an error and return true if the current architecture is not in the list +// of supported architectures. +static bool +CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, + ArrayRef SupportedArchs) { + llvm::Triple::ArchType CurArch = + S.getASTContext().getTargetInfo().getTriple().getArch(); + if (llvm::is_contained(SupportedArchs, CurArch)) + return false; + S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) + << TheCall->getSourceRange(); + return true; +} + +ExprResult +Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, + CallExpr *TheCall) { + ExprResult TheCallResult(TheCall); + + // Find out if any arguments are required to be integer constant expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); + if (Error != ASTContext::GE_None) + ICEArguments = 0; // Don't diagnose previously diagnosed errors. + + // If any arguments are required to be ICE's, check and diagnose. + for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { + // Skip arguments not required to be ICE's. + if ((ICEArguments & (1 << ArgNo)) == 0) continue; + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + ICEArguments &= ~(1 << ArgNo); + } + + switch (BuiltinID) { + case Builtin::BI__builtin___CFStringMakeConstantString: + assert(TheCall->getNumArgs() == 1 && + "Wrong # arguments to builtin CFStringMakeConstantString"); + if (CheckObjCString(TheCall->getArg(0))) + return ExprError(); + break; + case Builtin::BI__builtin_ms_va_start: + case Builtin::BI__builtin_stdarg_start: + case Builtin::BI__builtin_va_start: + if (SemaBuiltinVAStart(BuiltinID, TheCall)) + return ExprError(); + break; + case Builtin::BI__va_start: { + switch (Context.getTargetInfo().getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (SemaBuiltinVAStartARMMicrosoft(TheCall)) + return ExprError(); + break; + default: + if (SemaBuiltinVAStart(BuiltinID, TheCall)) + return ExprError(); + break; + } + break; + } + + // The acquire, release, and no fence variants are ARM and AArch64 only. + case Builtin::BI_interlockedbittestandset_acq: + case Builtin::BI_interlockedbittestandset_rel: + case Builtin::BI_interlockedbittestandset_nf: + case Builtin::BI_interlockedbittestandreset_acq: + case Builtin::BI_interlockedbittestandreset_rel: + case Builtin::BI_interlockedbittestandreset_nf: + if (CheckBuiltinTargetSupport( + *this, BuiltinID, TheCall, + {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + + // The 64-bit bittest variants are x64, ARM, and AArch64 only. + case Builtin::BI_bittest64: + case Builtin::BI_bittestandcomplement64: + case Builtin::BI_bittestandreset64: + case Builtin::BI_bittestandset64: + case Builtin::BI_interlockedbittestandreset64: + case Builtin::BI_interlockedbittestandset64: + if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, + {llvm::Triple::x86_64, llvm::Triple::arm, + llvm::Triple::thumb, llvm::Triple::aarch64})) + return ExprError(); + break; + + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: + if (SemaBuiltinUnorderedCompare(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + return ExprError(); + break; + case Builtin::BI__builtin_isfinite: + case Builtin::BI__builtin_isinf: + case Builtin::BI__builtin_isinf_sign: + case Builtin::BI__builtin_isnan: + case Builtin::BI__builtin_isnormal: + if (SemaBuiltinFPClassification(TheCall, 1)) + return ExprError(); + break; + case Builtin::BI__builtin_shufflevector: + return SemaBuiltinShuffleVector(TheCall); + // TheCall will be freed by the smart pointer here, but that's fine, since + // SemaBuiltinShuffleVector guts it, but then doesn't release it. + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_alloca_with_align: + if (SemaBuiltinAllocaWithAlign(TheCall)) + return ExprError(); + break; + case Builtin::BI__assume: + case Builtin::BI__builtin_assume: + if (SemaBuiltinAssume(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_assume_aligned: + if (SemaBuiltinAssumeAligned(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_object_size: + if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) + return ExprError(); + break; + case Builtin::BI__builtin_longjmp: + if (SemaBuiltinLongjmp(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_setjmp: + if (SemaBuiltinSetjmp(TheCall)) + return ExprError(); + break; + case Builtin::BI_setjmp: + case Builtin::BI_setjmpex: + if (checkArgCount(*this, TheCall, 1)) + return true; + break; + case Builtin::BI__builtin_classify_type: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__builtin_constant_p: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: + case Builtin::BI__sync_fetch_and_nand: + case Builtin::BI__sync_fetch_and_nand_1: + case Builtin::BI__sync_fetch_and_nand_2: + case Builtin::BI__sync_fetch_and_nand_4: + case Builtin::BI__sync_fetch_and_nand_8: + case Builtin::BI__sync_fetch_and_nand_16: + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: + case Builtin::BI__sync_nand_and_fetch: + case Builtin::BI__sync_nand_and_fetch_1: + case Builtin::BI__sync_nand_and_fetch_2: + case Builtin::BI__sync_nand_and_fetch_4: + case Builtin::BI__sync_nand_and_fetch_8: + case Builtin::BI__sync_nand_and_fetch_16: + case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: + case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__builtin_nontemporal_load: + case Builtin::BI__builtin_nontemporal_store: + return SemaBuiltinNontemporalOverloaded(TheCallResult); +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case Builtin::BI##ID: \ + return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); +#include "clang/Basic/Builtins.def" + case Builtin::BI__annotation: + if (SemaBuiltinMSVCAnnotation(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_annotation: + if (SemaBuiltinAnnotation(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_addressof: + if (SemaBuiltinAddressof(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + if (SemaBuiltinOverflow(*this, TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: { + bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; + ExprResult Res = + SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); + if (Res.isInvalid()) + CorrectDelayedTyposInExpr(TheCallResult.get()); + return Res; + } + case Builtin::BI__builtin_dump_struct: { + // We first want to ensure we are called with 2 arguments + if (checkArgCount(*this, TheCall, 2)) + return ExprError(); + // Ensure that the first argument is of type 'struct XX *' + const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); + const QualType PtrArgType = PtrArg->getType(); + if (!PtrArgType->isPointerType() || + !PtrArgType->getPointeeType()->isRecordType()) { + Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) + << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType + << "structure pointer"; + return ExprError(); } // Ensure that the second argument is of type 'FunctionType' @@ -4395,419 +4392,415 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, return false; } -/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' -/// for validity. Emit an error and return true on failure; return false -/// on success. -bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { - Expr *Fn = TheCall->getCallee(); - - if (checkVAStartABI(*this, BuiltinID, Fn)) - return true; - - if (TheCall->getNumArgs() > 2) { - Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << Fn->getSourceRange() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - return true; - } - - if (TheCall->getNumArgs() < 2) { - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs(); - } - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, TheCall, 0)) - return true; - - // Check that the current function is variadic, and get its last parameter. - ParmVarDecl *LastParam; - if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam)) - return true; - - // Verify that the second argument to the builtin is the last argument of the - // current function or method. - bool SecondArgIsLastNamedArgument = false; - const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); - - // These are valid if SecondArgIsLastNamedArgument is false after the next - // block. - QualType Type; - SourceLocation ParamLoc; - bool IsCRegister = false; - - if (const DeclRefExpr *DR = dyn_cast(Arg)) { - if (const ParmVarDecl *PV = dyn_cast(DR->getDecl())) { - SecondArgIsLastNamedArgument = PV == LastParam; - - Type = PV->getType(); - ParamLoc = PV->getLocation(); - IsCRegister = - PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; - } - } - - if (!SecondArgIsLastNamedArgument) - Diag(TheCall->getArg(1)->getLocStart(), - diag::warn_second_arg_of_va_start_not_last_named_param); - else if (IsCRegister || Type->isReferenceType() || - Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { - // Promotable integers are UB, but enumerations need a bit of - // extra checking to see what their promotable type actually is. - if (!Type->isPromotableIntegerType()) - return false; - if (!Type->isEnumeralType()) - return true; - const EnumDecl *ED = Type->getAs()->getDecl(); - return !(ED && - Context.typesAreCompatible(ED->getPromotionType(), Type)); - }()) { - unsigned Reason = 0; - if (Type->isReferenceType()) Reason = 1; - else if (IsCRegister) Reason = 2; - Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; - Diag(ParamLoc, diag::note_parameter_type) << Type; - } - - TheCall->setType(Context.VoidTy); - return false; -} - -bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { - // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, - // const char *named_addr); - - Expr *Func = Call->getCallee(); - - if (Call->getNumArgs() < 3) - return Diag(Call->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 3 << Call->getNumArgs(); - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, Call, 0)) - return true; - - // Check that the current function is variadic. - if (checkVAStartIsInVariadicFunction(*this, Func)) - return true; - - // __va_start on Windows does not validate the parameter qualifiers - - const Expr *Arg1 = Call->getArg(1)->IgnoreParens(); - const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr(); - - const Expr *Arg2 = Call->getArg(2)->IgnoreParens(); - const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr(); - - const QualType &ConstCharPtrTy = - Context.getPointerType(Context.CharTy.withConst()); - if (!Arg1Ty->isPointerType() || - Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) - Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg1->getType() << ConstCharPtrTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 2 << Arg1->getType() << ConstCharPtrTy; - - const QualType SizeTy = Context.getSizeType(); - if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) - Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg2->getType() << SizeTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 3 << Arg2->getType() << SizeTy; - - return false; -} - -/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and -/// friends. This is declared to take (...), so we have to check everything. -bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << 2 << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > 2) - return Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - ExprResult OrigArg0 = TheCall->getArg(0); - ExprResult OrigArg1 = TheCall->getArg(1); - - // Do standard promotions between the two arguments, returning their common - // type. - QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); - if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) - return true; - - // Make sure any conversions are pushed back into the call; this is - // type safe since unordered compare builtins are declared as "_Bool - // foo(...)". - TheCall->setArg(0, OrigArg0.get()); - TheCall->setArg(1, OrigArg1.get()); - - if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) - return false; - - // If the common type isn't a real floating type, then the arguments were - // invalid for this operation. - if (Res.isNull() || !Res->isRealFloatingType()) - return Diag(OrigArg0.get()->getLocStart(), - diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0.get()->getType() << OrigArg1.get()->getType() - << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); - - return false; -} - -/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like -/// __builtin_isnan and friends. This is declared to take (...), so we have -/// to check everything. We expect the last argument to be a floating point -/// value. -bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { - if (TheCall->getNumArgs() < NumArgs) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > NumArgs) - return Diag(TheCall->getArg(NumArgs)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - Expr *OrigArg = TheCall->getArg(NumArgs-1); - - if (OrigArg->isTypeDependent()) - return false; - - // This operation requires a non-_Complex floating-point number. - if (!OrigArg->getType()->isRealFloatingType()) - return Diag(OrigArg->getLocStart(), - diag::err_typecheck_call_invalid_unary_fp) - << OrigArg->getType() << OrigArg->getSourceRange(); - - // If this is an implicit conversion from float -> float, double, or - // long double, remove it. - if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { - // Only remove standard FloatCasts, leaving other casts inplace - if (Cast->getCastKind() == CK_FloatingCast) { - Expr *CastArg = Cast->getSubExpr(); - if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert( - (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) && - "promotion from float to either float, double, or long double is " - "the only expected cast here"); - Cast->setSubExpr(nullptr); - TheCall->setArg(NumArgs-1, CastArg); - } - } - } - - return false; -} - -// Customized Sema Checking for VSX builtins that have the following signature: -// vector [...] builtinName(vector [...], vector [...], const int); -// Which takes the same type of vectors (any legal vector type) for the first -// two arguments and takes compile time constant for the third argument. -// Example builtins are : -// vector double vec_xxpermdi(vector double, vector double, int); -// vector short vec_xxsldwi(vector short, vector short, int); -bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { - unsigned ExpectedNumArgs = 3; - if (TheCall->getNumArgs() < ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - if (TheCall->getNumArgs() > ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - // Check the third argument is a compile time constant - llvm::APSInt Value; - if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) - return Diag(TheCall->getLocStart(), - diag::err_vsx_builtin_nonconstant_argument) - << 3 /* argument index */ << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(2)->getLocStart(), - TheCall->getArg(2)->getLocEnd()); - - QualType Arg1Ty = TheCall->getArg(0)->getType(); - QualType Arg2Ty = TheCall->getArg(1)->getType(); - - // Check the type of argument 1 and argument 2 are vectors. - SourceLocation BuiltinLoc = TheCall->getLocStart(); - if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || - (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { - return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // Check the first two arguments are the same type. - if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { - return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // When default clang type checking is turned off and the customized type - // checking is used, the returning type of the function must be explicitly - // set. Otherwise it is _Bool by default. - TheCall->setType(Arg1Ty); - - return false; -} - -/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. -// This is declared to take (...), so we have to check everything. -ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); - - // Determine which of the following types of shufflevector we're checking: - // 1) unary, vector mask: (lhs, mask) - // 2) binary, scalar mask: (lhs, rhs, index, ..., index) - QualType resType = TheCall->getArg(0)->getType(); - unsigned numElements = 0; - - if (!TheCall->getArg(0)->isTypeDependent() && - !TheCall->getArg(1)->isTypeDependent()) { - QualType LHSType = TheCall->getArg(0)->getType(); - QualType RHSType = TheCall->getArg(1)->getType(); - - if (!LHSType->isVectorType() || !RHSType->isVectorType()) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - - numElements = LHSType->getAs()->getNumElements(); - unsigned numResElements = TheCall->getNumArgs() - 2; - - // Check to see if we have a call with 2 vector arguments, the unary shuffle - // with mask. If so, verify that RHS is an integer vector type with the - // same number of elts as lhs. - if (TheCall->getNumArgs() == 2) { - if (!RHSType->hasIntegerRepresentation() || - RHSType->getAs()->getNumElements() != numElements) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(1)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (numElements != numResElements) { - QualType eltType = LHSType->getAs()->getElementType(); - resType = Context.getVectorType(eltType, numResElements, - VectorType::GenericVector); - } - } - - for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - continue; - - llvm::APSInt Result(32); - if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_nonconstant_argument) - << TheCall->getArg(i)->getSourceRange()); - - // Allow -1 which will be translated to undef in the IR. - if (Result.isSigned() && Result.isAllOnesValue()) - continue; - - if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_argument_too_large) - << TheCall->getArg(i)->getSourceRange()); - } - - SmallVector exprs; - - for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { - exprs.push_back(TheCall->getArg(i)); - TheCall->setArg(i, nullptr); - } - - return new (Context) ShuffleVectorExpr(Context, exprs, resType, - TheCall->getCallee()->getLocStart(), - TheCall->getRParenLoc()); -} - -/// SemaConvertVectorExpr - Handle __builtin_convertvector -ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc) { - ExprValueKind VK = VK_RValue; - ExprObjectKind OK = OK_Ordinary; - QualType DstTy = TInfo->getType(); - QualType SrcTy = E->getType(); - - if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector) - << E->getSourceRange()); - if (!DstTy->isVectorType() && !DstTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector_type)); - - if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { - unsigned SrcElts = SrcTy->getAs()->getNumElements(); - unsigned DstElts = DstTy->getAs()->getNumElements(); - if (SrcElts != DstElts) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_incompatible_vector) - << E->getSourceRange()); - } - - return new (Context) - ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); -} - -/// SemaBuiltinPrefetch - Handle __builtin_prefetch. -// This is declared to take (const void*, ...) and can take two -// optional constant int args. -bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { - unsigned NumArgs = TheCall->getNumArgs(); - - if (NumArgs > 3) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs - << TheCall->getSourceRange(); - - // Argument 0 is checked for us and the remaining arguments must be - // constant integers. - for (unsigned i = 1; i != NumArgs; ++i) +/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' +/// for validity. Emit an error and return true on failure; return false +/// on success. +bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { + Expr *Fn = TheCall->getCallee(); + + if (checkVAStartABI(*this, BuiltinID, Fn)) + return true; + + if (TheCall->getNumArgs() > 2) { + Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << Fn->getSourceRange() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + return true; + } + + if (TheCall->getNumArgs() < 2) { + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs(); + } + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, TheCall, 0)) + return true; + + // Check that the current function is variadic, and get its last parameter. + ParmVarDecl *LastParam; + if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam)) + return true; + + // Verify that the second argument to the builtin is the last argument of the + // current function or method. + bool SecondArgIsLastNamedArgument = false; + const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); + + // These are valid if SecondArgIsLastNamedArgument is false after the next + // block. + QualType Type; + SourceLocation ParamLoc; + bool IsCRegister = false; + + if (const DeclRefExpr *DR = dyn_cast(Arg)) { + if (const ParmVarDecl *PV = dyn_cast(DR->getDecl())) { + SecondArgIsLastNamedArgument = PV == LastParam; + + Type = PV->getType(); + ParamLoc = PV->getLocation(); + IsCRegister = + PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; + } + } + + if (!SecondArgIsLastNamedArgument) + Diag(TheCall->getArg(1)->getLocStart(), + diag::warn_second_arg_of_va_start_not_last_named_param); + else if (IsCRegister || Type->isReferenceType() || + Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { + // Promotable integers are UB, but enumerations need a bit of + // extra checking to see what their promotable type actually is. + if (!Type->isPromotableIntegerType()) + return false; + if (!Type->isEnumeralType()) + return true; + const EnumDecl *ED = Type->getAs()->getDecl(); + return !(ED && + Context.typesAreCompatible(ED->getPromotionType(), Type)); + }()) { + unsigned Reason = 0; + if (Type->isReferenceType()) Reason = 1; + else if (IsCRegister) Reason = 2; + Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; + Diag(ParamLoc, diag::note_parameter_type) << Type; + } + + TheCall->setType(Context.VoidTy); + return false; +} + +bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { + // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, + // const char *named_addr); + + Expr *Func = Call->getCallee(); + + if (Call->getNumArgs() < 3) + return Diag(Call->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 3 << Call->getNumArgs(); + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, Call, 0)) + return true; + + // Check that the current function is variadic. + if (checkVAStartIsInVariadicFunction(*this, Func)) + return true; + + // __va_start on Windows does not validate the parameter qualifiers + + const Expr *Arg1 = Call->getArg(1)->IgnoreParens(); + const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr(); + + const Expr *Arg2 = Call->getArg(2)->IgnoreParens(); + const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr(); + + const QualType &ConstCharPtrTy = + Context.getPointerType(Context.CharTy.withConst()); + if (!Arg1Ty->isPointerType() || + Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) + Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) + << Arg1->getType() << ConstCharPtrTy + << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ + << 2 << Arg1->getType() << ConstCharPtrTy; + + const QualType SizeTy = Context.getSizeType(); + if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) + Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) + << Arg2->getType() << SizeTy + << 1 /* different class */ + << 0 /* qualifier difference */ + << 3 /* parameter mismatch */ + << 3 << Arg2->getType() << SizeTy; + + return false; +} + +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and +/// friends. This is declared to take (...), so we have to check everything. +bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << 2 << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > 2) + return Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + ExprResult OrigArg0 = TheCall->getArg(0); + ExprResult OrigArg1 = TheCall->getArg(1); + + // Do standard promotions between the two arguments, returning their common + // type. + QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); + if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) + return true; + + // Make sure any conversions are pushed back into the call; this is + // type safe since unordered compare builtins are declared as "_Bool + // foo(...)". + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); + + if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) + return false; + + // If the common type isn't a real floating type, then the arguments were + // invalid for this operation. + if (Res.isNull() || !Res->isRealFloatingType()) + return Diag(OrigArg0.get()->getLocStart(), + diag::err_typecheck_call_invalid_ordered_compare) + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); + + return false; +} + +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. We expect the last argument to be a floating point +/// value. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { + if (TheCall->getNumArgs() < NumArgs) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > NumArgs) + return Diag(TheCall->getArg(NumArgs)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + Expr *OrigArg = TheCall->getArg(NumArgs-1); + + if (OrigArg->isTypeDependent()) + return false; + + // This operation requires a non-_Complex floating-point number. + if (!OrigArg->getType()->isRealFloatingType()) + return Diag(OrigArg->getLocStart(), + diag::err_typecheck_call_invalid_unary_fp) + << OrigArg->getType() << OrigArg->getSourceRange(); + + // If this is an implicit conversion from float -> float or double, remove it. + if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { + // Only remove standard FloatCasts, leaving other casts inplace + if (Cast->getCastKind() == CK_FloatingCast) { + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && + "promotion from float to either float or double is the only expected cast here"); + Cast->setSubExpr(nullptr); + TheCall->setArg(NumArgs-1, CastArg); + } + } + } + + return false; +} + +// Customized Sema Checking for VSX builtins that have the following signature: +// vector [...] builtinName(vector [...], vector [...], const int); +// Which takes the same type of vectors (any legal vector type) for the first +// two arguments and takes compile time constant for the third argument. +// Example builtins are : +// vector double vec_xxpermdi(vector double, vector double, int); +// vector short vec_xxsldwi(vector short, vector short, int); +bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { + unsigned ExpectedNumArgs = 3; + if (TheCall->getNumArgs() < ExpectedNumArgs) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() + << TheCall->getSourceRange(); + + if (TheCall->getNumArgs() > ExpectedNumArgs) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() + << TheCall->getSourceRange(); + + // Check the third argument is a compile time constant + llvm::APSInt Value; + if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) + return Diag(TheCall->getLocStart(), + diag::err_vsx_builtin_nonconstant_argument) + << 3 /* argument index */ << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(2)->getLocStart(), + TheCall->getArg(2)->getLocEnd()); + + QualType Arg1Ty = TheCall->getArg(0)->getType(); + QualType Arg2Ty = TheCall->getArg(1)->getType(); + + // Check the type of argument 1 and argument 2 are vectors. + SourceLocation BuiltinLoc = TheCall->getLocStart(); + if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || + (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { + return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + } + + // Check the first two arguments are the same type. + if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { + return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + } + + // When default clang type checking is turned off and the customized type + // checking is used, the returning type of the function must be explicitly + // set. Otherwise it is _Bool by default. + TheCall->setType(Arg1Ty); + + return false; +} + +/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. +// This is declared to take (...), so we have to check everything. +ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return ExprError(Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << TheCall->getSourceRange()); + + // Determine which of the following types of shufflevector we're checking: + // 1) unary, vector mask: (lhs, mask) + // 2) binary, scalar mask: (lhs, rhs, index, ..., index) + QualType resType = TheCall->getArg(0)->getType(); + unsigned numElements = 0; + + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(1)->isTypeDependent()) { + QualType LHSType = TheCall->getArg(0)->getType(); + QualType RHSType = TheCall->getArg(1)->getType(); + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_non_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + + numElements = LHSType->getAs()->getNumElements(); + unsigned numResElements = TheCall->getNumArgs() - 2; + + // Check to see if we have a call with 2 vector arguments, the unary shuffle + // with mask. If so, verify that RHS is an integer vector type with the + // same number of elts as lhs. + if (TheCall->getNumArgs() == 2) { + if (!RHSType->hasIntegerRepresentation() || + RHSType->getAs()->getNumElements() != numElements) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { + return ExprError(Diag(TheCall->getLocStart(), + diag::err_vec_builtin_incompatible_vector) + << TheCall->getDirectCallee() + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd())); + } else if (numElements != numResElements) { + QualType eltType = LHSType->getAs()->getElementType(); + resType = Context.getVectorType(eltType, numResElements, + VectorType::GenericVector); + } + } + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + continue; + + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); + + // Allow -1 which will be translated to undef in the IR. + if (Result.isSigned() && Result.isAllOnesValue()) + continue; + + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_argument_too_large) + << TheCall->getArg(i)->getSourceRange()); + } + + SmallVector exprs; + + for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { + exprs.push_back(TheCall->getArg(i)); + TheCall->setArg(i, nullptr); + } + + return new (Context) ShuffleVectorExpr(Context, exprs, resType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc()); +} + +/// SemaConvertVectorExpr - Handle __builtin_convertvector +ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = TInfo->getType(); + QualType SrcTy = E->getType(); + + if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector) + << E->getSourceRange()); + if (!DstTy->isVectorType() && !DstTy->isDependentType()) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_non_vector_type)); + + if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { + unsigned SrcElts = SrcTy->getAs()->getNumElements(); + unsigned DstElts = DstTy->getAs()->getNumElements(); + if (SrcElts != DstElts) + return ExprError(Diag(BuiltinLoc, + diag::err_convertvector_incompatible_vector) + << E->getSourceRange()); + } + + return new (Context) + ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); +} + +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned NumArgs = TheCall->getNumArgs(); + + if (NumArgs > 3) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs + << TheCall->getSourceRange(); + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i = 1; i != NumArgs; ++i) if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) return true; diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c index 893a4459f7..7e999991f3 100644 --- a/test/Sema/builtins.c +++ b/test/Sema/builtins.c @@ -53,226 +53,203 @@ void test9(short v) { // overloaded atomics should be declared only once. void test9_1(volatile int* ptr, int val) { - __sync_fetch_and_add_4(ptr, val); -} -void test9_2(volatile int* ptr, int val) { - __sync_fetch_and_add(ptr, val); -} -void test9_3(volatile int* ptr, int val) { - __sync_fetch_and_add_4(ptr, val); - __sync_fetch_and_add(ptr, val); - __sync_fetch_and_add(ptr, val); - __sync_fetch_and_add_4(ptr, val); - __sync_fetch_and_add_4(ptr, val); -} - -void test9_4(volatile int* ptr, int val) { - // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} - __sync_fetch_and_nand(ptr, val); -} - -// rdar://7236819 -void test10(void) __attribute__((noreturn)); - -void test10(void) { - __asm__("int3"); - __builtin_unreachable(); - - // No warning about falling off the end of a noreturn function. -} - -void test11(int X) { - switch (X) { - case __builtin_eh_return_data_regno(0): // constant foldable. - break; - } - - __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} -} - -// PR5062 -void test12(void) __attribute__((__noreturn__)); -void test12(void) { - __builtin_trap(); // no warning because trap is noreturn. -} - -void test_unknown_builtin(int a, int b) { - __builtin_isles(a, b); // expected-error{{use of unknown builtin}} \ - // expected-note{{did you mean '__builtin_isless'?}} -} - -int test13() { - __builtin_eh_return(0, 0); // no warning, eh_return never returns. -} - -// -void test14() { - int old; - old = __sync_fetch_and_min((volatile int *)&old, 1); -} - -// -void test15(const char *s) { - __builtin_printf("string is %s\n", s); -} - -// PR7885 -int test16() { - return __builtin_constant_p() + // expected-error{{too few arguments}} - __builtin_constant_p(1, 2); // expected-error {{too many arguments}} -} - -const int test17_n = 0; -const char test17_c[] = {1, 2, 3, 0}; -const char test17_d[] = {1, 2, 3, 4}; -typedef int __attribute__((vector_size(16))) IntVector; -struct Aggregate { int n; char c; }; -enum Enum { EnumValue1, EnumValue2 }; - -typedef __typeof(sizeof(int)) size_t; -size_t strlen(const char *); - -void test17() { -#define ASSERT(...) { int arr[(__VA_ARGS__) ? 1 : -1]; } -#define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__)) -#define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__)) - - // __builtin_constant_p returns 1 if the argument folds to: - // - an arithmetic constant with value which is known at compile time - T(test17_n); - T(&test17_c[3] - test17_c); - T(3i + 5); // expected-warning {{imaginary constant}} - T(4.2 * 7.6); - T(EnumValue1); - T((enum Enum)(int)EnumValue2); - - // - the address of the first character of a string literal, losslessly cast - // to any type - T("string literal"); - T((double*)"string literal"); - T("string literal" + 0); - T((long)"string literal"); - - // ... and otherwise returns 0. - F("string literal" + 1); - F(&test17_n); - F(test17_c); - F(&test17_c); - F(&test17_d); - F((struct Aggregate){0, 1}); - F((IntVector){0, 1, 2, 3}); - - // Ensure that a technique used in glibc is handled correctly. -#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4) - // FIXME: These are incorrectly treated as ICEs because strlen is treated as - // a builtin. - ASSERT(OPT("abc")); - ASSERT(!OPT("abcd")); - // In these cases, the strlen is non-constant, but the __builtin_constant_p - // is 0: the array size is not an ICE but is foldable. - ASSERT(!OPT(test17_c)); // expected-warning {{folded}} - ASSERT(!OPT(&test17_c[0])); // expected-warning {{folded}} - ASSERT(!OPT((char*)test17_c)); // expected-warning {{folded}} - ASSERT(!OPT(test17_d)); // expected-warning {{folded}} - ASSERT(!OPT(&test17_d[0])); // expected-warning {{folded}} - ASSERT(!OPT((char*)test17_d)); // expected-warning {{folded}} - -#undef OPT -#undef T -#undef F -} - -void test18() { - char src[1024]; - char dst[2048]; - size_t result; - void *ptr; - - ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src), sizeof(dst)); - result = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); - result = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); - - ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src)); // expected-error {{too few arguments to function call}} - ptr = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} - ptr = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} -} - -void no_ms_builtins() { - __assume(1); // expected-warning {{implicit declaration}} - __noop(1); // expected-warning {{implicit declaration}} - __debugbreak(); // expected-warning {{implicit declaration}} -} - -void unavailable() { - __builtin_operator_new(0); // expected-error {{'__builtin_operator_new' is only available in C++}} - __builtin_operator_delete(0); // expected-error {{'__builtin_operator_delete' is only available in C++}} -} - -// rdar://18259539 -size_t strlcpy(char * restrict dst, const char * restrict src, size_t size); -size_t strlcat(char * restrict dst, const char * restrict src, size_t size); - -void Test19(void) -{ - static char b[40]; - static char buf[20]; - - strlcpy(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} \\ - // expected-note {{change size argument to be the size of the destination}} - __builtin___strlcpy_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcpy_chk' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} \ - // expected-warning {{'__builtin___strlcpy_chk' will always overflow destination buffer}} - - strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} - - __builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} \ - // expected-warning {{'__builtin___strlcat_chk' will always overflow destination buffer}} -} - -// rdar://11076881 -char * Test20(char *p, const char *in, unsigned n) -{ - static char buf[10]; - - __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} - - __builtin___memcpy_chk (p, "abcde", n, __builtin_object_size (p, 0)); - - __builtin___memcpy_chk (&buf[5], "abcde", 5, __builtin_object_size (&buf[5], 0)); - - __builtin___memcpy_chk (&buf[5], "abcde", n, __builtin_object_size (&buf[5], 0)); - - __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} - - return buf; -} - -void test21(const int *ptr) { - __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} - __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} -} - -void test22(void) { - (void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}} - (void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} - (void)__builtin_signbit(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}} - (void)__builtin_signbit(1.0); - (void)__builtin_signbit(1.0f); - (void)__builtin_signbit(1.0L); - - (void)__builtin_signbitf(); // expected-error{{too few arguments to function call, expected 1, have 0}} - (void)__builtin_signbitf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} - (void)__builtin_signbitf(1); - (void)__builtin_signbitf(1.0); - (void)__builtin_signbitf(1.0f); - (void)__builtin_signbitf(1.0L); - - (void)__builtin_signbitl(); // expected-error{{too few arguments to function call, expected 1, have 0}} - (void)__builtin_signbitl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} - (void)__builtin_signbitl(1); - (void)__builtin_signbitl(1.0); - (void)__builtin_signbitl(1.0f); - (void)__builtin_signbitl(1.0L); -} + __sync_fetch_and_add_4(ptr, val); +} +void test9_2(volatile int* ptr, int val) { + __sync_fetch_and_add(ptr, val); +} +void test9_3(volatile int* ptr, int val) { + __sync_fetch_and_add_4(ptr, val); + __sync_fetch_and_add(ptr, val); + __sync_fetch_and_add(ptr, val); + __sync_fetch_and_add_4(ptr, val); + __sync_fetch_and_add_4(ptr, val); +} + +void test9_4(volatile int* ptr, int val) { + // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} + __sync_fetch_and_nand(ptr, val); +} + +// rdar://7236819 +void test10(void) __attribute__((noreturn)); + +void test10(void) { + __asm__("int3"); + __builtin_unreachable(); + + // No warning about falling off the end of a noreturn function. +} + +void test11(int X) { + switch (X) { + case __builtin_eh_return_data_regno(0): // constant foldable. + break; + } + + __builtin_eh_return_data_regno(X); // expected-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}} +} + +// PR5062 +void test12(void) __attribute__((__noreturn__)); +void test12(void) { + __builtin_trap(); // no warning because trap is noreturn. +} + +void test_unknown_builtin(int a, int b) { + __builtin_isles(a, b); // expected-error{{use of unknown builtin}} \ + // expected-note{{did you mean '__builtin_isless'?}} +} + +int test13() { + __builtin_eh_return(0, 0); // no warning, eh_return never returns. +} + +// +void test14() { + int old; + old = __sync_fetch_and_min((volatile int *)&old, 1); +} + +// +void test15(const char *s) { + __builtin_printf("string is %s\n", s); +} + +// PR7885 +int test16() { + return __builtin_constant_p() + // expected-error{{too few arguments}} + __builtin_constant_p(1, 2); // expected-error {{too many arguments}} +} + +const int test17_n = 0; +const char test17_c[] = {1, 2, 3, 0}; +const char test17_d[] = {1, 2, 3, 4}; +typedef int __attribute__((vector_size(16))) IntVector; +struct Aggregate { int n; char c; }; +enum Enum { EnumValue1, EnumValue2 }; + +typedef __typeof(sizeof(int)) size_t; +size_t strlen(const char *); + +void test17() { +#define ASSERT(...) { int arr[(__VA_ARGS__) ? 1 : -1]; } +#define T(...) ASSERT(__builtin_constant_p(__VA_ARGS__)) +#define F(...) ASSERT(!__builtin_constant_p(__VA_ARGS__)) + + // __builtin_constant_p returns 1 if the argument folds to: + // - an arithmetic constant with value which is known at compile time + T(test17_n); + T(&test17_c[3] - test17_c); + T(3i + 5); // expected-warning {{imaginary constant}} + T(4.2 * 7.6); + T(EnumValue1); + T((enum Enum)(int)EnumValue2); + + // - the address of the first character of a string literal, losslessly cast + // to any type + T("string literal"); + T((double*)"string literal"); + T("string literal" + 0); + T((long)"string literal"); + + // ... and otherwise returns 0. + F("string literal" + 1); + F(&test17_n); + F(test17_c); + F(&test17_c); + F(&test17_d); + F((struct Aggregate){0, 1}); + F((IntVector){0, 1, 2, 3}); + + // Ensure that a technique used in glibc is handled correctly. +#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4) + // FIXME: These are incorrectly treated as ICEs because strlen is treated as + // a builtin. + ASSERT(OPT("abc")); + ASSERT(!OPT("abcd")); + // In these cases, the strlen is non-constant, but the __builtin_constant_p + // is 0: the array size is not an ICE but is foldable. + ASSERT(!OPT(test17_c)); // expected-warning {{folded}} + ASSERT(!OPT(&test17_c[0])); // expected-warning {{folded}} + ASSERT(!OPT((char*)test17_c)); // expected-warning {{folded}} + ASSERT(!OPT(test17_d)); // expected-warning {{folded}} + ASSERT(!OPT(&test17_d[0])); // expected-warning {{folded}} + ASSERT(!OPT((char*)test17_d)); // expected-warning {{folded}} + +#undef OPT +#undef T +#undef F +} + +void test18() { + char src[1024]; + char dst[2048]; + size_t result; + void *ptr; + + ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src), sizeof(dst)); + result = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); + result = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); + + ptr = __builtin___memccpy_chk(dst, src, '\037', sizeof(src)); // expected-error {{too few arguments to function call}} + ptr = __builtin___strlcpy_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} + ptr = __builtin___strlcat_chk(dst, src, sizeof(dst), sizeof(dst)); // expected-warning {{incompatible integer to pointer conversion}} +} + +void no_ms_builtins() { + __assume(1); // expected-warning {{implicit declaration}} + __noop(1); // expected-warning {{implicit declaration}} + __debugbreak(); // expected-warning {{implicit declaration}} +} + +void unavailable() { + __builtin_operator_new(0); // expected-error {{'__builtin_operator_new' is only available in C++}} + __builtin_operator_delete(0); // expected-error {{'__builtin_operator_delete' is only available in C++}} +} + +// rdar://18259539 +size_t strlcpy(char * restrict dst, const char * restrict src, size_t size); +size_t strlcat(char * restrict dst, const char * restrict src, size_t size); + +void Test19(void) +{ + static char b[40]; + static char buf[20]; + + strlcpy(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcpy' call appears to be size of the source; expected the size of the destination}} \\ + // expected-note {{change size argument to be the size of the destination}} + __builtin___strlcpy_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcpy_chk' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} \ + // expected-warning {{'__builtin___strlcpy_chk' will always overflow destination buffer}} + + strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} + + __builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \ + // expected-note {{change size argument to be the size of the destination}} \ + // expected-warning {{'__builtin___strlcat_chk' will always overflow destination buffer}} +} + +// rdar://11076881 +char * Test20(char *p, const char *in, unsigned n) +{ + static char buf[10]; + + __builtin___memcpy_chk (&buf[6], in, 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} + + __builtin___memcpy_chk (p, "abcde", n, __builtin_object_size (p, 0)); + + __builtin___memcpy_chk (&buf[5], "abcde", 5, __builtin_object_size (&buf[5], 0)); + + __builtin___memcpy_chk (&buf[5], "abcde", n, __builtin_object_size (&buf[5], 0)); + + __builtin___memcpy_chk (&buf[6], "abcde", 5, __builtin_object_size (&buf[6], 0)); // expected-warning {{'__builtin___memcpy_chk' will always overflow destination buffer}} + + return buf; +} + +void test21(const int *ptr) { + __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} + __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} +} -- GitLab From 4ede2bf4c9918758be3388ab015438db11146af4 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 19 Jun 2018 14:59:11 +0000 Subject: [PATCH 0180/1023] Implement semantic checking for __builtin_signbit. r242675 changed the signature for the signbit builtin but did not introduce proper semantic checking to ensure the arguments are as-expected. This patch groups the signbit builtin along with the other fp classification builtins. Fixes PR28172. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335050 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 15 +++++++++++---- test/Sema/builtins.c | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 5530bd8fe7..237484a4ca 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -972,6 +972,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin_isinf_sign: case Builtin::BI__builtin_isnan: case Builtin::BI__builtin_isnormal: + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: if (SemaBuiltinFPClassification(TheCall, 1)) return ExprError(); break; @@ -4592,15 +4595,19 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { diag::err_typecheck_call_invalid_unary_fp) << OrigArg->getType() << OrigArg->getSourceRange(); - // If this is an implicit conversion from float -> float or double, remove it. + // If this is an implicit conversion from float -> float, double, or + // long double, remove it. if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { // Only remove standard FloatCasts, leaving other casts inplace if (Cast->getCastKind() == CK_FloatingCast) { Expr *CastArg = Cast->getSubExpr(); if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && - "promotion from float to either float or double is the only expected cast here"); + assert( + (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) && + "promotion from float to either float, double, or long double is " + "the only expected cast here"); Cast->setSubExpr(nullptr); TheCall->setArg(NumArgs-1, CastArg); } diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c index 7e999991f3..a831d030ef 100644 --- a/test/Sema/builtins.c +++ b/test/Sema/builtins.c @@ -253,3 +253,26 @@ void test21(const int *ptr) { __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} } + +void test22(void) { + (void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbit(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}} + (void)__builtin_signbit(1.0); + (void)__builtin_signbit(1.0f); + (void)__builtin_signbit(1.0L); + + (void)__builtin_signbitf(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitf(1); + (void)__builtin_signbitf(1.0); + (void)__builtin_signbitf(1.0f); + (void)__builtin_signbitf(1.0L); + + (void)__builtin_signbitl(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitl(1); + (void)__builtin_signbitl(1.0); + (void)__builtin_signbitl(1.0f); + (void)__builtin_signbitl(1.0L); +} -- GitLab From 78e14633a4c4dad11a3327e56bda2703f4767491 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 19 Jun 2018 17:56:03 +0000 Subject: [PATCH 0181/1023] [Darwin] Add a warning for missing include path for libstdc++ Xcode 10 removes support for libstdc++, but the users just get a confusing include not file warning when including an STL header (when building for iOS6 which uses libstdc++ by default for example). This patch adds a new warning that lets the user know that the libstdc++ include path was not found to ensure that the user is more aware of why the error occurs. rdar://40830462 Differential Revision: https://reviews.llvm.org/D48297 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335063 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 5 ++ include/clang/Lex/HeaderSearch.h | 2 + lib/Frontend/InitHeaderSearch.cpp | 83 +++++++++++-------- test/Frontend/warning-stdlibcxx-darwin.cpp | 5 ++ 4 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 test/Frontend/warning-stdlibcxx-darwin.cpp diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 2211a92574..6add448871 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -236,4 +236,9 @@ def err_invalid_vfs_overlay : Error< def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup; + +def warn_stdlibcxx_not_found : Warning< + "include path for stdlibc++ headers not found; pass '-std=libc++' on the " + "command line to use the libc++ standard library instead">, + InGroup>; } diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 3d13162da7..fd52000954 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -272,6 +272,8 @@ public: FileManager &getFileMgr() const { return FileMgr; } + DiagnosticsEngine &getDiags() const { return Diags; } + /// Interface for setting the file search paths. void SetSearchPaths(const std::vector &dirs, unsigned angledDirIdx, unsigned systemDirIdx, diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d2fcc9a994..85aeec461b 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Config/config.h" // C_INCLUDE_DIRS +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/HeaderSearch.h" @@ -55,11 +56,13 @@ public: /// AddPath - Add the specified path to the specified group list, prefixing /// the sysroot if used. - void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); + /// Returns true if the path exists, false if it was ignored. + bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddUnmappedPath - Add the specified path to the specified group list, /// without performing any sysroot remapping. - void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, + /// Returns true if the path exists, false if it was ignored. + bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddSystemHeaderPrefix - Add the specified prefix to the system header @@ -70,10 +73,9 @@ public: /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu /// libstdc++. - void AddGnuCPlusPlusIncludePaths(StringRef Base, - StringRef ArchDir, - StringRef Dir32, - StringRef Dir64, + /// Returns true if the \p Base path was found, false if it does not exist. + bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, + StringRef Dir32, StringRef Dir64, const llvm::Triple &triple); /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW @@ -88,7 +90,8 @@ public: // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, + void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts, + const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); /// AddDefaultSystemIncludePaths - Adds the default system include paths so @@ -112,7 +115,7 @@ static bool CanPrefixSysroot(StringRef Path) { #endif } -void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { // Add the path with sysroot prepended, if desired and this is a system header // group. @@ -120,15 +123,14 @@ void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, SmallString<256> MappedPathStorage; StringRef MappedPathStr = Path.toStringRef(MappedPathStorage); if (CanPrefixSysroot(MappedPathStr)) { - AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); - return; + return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); } } - AddUnmappedPath(Path, Group, isFramework); + return AddUnmappedPath(Path, Group, isFramework); } -void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { assert(!Path.isTriviallyEmpty() && "can't handle empty path here"); @@ -150,7 +152,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) { IncludePath.push_back( std::make_pair(Group, DirectoryLookup(DE, Type, isFramework))); - return; + return true; } // Check to see if this is an apple-style headermap (which are not allowed to @@ -162,7 +164,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, IncludePath.push_back( std::make_pair(Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap))); - return; + return true; } } } @@ -170,15 +172,16 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (Verbose) llvm::errs() << "ignoring nonexistent directory \"" << MappedPathStr << "\"\n"; + return false; } -void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, +bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, StringRef Dir32, StringRef Dir64, const llvm::Triple &triple) { // Add the base dir - AddPath(Base, CXXSystem, false); + bool IsBaseFound = AddPath(Base, CXXSystem, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); @@ -190,6 +193,7 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, // Add the backward dir AddPath(Base + "/backward", CXXSystem, false); + return IsBaseFound; } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base, @@ -354,46 +358,55 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, } } -void InitHeaderSearch:: -AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { +void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( + const LangOptions &LangOpts, const llvm::Triple &triple, + const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); // FIXME: temporary hack: hard-coded paths. if (triple.isOSDarwin()) { + bool IsBaseFound = true; switch (triple.getArch()) { default: break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "powerpc-apple-darwin10", "", "ppc64", - triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "powerpc-apple-darwin10", "", "ppc64", - triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "powerpc-apple-darwin10", "", + "ppc64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "powerpc-apple-darwin10", "", + "ppc64", triple); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "i686-apple-darwin10", "", "x86_64", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "i686-apple-darwin8", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "i686-apple-darwin10", "", + "x86_64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); break; case llvm::Triple::arm: case llvm::Triple::thumb: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v7", "", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v6", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple); break; case llvm::Triple::aarch64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm64-apple-darwin10", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple); break; } + // Warn when compiling pure C++ / Objective-C++ only. + if (!IsBaseFound && + !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) { + Headers.getDiags().Report(SourceLocation(), + diag::warn_stdlibcxx_not_found); + } return; } @@ -478,7 +491,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, } AddPath("/usr/include/c++/v1", CXXSystem, false); } else { - AddDefaultCPlusPlusIncludePaths(triple, HSOpts); + AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts); } } diff --git a/test/Frontend/warning-stdlibcxx-darwin.cpp b/test/Frontend/warning-stdlibcxx-darwin.cpp new file mode 100644 index 0000000000..3c132b6a83 --- /dev/null +++ b/test/Frontend/warning-stdlibcxx-darwin.cpp @@ -0,0 +1,5 @@ +// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s +// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify +// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead + +// expected-no-diagnostics -- GitLab From 39bed5ede9c59c6f653e9a90135f88a0ef0e72f2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 19 Jun 2018 19:13:54 +0000 Subject: [PATCH 0182/1023] [X86] Rewrite the max and min reduction intrinsics to make better use of other functions and to reduce width to 256 and 128 bits were possible. We only need to use 512 bit vectors all the way through v8i64 reductions since those max instructions are new to avx512f and only available in 512 bits until SKX. For v16i32 and floating point we have legacy 128/256 bit instructions we can use. I've tried to use other intrinsics to reduce the verbosity of the code and avoid having to mention all the shuffles. I've also removed all the -1 shuffle indices so the output sequence is fully specified and not left to backend optimization. Differential Revision: https://reviews.llvm.org/D47401 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335070 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 343 +- test/CodeGen/avx512-reduceMinMaxIntrin.c | 4883 ++++++++++++---------- 2 files changed, 2716 insertions(+), 2510 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index e1e0051404..ead3f8ef58 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -9579,293 +9579,186 @@ _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { #undef _mm512_reduce_operator_32bit #undef _mm512_mask_reduce_operator_32bit -/* Used bisection method. At each step, we partition the vector with previous - * step in half, and the operation is performed on its two halves. - * This takes log2(n) steps where n is the number of elements in the vector. - * This macro uses only intrinsics from the AVX512F feature. - - * Vec512 - Vector with size of 512. - * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: - * __mm512_max_epi64 - * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] - * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] - */ - -#define _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2) __extension__({ \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, 1, 2, 3, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 4, 5, 6, 7, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, 1, -1, -1, -1, -1, -1, -1),\ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 2, 3, -1, -1, -1, -1, -1, \ - -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, -1, -1, -1, -1, -1, -1, -1),\ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 1, -1, -1, -1, -1, -1, -1, -1))\ - ; \ - return Vec512[0]; \ - }) +#define _mm512_mask_reduce_operator(op) \ + __m512i __t1 = (__m512i)__builtin_shufflevector((__v8di)__V, (__v8di)__V, 4, 5, 6, 7, 0, 1, 2, 3); \ + __m512i __t2 = _mm512_##op(__V, __t1); \ + __m512i __t3 = (__m512i)__builtin_shufflevector((__v8di)__t2, (__v8di)__t2, 2, 3, 0, 1, 6, 7, 4, 5); \ + __m512i __t4 = _mm512_##op(__t2, __t3); \ + __m512i __t5 = (__m512i)__builtin_shufflevector((__v8di)__t4, (__v8di)__t4, 1, 0, 3, 2, 5, 4, 7, 6); \ + __v8di __t6 = (__v8di)_mm512_##op(__t4, __t5); \ + return __t6[0]; static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epi64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, max_epi64, i, i); + _mm512_mask_reduce_operator(max_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epu64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_max_pd(__m512d __V) { - _mm512_reduce_maxMin_64bit(__V, max_pd, d, f); + _mm512_mask_reduce_operator(max_epu64); } -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epi64 -(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, min_epi64, i, i); +static __inline__ long long __DEFAULT_FN_ATTRS +_mm512_reduce_min_epi64(__m512i __V) { + _mm512_mask_reduce_operator(min_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epu64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_min_pd(__m512d __V) { - _mm512_reduce_maxMin_64bit(__V, min_pd, d, f); + _mm512_mask_reduce_operator(min_epu64); } -/* Vec512 - Vector with size 512. - * Vec512Neutral - A 512 length vector with elements set to the identity element - * Identity element: {max_epi,0x8000000000000000} - * {max_epu,0x0000000000000000} - * {max_pd, 0xFFF0000000000000} - * {min_epi,0x7FFFFFFFFFFFFFFF} - * {min_epu,0xFFFFFFFFFFFFFFFF} - * {min_pd, 0x7FF0000000000000} - * - * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: - * __mm512_max_epi64 - * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] - * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] - * T3 - Can get 'q' q word and 'pd' for packed double. - * [__builtin_ia32_select{q|pd}_512] - * Mask - Intrinsic Mask - */ - -#define _mm512_mask_reduce_maxMin_64bit(Vec512, Vec512Neutral, IntrinName, T1, \ - T2, T3, Mask) \ - __extension__({ \ - Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ - (__mmask8)Mask, \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512Neutral); \ - _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2); \ - }) - static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x8000000000000000), - max_epi64, i, i, q, __M); + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(-__LONG_LONG_MAX__ - 1LL), __M, __V); + _mm512_mask_reduce_operator(max_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x0000000000000000), - max_epu64, i, i, q, __M); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(-__builtin_inf()), - max_pd, d, f, pd, __M); + __V = _mm512_maskz_mov_epi64(__M, __V); + _mm512_mask_reduce_operator(max_epu64); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF), - min_epi64, i, i, q, __M); + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(__LONG_LONG_MAX__), __M, __V); + _mm512_mask_reduce_operator(min_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), - min_epu64, i, i, q, __M); -} + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __V); + _mm512_mask_reduce_operator(min_epu64); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256i __t1 = _mm512_extracti64x4_epi64(__V, 0); \ + __m256i __t2 = _mm512_extracti64x4_epi64(__V, 1); \ + __m256i __t3 = _mm256_##op(__t1, __t2); \ + __m128i __t4 = _mm256_extracti128_si256(__t3, 0); \ + __m128i __t5 = _mm256_extracti128_si256(__t3, 1); \ + __m128i __t6 = _mm_##op(__t4, __t5); \ + __m128i __t7 = (__m128i)__builtin_shufflevector((__v4si)__t6, (__v4si)__t6, 2, 3, 0, 1); \ + __m128i __t8 = _mm_##op(__t6, __t7); \ + __m128i __t9 = (__m128i)__builtin_shufflevector((__v4si)__t8, (__v4si)__t8, 1, 0, 3, 2); \ + __v4si __t10 = (__v4si)_mm_##op(__t8, __t9); \ + return __t10[0]; -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(__builtin_inf()), - min_pd, d, f, pd, __M); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_reduce_max_epi32(__m512i __V) { + _mm512_mask_reduce_operator(max_epi32); } -#undef _mm512_reduce_maxMin_64bit -#undef _mm512_mask_reduce_maxMin_64bit -/* Vec512 - Vector with size 512. - * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: - * __mm512_max_epi32 - * T1 - Can get 'i' for int and ' ' .[__m512{i|}] - * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] - */ - -#define _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2) __extension__({ \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, 2, 3, 4, 5, 6, 7, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 8, 9, 10, 11, 12, 13, 14, 15, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, 2, 3, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 4, 5, 6, 7, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 2, 3, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, -1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 1, -1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - return Vec512[0]; \ - }) +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_reduce_max_epu32(__m512i __V) { + _mm512_mask_reduce_operator(max_epu32); +} -static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_max_epi32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, max_epi32, i, i); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_reduce_min_epi32(__m512i __V) { + _mm512_mask_reduce_operator(min_epi32); } static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_max_epu32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, max_epu32, i, i); +_mm512_reduce_min_epu32(__m512i __V) { + _mm512_mask_reduce_operator(min_epu32); } -static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_max_ps(__m512 a) { - _mm512_reduce_maxMin_32bit(a, max_ps, , f); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(-__INT_MAX__ - 1), __M, __V); + _mm512_mask_reduce_operator(max_epi32); } -static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_min_epi32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, min_epi32, i, i); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { + __V = _mm512_maskz_mov_epi32(__M, __V); + _mm512_mask_reduce_operator(max_epu32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_min_epu32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, min_epu32, i, i); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(__INT_MAX__), __M, __V); + _mm512_mask_reduce_operator(min_epi32); } -static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_min_ps(__m512 a) { - _mm512_reduce_maxMin_32bit(a, min_ps, , f); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V); + _mm512_mask_reduce_operator(min_epu32); } -/* Vec512 - Vector with size 512. - * Vec512Neutral - A 512 length vector with elements set to the identity element - * Identity element: {max_epi,0x80000000} - * {max_epu,0x00000000} - * {max_ps, 0xFF800000} - * {min_epi,0x7FFFFFFF} - * {min_epu,0xFFFFFFFF} - * {min_ps, 0x7F800000} - * - * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: - * __mm512_max_epi32 - * T1 - Can get 'i' for int and ' ' .[__m512{i|}] - * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] - * T3 - Can get 'q' q word and 'pd' for packed double. - * [__builtin_ia32_select{q|pd}_512] - * Mask - Intrinsic Mask - */ +#define _mm512_mask_reduce_operator(op) \ + __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \ + __m256d __t2 = _mm512_extractf64x4_pd(__V, 1); \ + __m256d __t3 = _mm256_##op(__t1, __t2); \ + __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \ + __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \ + __m128d __t6 = _mm_##op(__t4, __t5); \ + __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \ + __m128d __t8 = _mm_##op(__t6, __t7); \ + return __t8[0]; -#define _mm512_mask_reduce_maxMin_32bit(Vec512, Vec512Neutral, IntrinName, T1, \ - T2, T3, Mask) \ - __extension__({ \ - Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ - (__mmask16)Mask, \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512Neutral); \ - _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2); \ - }) +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_max_pd(__m512d __V) { + _mm512_mask_reduce_operator(max_pd); +} -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x80000000), max_epi32, - i, i, d, __M); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_min_pd(__m512d __V) { + _mm512_mask_reduce_operator(min_pd); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x00000000), max_epu32, - i, i, d, __M); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { + __V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V); + _mm512_mask_reduce_operator(max_pd); } +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { + __V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V); + _mm512_mask_reduce_operator(min_pd); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 0); \ + __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 1); \ + __m256 __t3 = _mm256_##op(__t1, __t2); \ + __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \ + __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \ + __m128 __t6 = _mm_##op(__t4, __t5); \ + __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \ + __m128 __t8 = _mm_##op(__t6, __t7); \ + __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \ + __m128 __t10 = _mm_##op(__t8, __t9); \ + return __t10[0]; + static __inline__ float __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { - _mm512_mask_reduce_maxMin_32bit(__V,_mm512_set1_ps(-__builtin_inff()), max_ps, , f, - ps, __M); +_mm512_reduce_max_ps(__m512 __V) { + _mm512_mask_reduce_operator(max_ps); } -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x7FFFFFFF), min_epi32, - i, i, d, __M); +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_reduce_min_ps(__m512 __V) { + _mm512_mask_reduce_operator(min_ps); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0xFFFFFFFF), min_epu32, - i, i, d, __M); +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { + __V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V); + _mm512_mask_reduce_operator(max_ps); } static __inline__ float __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_ps(__builtin_inff()), min_ps, , f, - ps, __M); + __V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V); + _mm512_mask_reduce_operator(min_ps); } -#undef _mm512_reduce_maxMin_32bit -#undef _mm512_mask_reduce_maxMin_32bit +#undef _mm512_mask_reduce_operator #undef __DEFAULT_FN_ATTRS diff --git a/test/CodeGen/avx512-reduceMinMaxIntrin.c b/test/CodeGen/avx512-reduceMinMaxIntrin.c index 7b6284dfbc..6bbe626433 100644 --- a/test/CodeGen/avx512-reduceMinMaxIntrin.c +++ b/test/CodeGen/avx512-reduceMinMaxIntrin.c @@ -3,2406 +3,2719 @@ #include // CHECK-LABEL: define i64 @test_mm512_reduce_max_epi64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp sgt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp sgt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp sgt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp sgt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_reduce_max_epi64(__m512i __W){ return _mm512_reduce_max_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_max_epu64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp ugt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp ugt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_max_epu64(__m512i __W){ return _mm512_reduce_max_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_max_pd(<8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> -// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP2]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP5]], <4 x double>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP6]], <4 x double>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP7]], <4 x double> [[TMP8]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP9]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE7_I]], <2 x double>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE10_I]], <2 x double>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP13]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP15]], <2 x double>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP16]], <2 x double> [[TMP17]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP20]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP22]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP23]], <2 x double> [[TMP24]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP25]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP26]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_reduce_max_pd(__m512d __W){ return _mm512_reduce_max_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epi64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp slt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp slt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp slt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp slt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_reduce_min_epi64(__m512i __W){ return _mm512_reduce_min_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epu64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp ult <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp ult <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ult <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ult <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_min_epu64(__m512i __W){ return _mm512_reduce_min_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_min_pd(<8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> -// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP2]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP5]], <4 x double>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP6]], <4 x double>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP7]], <4 x double> [[TMP8]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP9]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE7_I]], <2 x double>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE10_I]], <2 x double>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP13]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP15]], <2 x double>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP16]], <2 x double> [[TMP17]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP20]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP22]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP23]], <2 x double> [[TMP24]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP25]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP26]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_reduce_min_pd(__m512d __W){ return _mm512_reduce_min_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp sgt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp sgt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp sgt <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 0, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp ugt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp ugt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i8 [[TMP2]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = bitcast i8 [[TMP4]] to <8 x i1> +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP27]], <8 x i64>* [[__A_ADDR_I6_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP29]], [[TMP30]] +// CHECK-NEXT: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP29]], <8 x i64> [[TMP30]] +// CHECK-NEXT: store <8 x i64> [[TMP32]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP33]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long test_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epu64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 -// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] -// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 -// CHECK: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64 -// CHECK: ret i64 [[CONV]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] +// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP19]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP20]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP22]], <4 x double>* [[__A_ADDR_I18_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP23]], <4 x double>* [[__B_ADDR_I19_I]], align 32 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I18_I]], align 32 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I19_I]], align 32 +// CHECK-NEXT: [[TMP26:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP24]], <4 x double> [[TMP25]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP26]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x double> [[TMP27]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE9_I]], <2 x double>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x double> [[TMP29]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP30]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP32]], <2 x double>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP33]], <2 x double> [[TMP34]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <2 x double> [[TMP36]], <2 x double> [[TMP37]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE14_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP39]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP40]], <2 x double> [[TMP41]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP42]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP43]], i32 0 +// CHECK-NEXT: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64 +// CHECK-NEXT: ret i64 [[CONV]] long long test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_max_pd(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp slt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp slt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp slt <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp ult <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp ult <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp ult <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epu64(__M, __W); } // CHECK-LABEL: define double @test_mm512_mask_reduce_min_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 -// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] -// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] +// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP19]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP20]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP22]], <4 x double>* [[__A_ADDR_I18_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP23]], <4 x double>* [[__B_ADDR_I19_I]], align 32 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I18_I]], align 32 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I19_I]], align 32 +// CHECK-NEXT: [[TMP26:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP24]], <4 x double> [[TMP25]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP26]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x double> [[TMP27]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE9_I]], <2 x double>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x double> [[TMP29]], <4 x double> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP30]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP32]], <2 x double>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP33]], <2 x double> [[TMP34]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <2 x double> [[TMP36]], <2 x double> [[TMP37]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE14_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP39]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP40]], <2 x double> [[TMP41]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP42]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP43]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_min_pd(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epi32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp sgt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp sgt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp sgt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp sgt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> +// CHECK-NEXT: [[TMP11:%.*]] = icmp sgt <8 x i32> [[TMP8]], [[TMP10]] +// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] +// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> +// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <4 x i32> [[TMP21]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp sgt <4 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> +// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> +// CHECK-NEXT: [[TMP52:%.*]] = icmp sgt <4 x i32> [[TMP49]], [[TMP51]] +// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] +// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_reduce_max_epi32(__m512i __W){ return _mm512_reduce_max_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epu32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp ugt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp ugt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp ugt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp ugt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> +// CHECK-NEXT: [[TMP11:%.*]] = icmp ugt <8 x i32> [[TMP8]], [[TMP10]] +// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] +// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> +// CHECK-NEXT: [[TMP24:%.*]] = icmp ugt <4 x i32> [[TMP21]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp ugt <4 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> +// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> +// CHECK-NEXT: [[TMP52:%.*]] = icmp ugt <4 x i32> [[TMP49]], [[TMP51]] +// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] +// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_reduce_max_epu32(__m512i __W){ return _mm512_reduce_max_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_max_ps(<16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> -// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> -// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x double> [[TMP3]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP4]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <16 x float> [[TMP5]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP6]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x double> [[TMP7]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP9]], <8 x float>* [[__A_ADDR_I20_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP10]], <8 x float>* [[__B_ADDR_I21_I]], align 32 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I20_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I21_I]], align 32 +// CHECK-NEXT: [[TMP13:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP11]], <8 x float> [[TMP12]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP13]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <8 x float> [[TMP14]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE7_I]], <4 x float>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <8 x float> [[TMP16]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP17]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP19]], <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP20]], <4 x float> [[TMP21]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x float> [[TMP23]], <4 x float> [[TMP24]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP26]], <4 x float>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP27]], <4 x float> [[TMP28]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP30]], <4 x float> [[TMP31]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP33]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP34]], <4 x float> [[TMP35]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP36]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP37]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_reduce_max_ps(__m512 __W){ return _mm512_reduce_max_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epi32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp slt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp slt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp slt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp slt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> +// CHECK-NEXT: [[TMP11:%.*]] = icmp slt <8 x i32> [[TMP8]], [[TMP10]] +// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] +// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> +// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <4 x i32> [[TMP21]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp slt <4 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> +// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> +// CHECK-NEXT: [[TMP52:%.*]] = icmp slt <4 x i32> [[TMP49]], [[TMP51]] +// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] +// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_reduce_min_epi32(__m512i __W){ return _mm512_reduce_min_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epu32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp ult <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp ult <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp ult <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp ult <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> +// CHECK-NEXT: [[TMP11:%.*]] = icmp ult <8 x i32> [[TMP8]], [[TMP10]] +// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] +// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> +// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <4 x i32> [[TMP21]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp ult <4 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> +// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> +// CHECK-NEXT: [[TMP52:%.*]] = icmp ult <4 x i32> [[TMP49]], [[TMP51]] +// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] +// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_reduce_min_epu32(__m512i __W){ return _mm512_reduce_min_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_min_ps(<16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> -// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> -// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x double> [[TMP3]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP4]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <16 x float> [[TMP5]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP6]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x double> [[TMP7]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP9]], <8 x float>* [[__A_ADDR_I20_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP10]], <8 x float>* [[__B_ADDR_I21_I]], align 32 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I20_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I21_I]], align 32 +// CHECK-NEXT: [[TMP13:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP11]], <8 x float> [[TMP12]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP13]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <8 x float> [[TMP14]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE7_I]], <4 x float>* [[TMP5_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[TMP5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <8 x float> [[TMP16]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[TMP8_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[TMP8_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP17]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP19]], <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP20]], <4 x float> [[TMP21]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x float> [[TMP23]], <4 x float> [[TMP24]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP26]], <4 x float>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I16_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP27]], <4 x float> [[TMP28]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP30]], <4 x float> [[TMP31]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP33]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP34]], <4 x float> [[TMP35]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP36]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP37]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_reduce_min_ps(__m512 __W){ return _mm512_reduce_min_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp sgt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp sgt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp sgt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp sgt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> +// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i32> [[TMP37]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> +// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> +// CHECK-NEXT: [[TMP53:%.*]] = icmp sgt <4 x i32> [[TMP50]], [[TMP52]] +// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> +// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> +// CHECK-NEXT: [[TMP67:%.*]] = icmp sgt <4 x i32> [[TMP64]], [[TMP66]] +// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> +// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> +// CHECK-NEXT: [[TMP81:%.*]] = icmp sgt <4 x i32> [[TMP78]], [[TMP80]] +// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] +// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 0, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp ugt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp ugt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp ugt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp ugt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i16 [[TMP2]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <8 x i64> [[TMP5]] to <16 x i32> +// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <8 x i64> [[TMP7]] to <16 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = bitcast i16 [[TMP4]] to <16 x i1> +// CHECK-NEXT: [[TMP10:%.*]] = select <16 x i1> [[TMP9]], <16 x i32> [[TMP6]], <16 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <16 x i32> [[TMP10]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP14]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE4_I]], <4 x i64>* [[TMP2_I]], align 32 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP15]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP17:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP16]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP17]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP18:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <4 x i64> [[TMP18]] to <8 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP21:%.*]] = bitcast <4 x i64> [[TMP20]] to <8 x i32> +// CHECK-NEXT: [[TMP22:%.*]] = icmp ugt <8 x i32> [[TMP19]], [[TMP21]] +// CHECK-NEXT: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i32> [[TMP19]], <8 x i32> [[TMP21]] +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i32> [[TMP23]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP24]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i64> [[TMP25]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE8_I]], <2 x i64>* [[TMP6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <2 x i64>, <2 x i64>* [[TMP6_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE11_I:%.*]] = shufflevector <4 x i64> [[TMP27]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE11_I]], <2 x i64>* [[TMP9_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[TMP9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V1_ADDR_I19_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP30]], <2 x i64>* [[__V2_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = bitcast <2 x i64> [[TMP31]] to <4 x i32> +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = bitcast <2 x i64> [[TMP33]] to <4 x i32> +// CHECK-NEXT: [[TMP35:%.*]] = icmp ugt <4 x i32> [[TMP32]], [[TMP34]] +// CHECK-NEXT: [[TMP36:%.*]] = select <4 x i1> [[TMP35]], <4 x i32> [[TMP32]], <4 x i32> [[TMP34]] +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i32> [[TMP36]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP37]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = bitcast <2 x i64> [[TMP38]] to <4 x i32> +// CHECK-NEXT: [[TMP40:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = bitcast <2 x i64> [[TMP40]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE13_I:%.*]] = shufflevector <4 x i32> [[TMP39]], <4 x i32> [[TMP41]], <4 x i32> +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <4 x i32> [[SHUFFLE13_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I17_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I17_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32> +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32> +// CHECK-NEXT: [[TMP49:%.*]] = icmp ugt <4 x i32> [[TMP46]], [[TMP48]] +// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]] +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32> +// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE15_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> +// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE15_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32> +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32> +// CHECK-NEXT: [[TMP63:%.*]] = icmp ugt <4 x i32> [[TMP60]], [[TMP62]] +// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]] +// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP64]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP66]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_max_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 -// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 -// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 -// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 -// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 -// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 -// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 -// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 -// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 -// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] -// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> -// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__A_ADDR_I22_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I23_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> +// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] +// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <4 x double> [[TMP28]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP29]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <16 x float> [[TMP30]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x double> [[TMP32]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP34]], <8 x float>* [[__A_ADDR_I22_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP35]], <8 x float>* [[__B_ADDR_I23_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I22_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I23_I]], align 32 +// CHECK-NEXT: [[TMP38:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP36]], <8 x float> [[TMP37]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP38]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <8 x float> [[TMP39]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE9_I]], <4 x float>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <8 x float> [[TMP41]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP42]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__A_ADDR_I20_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP44]], <4 x float>* [[__B_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP45]], <4 x float> [[TMP46]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP48]], <4 x float> [[TMP49]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP51]], <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP54:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP52]], <4 x float> [[TMP53]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x float> [[TMP55]], <4 x float> [[TMP56]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE16_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP58]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP61:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP59]], <4 x float> [[TMP60]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP61]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP62]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_max_ps(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp slt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp slt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp slt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp slt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> +// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i32> [[TMP37]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> +// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> +// CHECK-NEXT: [[TMP53:%.*]] = icmp slt <4 x i32> [[TMP50]], [[TMP52]] +// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> +// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> +// CHECK-NEXT: [[TMP67:%.*]] = icmp slt <4 x i32> [[TMP64]], [[TMP66]] +// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> +// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> +// CHECK-NEXT: [[TMP81:%.*]] = icmp slt <4 x i32> [[TMP78]], [[TMP80]] +// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] +// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp ult <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp ult <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp ult <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp ult <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> +// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i32> [[TMP37]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> +// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> +// CHECK-NEXT: [[TMP53:%.*]] = icmp ult <4 x i32> [[TMP50]], [[TMP52]] +// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> +// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> +// CHECK-NEXT: [[TMP67:%.*]] = icmp ult <4 x i32> [[TMP64]], [[TMP66]] +// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> +// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> +// CHECK-NEXT: [[TMP81:%.*]] = icmp ult <4 x i32> [[TMP78]], [[TMP80]] +// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] +// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_min_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 -// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 -// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 -// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 -// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 -// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 -// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 -// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 -// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 -// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] -// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> -// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__A_ADDR_I22_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I23_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> +// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] +// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <4 x double> [[TMP28]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP29]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <16 x float> [[TMP30]] to <8 x double> +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x double> [[TMP32]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP34]], <8 x float>* [[__A_ADDR_I22_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP35]], <8 x float>* [[__B_ADDR_I23_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I22_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I23_I]], align 32 +// CHECK-NEXT: [[TMP38:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP36]], <8 x float> [[TMP37]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP38]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <8 x float> [[TMP39]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE9_I]], <4 x float>* [[TMP7_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[TMP7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <8 x float> [[TMP41]], <8 x float> zeroinitializer, <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[TMP10_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[TMP10_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP42]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__A_ADDR_I20_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP44]], <4 x float>* [[__B_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I20_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I21_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP45]], <4 x float> [[TMP46]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP48]], <4 x float> [[TMP49]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP51]], <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 +// CHECK-NEXT: [[TMP54:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP52]], <4 x float> [[TMP53]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x float> [[TMP55]], <4 x float> [[TMP56]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE16_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP58]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP61:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP59]], <4 x float> [[TMP60]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP61]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP62]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_min_ps(__M, __W); } -- GitLab From 93465efb1872e0e1e410e4c1f44c9cb9bf4640a4 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 19 Jun 2018 19:37:07 +0000 Subject: [PATCH 0183/1023] Revert r335070 "[X86] Rewrite the max and min reduction intrinsics to make better use of other functions and to reduce width to 256 and 128 bits were possible." The test changes are failing the buildbot and its going to take me some time to fix it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335072 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 343 +- test/CodeGen/avx512-reduceMinMaxIntrin.c | 4883 ++++++++++------------ 2 files changed, 2510 insertions(+), 2716 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index ead3f8ef58..e1e0051404 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -9579,186 +9579,293 @@ _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { #undef _mm512_reduce_operator_32bit #undef _mm512_mask_reduce_operator_32bit -#define _mm512_mask_reduce_operator(op) \ - __m512i __t1 = (__m512i)__builtin_shufflevector((__v8di)__V, (__v8di)__V, 4, 5, 6, 7, 0, 1, 2, 3); \ - __m512i __t2 = _mm512_##op(__V, __t1); \ - __m512i __t3 = (__m512i)__builtin_shufflevector((__v8di)__t2, (__v8di)__t2, 2, 3, 0, 1, 6, 7, 4, 5); \ - __m512i __t4 = _mm512_##op(__t2, __t3); \ - __m512i __t5 = (__m512i)__builtin_shufflevector((__v8di)__t4, (__v8di)__t4, 1, 0, 3, 2, 5, 4, 7, 6); \ - __v8di __t6 = (__v8di)_mm512_##op(__t4, __t5); \ - return __t6[0]; +/* Used bisection method. At each step, we partition the vector with previous + * step in half, and the operation is performed on its two halves. + * This takes log2(n) steps where n is the number of elements in the vector. + * This macro uses only intrinsics from the AVX512F feature. + + * Vec512 - Vector with size of 512. + * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: + * __mm512_max_epi64 + * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] + * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] + */ + +#define _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2) __extension__({ \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 0, 1, 2, 3, -1, -1, -1, -1), \ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 4, 5, 6, 7, -1, -1, -1, -1)); \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 0, 1, -1, -1, -1, -1, -1, -1),\ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 2, 3, -1, -1, -1, -1, -1, \ + -1)); \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 0, -1, -1, -1, -1, -1, -1, -1),\ + (__m512##T1)__builtin_shufflevector( \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512, \ + 1, -1, -1, -1, -1, -1, -1, -1))\ + ; \ + return Vec512[0]; \ + }) static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epi64(__m512i __V) { - _mm512_mask_reduce_operator(max_epi64); + _mm512_reduce_maxMin_64bit(__V, max_epi64, i, i); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epu64(__m512i __V) { - _mm512_mask_reduce_operator(max_epu64); + _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i); } -static __inline__ long long __DEFAULT_FN_ATTRS -_mm512_reduce_min_epi64(__m512i __V) { - _mm512_mask_reduce_operator(min_epi64); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_max_pd(__m512d __V) { + _mm512_reduce_maxMin_64bit(__V, max_pd, d, f); +} + +static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epi64 +(__m512i __V) { + _mm512_reduce_maxMin_64bit(__V, min_epi64, i, i); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epu64(__m512i __V) { - _mm512_mask_reduce_operator(min_epu64); + _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i); +} + +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_min_pd(__m512d __V) { + _mm512_reduce_maxMin_64bit(__V, min_pd, d, f); } +/* Vec512 - Vector with size 512. + * Vec512Neutral - A 512 length vector with elements set to the identity element + * Identity element: {max_epi,0x8000000000000000} + * {max_epu,0x0000000000000000} + * {max_pd, 0xFFF0000000000000} + * {min_epi,0x7FFFFFFFFFFFFFFF} + * {min_epu,0xFFFFFFFFFFFFFFFF} + * {min_pd, 0x7FF0000000000000} + * + * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: + * __mm512_max_epi64 + * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] + * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] + * T3 - Can get 'q' q word and 'pd' for packed double. + * [__builtin_ia32_select{q|pd}_512] + * Mask - Intrinsic Mask + */ + +#define _mm512_mask_reduce_maxMin_64bit(Vec512, Vec512Neutral, IntrinName, T1, \ + T2, T3, Mask) \ + __extension__({ \ + Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ + (__mmask8)Mask, \ + (__v8d##T2)Vec512, \ + (__v8d##T2)Vec512Neutral); \ + _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2); \ + }) + static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __V) { - __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(-__LONG_LONG_MAX__ - 1LL), __M, __V); - _mm512_mask_reduce_operator(max_epi64); + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x8000000000000000), + max_epi64, i, i, q, __M); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __V) { - __V = _mm512_maskz_mov_epi64(__M, __V); - _mm512_mask_reduce_operator(max_epu64); + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x0000000000000000), + max_epu64, i, i, q, __M); +} + +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(-__builtin_inf()), + max_pd, d, f, pd, __M); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __V) { - __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(__LONG_LONG_MAX__), __M, __V); - _mm512_mask_reduce_operator(min_epi64); + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF), + min_epi64, i, i, q, __M); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) { - __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __V); - _mm512_mask_reduce_operator(min_epu64); -} -#undef _mm512_mask_reduce_operator - -#define _mm512_mask_reduce_operator(op) \ - __m256i __t1 = _mm512_extracti64x4_epi64(__V, 0); \ - __m256i __t2 = _mm512_extracti64x4_epi64(__V, 1); \ - __m256i __t3 = _mm256_##op(__t1, __t2); \ - __m128i __t4 = _mm256_extracti128_si256(__t3, 0); \ - __m128i __t5 = _mm256_extracti128_si256(__t3, 1); \ - __m128i __t6 = _mm_##op(__t4, __t5); \ - __m128i __t7 = (__m128i)__builtin_shufflevector((__v4si)__t6, (__v4si)__t6, 2, 3, 0, 1); \ - __m128i __t8 = _mm_##op(__t6, __t7); \ - __m128i __t9 = (__m128i)__builtin_shufflevector((__v4si)__t8, (__v4si)__t8, 1, 0, 3, 2); \ - __v4si __t10 = (__v4si)_mm_##op(__t8, __t9); \ - return __t10[0]; - -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_reduce_max_epi32(__m512i __V) { - _mm512_mask_reduce_operator(max_epi32); + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), + min_epu64, i, i, q, __M); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_max_epu32(__m512i __V) { - _mm512_mask_reduce_operator(max_epu32); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { + _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(__builtin_inf()), + min_pd, d, f, pd, __M); } +#undef _mm512_reduce_maxMin_64bit +#undef _mm512_mask_reduce_maxMin_64bit -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_reduce_min_epi32(__m512i __V) { - _mm512_mask_reduce_operator(min_epi32); +/* Vec512 - Vector with size 512. + * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: + * __mm512_max_epi32 + * T1 - Can get 'i' for int and ' ' .[__m512{i|}] + * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] + */ + +#define _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2) __extension__({ \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 0, 1, 2, 3, 4, 5, 6, 7, \ + -1, -1, -1, -1, -1, -1, -1, -1), \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 8, 9, 10, 11, 12, 13, 14, 15, \ + -1, -1, -1, -1, -1, -1, -1, -1)); \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 0, 1, 2, 3, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1), \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 4, 5, 6, 7, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1)); \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 0, 1, -1, -1, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1), \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 2, 3, -1, -1, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1)); \ + Vec512 = _mm512_##IntrinName( \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 0, -1, -1, -1, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1), \ + (__m512##T1)__builtin_shufflevector( \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512, \ + 1, -1, -1, -1, -1, -1, -1, -1, \ + -1, -1, -1, -1, -1, -1, -1, -1)); \ + return Vec512[0]; \ + }) + +static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_max_epi32(__m512i a) { + _mm512_reduce_maxMin_32bit(a, max_epi32, i, i); } static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_min_epu32(__m512i __V) { - _mm512_mask_reduce_operator(min_epu32); +_mm512_reduce_max_epu32(__m512i a) { + _mm512_reduce_maxMin_32bit(a, max_epu32, i, i); } -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { - __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(-__INT_MAX__ - 1), __M, __V); - _mm512_mask_reduce_operator(max_epi32); +static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_max_ps(__m512 a) { + _mm512_reduce_maxMin_32bit(a, max_ps, , f); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { - __V = _mm512_maskz_mov_epi32(__M, __V); - _mm512_mask_reduce_operator(max_epu32); +static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_min_epi32(__m512i a) { + _mm512_reduce_maxMin_32bit(a, min_epi32, i, i); } -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { - __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(__INT_MAX__), __M, __V); - _mm512_mask_reduce_operator(min_epi32); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_reduce_min_epu32(__m512i a) { + _mm512_reduce_maxMin_32bit(a, min_epu32, i, i); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { - __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V); - _mm512_mask_reduce_operator(min_epu32); +static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_min_ps(__m512 a) { + _mm512_reduce_maxMin_32bit(a, min_ps, , f); } -#define _mm512_mask_reduce_operator(op) \ - __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \ - __m256d __t2 = _mm512_extractf64x4_pd(__V, 1); \ - __m256d __t3 = _mm256_##op(__t1, __t2); \ - __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \ - __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \ - __m128d __t6 = _mm_##op(__t4, __t5); \ - __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \ - __m128d __t8 = _mm_##op(__t6, __t7); \ - return __t8[0]; +/* Vec512 - Vector with size 512. + * Vec512Neutral - A 512 length vector with elements set to the identity element + * Identity element: {max_epi,0x80000000} + * {max_epu,0x00000000} + * {max_ps, 0xFF800000} + * {min_epi,0x7FFFFFFF} + * {min_epu,0xFFFFFFFF} + * {min_ps, 0x7F800000} + * + * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: + * __mm512_max_epi32 + * T1 - Can get 'i' for int and ' ' .[__m512{i|}] + * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] + * T3 - Can get 'q' q word and 'pd' for packed double. + * [__builtin_ia32_select{q|pd}_512] + * Mask - Intrinsic Mask + */ -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_max_pd(__m512d __V) { - _mm512_mask_reduce_operator(max_pd); -} +#define _mm512_mask_reduce_maxMin_32bit(Vec512, Vec512Neutral, IntrinName, T1, \ + T2, T3, Mask) \ + __extension__({ \ + Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ + (__mmask16)Mask, \ + (__v16s##T2)Vec512, \ + (__v16s##T2)Vec512Neutral); \ + _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2); \ + }) -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_min_pd(__m512d __V) { - _mm512_mask_reduce_operator(min_pd); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { + _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x80000000), max_epi32, + i, i, d, __M); } -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { - __V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V); - _mm512_mask_reduce_operator(max_pd); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { + _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x00000000), max_epu32, + i, i, d, __M); } -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { - __V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V); - _mm512_mask_reduce_operator(min_pd); -} -#undef _mm512_mask_reduce_operator - -#define _mm512_mask_reduce_operator(op) \ - __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 0); \ - __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 1); \ - __m256 __t3 = _mm256_##op(__t1, __t2); \ - __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \ - __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \ - __m128 __t6 = _mm_##op(__t4, __t5); \ - __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \ - __m128 __t8 = _mm_##op(__t6, __t7); \ - __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \ - __m128 __t10 = _mm_##op(__t8, __t9); \ - return __t10[0]; - static __inline__ float __DEFAULT_FN_ATTRS -_mm512_reduce_max_ps(__m512 __V) { - _mm512_mask_reduce_operator(max_ps); +_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { + _mm512_mask_reduce_maxMin_32bit(__V,_mm512_set1_ps(-__builtin_inff()), max_ps, , f, + ps, __M); } -static __inline__ float __DEFAULT_FN_ATTRS -_mm512_reduce_min_ps(__m512 __V) { - _mm512_mask_reduce_operator(min_ps); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { + _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x7FFFFFFF), min_epi32, + i, i, d, __M); } -static __inline__ float __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { - __V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V); - _mm512_mask_reduce_operator(max_ps); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { + _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0xFFFFFFFF), min_epu32, + i, i, d, __M); } static __inline__ float __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) { - __V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V); - _mm512_mask_reduce_operator(min_ps); + _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_ps(__builtin_inff()), min_ps, , f, + ps, __M); } -#undef _mm512_mask_reduce_operator +#undef _mm512_reduce_maxMin_32bit +#undef _mm512_mask_reduce_maxMin_32bit #undef __DEFAULT_FN_ATTRS diff --git a/test/CodeGen/avx512-reduceMinMaxIntrin.c b/test/CodeGen/avx512-reduceMinMaxIntrin.c index 6bbe626433..7b6284dfbc 100644 --- a/test/CodeGen/avx512-reduceMinMaxIntrin.c +++ b/test/CodeGen/avx512-reduceMinMaxIntrin.c @@ -3,2719 +3,2406 @@ #include // CHECK-LABEL: define i64 @test_mm512_reduce_max_epi64(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = icmp sgt <8 x i64> [[TMP13]], [[TMP14]] -// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] -// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = icmp sgt <8 x i64> [[TMP21]], [[TMP22]] -// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] -// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP17:%.*]] = icmp sgt <8 x i64> [[TMP14]], [[TMP15]] +// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> +// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP26:%.*]] = icmp sgt <8 x i64> [[TMP23]], [[TMP24]] +// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] +// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] long long test_mm512_reduce_max_epi64(__m512i __W){ return _mm512_reduce_max_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_max_epu64(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] -// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] -// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] -// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] -// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP17:%.*]] = icmp ugt <8 x i64> [[TMP14]], [[TMP15]] +// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> +// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP26:%.*]] = icmp ugt <8 x i64> [[TMP23]], [[TMP24]] +// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] +// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_max_epu64(__m512i __W){ return _mm512_reduce_max_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_max_pd(<8 x double> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP2]], <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP5]], <4 x double>* [[__A_ADDR_I16_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP6]], <4 x double>* [[__B_ADDR_I17_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I16_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I17_I]], align 32 -// CHECK-NEXT: [[TMP9:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP7]], <4 x double> [[TMP8]]) #2 -// CHECK-NEXT: store <4 x double> [[TMP9]], <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE7_I]], <2 x double>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP12:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE10_I]], <2 x double>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP13]], <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP14:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__A_ADDR_I14_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP15]], <2 x double>* [[__B_ADDR_I15_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I14_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I15_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP16]], <2 x double> [[TMP17]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP20]], <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP22]], <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP24:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP25:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP23]], <2 x double> [[TMP24]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP25]], <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP26:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP26]], i32 0 -// CHECK-NEXT: ret double [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> +// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> +// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 +// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 +// CHECK: ret double [[VECEXT_I]] double test_mm512_reduce_max_pd(__m512d __W){ return _mm512_reduce_max_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epi64(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = icmp slt <8 x i64> [[TMP13]], [[TMP14]] -// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] -// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = icmp slt <8 x i64> [[TMP21]], [[TMP22]] -// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] -// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP17:%.*]] = icmp slt <8 x i64> [[TMP14]], [[TMP15]] +// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> +// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP26:%.*]] = icmp slt <8 x i64> [[TMP23]], [[TMP24]] +// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] +// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] long long test_mm512_reduce_min_epi64(__m512i __W){ return _mm512_reduce_min_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epu64(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] -// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = icmp ult <8 x i64> [[TMP13]], [[TMP14]] -// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] -// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = icmp ult <8 x i64> [[TMP21]], [[TMP22]] -// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] -// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] +// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP17:%.*]] = icmp ult <8 x i64> [[TMP14]], [[TMP15]] +// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> +// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP26:%.*]] = icmp ult <8 x i64> [[TMP23]], [[TMP24]] +// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] +// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_min_epu64(__m512i __W){ return _mm512_reduce_min_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_min_pd(<8 x double> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP2]], <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP5]], <4 x double>* [[__A_ADDR_I16_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP6]], <4 x double>* [[__B_ADDR_I17_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I16_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I17_I]], align 32 -// CHECK-NEXT: [[TMP9:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP7]], <4 x double> [[TMP8]]) #2 -// CHECK-NEXT: store <4 x double> [[TMP9]], <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE7_I]], <2 x double>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP12:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE10_I]], <2 x double>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP13]], <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP14:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__A_ADDR_I14_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP15]], <2 x double>* [[__B_ADDR_I15_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I14_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I15_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP16]], <2 x double> [[TMP17]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP20]], <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP22]], <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP24:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP25:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP23]], <2 x double> [[TMP24]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP25]], <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP26:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP26]], i32 0 -// CHECK-NEXT: ret double [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> +// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> +// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 +// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 +// CHECK: ret double [[VECEXT_I]] double test_mm512_reduce_min_pd(__m512d __W){ return _mm512_reduce_min_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 -// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> -// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <8 x i64> [[TMP22]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] -// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP32:%.*]] = icmp sgt <8 x i64> [[TMP30]], [[TMP31]] -// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] -// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP38]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] -// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 +// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] +// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP22:%.*]] = icmp sgt <8 x i64> [[TMP19]], [[TMP20]] +// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] +// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = icmp sgt <8 x i64> [[TMP28]], [[TMP29]] +// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] +// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> +// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP37]], [[TMP38]] +// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] +// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i8 [[TMP2]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = bitcast i8 [[TMP4]] to <8 x i1> -// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] -// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] -// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] -// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] -// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP27]], <8 x i64>* [[__A_ADDR_I6_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I6_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP29]], [[TMP30]] -// CHECK-NEXT: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP29]], <8 x i64> [[TMP30]] -// CHECK-NEXT: store <8 x i64> [[TMP32]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP33]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: store i64 0, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 +// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] +// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP22:%.*]] = icmp ugt <8 x i64> [[TMP19]], [[TMP20]] +// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] +// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP28]], [[TMP29]] +// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] +// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> +// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP40:%.*]] = icmp ugt <8 x i64> [[TMP37]], [[TMP38]] +// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] +// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] unsigned long test_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epu64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 -// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> -// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] -// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP19:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP19]], <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP20]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP22]], <4 x double>* [[__A_ADDR_I18_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP23]], <4 x double>* [[__B_ADDR_I19_I]], align 32 -// CHECK-NEXT: [[TMP24:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I18_I]], align 32 -// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I19_I]], align 32 -// CHECK-NEXT: [[TMP26:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP24]], <4 x double> [[TMP25]]) #2 -// CHECK-NEXT: store <4 x double> [[TMP26]], <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP27:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x double> [[TMP27]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE9_I]], <2 x double>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP29:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x double> [[TMP29]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP30]], <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP31:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP32]], <2 x double>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP33]], <2 x double> [[TMP34]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <2 x double> [[TMP36]], <2 x double> [[TMP37]], <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE14_I]], <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP38:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP39]], <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP40:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP40]], <2 x double> [[TMP41]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP42]], <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP43]], i32 0 -// CHECK-NEXT: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64 -// CHECK-NEXT: ret i64 [[CONV]] +// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 +// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] +// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> +// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 +// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 +// CHECK: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64 +// CHECK: ret i64 [[CONV]] long long test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_max_pd(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 -// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> -// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <8 x i64> [[TMP22]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] -// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP32:%.*]] = icmp slt <8 x i64> [[TMP30]], [[TMP31]] -// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] -// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP38]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] -// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 +// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] +// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP22:%.*]] = icmp slt <8 x i64> [[TMP19]], [[TMP20]] +// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] +// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = icmp slt <8 x i64> [[TMP28]], [[TMP29]] +// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] +// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> +// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP37]], [[TMP38]] +// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] +// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 -// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> -// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <8 x i64> [[TMP22]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] -// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 -// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 -// CHECK-NEXT: [[TMP32:%.*]] = icmp ult <8 x i64> [[TMP30]], [[TMP31]] -// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] -// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> -// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 -// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP38]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] -// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK-NEXT: ret i64 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 +// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] +// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP22:%.*]] = icmp ult <8 x i64> [[TMP19]], [[TMP20]] +// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] +// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = icmp ult <8 x i64> [[TMP28]], [[TMP29]] +// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] +// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> +// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> +// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP37]], [[TMP38]] +// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] +// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epu64(__M, __W); } // CHECK-LABEL: define double @test_mm512_mask_reduce_min_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 -// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> -// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] -// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP19:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP19]], <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP20]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP22]], <4 x double>* [[__A_ADDR_I18_I]], align 32 -// CHECK-NEXT: store <4 x double> [[TMP23]], <4 x double>* [[__B_ADDR_I19_I]], align 32 -// CHECK-NEXT: [[TMP24:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I18_I]], align 32 -// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I19_I]], align 32 -// CHECK-NEXT: [[TMP26:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP24]], <4 x double> [[TMP25]]) #2 -// CHECK-NEXT: store <4 x double> [[TMP26]], <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP27:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x double> [[TMP27]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE9_I]], <2 x double>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP29:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x double> [[TMP29]], <4 x double> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE12_I]], <2 x double>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP30]], <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP31:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP32]], <2 x double>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP33]], <2 x double> [[TMP34]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <2 x double> [[TMP36]], <2 x double> [[TMP37]], <2 x i32> -// CHECK-NEXT: store <2 x double> [[SHUFFLE14_I]], <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP38:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x double> [[TMP39]], <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP40:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP40]], <2 x double> [[TMP41]]) #2 -// CHECK-NEXT: store <2 x double> [[TMP42]], <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP43]], i32 0 -// CHECK-NEXT: ret double [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 +// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 +// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> +// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] +// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> +// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> +// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 +// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> +// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 +// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 +// CHECK: ret double [[VECEXT_I]] double test_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_min_pd(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epi32(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> -// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> -// CHECK-NEXT: [[TMP11:%.*]] = icmp sgt <8 x i32> [[TMP8]], [[TMP10]] -// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] -// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> -// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <4 x i32> [[TMP21]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> -// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = icmp sgt <4 x i32> [[TMP35]], [[TMP37]] -// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] -// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> -// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> -// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> -// CHECK-NEXT: [[TMP52:%.*]] = icmp sgt <4 x i32> [[TMP49]], [[TMP51]] -// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] -// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> +// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> +// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> +// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> +// CHECK: [[TMP17:%.*]] = icmp sgt <16 x i32> [[TMP12]], [[TMP14]] +// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] +// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> +// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> +// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> +// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> +// CHECK: [[TMP36:%.*]] = icmp sgt <16 x i32> [[TMP31]], [[TMP33]] +// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] +// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> +// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> +// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> +// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> +// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> +// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> +// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> +// CHECK: [[TMP55:%.*]] = icmp sgt <16 x i32> [[TMP50]], [[TMP52]] +// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] +// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> +// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> +// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> +// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> +// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> +// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> +// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> +// CHECK: [[TMP74:%.*]] = icmp sgt <16 x i32> [[TMP69]], [[TMP71]] +// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] +// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] int test_mm512_reduce_max_epi32(__m512i __W){ return _mm512_reduce_max_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epu32(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> -// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> -// CHECK-NEXT: [[TMP11:%.*]] = icmp ugt <8 x i32> [[TMP8]], [[TMP10]] -// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] -// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> -// CHECK-NEXT: [[TMP24:%.*]] = icmp ugt <4 x i32> [[TMP21]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> -// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = icmp ugt <4 x i32> [[TMP35]], [[TMP37]] -// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] -// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> -// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> -// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> -// CHECK-NEXT: [[TMP52:%.*]] = icmp ugt <4 x i32> [[TMP49]], [[TMP51]] -// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] -// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> +// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> +// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> +// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> +// CHECK: [[TMP17:%.*]] = icmp ugt <16 x i32> [[TMP12]], [[TMP14]] +// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] +// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> +// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> +// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> +// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> +// CHECK: [[TMP36:%.*]] = icmp ugt <16 x i32> [[TMP31]], [[TMP33]] +// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] +// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> +// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> +// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> +// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> +// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> +// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> +// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> +// CHECK: [[TMP55:%.*]] = icmp ugt <16 x i32> [[TMP50]], [[TMP52]] +// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] +// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> +// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> +// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> +// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> +// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> +// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> +// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> +// CHECK: [[TMP74:%.*]] = icmp ugt <16 x i32> [[TMP69]], [[TMP71]] +// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] +// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] unsigned int test_mm512_reduce_max_epu32(__m512i __W){ return _mm512_reduce_max_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_max_ps(<16 x float> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x double> [[TMP3]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP4]], <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = bitcast <16 x float> [[TMP5]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP6]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x double> [[TMP7]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP9]], <8 x float>* [[__A_ADDR_I20_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP10]], <8 x float>* [[__B_ADDR_I21_I]], align 32 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I20_I]], align 32 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I21_I]], align 32 -// CHECK-NEXT: [[TMP13:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP11]], <8 x float> [[TMP12]]) #2 -// CHECK-NEXT: store <8 x float> [[TMP13]], <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <8 x float> [[TMP14]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE7_I]], <4 x float>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <8 x float> [[TMP16]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP17]], <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP19]], <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP22:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP20]], <4 x float> [[TMP21]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x float> [[TMP23]], <4 x float> [[TMP24]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP25:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP26]], <4 x float>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP29:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP27]], <4 x float> [[TMP28]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP30]], <4 x float> [[TMP31]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP33]], <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP36:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP34]], <4 x float> [[TMP35]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP36]], <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP37]], i32 0 -// CHECK-NEXT: ret float [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> +// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> +// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 +// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> +// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 +// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> +// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 +// CHECK: ret float [[VECEXT_I]] float test_mm512_reduce_max_ps(__m512 __W){ return _mm512_reduce_max_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epi32(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> -// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> -// CHECK-NEXT: [[TMP11:%.*]] = icmp slt <8 x i32> [[TMP8]], [[TMP10]] -// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] -// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> -// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <4 x i32> [[TMP21]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> -// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = icmp slt <4 x i32> [[TMP35]], [[TMP37]] -// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] -// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> -// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> -// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> -// CHECK-NEXT: [[TMP52:%.*]] = icmp slt <4 x i32> [[TMP49]], [[TMP51]] -// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] -// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> +// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> +// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> +// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> +// CHECK: [[TMP17:%.*]] = icmp slt <16 x i32> [[TMP12]], [[TMP14]] +// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] +// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> +// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> +// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> +// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> +// CHECK: [[TMP36:%.*]] = icmp slt <16 x i32> [[TMP31]], [[TMP33]] +// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] +// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> +// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> +// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> +// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> +// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> +// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> +// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> +// CHECK: [[TMP55:%.*]] = icmp slt <16 x i32> [[TMP50]], [[TMP52]] +// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] +// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> +// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> +// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> +// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> +// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> +// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> +// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> +// CHECK: [[TMP74:%.*]] = icmp slt <16 x i32> [[TMP69]], [[TMP71]] +// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] +// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] int test_mm512_reduce_min_epi32(__m512i __W){ return _mm512_reduce_min_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epu32(<8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I16_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP2]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE3_I]], <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP1_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP6:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP5]], <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP6]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> -// CHECK-NEXT: [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = bitcast <4 x i64> [[TMP9]] to <8 x i32> -// CHECK-NEXT: [[TMP11:%.*]] = icmp ult <8 x i32> [[TMP8]], [[TMP10]] -// CHECK-NEXT: [[TMP12:%.*]] = select <8 x i1> [[TMP11]], <8 x i32> [[TMP8]], <8 x i32> [[TMP10]] -// CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i32> [[TMP12]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <4 x i64> [[TMP14]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE7_I]], <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i64> [[TMP16]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE10_I]], <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP17]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP18]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP19]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = bitcast <2 x i64> [[TMP20]] to <4 x i32> -// CHECK-NEXT: [[TMP22:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = bitcast <2 x i64> [[TMP22]] to <4 x i32> -// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <4 x i32> [[TMP21]], [[TMP23]] -// CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP24]], <4 x i32> [[TMP21]], <4 x i32> [[TMP23]] -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <4 x i32> [[TMP25]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> -// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i32> [[TMP28]], <4 x i32> [[TMP30]], <4 x i32> -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x i32> [[SHUFFLE12_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP31]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP32]], <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> -// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = icmp ult <4 x i32> [[TMP35]], [[TMP37]] -// CHECK-NEXT: [[TMP39:%.*]] = select <4 x i1> [[TMP38]], <4 x i32> [[TMP35]], <4 x i32> [[TMP37]] -// CHECK-NEXT: [[TMP40:%.*]] = bitcast <4 x i32> [[TMP39]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP42]], <4 x i32> [[TMP44]], <4 x i32> -// CHECK-NEXT: [[TMP45:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP45]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> -// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> -// CHECK-NEXT: [[TMP52:%.*]] = icmp ult <4 x i32> [[TMP49]], [[TMP51]] -// CHECK-NEXT: [[TMP53:%.*]] = select <4 x i1> [[TMP52]], <4 x i32> [[TMP49]], <4 x i32> [[TMP51]] -// CHECK-NEXT: [[TMP54:%.*]] = bitcast <4 x i32> [[TMP53]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP53]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP55]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> +// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> +// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> +// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> +// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> +// CHECK: [[TMP17:%.*]] = icmp ult <16 x i32> [[TMP12]], [[TMP14]] +// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] +// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> +// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> +// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> +// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> +// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> +// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> +// CHECK: [[TMP36:%.*]] = icmp ult <16 x i32> [[TMP31]], [[TMP33]] +// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] +// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> +// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> +// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> +// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> +// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> +// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> +// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> +// CHECK: [[TMP55:%.*]] = icmp ult <16 x i32> [[TMP50]], [[TMP52]] +// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] +// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> +// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> +// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> +// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> +// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> +// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> +// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> +// CHECK: [[TMP74:%.*]] = icmp ult <16 x i32> [[TMP69]], [[TMP71]] +// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] +// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] unsigned int test_mm512_reduce_min_epu32(__m512i __W){ return _mm512_reduce_min_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_min_ps(<16 x float> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP1_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x double> [[TMP3]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP4]], <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = bitcast <16 x float> [[TMP5]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP6]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE3_I]], <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP1_I]], align 32 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x double> [[TMP7]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP9]], <8 x float>* [[__A_ADDR_I20_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP10]], <8 x float>* [[__B_ADDR_I21_I]], align 32 -// CHECK-NEXT: [[TMP11:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I20_I]], align 32 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I21_I]], align 32 -// CHECK-NEXT: [[TMP13:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP11]], <8 x float> [[TMP12]]) #2 -// CHECK-NEXT: store <8 x float> [[TMP13]], <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE7_I:%.*]] = shufflevector <8 x float> [[TMP14]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE7_I]], <4 x float>* [[TMP5_I]], align 16 -// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[TMP5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP16:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <8 x float> [[TMP16]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[TMP8_I]], align 16 -// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[TMP8_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP17]], <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP18:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP19]], <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP22:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP20]], <4 x float> [[TMP21]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x float> [[TMP23]], <4 x float> [[TMP24]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP25:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP26]], <4 x float>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I16_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP29:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP27]], <4 x float> [[TMP28]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP30]], <4 x float> [[TMP31]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP33]], <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP35:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP36:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP34]], <4 x float> [[TMP35]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP36]], <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP37:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP37]], i32 0 -// CHECK-NEXT: ret float [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> +// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> +// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 +// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 +// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 +// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 +// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> +// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 +// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 +// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> +// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 +// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 +// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 +// CHECK: ret float [[VECEXT_I]] float test_mm512_reduce_min_ps(__m512 __W){ return _mm512_reduce_min_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 -// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 -// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 -// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 -// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 -// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 -// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 -// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 -// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 -// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> -// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] -// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> -// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i32> [[TMP37]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> -// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> -// CHECK-NEXT: [[TMP53:%.*]] = icmp sgt <4 x i32> [[TMP50]], [[TMP52]] -// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] -// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> -// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> -// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> -// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> -// CHECK-NEXT: [[TMP67:%.*]] = icmp sgt <4 x i32> [[TMP64]], [[TMP66]] -// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] -// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> -// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> -// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> -// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> -// CHECK-NEXT: [[TMP81:%.*]] = icmp sgt <4 x i32> [[TMP78]], [[TMP80]] -// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] -// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 +// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 +// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 +// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 +// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 +// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 +// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 +// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 +// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 +// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 +// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 +// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 +// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 +// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 +// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 +// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 +// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> +// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] +// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> +// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> +// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> +// CHECK: [[TMP42:%.*]] = icmp sgt <16 x i32> [[TMP37]], [[TMP39]] +// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] +// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> +// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> +// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> +// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> +// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> +// CHECK: [[TMP61:%.*]] = icmp sgt <16 x i32> [[TMP56]], [[TMP58]] +// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] +// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> +// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> +// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> +// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> +// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> +// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> +// CHECK: [[TMP80:%.*]] = icmp sgt <16 x i32> [[TMP75]], [[TMP77]] +// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] +// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> +// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> +// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> +// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> +// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> +// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> +// CHECK: [[TMP99:%.*]] = icmp sgt <16 x i32> [[TMP94]], [[TMP96]] +// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] +// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] int test_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I17_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i16 [[TMP2]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP6:%.*]] = bitcast <8 x i64> [[TMP5]] to <16 x i32> -// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 -// CHECK-NEXT: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 -// CHECK-NEXT: [[TMP8:%.*]] = bitcast <8 x i64> [[TMP7]] to <16 x i32> -// CHECK-NEXT: [[TMP9:%.*]] = bitcast i16 [[TMP4]] to <16 x i1> -// CHECK-NEXT: [[TMP10:%.*]] = select <16 x i1> [[TMP9]], <16 x i32> [[TMP6]], <16 x i32> [[TMP8]] -// CHECK-NEXT: [[TMP11:%.*]] = bitcast <16 x i32> [[TMP10]] to <8 x i64> -// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP13]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP14]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE4_I]], <4 x i64>* [[TMP2_I]], align 32 -// CHECK-NEXT: [[TMP15:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP15]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP17:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP16]], <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP17]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP18:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP19:%.*]] = bitcast <4 x i64> [[TMP18]] to <8 x i32> -// CHECK-NEXT: [[TMP20:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP21:%.*]] = bitcast <4 x i64> [[TMP20]] to <8 x i32> -// CHECK-NEXT: [[TMP22:%.*]] = icmp ugt <8 x i32> [[TMP19]], [[TMP21]] -// CHECK-NEXT: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i32> [[TMP19]], <8 x i32> [[TMP21]] -// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i32> [[TMP23]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP24]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP25:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i64> [[TMP25]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE8_I]], <2 x i64>* [[TMP6_I]], align 16 -// CHECK-NEXT: [[TMP26:%.*]] = load <2 x i64>, <2 x i64>* [[TMP6_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP27:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE11_I:%.*]] = shufflevector <4 x i64> [[TMP27]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE11_I]], <2 x i64>* [[TMP9_I]], align 16 -// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[TMP9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V1_ADDR_I19_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP30]], <2 x i64>* [[__V2_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP31:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP32:%.*]] = bitcast <2 x i64> [[TMP31]] to <4 x i32> -// CHECK-NEXT: [[TMP33:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP34:%.*]] = bitcast <2 x i64> [[TMP33]] to <4 x i32> -// CHECK-NEXT: [[TMP35:%.*]] = icmp ugt <4 x i32> [[TMP32]], [[TMP34]] -// CHECK-NEXT: [[TMP36:%.*]] = select <4 x i1> [[TMP35]], <4 x i32> [[TMP32]], <4 x i32> [[TMP34]] -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i32> [[TMP36]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP37]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP38:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP39:%.*]] = bitcast <2 x i64> [[TMP38]] to <4 x i32> -// CHECK-NEXT: [[TMP40:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = bitcast <2 x i64> [[TMP40]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE13_I:%.*]] = shufflevector <4 x i32> [[TMP39]], <4 x i32> [[TMP41]], <4 x i32> -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <4 x i32> [[SHUFFLE13_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I17_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I17_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32> -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32> -// CHECK-NEXT: [[TMP49:%.*]] = icmp ugt <4 x i32> [[TMP46]], [[TMP48]] -// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]] -// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32> -// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE15_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> -// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE15_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32> -// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32> -// CHECK-NEXT: [[TMP63:%.*]] = icmp ugt <4 x i32> [[TMP60]], [[TMP62]] -// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]] -// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP64]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP66:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP66]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: store i32 0, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 +// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 +// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 +// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 +// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 +// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 +// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 +// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 +// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 +// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 +// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 +// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 +// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 +// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 +// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 +// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 +// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> +// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] +// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> +// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> +// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> +// CHECK: [[TMP42:%.*]] = icmp ugt <16 x i32> [[TMP37]], [[TMP39]] +// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] +// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> +// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> +// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> +// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> +// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> +// CHECK: [[TMP61:%.*]] = icmp ugt <16 x i32> [[TMP56]], [[TMP58]] +// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] +// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> +// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> +// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> +// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> +// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> +// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> +// CHECK: [[TMP80:%.*]] = icmp ugt <16 x i32> [[TMP75]], [[TMP77]] +// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] +// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> +// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> +// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> +// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> +// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> +// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> +// CHECK: [[TMP99:%.*]] = icmp ugt <16 x i32> [[TMP94]], [[TMP96]] +// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] +// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] unsigned int test_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_max_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__A_ADDR_I22_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__B_ADDR_I23_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 -// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 -// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 -// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 -// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 -// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 -// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 -// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 -// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 -// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> -// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] -// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP28:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP29:%.*]] = bitcast <4 x double> [[TMP28]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP29]], <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <16 x float> [[TMP30]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP32:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x double> [[TMP32]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP34]], <8 x float>* [[__A_ADDR_I22_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP35]], <8 x float>* [[__B_ADDR_I23_I]], align 32 -// CHECK-NEXT: [[TMP36:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I22_I]], align 32 -// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I23_I]], align 32 -// CHECK-NEXT: [[TMP38:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP36]], <8 x float> [[TMP37]]) #2 -// CHECK-NEXT: store <8 x float> [[TMP38]], <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP39:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <8 x float> [[TMP39]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE9_I]], <4 x float>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <8 x float> [[TMP41]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP42]], <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP43:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__A_ADDR_I20_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP44]], <4 x float>* [[__B_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP45]], <4 x float> [[TMP46]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP48]], <4 x float> [[TMP49]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP50:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP51]], <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP54:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP52]], <4 x float> [[TMP53]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x float> [[TMP55]], <4 x float> [[TMP56]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE16_I]], <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP58]], <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP60:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP61:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP59]], <4 x float> [[TMP60]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP61]], <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP62]], i32 0 -// CHECK-NEXT: ret float [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 +// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 +// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 +// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 +// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 +// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 +// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 +// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 +// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 +// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] +// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> +// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 +// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> +// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 +// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> +// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 +// CHECK: ret float [[VECEXT_I]] float test_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_max_ps(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 -// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 -// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 -// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 -// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 -// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 -// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 -// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 -// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 -// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> -// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] -// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> -// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i32> [[TMP37]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> -// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> -// CHECK-NEXT: [[TMP53:%.*]] = icmp slt <4 x i32> [[TMP50]], [[TMP52]] -// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] -// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> -// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> -// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> -// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> -// CHECK-NEXT: [[TMP67:%.*]] = icmp slt <4 x i32> [[TMP64]], [[TMP66]] -// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] -// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> -// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> -// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> -// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> -// CHECK-NEXT: [[TMP81:%.*]] = icmp slt <4 x i32> [[TMP78]], [[TMP80]] -// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] -// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 +// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 +// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 +// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 +// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 +// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 +// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 +// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 +// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 +// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 +// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 +// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 +// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 +// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 +// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 +// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 +// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> +// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] +// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> +// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> +// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> +// CHECK: [[TMP42:%.*]] = icmp slt <16 x i32> [[TMP37]], [[TMP39]] +// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] +// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> +// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> +// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> +// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> +// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> +// CHECK: [[TMP61:%.*]] = icmp slt <16 x i32> [[TMP56]], [[TMP58]] +// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] +// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> +// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> +// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> +// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> +// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> +// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> +// CHECK: [[TMP80:%.*]] = icmp slt <16 x i32> [[TMP75]], [[TMP77]] +// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] +// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> +// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> +// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> +// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> +// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> +// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> +// CHECK: [[TMP99:%.*]] = icmp slt <16 x i32> [[TMP94]], [[TMP96]] +// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] +// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] int test_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__V1_ADDR_I20_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I21_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I18_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I19_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 -// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 -// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 -// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 -// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 -// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 -// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 -// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 -// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 -// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> -// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> -// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] -// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> -// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE_I]], <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i64>, <4 x i64>* [[TMP_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP31]], <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP32]], <8 x i64> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x i64> [[SHUFFLE5_I]], <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[TMP3_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP35:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP34]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: store <4 x i64> [[TMP35]], <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> -// CHECK-NEXT: [[TMP38:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 -// CHECK-NEXT: [[TMP39:%.*]] = bitcast <4 x i64> [[TMP38]] to <8 x i32> -// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i32> [[TMP37]], [[TMP39]] -// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i32> [[TMP37]], <8 x i32> [[TMP39]] -// CHECK-NEXT: [[TMP42:%.*]] = bitcast <8 x i32> [[TMP41]] to <4 x i64> -// CHECK-NEXT: store <4 x i64> [[TMP42]], <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP43:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i64> [[TMP43]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE9_I]], <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <4 x i64> [[TMP45]], <4 x i64> zeroinitializer, <2 x i32> -// CHECK-NEXT: store <2 x i64> [[SHUFFLE12_I]], <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP46]], <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP48]], <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP50:%.*]] = bitcast <2 x i64> [[TMP49]] to <4 x i32> -// CHECK-NEXT: [[TMP51:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = bitcast <2 x i64> [[TMP51]] to <4 x i32> -// CHECK-NEXT: [[TMP53:%.*]] = icmp ult <4 x i32> [[TMP50]], [[TMP52]] -// CHECK-NEXT: [[TMP54:%.*]] = select <4 x i1> [[TMP53]], <4 x i32> [[TMP50]], <4 x i32> [[TMP52]] -// CHECK-NEXT: [[TMP55:%.*]] = bitcast <4 x i32> [[TMP54]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP55]], <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP56:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = bitcast <2 x i64> [[TMP56]] to <4 x i32> -// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = bitcast <2 x i64> [[TMP58]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x i32> [[TMP57]], <4 x i32> [[TMP59]], <4 x i32> -// CHECK-NEXT: [[TMP60:%.*]] = bitcast <4 x i32> [[SHUFFLE14_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP60]], <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP61]], <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP62]], <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP63:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP64:%.*]] = bitcast <2 x i64> [[TMP63]] to <4 x i32> -// CHECK-NEXT: [[TMP65:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP66:%.*]] = bitcast <2 x i64> [[TMP65]] to <4 x i32> -// CHECK-NEXT: [[TMP67:%.*]] = icmp ult <4 x i32> [[TMP64]], [[TMP66]] -// CHECK-NEXT: [[TMP68:%.*]] = select <4 x i1> [[TMP67]], <4 x i32> [[TMP64]], <4 x i32> [[TMP66]] -// CHECK-NEXT: [[TMP69:%.*]] = bitcast <4 x i32> [[TMP68]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP69]], <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP70:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP71:%.*]] = bitcast <2 x i64> [[TMP70]] to <4 x i32> -// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP73:%.*]] = bitcast <2 x i64> [[TMP72]] to <4 x i32> -// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x i32> [[TMP71]], <4 x i32> [[TMP73]], <4 x i32> -// CHECK-NEXT: [[TMP74:%.*]] = bitcast <4 x i32> [[SHUFFLE16_I]] to <2 x i64> -// CHECK-NEXT: store <2 x i64> [[TMP74]], <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP76:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP75]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: store <2 x i64> [[TMP76]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP77:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP78:%.*]] = bitcast <2 x i64> [[TMP77]] to <4 x i32> -// CHECK-NEXT: [[TMP79:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP80:%.*]] = bitcast <2 x i64> [[TMP79]] to <4 x i32> -// CHECK-NEXT: [[TMP81:%.*]] = icmp ult <4 x i32> [[TMP78]], [[TMP80]] -// CHECK-NEXT: [[TMP82:%.*]] = select <4 x i1> [[TMP81]], <4 x i32> [[TMP78]], <4 x i32> [[TMP80]] -// CHECK-NEXT: [[TMP83:%.*]] = bitcast <4 x i32> [[TMP82]] to <2 x i64> -// CHECK-NEXT: store <4 x i32> [[TMP82]], <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP84:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP84]], i32 0 -// CHECK-NEXT: ret i32 [[VECEXT_I]] +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> +// CHECK: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 +// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 +// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 +// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 +// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 +// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 +// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 +// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 +// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 +// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 +// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 +// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 +// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 +// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 +// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 +// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 +// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> +// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] +// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> +// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> +// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> +// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> +// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> +// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> +// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> +// CHECK: [[TMP42:%.*]] = icmp ult <16 x i32> [[TMP37]], [[TMP39]] +// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] +// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> +// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> +// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> +// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> +// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> +// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> +// CHECK: [[TMP61:%.*]] = icmp ult <16 x i32> [[TMP56]], [[TMP58]] +// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] +// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> +// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> +// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> +// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> +// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> +// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> +// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> +// CHECK: [[TMP80:%.*]] = icmp ult <16 x i32> [[TMP75]], [[TMP77]] +// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] +// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> +// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> +// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> +// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> +// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> +// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> +// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> +// CHECK: [[TMP99:%.*]] = icmp ult <16 x i32> [[TMP94]], [[TMP96]] +// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] +// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> +// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 +// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 +// CHECK: ret i32 [[CONV_I]] unsigned int test_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_min_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK-NEXT: entry: -// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__A_ADDR_I22_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__B_ADDR_I23_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__A_ADDR_I20_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I21_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A_ADDR_I18_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I19_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[TMP3_I:%.*]] = alloca <4 x double>, align 32 -// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 -// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[TMP10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 -// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 -// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 -// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 -// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 -// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 -// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 -// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 -// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 -// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 -// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 -// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 -// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 -// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 -// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 -// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 -// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 -// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 -// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 -// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 -// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> -// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] -// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE_I]], <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP28:%.*]] = load <4 x double>, <4 x double>* [[TMP_I]], align 32 -// CHECK-NEXT: [[TMP29:%.*]] = bitcast <4 x double> [[TMP28]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP29]], <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK-NEXT: [[TMP31:%.*]] = bitcast <16 x float> [[TMP30]] to <8 x double> -// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x double> [[SHUFFLE5_I]], <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP32:%.*]] = load <4 x double>, <4 x double>* [[TMP3_I]], align 32 -// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x double> [[TMP32]] to <8 x float> -// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 -// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP34]], <8 x float>* [[__A_ADDR_I22_I]], align 32 -// CHECK-NEXT: store <8 x float> [[TMP35]], <8 x float>* [[__B_ADDR_I23_I]], align 32 -// CHECK-NEXT: [[TMP36:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I22_I]], align 32 -// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I23_I]], align 32 -// CHECK-NEXT: [[TMP38:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP36]], <8 x float> [[TMP37]]) #2 -// CHECK-NEXT: store <8 x float> [[TMP38]], <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[TMP39:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <8 x float> [[TMP39]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE9_I]], <4 x float>* [[TMP7_I]], align 16 -// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[TMP7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP41:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 -// CHECK-NEXT: [[SHUFFLE12_I:%.*]] = shufflevector <8 x float> [[TMP41]], <8 x float> zeroinitializer, <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE12_I]], <4 x float>* [[TMP10_I]], align 16 -// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[TMP10_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP42]], <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: [[TMP43:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 -// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__A_ADDR_I20_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP44]], <4 x float>* [[__B_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I20_I]], align 16 -// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I21_I]], align 16 -// CHECK-NEXT: [[TMP47:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP45]], <4 x float> [[TMP46]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[SHUFFLE14_I:%.*]] = shufflevector <4 x float> [[TMP48]], <4 x float> [[TMP49]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE14_I]], <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: [[TMP50:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 -// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP51]], <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I18_I]], align 16 -// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I19_I]], align 16 -// CHECK-NEXT: [[TMP54:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP52]], <4 x float> [[TMP53]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[SHUFFLE16_I:%.*]] = shufflevector <4 x float> [[TMP55]], <4 x float> [[TMP56]], <4 x i32> -// CHECK-NEXT: store <4 x float> [[SHUFFLE16_I]], <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: [[TMP57:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 -// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: store <4 x float> [[TMP58]], <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP59:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP60:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 -// CHECK-NEXT: [[TMP61:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP59]], <4 x float> [[TMP60]]) #2 -// CHECK-NEXT: store <4 x float> [[TMP61]], <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[TMP62:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 -// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP62]], i32 0 -// CHECK-NEXT: ret float [[VECEXT_I]] +// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 +// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 +// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 +// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 +// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 +// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 +// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 +// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 +// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 +// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 +// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 +// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 +// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 +// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 +// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 +// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 +// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 +// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 +// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> +// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] +// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> +// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 +// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 +// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 +// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 +// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> +// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 +// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 +// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 +// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 +// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> +// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 +// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 +// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 +// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> +// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> +// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 +// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 +// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 +// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 +// CHECK: ret float [[VECEXT_I]] float test_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_min_ps(__M, __W); } -- GitLab From 4e85e01664ee5e402a1f4c1300e5218def9d6800 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 19 Jun 2018 19:43:07 +0000 Subject: [PATCH 0184/1023] Revert r335063 as it causes bot failures git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335073 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 5 -- include/clang/Lex/HeaderSearch.h | 2 - lib/Frontend/InitHeaderSearch.cpp | 83 ++++++++----------- test/Frontend/warning-stdlibcxx-darwin.cpp | 5 -- 4 files changed, 35 insertions(+), 60 deletions(-) delete mode 100644 test/Frontend/warning-stdlibcxx-darwin.cpp diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 6add448871..2211a92574 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -236,9 +236,4 @@ def err_invalid_vfs_overlay : Error< def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup; - -def warn_stdlibcxx_not_found : Warning< - "include path for stdlibc++ headers not found; pass '-std=libc++' on the " - "command line to use the libc++ standard library instead">, - InGroup>; } diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index fd52000954..3d13162da7 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -272,8 +272,6 @@ public: FileManager &getFileMgr() const { return FileMgr; } - DiagnosticsEngine &getDiags() const { return Diags; } - /// Interface for setting the file search paths. void SetSearchPaths(const std::vector &dirs, unsigned angledDirIdx, unsigned systemDirIdx, diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 85aeec461b..d2fcc9a994 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -14,7 +14,6 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Config/config.h" // C_INCLUDE_DIRS -#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/HeaderSearch.h" @@ -56,13 +55,11 @@ public: /// AddPath - Add the specified path to the specified group list, prefixing /// the sysroot if used. - /// Returns true if the path exists, false if it was ignored. - bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); + void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddUnmappedPath - Add the specified path to the specified group list, /// without performing any sysroot remapping. - /// Returns true if the path exists, false if it was ignored. - bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, + void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddSystemHeaderPrefix - Add the specified prefix to the system header @@ -73,9 +70,10 @@ public: /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu /// libstdc++. - /// Returns true if the \p Base path was found, false if it does not exist. - bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, - StringRef Dir32, StringRef Dir64, + void AddGnuCPlusPlusIncludePaths(StringRef Base, + StringRef ArchDir, + StringRef Dir32, + StringRef Dir64, const llvm::Triple &triple); /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW @@ -90,8 +88,7 @@ public: // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts, - const llvm::Triple &triple, + void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); /// AddDefaultSystemIncludePaths - Adds the default system include paths so @@ -115,7 +112,7 @@ static bool CanPrefixSysroot(StringRef Path) { #endif } -bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, +void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { // Add the path with sysroot prepended, if desired and this is a system header // group. @@ -123,14 +120,15 @@ bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, SmallString<256> MappedPathStorage; StringRef MappedPathStr = Path.toStringRef(MappedPathStorage); if (CanPrefixSysroot(MappedPathStr)) { - return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); + AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); + return; } } - return AddUnmappedPath(Path, Group, isFramework); + AddUnmappedPath(Path, Group, isFramework); } -bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, +void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { assert(!Path.isTriviallyEmpty() && "can't handle empty path here"); @@ -152,7 +150,7 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) { IncludePath.push_back( std::make_pair(Group, DirectoryLookup(DE, Type, isFramework))); - return true; + return; } // Check to see if this is an apple-style headermap (which are not allowed to @@ -164,7 +162,7 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, IncludePath.push_back( std::make_pair(Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap))); - return true; + return; } } } @@ -172,16 +170,15 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (Verbose) llvm::errs() << "ignoring nonexistent directory \"" << MappedPathStr << "\"\n"; - return false; } -bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, +void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, StringRef Dir32, StringRef Dir64, const llvm::Triple &triple) { // Add the base dir - bool IsBaseFound = AddPath(Base, CXXSystem, false); + AddPath(Base, CXXSystem, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); @@ -193,7 +190,6 @@ bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, // Add the backward dir AddPath(Base + "/backward", CXXSystem, false); - return IsBaseFound; } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base, @@ -358,55 +354,46 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, } } -void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( - const LangOptions &LangOpts, const llvm::Triple &triple, - const HeaderSearchOptions &HSOpts) { +void InitHeaderSearch:: +AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); // FIXME: temporary hack: hard-coded paths. if (triple.isOSDarwin()) { - bool IsBaseFound = true; switch (triple.getArch()) { default: break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "powerpc-apple-darwin10", "", - "ppc64", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "powerpc-apple-darwin10", "", - "ppc64", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "powerpc-apple-darwin10", "", "ppc64", + triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "powerpc-apple-darwin10", "", "ppc64", + triple); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "i686-apple-darwin10", "", - "x86_64", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "i686-apple-darwin10", "", "x86_64", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "i686-apple-darwin8", "", "", triple); break; case llvm::Triple::arm: case llvm::Triple::thumb: - IsBaseFound = AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "arm-apple-darwin10", "v7", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "arm-apple-darwin10", "v6", "", triple); break; case llvm::Triple::aarch64: - IsBaseFound = AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "arm64-apple-darwin10", "", "", triple); break; } - // Warn when compiling pure C++ / Objective-C++ only. - if (!IsBaseFound && - !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) { - Headers.getDiags().Report(SourceLocation(), - diag::warn_stdlibcxx_not_found); - } return; } @@ -491,7 +478,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, } AddPath("/usr/include/c++/v1", CXXSystem, false); } else { - AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts); + AddDefaultCPlusPlusIncludePaths(triple, HSOpts); } } diff --git a/test/Frontend/warning-stdlibcxx-darwin.cpp b/test/Frontend/warning-stdlibcxx-darwin.cpp deleted file mode 100644 index 3c132b6a83..0000000000 --- a/test/Frontend/warning-stdlibcxx-darwin.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify -// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead - -// expected-no-diagnostics -- GitLab From a194a6649eaa8d0c410a0bd7e7ae518b15f1adec Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 19 Jun 2018 21:00:30 +0000 Subject: [PATCH 0185/1023] Recommit r335070 "[X86] Rewrite the max and min reduction intrinsics to make better use of other functions and to reduce width to 256 and 128 bits were possible."" Test has been updated to reflect the IRGen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335075 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 343 +- test/CodeGen/avx512-reduceMinMaxIntrin.c | 4694 +++++++++++----------- 2 files changed, 2525 insertions(+), 2512 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index e1e0051404..ead3f8ef58 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -9579,293 +9579,186 @@ _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { #undef _mm512_reduce_operator_32bit #undef _mm512_mask_reduce_operator_32bit -/* Used bisection method. At each step, we partition the vector with previous - * step in half, and the operation is performed on its two halves. - * This takes log2(n) steps where n is the number of elements in the vector. - * This macro uses only intrinsics from the AVX512F feature. - - * Vec512 - Vector with size of 512. - * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: - * __mm512_max_epi64 - * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] - * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] - */ - -#define _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2) __extension__({ \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, 1, 2, 3, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 4, 5, 6, 7, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, 1, -1, -1, -1, -1, -1, -1),\ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 2, 3, -1, -1, -1, -1, -1, \ - -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, -1, -1, -1, -1, -1, -1, -1),\ - (__m512##T1)__builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 1, -1, -1, -1, -1, -1, -1, -1))\ - ; \ - return Vec512[0]; \ - }) +#define _mm512_mask_reduce_operator(op) \ + __m512i __t1 = (__m512i)__builtin_shufflevector((__v8di)__V, (__v8di)__V, 4, 5, 6, 7, 0, 1, 2, 3); \ + __m512i __t2 = _mm512_##op(__V, __t1); \ + __m512i __t3 = (__m512i)__builtin_shufflevector((__v8di)__t2, (__v8di)__t2, 2, 3, 0, 1, 6, 7, 4, 5); \ + __m512i __t4 = _mm512_##op(__t2, __t3); \ + __m512i __t5 = (__m512i)__builtin_shufflevector((__v8di)__t4, (__v8di)__t4, 1, 0, 3, 2, 5, 4, 7, 6); \ + __v8di __t6 = (__v8di)_mm512_##op(__t4, __t5); \ + return __t6[0]; static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epi64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, max_epi64, i, i); + _mm512_mask_reduce_operator(max_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_max_epu64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_max_pd(__m512d __V) { - _mm512_reduce_maxMin_64bit(__V, max_pd, d, f); + _mm512_mask_reduce_operator(max_epu64); } -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epi64 -(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, min_epi64, i, i); +static __inline__ long long __DEFAULT_FN_ATTRS +_mm512_reduce_min_epi64(__m512i __V) { + _mm512_mask_reduce_operator(min_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epu64(__m512i __V) { - _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_reduce_min_pd(__m512d __V) { - _mm512_reduce_maxMin_64bit(__V, min_pd, d, f); + _mm512_mask_reduce_operator(min_epu64); } -/* Vec512 - Vector with size 512. - * Vec512Neutral - A 512 length vector with elements set to the identity element - * Identity element: {max_epi,0x8000000000000000} - * {max_epu,0x0000000000000000} - * {max_pd, 0xFFF0000000000000} - * {min_epi,0x7FFFFFFFFFFFFFFF} - * {min_epu,0xFFFFFFFFFFFFFFFF} - * {min_pd, 0x7FF0000000000000} - * - * IntrinName - Can be one of following: {max|min}_{epi64|epu64|pd} for example: - * __mm512_max_epi64 - * T1 - Can get 'i' for int and 'd' for double.[__m512{i|d}] - * T2 - Can get 'i' for int and 'f' for float. [__v8d{i|f}] - * T3 - Can get 'q' q word and 'pd' for packed double. - * [__builtin_ia32_select{q|pd}_512] - * Mask - Intrinsic Mask - */ - -#define _mm512_mask_reduce_maxMin_64bit(Vec512, Vec512Neutral, IntrinName, T1, \ - T2, T3, Mask) \ - __extension__({ \ - Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ - (__mmask8)Mask, \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512Neutral); \ - _mm512_reduce_maxMin_64bit(Vec512, IntrinName, T1, T2); \ - }) - static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x8000000000000000), - max_epi64, i, i, q, __M); + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(-__LONG_LONG_MAX__ - 1LL), __M, __V); + _mm512_mask_reduce_operator(max_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x0000000000000000), - max_epu64, i, i, q, __M); -} - -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(-__builtin_inf()), - max_pd, d, f, pd, __M); + __V = _mm512_maskz_mov_epi64(__M, __V); + _mm512_mask_reduce_operator(max_epu64); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF), - min_epi64, i, i, q, __M); + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(__LONG_LONG_MAX__), __M, __V); + _mm512_mask_reduce_operator(min_epi64); } static __inline__ unsigned long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), - min_epu64, i, i, q, __M); -} + __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __V); + _mm512_mask_reduce_operator(min_epu64); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256i __t1 = _mm512_extracti64x4_epi64(__V, 0); \ + __m256i __t2 = _mm512_extracti64x4_epi64(__V, 1); \ + __m256i __t3 = _mm256_##op(__t1, __t2); \ + __m128i __t4 = _mm256_extracti128_si256(__t3, 0); \ + __m128i __t5 = _mm256_extracti128_si256(__t3, 1); \ + __m128i __t6 = _mm_##op(__t4, __t5); \ + __m128i __t7 = (__m128i)__builtin_shufflevector((__v4si)__t6, (__v4si)__t6, 2, 3, 0, 1); \ + __m128i __t8 = _mm_##op(__t6, __t7); \ + __m128i __t9 = (__m128i)__builtin_shufflevector((__v4si)__t8, (__v4si)__t8, 1, 0, 3, 2); \ + __v4si __t10 = (__v4si)_mm_##op(__t8, __t9); \ + return __t10[0]; -static __inline__ double __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { - _mm512_mask_reduce_maxMin_64bit(__V, _mm512_set1_pd(__builtin_inf()), - min_pd, d, f, pd, __M); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_reduce_max_epi32(__m512i __V) { + _mm512_mask_reduce_operator(max_epi32); } -#undef _mm512_reduce_maxMin_64bit -#undef _mm512_mask_reduce_maxMin_64bit -/* Vec512 - Vector with size 512. - * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: - * __mm512_max_epi32 - * T1 - Can get 'i' for int and ' ' .[__m512{i|}] - * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] - */ - -#define _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2) __extension__({ \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, 2, 3, 4, 5, 6, 7, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 8, 9, 10, 11, 12, 13, 14, 15, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, 2, 3, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 4, 5, 6, 7, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 2, 3, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - Vec512 = _mm512_##IntrinName( \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, -1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1), \ - (__m512##T1)__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 1, -1, -1, -1, -1, -1, -1, -1, \ - -1, -1, -1, -1, -1, -1, -1, -1)); \ - return Vec512[0]; \ - }) +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_reduce_max_epu32(__m512i __V) { + _mm512_mask_reduce_operator(max_epu32); +} -static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_max_epi32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, max_epi32, i, i); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_reduce_min_epi32(__m512i __V) { + _mm512_mask_reduce_operator(min_epi32); } static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_max_epu32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, max_epu32, i, i); +_mm512_reduce_min_epu32(__m512i __V) { + _mm512_mask_reduce_operator(min_epu32); } -static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_max_ps(__m512 a) { - _mm512_reduce_maxMin_32bit(a, max_ps, , f); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(-__INT_MAX__ - 1), __M, __V); + _mm512_mask_reduce_operator(max_epi32); } -static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_min_epi32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, min_epi32, i, i); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { + __V = _mm512_maskz_mov_epi32(__M, __V); + _mm512_mask_reduce_operator(max_epu32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_reduce_min_epu32(__m512i a) { - _mm512_reduce_maxMin_32bit(a, min_epu32, i, i); +static __inline__ int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(__INT_MAX__), __M, __V); + _mm512_mask_reduce_operator(min_epi32); } -static __inline__ float __DEFAULT_FN_ATTRS _mm512_reduce_min_ps(__m512 a) { - _mm512_reduce_maxMin_32bit(a, min_ps, , f); +static __inline__ unsigned int __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { + __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V); + _mm512_mask_reduce_operator(min_epu32); } -/* Vec512 - Vector with size 512. - * Vec512Neutral - A 512 length vector with elements set to the identity element - * Identity element: {max_epi,0x80000000} - * {max_epu,0x00000000} - * {max_ps, 0xFF800000} - * {min_epi,0x7FFFFFFF} - * {min_epu,0xFFFFFFFF} - * {min_ps, 0x7F800000} - * - * IntrinName - Can be one of following: {max|min}_{epi32|epu32|ps} for example: - * __mm512_max_epi32 - * T1 - Can get 'i' for int and ' ' .[__m512{i|}] - * T2 - Can get 'i' for int and 'f' for float.[__v16s{i|f}] - * T3 - Can get 'q' q word and 'pd' for packed double. - * [__builtin_ia32_select{q|pd}_512] - * Mask - Intrinsic Mask - */ +#define _mm512_mask_reduce_operator(op) \ + __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \ + __m256d __t2 = _mm512_extractf64x4_pd(__V, 1); \ + __m256d __t3 = _mm256_##op(__t1, __t2); \ + __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \ + __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \ + __m128d __t6 = _mm_##op(__t4, __t5); \ + __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \ + __m128d __t8 = _mm_##op(__t6, __t7); \ + return __t8[0]; -#define _mm512_mask_reduce_maxMin_32bit(Vec512, Vec512Neutral, IntrinName, T1, \ - T2, T3, Mask) \ - __extension__({ \ - Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ - (__mmask16)Mask, \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512Neutral); \ - _mm512_reduce_maxMin_32bit(Vec512, IntrinName, T1, T2); \ - }) +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_max_pd(__m512d __V) { + _mm512_mask_reduce_operator(max_pd); +} -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x80000000), max_epi32, - i, i, d, __M); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_reduce_min_pd(__m512d __V) { + _mm512_mask_reduce_operator(min_pd); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x00000000), max_epu32, - i, i, d, __M); +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { + __V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V); + _mm512_mask_reduce_operator(max_pd); } +static __inline__ double __DEFAULT_FN_ATTRS +_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { + __V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V); + _mm512_mask_reduce_operator(min_pd); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 0); \ + __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 1); \ + __m256 __t3 = _mm256_##op(__t1, __t2); \ + __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \ + __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \ + __m128 __t6 = _mm_##op(__t4, __t5); \ + __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \ + __m128 __t8 = _mm_##op(__t6, __t7); \ + __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \ + __m128 __t10 = _mm_##op(__t8, __t9); \ + return __t10[0]; + static __inline__ float __DEFAULT_FN_ATTRS -_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { - _mm512_mask_reduce_maxMin_32bit(__V,_mm512_set1_ps(-__builtin_inff()), max_ps, , f, - ps, __M); +_mm512_reduce_max_ps(__m512 __V) { + _mm512_mask_reduce_operator(max_ps); } -static __inline__ int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0x7FFFFFFF), min_epi32, - i, i, d, __M); +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_reduce_min_ps(__m512 __V) { + _mm512_mask_reduce_operator(min_ps); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS -_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_epi32(0xFFFFFFFF), min_epu32, - i, i, d, __M); +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { + __V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V); + _mm512_mask_reduce_operator(max_ps); } static __inline__ float __DEFAULT_FN_ATTRS _mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) { - _mm512_mask_reduce_maxMin_32bit(__V, _mm512_set1_ps(__builtin_inff()), min_ps, , f, - ps, __M); + __V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V); + _mm512_mask_reduce_operator(min_ps); } -#undef _mm512_reduce_maxMin_32bit -#undef _mm512_mask_reduce_maxMin_32bit +#undef _mm512_mask_reduce_operator #undef __DEFAULT_FN_ATTRS diff --git a/test/CodeGen/avx512-reduceMinMaxIntrin.c b/test/CodeGen/avx512-reduceMinMaxIntrin.c index 7b6284dfbc..fde7c0a273 100644 --- a/test/CodeGen/avx512-reduceMinMaxIntrin.c +++ b/test/CodeGen/avx512-reduceMinMaxIntrin.c @@ -3,2406 +3,2526 @@ #include // CHECK-LABEL: define i64 @test_mm512_reduce_max_epi64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp sgt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp sgt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp sgt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp sgt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp sgt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_reduce_max_epi64(__m512i __W){ return _mm512_reduce_max_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_max_epu64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp ugt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp ugt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ugt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_max_epu64(__m512i __W){ return _mm512_reduce_max_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_max_pd(<8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> -// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I9_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT2_I]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP3]], <4 x double>* [[__A_ADDR_I10_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__B_ADDR_I11_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I10_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I11_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP5]], <4 x double> [[TMP6]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP7]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x double> [[TMP8]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT4_I]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT5_I]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP10:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP10]], <2 x double>* [[__A_ADDR_I8_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__B_ADDR_I9_I]], align 16 +// CHECK-NEXT: [[TMP12:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I8_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I9_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP12]], <2 x double> [[TMP13]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP15]], <2 x double> [[TMP16]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP17]], <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP19]], <2 x double> [[TMP20]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP22]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_reduce_max_pd(__m512d __W){ return _mm512_reduce_max_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epi64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp slt <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp slt <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp slt <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp slt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp slt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_reduce_min_epi64(__m512i __W){ return _mm512_reduce_min_epi64(__W); } // CHECK-LABEL: define i64 @test_mm512_reduce_min_epu64(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP3]], <8 x i64> [[TMP4]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] -// CHECK: [[TMP9:%.*]] = select <8 x i1> [[TMP8]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] -// CHECK: store <8 x i64> [[TMP9]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP10]], <8 x i64> [[TMP11]], <8 x i32> -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> [[TMP13]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP17:%.*]] = icmp ult <8 x i64> [[TMP14]], [[TMP15]] -// CHECK: [[TMP18:%.*]] = select <8 x i1> [[TMP17]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] -// CHECK: store <8 x i64> [[TMP18]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP19]], <8 x i64> [[TMP20]], <8 x i32> -// CHECK: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP21]], <8 x i64> [[TMP22]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP26:%.*]] = icmp ult <8 x i64> [[TMP23]], [[TMP24]] -// CHECK: [[TMP27:%.*]] = select <8 x i1> [[TMP26]], <8 x i64> [[TMP23]], <8 x i64> [[TMP24]] -// CHECK: store <8 x i64> [[TMP27]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP28]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> [[TMP2]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = icmp ult <8 x i64> [[TMP5]], [[TMP6]] +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ult <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I5_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ult <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP25]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long long test_mm512_reduce_min_epu64(__m512i __W){ return _mm512_reduce_min_epu64(__W); } // CHECK-LABEL: define double @test_mm512_reduce_min_pd(<8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I8_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> [[TMP2]], <8 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP3]], <8 x double> [[TMP4]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP5]], <8 x double> [[TMP6]], <8 x double> [[TMP7]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP8]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <8 x double> [[TMP9]], <8 x double> [[TMP10]], <8 x i32> -// CHECK: [[TMP11:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP11]], <8 x double> [[TMP12]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE2_I]], <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP13]], <8 x double> [[TMP14]], <8 x double> [[TMP15]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP16]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE5_I]], <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I9_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I8_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP21]], <8 x double> [[TMP22]], <8 x double> [[TMP23]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP24]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP25]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I9_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP0]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP1]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT2_I]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP3]], <4 x double>* [[__A_ADDR_I10_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP4]], <4 x double>* [[__B_ADDR_I11_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I10_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I11_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP5]], <4 x double> [[TMP6]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP7]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x double> [[TMP8]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT4_I]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT5_I]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP10:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP11:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP10]], <2 x double>* [[__A_ADDR_I8_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP11]], <2 x double>* [[__B_ADDR_I9_I]], align 16 +// CHECK-NEXT: [[TMP12:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I8_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I9_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP12]], <2 x double> [[TMP13]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP14]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP15]], <2 x double> [[TMP16]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP17]], <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP18]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP19]], <2 x double> [[TMP20]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP21]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP22]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_reduce_min_pd(__m512d __W){ return _mm512_reduce_min_pd(__W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp sgt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp sgt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 -9223372036854775808, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp sgt <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp sgt <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp sgt <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 0, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp ugt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp ugt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i8 [[TMP2]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = bitcast i8 [[TMP4]] to <8 x i1> +// CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP7]], <8 x i64> [[TMP5]], <8 x i64> [[TMP6]] +// CHECK-NEXT: store <8 x i64> [[TMP8]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP9]], <8 x i64> [[TMP10]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = icmp ugt <8 x i64> [[TMP13]], [[TMP14]] +// CHECK-NEXT: [[TMP16:%.*]] = select <8 x i1> [[TMP15]], <8 x i64> [[TMP13]], <8 x i64> [[TMP14]] +// CHECK-NEXT: store <8 x i64> [[TMP16]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE2_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE2_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = icmp ugt <8 x i64> [[TMP21]], [[TMP22]] +// CHECK-NEXT: [[TMP24:%.*]] = select <8 x i1> [[TMP23]], <8 x i64> [[TMP21]], <8 x i64> [[TMP22]] +// CHECK-NEXT: store <8 x i64> [[TMP24]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP25]], <8 x i64> [[TMP26]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP27]], <8 x i64>* [[__A_ADDR_I6_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I6_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <8 x i64> [[TMP29]], [[TMP30]] +// CHECK-NEXT: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP29]], <8 x i64> [[TMP30]] +// CHECK-NEXT: store <8 x i64> [[TMP32]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP33]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] unsigned long test_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_max_epu64(__M, __W); } -// CHECK-LABEL: define i64 @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 -// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] -// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 -// CHECK: [[CONV:%.*]] = fptosi double [[VECEXT_I]] to i64 -// CHECK: ret i64 [[CONV]] -long long test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){ +// CHECK-LABEL: define double @test_mm512_mask_reduce_max_pd(i8 zeroext %__M, <8 x double> %__W) #0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store double 0xFFF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] +// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT4_I]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP20]], <4 x double>* [[__A_ADDR_I12_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__B_ADDR_I13_I]], align 32 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I12_I]], align 32 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I13_I]], align 32 +// CHECK-NEXT: [[TMP24:%.*]] = call <4 x double> @llvm.x86.avx.max.pd.256(<4 x double> [[TMP22]], <4 x double> [[TMP23]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP24]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x double> [[TMP25]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT6_I]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x double> [[TMP26]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT7_I]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP27]], <2 x double>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP29]], <2 x double> [[TMP30]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP32]], <2 x double> [[TMP33]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP34]], <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = call <2 x double> @llvm.x86.sse2.max.pd(<2 x double> [[TMP36]], <2 x double> [[TMP37]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP39]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] +double test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_max_pd(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epi64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp slt <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp slt <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 9223372036854775807, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp slt <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp slt <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp slt <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epi64(__M, __W); } // CHECK-LABEL: define i64 @test_mm512_mask_reduce_min_epu64(i8 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP11]], i32 7 -// CHECK: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x i64> [[TMP3]], <8 x i64> [[TMP12]] -// CHECK: store <8 x i64> [[TMP14]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP15]], <8 x i64> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x i64> [[TMP17]], <8 x i64> [[TMP18]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE1_I]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP22:%.*]] = icmp ult <8 x i64> [[TMP19]], [[TMP20]] -// CHECK: [[TMP23:%.*]] = select <8 x i1> [[TMP22]], <8 x i64> [[TMP19]], <8 x i64> [[TMP20]] -// CHECK: store <8 x i64> [[TMP23]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP24]], <8 x i64> [[TMP25]], <8 x i32> -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE4_I]], <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = icmp ult <8 x i64> [[TMP28]], [[TMP29]] -// CHECK: [[TMP32:%.*]] = select <8 x i1> [[TMP31]], <8 x i64> [[TMP28]], <8 x i64> [[TMP29]] -// CHECK: store <8 x i64> [[TMP32]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x i64> [[TMP33]], <8 x i64> [[TMP34]], <8 x i32> -// CHECK: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x i64> [[TMP35]], <8 x i64> [[TMP36]], <8 x i32> -// CHECK: store <8 x i64> [[SHUFFLE6_I]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[SHUFFLE7_I]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP37]], [[TMP38]] -// CHECK: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP37]], <8 x i64> [[TMP38]] -// CHECK: store <8 x i64> [[TMP41]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 -// CHECK: ret i64 [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I11_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I9_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I10_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I7_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I8_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__D_ADDR_I_I:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i64 -1, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x i64> undef, i64 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x i64> [[VECINIT_I_I]], i64 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x i64> [[VECINIT1_I_I]], i64 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x i64> [[VECINIT2_I_I]], i64 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x i64> [[VECINIT3_I_I]], i64 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x i64> [[VECINIT4_I_I]], i64 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x i64> [[VECINIT5_I_I]], i64 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i64, i64* [[__D_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x i64> [[VECINIT6_I_I]], i64 [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x i64> [[VECINIT7_I_I]], <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP10]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x i64> [[TMP12]], <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I11_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x i64> [[TMP14]], <8 x i64> [[TMP15]] +// CHECK-NEXT: store <8 x i64> [[TMP17]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i64> [[TMP18]], <8 x i64> [[TMP19]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE_I]], <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__T1_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP20]], <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I9_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I10_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = icmp ult <8 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[TMP25:%.*]] = select <8 x i1> [[TMP24]], <8 x i64> [[TMP22]], <8 x i64> [[TMP23]] +// CHECK-NEXT: store <8 x i64> [[TMP25]], <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[SHUFFLE3_I:%.*]] = shufflevector <8 x i64> [[TMP26]], <8 x i64> [[TMP27]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE3_I]], <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__T2_I]], align 64 +// CHECK-NEXT: [[TMP29:%.*]] = load <8 x i64>, <8 x i64>* [[__T3_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP28]], <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I7_I]], align 64 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I8_I]], align 64 +// CHECK-NEXT: [[TMP32:%.*]] = icmp ult <8 x i64> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[TMP33:%.*]] = select <8 x i1> [[TMP32]], <8 x i64> [[TMP30]], <8 x i64> [[TMP31]] +// CHECK-NEXT: store <8 x i64> [[TMP33]], <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[SHUFFLE5_I:%.*]] = shufflevector <8 x i64> [[TMP34]], <8 x i64> [[TMP35]], <8 x i32> +// CHECK-NEXT: store <8 x i64> [[SHUFFLE5_I]], <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__T4_I]], align 64 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x i64>, <8 x i64>* [[__T5_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP36]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP37]], <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP40:%.*]] = icmp ult <8 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[TMP41:%.*]] = select <8 x i1> [[TMP40]], <8 x i64> [[TMP38]], <8 x i64> [[TMP39]] +// CHECK-NEXT: store <8 x i64> [[TMP41]], <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[TMP42:%.*]] = load <8 x i64>, <8 x i64>* [[__T6_I]], align 64 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP42]], i32 0 +// CHECK-NEXT: ret i64 [[VECEXT_I]] long long test_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __W){ return _mm512_mask_reduce_min_epu64(__M, __W); } // CHECK-LABEL: define double @test_mm512_mask_reduce_min_pd(i8 zeroext %__M, <8 x double> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I9_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I10_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I11_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i8, align 1 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i8, align 1 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 -// CHECK: store i8 %__M, i8* [[__M_ADDR]], align 1 -// CHECK: store <8 x double> %__W, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 -// CHECK: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 -// CHECK: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 -// CHECK: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 -// CHECK: [[TMP3:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP11]], i32 7 -// CHECK: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP13:%.*]] = bitcast i8 [[TMP2]] to <8 x i1> -// CHECK: [[TMP14:%.*]] = select <8 x i1> [[TMP13]], <8 x double> [[TMP3]], <8 x double> [[TMP12]] -// CHECK: store <8 x double> [[TMP14]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP16:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x double> [[TMP15]], <8 x double> [[TMP16]], <8 x i32> -// CHECK: [[TMP17:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <8 x double> [[TMP17]], <8 x double> [[TMP18]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE_I]], <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE1_I]], <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP22:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP19]], <8 x double> [[TMP20]], <8 x double> [[TMP21]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP22]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <8 x double> [[TMP23]], <8 x double> [[TMP24]], <8 x i32> -// CHECK: [[TMP25:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <8 x double> [[TMP25]], <8 x double> [[TMP26]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE3_I]], <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE4_I]], <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I10_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I11_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I9_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP27]], <8 x double> [[TMP28]], <8 x double> [[TMP29]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP30]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <8 x double> [[TMP31]], <8 x double> [[TMP32]], <8 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <8 x double> [[TMP33]], <8 x double> [[TMP34]], <8 x i32> -// CHECK: store <8 x double> [[SHUFFLE6_I]], <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x double> [[SHUFFLE7_I]], <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x double>, <8 x double>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <8 x double> zeroinitializer, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <8 x double>, <8 x double>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> [[TMP35]], <8 x double> [[TMP36]], <8 x double> [[TMP37]], i8 -1, i32 4) #2 -// CHECK: store <8 x double> [[TMP38]], <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x double> [[TMP39]], i32 0 -// CHECK: ret double [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x double>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i8, align 1 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x double>, align 64 +// CHECK-NEXT: store i8 [[__M:%.*]], i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: store <8 x double> [[__W:%.*]], <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[__M_ADDR]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x double>, <8 x double>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i8 [[TMP0]], i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP1]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store double 0x7FF0000000000000, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <8 x double> [[VECINIT_I_I]], double [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <8 x double> [[VECINIT1_I_I]], double [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <8 x double> [[VECINIT2_I_I]], double [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <8 x double> [[VECINIT3_I_I]], double [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <8 x double> [[VECINIT4_I_I]], double [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <8 x double> [[VECINIT5_I_I]], double [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load double, double* [[__W_ADDR_I_I]], align 8 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <8 x double> [[VECINIT6_I_I]], double [[TMP9]], i32 7 +// CHECK-NEXT: store <8 x double> [[VECINIT7_I_I]], <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x double>, <8 x double>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[__M_ADDR_I]], align 1 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x double> [[TMP10]], <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i8 [[TMP11]], i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: store <8 x double> [[TMP12]], <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[__U_ADDR_I_I]], align 1 +// CHECK-NEXT: [[TMP14:%.*]] = load <8 x double>, <8 x double>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP15:%.*]] = load <8 x double>, <8 x double>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP16:%.*]] = bitcast i8 [[TMP13]] to <8 x i1> +// CHECK-NEXT: [[TMP17:%.*]] = select <8 x i1> [[TMP16]], <8 x double> [[TMP14]], <8 x double> [[TMP15]] +// CHECK-NEXT: store <8 x double> [[TMP17]], <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP18]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT_I]], <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = load <8 x double>, <8 x double>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP19]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: store <4 x double> [[EXTRACT4_I]], <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x double>, <4 x double>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x double>, <4 x double>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP20]], <4 x double>* [[__A_ADDR_I12_I]], align 32 +// CHECK-NEXT: store <4 x double> [[TMP21]], <4 x double>* [[__B_ADDR_I13_I]], align 32 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x double>, <4 x double>* [[__A_ADDR_I12_I]], align 32 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x double>, <4 x double>* [[__B_ADDR_I13_I]], align 32 +// CHECK-NEXT: [[TMP24:%.*]] = call <4 x double> @llvm.x86.avx.min.pd.256(<4 x double> [[TMP22]], <4 x double> [[TMP23]]) #2 +// CHECK-NEXT: store <4 x double> [[TMP24]], <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP25:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x double> [[TMP25]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT6_I]], <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x double>, <4 x double>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x double> [[TMP26]], <4 x double> undef, <2 x i32> +// CHECK-NEXT: store <2 x double> [[EXTRACT7_I]], <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x double>, <2 x double>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x double>, <2 x double>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP27]], <2 x double>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP28]], <2 x double>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x double>, <2 x double>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP29]], <2 x double> [[TMP30]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP31]], <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP32]], <2 x double> [[TMP33]], <2 x i32> +// CHECK-NEXT: store <2 x double> [[SHUFFLE_I]], <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x double>, <2 x double>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = load <2 x double>, <2 x double>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP34]], <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x double> [[TMP35]], <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x double>, <2 x double>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x double>, <2 x double>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = call <2 x double> @llvm.x86.sse2.min.pd(<2 x double> [[TMP36]], <2 x double> [[TMP37]]) #2 +// CHECK-NEXT: store <2 x double> [[TMP38]], <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x double>, <2 x double>* [[__T8_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x double> [[TMP39]], i32 0 +// CHECK-NEXT: ret double [[VECEXT_I]] double test_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __W){ return _mm512_mask_reduce_min_pd(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epi32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp sgt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp sgt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp sgt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp sgt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32> +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = icmp sgt <8 x i32> [[TMP6]], [[TMP8]] +// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32> +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = icmp sgt <4 x i32> [[TMP17]], [[TMP19]] +// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]] +// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32> +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32> +// CHECK-NEXT: [[TMP34:%.*]] = icmp sgt <4 x i32> [[TMP31]], [[TMP33]] +// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]] +// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32> +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> +// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32> +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32> +// CHECK-NEXT: [[TMP48:%.*]] = icmp sgt <4 x i32> [[TMP45]], [[TMP47]] +// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]] +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_reduce_max_epi32(__m512i __W){ return _mm512_reduce_max_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_max_epu32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp ugt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp ugt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp ugt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp ugt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32> +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = icmp ugt <8 x i32> [[TMP6]], [[TMP8]] +// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32> +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = icmp ugt <4 x i32> [[TMP17]], [[TMP19]] +// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]] +// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32> +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32> +// CHECK-NEXT: [[TMP34:%.*]] = icmp ugt <4 x i32> [[TMP31]], [[TMP33]] +// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]] +// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32> +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> +// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32> +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32> +// CHECK-NEXT: [[TMP48:%.*]] = icmp ugt <4 x i32> [[TMP45]], [[TMP47]] +// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]] +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_reduce_max_epu32(__m512i __W){ return _mm512_reduce_max_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_max_ps(<16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> -// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> -// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP3]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = bitcast <16 x float> [[TMP4]] to <8 x double> +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP5]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x double> [[EXTRACT2_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP6]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP7]], <8 x float>* [[__A_ADDR_I14_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__B_ADDR_I15_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I14_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I15_I]], align 32 +// CHECK-NEXT: [[TMP11:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP9]], <8 x float> [[TMP10]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP11]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x float> [[TMP12]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT4_I]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <8 x float> [[TMP13]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT5_I]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP14]], <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP16]], <4 x float> [[TMP17]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP21]], <4 x float>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP23]], <4 x float> [[TMP24]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x float> [[TMP26]], <4 x float> [[TMP27]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE8_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP28]], <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP30]], <4 x float> [[TMP31]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP33]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_reduce_max_ps(__m512 __W){ return _mm512_reduce_max_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epi32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp slt <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp slt <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp slt <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp slt <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32> +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = icmp slt <8 x i32> [[TMP6]], [[TMP8]] +// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32> +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = icmp slt <4 x i32> [[TMP17]], [[TMP19]] +// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]] +// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32> +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32> +// CHECK-NEXT: [[TMP34:%.*]] = icmp slt <4 x i32> [[TMP31]], [[TMP33]] +// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]] +// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32> +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> +// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32> +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32> +// CHECK-NEXT: [[TMP48:%.*]] = icmp slt <4 x i32> [[TMP45]], [[TMP47]] +// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]] +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_reduce_min_epi32(__m512i __W){ return _mm512_reduce_min_epi32(__W); } // CHECK-LABEL: define i32 @test_mm512_reduce_min_epu32(<8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store <8 x i64> [[TMP0]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to <16 x i32> -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP2]], <16 x i32> [[TMP4]], <16 x i32> -// CHECK: [[TMP5:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP6:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP7:%.*]] = bitcast <8 x i64> [[TMP6]] to <16 x i32> -// CHECK: [[TMP8:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = bitcast <8 x i64> [[TMP8]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP7]], <16 x i32> [[TMP9]], <16 x i32> -// CHECK: [[TMP10:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP5]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP10]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP11:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP12:%.*]] = bitcast <8 x i64> [[TMP11]] to <16 x i32> -// CHECK: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP14:%.*]] = bitcast <8 x i64> [[TMP13]] to <16 x i32> -// CHECK: [[TMP17:%.*]] = icmp ult <16 x i32> [[TMP12]], [[TMP14]] -// CHECK: [[TMP18:%.*]] = select <16 x i1> [[TMP17]], <16 x i32> [[TMP12]], <16 x i32> [[TMP14]] -// CHECK: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP19]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast <8 x i64> [[TMP20]] to <16 x i32> -// CHECK: [[TMP22:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = bitcast <8 x i64> [[TMP22]] to <16 x i32> -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x i32> [[TMP21]], <16 x i32> [[TMP23]], <16 x i32> -// CHECK: [[TMP24:%.*]] = bitcast <16 x i32> [[SHUFFLE2_I]] to <8 x i64> -// CHECK: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> -// CHECK: [[TMP27:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = bitcast <8 x i64> [[TMP27]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP26]], <16 x i32> [[TMP28]], <16 x i32> -// CHECK: [[TMP29:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP24]], <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <8 x i64> [[TMP29]], <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP31:%.*]] = bitcast <8 x i64> [[TMP30]] to <16 x i32> -// CHECK: [[TMP32:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP33:%.*]] = bitcast <8 x i64> [[TMP32]] to <16 x i32> -// CHECK: [[TMP36:%.*]] = icmp ult <16 x i32> [[TMP31]], [[TMP33]] -// CHECK: [[TMP37:%.*]] = select <16 x i1> [[TMP36]], <16 x i32> [[TMP31]], <16 x i32> [[TMP33]] -// CHECK: [[TMP38:%.*]] = bitcast <16 x i32> [[TMP37]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP38]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = bitcast <8 x i64> [[TMP39]] to <16 x i32> -// CHECK: [[TMP41:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = bitcast <8 x i64> [[TMP41]] to <16 x i32> -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x i32> [[TMP40]], <16 x i32> [[TMP42]], <16 x i32> -// CHECK: [[TMP43:%.*]] = bitcast <16 x i32> [[SHUFFLE5_I]] to <8 x i64> -// CHECK: [[TMP44:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = bitcast <8 x i64> [[TMP44]] to <16 x i32> -// CHECK: [[TMP46:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = bitcast <8 x i64> [[TMP46]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP45]], <16 x i32> [[TMP47]], <16 x i32> -// CHECK: [[TMP48:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP43]], <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <8 x i64> [[TMP48]], <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP49:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP50:%.*]] = bitcast <8 x i64> [[TMP49]] to <16 x i32> -// CHECK: [[TMP51:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP52:%.*]] = bitcast <8 x i64> [[TMP51]] to <16 x i32> -// CHECK: [[TMP55:%.*]] = icmp ult <16 x i32> [[TMP50]], [[TMP52]] -// CHECK: [[TMP56:%.*]] = select <16 x i1> [[TMP55]], <16 x i32> [[TMP50]], <16 x i32> [[TMP52]] -// CHECK: [[TMP57:%.*]] = bitcast <16 x i32> [[TMP56]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP57]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP58:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP59:%.*]] = bitcast <8 x i64> [[TMP58]] to <16 x i32> -// CHECK: [[TMP60:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP61:%.*]] = bitcast <8 x i64> [[TMP60]] to <16 x i32> -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x i32> [[TMP59]], <16 x i32> [[TMP61]], <16 x i32> -// CHECK: [[TMP62:%.*]] = bitcast <16 x i32> [[SHUFFLE8_I]] to <8 x i64> -// CHECK: [[TMP63:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = bitcast <8 x i64> [[TMP63]] to <16 x i32> -// CHECK: [[TMP65:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP66:%.*]] = bitcast <8 x i64> [[TMP65]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP64]], <16 x i32> [[TMP66]], <16 x i32> -// CHECK: [[TMP67:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP62]], <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <8 x i64> [[TMP67]], <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP68:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP69:%.*]] = bitcast <8 x i64> [[TMP68]] to <16 x i32> -// CHECK: [[TMP70:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP71:%.*]] = bitcast <8 x i64> [[TMP70]] to <16 x i32> -// CHECK: [[TMP74:%.*]] = icmp ult <16 x i32> [[TMP69]], [[TMP71]] -// CHECK: [[TMP75:%.*]] = select <16 x i1> [[TMP74]], <16 x i32> [[TMP69]], <16 x i32> [[TMP71]] -// CHECK: [[TMP76:%.*]] = bitcast <16 x i32> [[TMP75]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP76]], <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP77:%.*]] = load <8 x i64>, <8 x i64>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP77]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I10_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP1]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP2:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x i64> [[TMP2]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT2_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP3]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i64> [[TMP5]] to <8 x i32> +// CHECK-NEXT: [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i64> [[TMP7]] to <8 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = icmp ult <8 x i32> [[TMP6]], [[TMP8]] +// CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP9]], <8 x i32> [[TMP6]], <8 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <8 x i32> [[TMP10]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP11]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT4_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP13]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP14]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP15]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = bitcast <2 x i64> [[TMP16]] to <4 x i32> +// CHECK-NEXT: [[TMP18:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i64> [[TMP18]] to <4 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = icmp ult <4 x i32> [[TMP17]], [[TMP19]] +// CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP20]], <4 x i32> [[TMP17]], <4 x i32> [[TMP19]] +// CHECK-NEXT: [[TMP22:%.*]] = bitcast <4 x i32> [[TMP21]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP22]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <2 x i64> [[TMP23]] to <4 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <2 x i64> [[TMP25]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP24]], <4 x i32> [[TMP26]], <4 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP27]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP28]], <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP29]], <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <2 x i64> [[TMP30]] to <4 x i32> +// CHECK-NEXT: [[TMP32:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <2 x i64> [[TMP32]] to <4 x i32> +// CHECK-NEXT: [[TMP34:%.*]] = icmp ult <4 x i32> [[TMP31]], [[TMP33]] +// CHECK-NEXT: [[TMP35:%.*]] = select <4 x i1> [[TMP34]], <4 x i32> [[TMP31]], <4 x i32> [[TMP33]] +// CHECK-NEXT: [[TMP36:%.*]] = bitcast <4 x i32> [[TMP35]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP36]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = bitcast <2 x i64> [[TMP37]] to <4 x i32> +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <2 x i64> [[TMP39]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x i32> [[TMP38]], <4 x i32> [[TMP40]], <4 x i32> +// CHECK-NEXT: [[TMP41:%.*]] = bitcast <4 x i32> [[SHUFFLE8_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP41]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP42]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = bitcast <2 x i64> [[TMP44]] to <4 x i32> +// CHECK-NEXT: [[TMP46:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = bitcast <2 x i64> [[TMP46]] to <4 x i32> +// CHECK-NEXT: [[TMP48:%.*]] = icmp ult <4 x i32> [[TMP45]], [[TMP47]] +// CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP48]], <4 x i32> [[TMP45]], <4 x i32> [[TMP47]] +// CHECK-NEXT: [[TMP50:%.*]] = bitcast <4 x i32> [[TMP49]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP49]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP51]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_reduce_min_epu32(__m512i __W){ return _mm512_reduce_min_epu32(__W); } // CHECK-LABEL: define float @test_mm512_reduce_min_ps(<16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I11_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[A_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store <16 x float> [[TMP0]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP1]], <16 x float> [[TMP2]], <16 x i32> -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP3]], <16 x float> [[TMP4]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP5:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP6:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP7:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP8:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP5]], <16 x float> [[TMP6]], <16 x float> [[TMP7]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP8]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP9:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP10:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE2_I:%.*]] = shufflevector <16 x float> [[TMP9]], <16 x float> [[TMP10]], <16 x i32> -// CHECK: [[TMP11:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP12:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> [[TMP12]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE2_I]], <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: [[TMP13:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I18_I]], align 64 -// CHECK: [[TMP14:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP15:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I17_I]], align 64 -// CHECK: [[TMP16:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP13]], <16 x float> [[TMP14]], <16 x float> [[TMP15]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP16]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP17:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE5_I:%.*]] = shufflevector <16 x float> [[TMP17]], <16 x float> [[TMP18]], <16 x i32> -// CHECK: [[TMP19:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP19]], <16 x float> [[TMP20]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE5_I]], <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I15_I]], align 64 -// CHECK: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I14_I]], align 64 -// CHECK: [[TMP24:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP21]], <16 x float> [[TMP22]], <16 x float> [[TMP23]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP24]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE8_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE8_I]], <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I12_I]], align 64 -// CHECK: [[TMP30:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I11_I]], align 64 -// CHECK: [[TMP32:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP29]], <16 x float> [[TMP30]], <16 x float> [[TMP31]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP32]], <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[A_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP33]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I11_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP0]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x float> [[TMP1]] to <8 x double> +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP3]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP4:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP5:%.*]] = bitcast <16 x float> [[TMP4]] to <8 x double> +// CHECK-NEXT: [[EXTRACT2_I:%.*]] = shufflevector <8 x double> [[TMP5]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x double> [[EXTRACT2_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP6]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP7:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP8:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP7]], <8 x float>* [[__A_ADDR_I14_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP8]], <8 x float>* [[__B_ADDR_I15_I]], align 32 +// CHECK-NEXT: [[TMP9:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I14_I]], align 32 +// CHECK-NEXT: [[TMP10:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I15_I]], align 32 +// CHECK-NEXT: [[TMP11:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP9]], <8 x float> [[TMP10]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP11]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x float> [[TMP12]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT4_I]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <8 x float> [[TMP13]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT5_I]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP14]], <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP15]], <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP17:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP18:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP16]], <4 x float> [[TMP17]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP18]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP19:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP22:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP21]], <4 x float>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP22]], <4 x float>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I10_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP23]], <4 x float> [[TMP24]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP25]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE8_I:%.*]] = shufflevector <4 x float> [[TMP26]], <4 x float> [[TMP27]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE8_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP29:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP28]], <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP29]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP31:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP32:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP30]], <4 x float> [[TMP31]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP32]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP33]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_reduce_min_ps(__m512 __W){ return _mm512_reduce_min_ps(__W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp sgt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp sgt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp sgt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp sgt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 -2147483648, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp sgt <8 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32> +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32> +// CHECK-NEXT: [[TMP49:%.*]] = icmp sgt <4 x i32> [[TMP46]], [[TMP48]] +// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]] +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32> +// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> +// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32> +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32> +// CHECK-NEXT: [[TMP63:%.*]] = icmp sgt <4 x i32> [[TMP60]], [[TMP62]] +// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]] +// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32> +// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> +// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32> +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32> +// CHECK-NEXT: [[TMP77:%.*]] = icmp sgt <4 x i32> [[TMP74]], [[TMP76]] +// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]] +// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_max_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 0, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp ugt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp ugt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp ugt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp ugt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I11_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i16 [[TMP2]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP3]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP5:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP6:%.*]] = bitcast <8 x i64> [[TMP5]] to <16 x i32> +// CHECK-NEXT: store <8 x i64> zeroinitializer, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP7:%.*]] = load <8 x i64>, <8 x i64>* [[DOTCOMPOUNDLITERAL_I_I_I]], align 64 +// CHECK-NEXT: [[TMP8:%.*]] = bitcast <8 x i64> [[TMP7]] to <16 x i32> +// CHECK-NEXT: [[TMP9:%.*]] = bitcast i16 [[TMP4]] to <16 x i1> +// CHECK-NEXT: [[TMP10:%.*]] = select <16 x i1> [[TMP9]], <16 x i32> [[TMP6]], <16 x i32> [[TMP8]] +// CHECK-NEXT: [[TMP11:%.*]] = bitcast <16 x i32> [[TMP10]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP11]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP12:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP12]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP13:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT3_I:%.*]] = shufflevector <8 x i64> [[TMP13]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT3_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP14:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP15:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP14]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP15]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP16:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP17:%.*]] = bitcast <4 x i64> [[TMP16]] to <8 x i32> +// CHECK-NEXT: [[TMP18:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <4 x i64> [[TMP18]] to <8 x i32> +// CHECK-NEXT: [[TMP20:%.*]] = icmp ugt <8 x i32> [[TMP17]], [[TMP19]] +// CHECK-NEXT: [[TMP21:%.*]] = select <8 x i1> [[TMP20]], <8 x i32> [[TMP17]], <8 x i32> [[TMP19]] +// CHECK-NEXT: [[TMP22:%.*]] = bitcast <8 x i32> [[TMP21]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP22]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP23:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT5_I:%.*]] = shufflevector <4 x i64> [[TMP23]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT5_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP24:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP24]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP25:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP26:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP25]], <2 x i64>* [[__V1_ADDR_I13_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP26]], <2 x i64>* [[__V2_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP27:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <2 x i64> [[TMP27]] to <4 x i32> +// CHECK-NEXT: [[TMP29:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <2 x i64> [[TMP29]] to <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = icmp ugt <4 x i32> [[TMP28]], [[TMP30]] +// CHECK-NEXT: [[TMP32:%.*]] = select <4 x i1> [[TMP31]], <4 x i32> [[TMP28]], <4 x i32> [[TMP30]] +// CHECK-NEXT: [[TMP33:%.*]] = bitcast <4 x i32> [[TMP32]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP33]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP34:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <2 x i64> [[TMP34]] to <4 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <2 x i64> [[TMP36]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP35]], <4 x i32> [[TMP37]], <4 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP38]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP39]], <2 x i64>* [[__V1_ADDR_I11_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP40]], <2 x i64>* [[__V2_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I11_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = bitcast <2 x i64> [[TMP41]] to <4 x i32> +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = bitcast <2 x i64> [[TMP43]] to <4 x i32> +// CHECK-NEXT: [[TMP45:%.*]] = icmp ugt <4 x i32> [[TMP42]], [[TMP44]] +// CHECK-NEXT: [[TMP46:%.*]] = select <4 x i1> [[TMP45]], <4 x i32> [[TMP42]], <4 x i32> [[TMP44]] +// CHECK-NEXT: [[TMP47:%.*]] = bitcast <4 x i32> [[TMP46]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP47]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = bitcast <2 x i64> [[TMP48]] to <4 x i32> +// CHECK-NEXT: [[TMP50:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <2 x i64> [[TMP50]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE9_I:%.*]] = shufflevector <4 x i32> [[TMP49]], <4 x i32> [[TMP51]], <4 x i32> +// CHECK-NEXT: [[TMP52:%.*]] = bitcast <4 x i32> [[SHUFFLE9_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP52]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP53]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP54]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = bitcast <2 x i64> [[TMP55]] to <4 x i32> +// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = bitcast <2 x i64> [[TMP57]] to <4 x i32> +// CHECK-NEXT: [[TMP59:%.*]] = icmp ugt <4 x i32> [[TMP56]], [[TMP58]] +// CHECK-NEXT: [[TMP60:%.*]] = select <4 x i1> [[TMP59]], <4 x i32> [[TMP56]], <4 x i32> [[TMP58]] +// CHECK-NEXT: [[TMP61:%.*]] = bitcast <4 x i32> [[TMP60]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP60]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP62]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_max_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_max_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 -// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 -// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 -// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 -// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 -// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 -// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 -// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 -// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 -// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] -// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> -// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store float 0xFFF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> +// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] +// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP28]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <16 x float> [[TMP29]] to <8 x double> +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP30]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x double> [[EXTRACT4_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP31]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP32]], <8 x float>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = call <8 x float> @llvm.x86.avx.max.ps.256(<8 x float> [[TMP34]], <8 x float> [[TMP35]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP36]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <8 x float> [[TMP37]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT6_I]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <8 x float> [[TMP38]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT7_I]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP39]], <4 x float>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP41]], <4 x float> [[TMP42]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP44]], <4 x float> [[TMP45]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP46]], <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP48]], <4 x float> [[TMP49]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x float> [[TMP51]], <4 x float> [[TMP52]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP54:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP53]], <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> [[TMP55]], <4 x float> [[TMP56]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP58]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_max_ps(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epi32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp slt <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp slt <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp slt <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp slt <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 2147483647, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp slt <8 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32> +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32> +// CHECK-NEXT: [[TMP49:%.*]] = icmp slt <4 x i32> [[TMP46]], [[TMP48]] +// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]] +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32> +// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> +// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32> +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32> +// CHECK-NEXT: [[TMP63:%.*]] = icmp slt <4 x i32> [[TMP60]], [[TMP62]] +// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]] +// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32> +// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> +// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32> +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32> +// CHECK-NEXT: [[TMP77:%.*]] = icmp slt <4 x i32> [[TMP74]], [[TMP76]] +// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]] +// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] int test_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epi32(__M, __W); } // CHECK-LABEL: define i32 @test_mm512_mask_reduce_min_epu32(i16 zeroext %__M, <8 x i64> %__W) #0 { -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <8 x i64> %__W, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP4:%.*]] = bitcast <8 x i64> [[TMP3]] to <16 x i32> -// CHECK: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP5]], i32 0 -// CHECK: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP6]], i32 1 -// CHECK: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP7]], i32 2 -// CHECK: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP8]], i32 3 -// CHECK: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP9]], i32 4 -// CHECK: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP10]], i32 5 -// CHECK: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP11]], i32 6 -// CHECK: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP12]], i32 7 -// CHECK: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP13]], i32 8 -// CHECK: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP14]], i32 9 -// CHECK: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP15]], i32 10 -// CHECK: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP16]], i32 11 -// CHECK: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP17]], i32 12 -// CHECK: [[TMP18:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP18]], i32 13 -// CHECK: [[TMP19:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP19]], i32 14 -// CHECK: [[TMP20:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP20]], i32 15 -// CHECK: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = load <16 x i32>, <16 x i32>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP22:%.*]] = bitcast <16 x i32> [[TMP21]] to <8 x i64> -// CHECK: [[TMP23:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP24:%.*]] = select <16 x i1> [[TMP23]], <16 x i32> [[TMP4]], <16 x i32> [[TMP21]] -// CHECK: [[TMP25:%.*]] = bitcast <16 x i32> [[TMP24]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP25]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP27:%.*]] = bitcast <8 x i64> [[TMP26]] to <16 x i32> -// CHECK: [[TMP28:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP29:%.*]] = bitcast <8 x i64> [[TMP28]] to <16 x i32> -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i32> [[TMP27]], <16 x i32> [[TMP29]], <16 x i32> -// CHECK: [[TMP30:%.*]] = bitcast <16 x i32> [[SHUFFLE_I]] to <8 x i64> -// CHECK: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = bitcast <8 x i64> [[TMP31]] to <16 x i32> -// CHECK: [[TMP33:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = bitcast <8 x i64> [[TMP33]] to <16 x i32> -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x i32> [[TMP32]], <16 x i32> [[TMP34]], <16 x i32> -// CHECK: [[TMP35:%.*]] = bitcast <16 x i32> [[SHUFFLE1_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP30]], <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <8 x i64> [[TMP35]], <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP37:%.*]] = bitcast <8 x i64> [[TMP36]] to <16 x i32> -// CHECK: [[TMP38:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP39:%.*]] = bitcast <8 x i64> [[TMP38]] to <16 x i32> -// CHECK: [[TMP42:%.*]] = icmp ult <16 x i32> [[TMP37]], [[TMP39]] -// CHECK: [[TMP43:%.*]] = select <16 x i1> [[TMP42]], <16 x i32> [[TMP37]], <16 x i32> [[TMP39]] -// CHECK: [[TMP44:%.*]] = bitcast <16 x i32> [[TMP43]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP44]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP46:%.*]] = bitcast <8 x i64> [[TMP45]] to <16 x i32> -// CHECK: [[TMP47:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = bitcast <8 x i64> [[TMP47]] to <16 x i32> -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x i32> [[TMP46]], <16 x i32> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = bitcast <16 x i32> [[SHUFFLE3_I]] to <8 x i64> -// CHECK: [[TMP50:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP51:%.*]] = bitcast <8 x i64> [[TMP50]] to <16 x i32> -// CHECK: [[TMP52:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP53:%.*]] = bitcast <8 x i64> [[TMP52]] to <16 x i32> -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x i32> [[TMP51]], <16 x i32> [[TMP53]], <16 x i32> -// CHECK: [[TMP54:%.*]] = bitcast <16 x i32> [[SHUFFLE4_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP49]], <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <8 x i64> [[TMP54]], <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP56:%.*]] = bitcast <8 x i64> [[TMP55]] to <16 x i32> -// CHECK: [[TMP57:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP58:%.*]] = bitcast <8 x i64> [[TMP57]] to <16 x i32> -// CHECK: [[TMP61:%.*]] = icmp ult <16 x i32> [[TMP56]], [[TMP58]] -// CHECK: [[TMP62:%.*]] = select <16 x i1> [[TMP61]], <16 x i32> [[TMP56]], <16 x i32> [[TMP58]] -// CHECK: [[TMP63:%.*]] = bitcast <16 x i32> [[TMP62]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP63]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP64:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP65:%.*]] = bitcast <8 x i64> [[TMP64]] to <16 x i32> -// CHECK: [[TMP66:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP67:%.*]] = bitcast <8 x i64> [[TMP66]] to <16 x i32> -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x i32> [[TMP65]], <16 x i32> [[TMP67]], <16 x i32> -// CHECK: [[TMP68:%.*]] = bitcast <16 x i32> [[SHUFFLE6_I]] to <8 x i64> -// CHECK: [[TMP69:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP70:%.*]] = bitcast <8 x i64> [[TMP69]] to <16 x i32> -// CHECK: [[TMP71:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP72:%.*]] = bitcast <8 x i64> [[TMP71]] to <16 x i32> -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x i32> [[TMP70]], <16 x i32> [[TMP72]], <16 x i32> -// CHECK: [[TMP73:%.*]] = bitcast <16 x i32> [[SHUFFLE7_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP68]], <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <8 x i64> [[TMP73]], <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP74:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP75:%.*]] = bitcast <8 x i64> [[TMP74]] to <16 x i32> -// CHECK: [[TMP76:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP77:%.*]] = bitcast <8 x i64> [[TMP76]] to <16 x i32> -// CHECK: [[TMP80:%.*]] = icmp ult <16 x i32> [[TMP75]], [[TMP77]] -// CHECK: [[TMP81:%.*]] = select <16 x i1> [[TMP80]], <16 x i32> [[TMP75]], <16 x i32> [[TMP77]] -// CHECK: [[TMP82:%.*]] = bitcast <16 x i32> [[TMP81]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP82]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP83:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP84:%.*]] = bitcast <8 x i64> [[TMP83]] to <16 x i32> -// CHECK: [[TMP85:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP86:%.*]] = bitcast <8 x i64> [[TMP85]] to <16 x i32> -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x i32> [[TMP84]], <16 x i32> [[TMP86]], <16 x i32> -// CHECK: [[TMP87:%.*]] = bitcast <16 x i32> [[SHUFFLE9_I]] to <8 x i64> -// CHECK: [[TMP88:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP89:%.*]] = bitcast <8 x i64> [[TMP88]] to <16 x i32> -// CHECK: [[TMP90:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP91:%.*]] = bitcast <8 x i64> [[TMP90]] to <16 x i32> -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x i32> [[TMP89]], <16 x i32> [[TMP91]], <16 x i32> -// CHECK: [[TMP92:%.*]] = bitcast <16 x i32> [[SHUFFLE10_I]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP87]], <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <8 x i64> [[TMP92]], <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP93:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP94:%.*]] = bitcast <8 x i64> [[TMP93]] to <16 x i32> -// CHECK: [[TMP95:%.*]] = load <8 x i64>, <8 x i64>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP96:%.*]] = bitcast <8 x i64> [[TMP95]] to <16 x i32> -// CHECK: [[TMP99:%.*]] = icmp ult <16 x i32> [[TMP94]], [[TMP96]] -// CHECK: [[TMP100:%.*]] = select <16 x i1> [[TMP99]], <16 x i32> [[TMP94]], <16 x i32> [[TMP96]] -// CHECK: [[TMP101:%.*]] = bitcast <16 x i32> [[TMP100]] to <8 x i64> -// CHECK: store <8 x i64> [[TMP101]], <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP102:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <8 x i64> [[TMP102]], i32 0 -// CHECK: [[CONV_I:%.*]] = trunc i64 [[VECEXT_I]] to i32 -// CHECK: ret i32 [[CONV_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__V1_ADDR_I14_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I15_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I12_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I13_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V1_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__V2_ADDR_I_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__S_ADDR_I_I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x i32>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <4 x i64>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <2 x i64>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <8 x i64>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <8 x i64> [[__W:%.*]], <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP1]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store i32 -1, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x i32> undef, i32 [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x i32> [[VECINIT_I_I]], i32 [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x i32> [[VECINIT1_I_I]], i32 [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x i32> [[VECINIT2_I_I]], i32 [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x i32> [[VECINIT3_I_I]], i32 [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x i32> [[VECINIT4_I_I]], i32 [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x i32> [[VECINIT5_I_I]], i32 [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x i32> [[VECINIT6_I_I]], i32 [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x i32> [[VECINIT7_I_I]], i32 [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x i32> [[VECINIT8_I_I]], i32 [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x i32> [[VECINIT9_I_I]], i32 [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x i32> [[VECINIT10_I_I]], i32 [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x i32> [[VECINIT11_I_I]], i32 [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x i32> [[VECINIT12_I_I]], i32 [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x i32> [[VECINIT13_I_I]], i32 [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[__S_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x i32> [[VECINIT14_I_I]], i32 [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x i32> [[VECINIT15_I_I]], <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x i32>, <16 x i32>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = bitcast <16 x i32> [[TMP18]] to <8 x i64> +// CHECK-NEXT: [[TMP20:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP21:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <8 x i64> [[TMP19]], <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP20]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <8 x i64> [[TMP21]], <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP23:%.*]] = load <8 x i64>, <8 x i64>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast <8 x i64> [[TMP23]] to <16 x i32> +// CHECK-NEXT: [[TMP25:%.*]] = load <8 x i64>, <8 x i64>* [[__W_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = bitcast <8 x i64> [[TMP25]] to <16 x i32> +// CHECK-NEXT: [[TMP27:%.*]] = bitcast i16 [[TMP22]] to <16 x i1> +// CHECK-NEXT: [[TMP28:%.*]] = select <16 x i1> [[TMP27]], <16 x i32> [[TMP24]], <16 x i32> [[TMP26]] +// CHECK-NEXT: [[TMP29:%.*]] = bitcast <16 x i32> [[TMP28]] to <8 x i64> +// CHECK-NEXT: store <8 x i64> [[TMP29]], <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x i64> [[TMP30]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT_I]], <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP31:%.*]] = load <8 x i64>, <8 x i64>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x i64> [[TMP31]], <8 x i64> undef, <4 x i32> +// CHECK-NEXT: store <4 x i64> [[EXTRACT4_I]], <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <4 x i64>, <4 x i64>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <4 x i64>, <4 x i64>* [[__T2_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP32]], <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: store <4 x i64> [[TMP33]], <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <4 x i64>, <4 x i64>* [[__A2_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = bitcast <4 x i64> [[TMP34]] to <8 x i32> +// CHECK-NEXT: [[TMP36:%.*]] = load <4 x i64>, <4 x i64>* [[__B_ADDR_I_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = bitcast <4 x i64> [[TMP36]] to <8 x i32> +// CHECK-NEXT: [[TMP38:%.*]] = icmp ult <8 x i32> [[TMP35]], [[TMP37]] +// CHECK-NEXT: [[TMP39:%.*]] = select <8 x i1> [[TMP38]], <8 x i32> [[TMP35]], <8 x i32> [[TMP37]] +// CHECK-NEXT: [[TMP40:%.*]] = bitcast <8 x i32> [[TMP39]] to <4 x i64> +// CHECK-NEXT: store <4 x i64> [[TMP40]], <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP41:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <4 x i64> [[TMP41]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT6_I]], <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x i64>, <4 x i64>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <4 x i64> [[TMP42]], <4 x i64> undef, <2 x i32> +// CHECK-NEXT: store <2 x i64> [[EXTRACT7_I]], <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = load <2 x i64>, <2 x i64>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <2 x i64>, <2 x i64>* [[__T5_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP43]], <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP44]], <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = bitcast <2 x i64> [[TMP45]] to <4 x i32> +// CHECK-NEXT: [[TMP47:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = bitcast <2 x i64> [[TMP47]] to <4 x i32> +// CHECK-NEXT: [[TMP49:%.*]] = icmp ult <4 x i32> [[TMP46]], [[TMP48]] +// CHECK-NEXT: [[TMP50:%.*]] = select <4 x i1> [[TMP49]], <4 x i32> [[TMP46]], <4 x i32> [[TMP48]] +// CHECK-NEXT: [[TMP51:%.*]] = bitcast <4 x i32> [[TMP50]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP51]], <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = bitcast <2 x i64> [[TMP52]] to <4 x i32> +// CHECK-NEXT: [[TMP54:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = bitcast <2 x i64> [[TMP54]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> [[TMP53]], <4 x i32> [[TMP55]], <4 x i32> +// CHECK-NEXT: [[TMP56:%.*]] = bitcast <4 x i32> [[SHUFFLE_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP56]], <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = load <2 x i64>, <2 x i64>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <2 x i64>, <2 x i64>* [[__T7_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP57]], <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP58]], <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP59:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP60:%.*]] = bitcast <2 x i64> [[TMP59]] to <4 x i32> +// CHECK-NEXT: [[TMP61:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP62:%.*]] = bitcast <2 x i64> [[TMP61]] to <4 x i32> +// CHECK-NEXT: [[TMP63:%.*]] = icmp ult <4 x i32> [[TMP60]], [[TMP62]] +// CHECK-NEXT: [[TMP64:%.*]] = select <4 x i1> [[TMP63]], <4 x i32> [[TMP60]], <4 x i32> [[TMP62]] +// CHECK-NEXT: [[TMP65:%.*]] = bitcast <4 x i32> [[TMP64]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP65]], <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP66:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP67:%.*]] = bitcast <2 x i64> [[TMP66]] to <4 x i32> +// CHECK-NEXT: [[TMP68:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP69:%.*]] = bitcast <2 x i64> [[TMP68]] to <4 x i32> +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x i32> [[TMP67]], <4 x i32> [[TMP69]], <4 x i32> +// CHECK-NEXT: [[TMP70:%.*]] = bitcast <4 x i32> [[SHUFFLE10_I]] to <2 x i64> +// CHECK-NEXT: store <2 x i64> [[TMP70]], <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP71:%.*]] = load <2 x i64>, <2 x i64>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP72:%.*]] = load <2 x i64>, <2 x i64>* [[__T9_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP71]], <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: store <2 x i64> [[TMP72]], <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP73:%.*]] = load <2 x i64>, <2 x i64>* [[__V1_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP74:%.*]] = bitcast <2 x i64> [[TMP73]] to <4 x i32> +// CHECK-NEXT: [[TMP75:%.*]] = load <2 x i64>, <2 x i64>* [[__V2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP76:%.*]] = bitcast <2 x i64> [[TMP75]] to <4 x i32> +// CHECK-NEXT: [[TMP77:%.*]] = icmp ult <4 x i32> [[TMP74]], [[TMP76]] +// CHECK-NEXT: [[TMP78:%.*]] = select <4 x i1> [[TMP77]], <4 x i32> [[TMP74]], <4 x i32> [[TMP76]] +// CHECK-NEXT: [[TMP79:%.*]] = bitcast <4 x i32> [[TMP78]] to <2 x i64> +// CHECK-NEXT: store <4 x i32> [[TMP78]], <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP80:%.*]] = load <4 x i32>, <4 x i32>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[TMP80]], i32 0 +// CHECK-NEXT: ret i32 [[VECEXT_I]] unsigned int test_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __W){ return _mm512_mask_reduce_min_epu32(__M, __W); } // CHECK-LABEL: define float @test_mm512_mask_reduce_min_ps(i16 zeroext %__M, <16 x float> %__W) #0 { -// CHECK: [[_COMPOUNDLITERAL_I_I18_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I19_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I20_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I15_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I16_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I17_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I12_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I13_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I14_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[_COMPOUNDLITERAL_I_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__B_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 -// CHECK: [[_COMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR_I:%.*]] = alloca i16, align 2 -// CHECK: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 -// CHECK: [[__M_ADDR:%.*]] = alloca i16, align 2 -// CHECK: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 -// CHECK: store i16 %__M, i16* [[__M_ADDR]], align 2 -// CHECK: store <16 x float> %__W, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 -// CHECK: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 -// CHECK: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 -// CHECK: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP2:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 -// CHECK: [[TMP3:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP4]], i32 0 -// CHECK: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP5]], i32 1 -// CHECK: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP6]], i32 2 -// CHECK: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP7]], i32 3 -// CHECK: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP8]], i32 4 -// CHECK: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP9]], i32 5 -// CHECK: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP10]], i32 6 -// CHECK: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP11]], i32 7 -// CHECK: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP12]], i32 8 -// CHECK: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP13]], i32 9 -// CHECK: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP14]], i32 10 -// CHECK: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP15]], i32 11 -// CHECK: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP16]], i32 12 -// CHECK: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP17]], i32 13 -// CHECK: [[TMP18:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP18]], i32 14 -// CHECK: [[TMP19:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 -// CHECK: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP19]], i32 15 -// CHECK: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I]], align 64 -// CHECK: [[TMP21:%.*]] = bitcast i16 [[TMP2]] to <16 x i1> -// CHECK: [[TMP22:%.*]] = select <16 x i1> [[TMP21]], <16 x float> [[TMP3]], <16 x float> [[TMP20]] -// CHECK: store <16 x float> [[TMP22]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP24:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP24]], <16 x i32> -// CHECK: [[TMP25:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE1_I:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> [[TMP26]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE_I]], <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE1_I]], <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: [[TMP27:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I19_I]], align 64 -// CHECK: [[TMP28:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I20_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I18_I]], align 64 -// CHECK: [[TMP30:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP27]], <16 x float> [[TMP28]], <16 x float> [[TMP29]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP30]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP31:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP32:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE3_I:%.*]] = shufflevector <16 x float> [[TMP31]], <16 x float> [[TMP32]], <16 x i32> -// CHECK: [[TMP33:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP34:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE4_I:%.*]] = shufflevector <16 x float> [[TMP33]], <16 x float> [[TMP34]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE3_I]], <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE4_I]], <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: [[TMP35:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I16_I]], align 64 -// CHECK: [[TMP36:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I17_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP37:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I15_I]], align 64 -// CHECK: [[TMP38:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP35]], <16 x float> [[TMP36]], <16 x float> [[TMP37]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP38]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP39:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP40:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE6_I:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP40]], <16 x i32> -// CHECK: [[TMP41:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP42:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE7_I:%.*]] = shufflevector <16 x float> [[TMP41]], <16 x float> [[TMP42]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE6_I]], <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE7_I]], <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: [[TMP43:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I13_I]], align 64 -// CHECK: [[TMP44:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I14_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP45:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I12_I]], align 64 -// CHECK: [[TMP46:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP43]], <16 x float> [[TMP44]], <16 x float> [[TMP45]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP46]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP47:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP48:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE9_I:%.*]] = shufflevector <16 x float> [[TMP47]], <16 x float> [[TMP48]], <16 x i32> -// CHECK: [[TMP49:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP50:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[SHUFFLE10_I:%.*]] = shufflevector <16 x float> [[TMP49]], <16 x float> [[TMP50]], <16 x i32> -// CHECK: store <16 x float> [[SHUFFLE9_I]], <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: store <16 x float> [[SHUFFLE10_I]], <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: [[TMP51:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 -// CHECK: [[TMP52:%.*]] = load <16 x float>, <16 x float>* [[__B_ADDR_I_I]], align 64 -// CHECK: store <16 x float> zeroinitializer, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP53:%.*]] = load <16 x float>, <16 x float>* [[_COMPOUNDLITERAL_I_I_I]], align 64 -// CHECK: [[TMP54:%.*]] = call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> [[TMP51]], <16 x float> [[TMP52]], <16 x float> [[TMP53]], i16 -1, i32 4) #2 -// CHECK: store <16 x float> [[TMP54]], <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[TMP55:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 -// CHECK: [[VECEXT_I:%.*]] = extractelement <16 x float> [[TMP55]], i32 0 -// CHECK: ret float [[VECEXT_I]] +// CHECK-NEXT: entry: +// CHECK-NEXT: [[__W2_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__U_ADDR_I_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__A_ADDR_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__A_ADDR_I16_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__B_ADDR_I17_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__A_ADDR_I14_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I15_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A_ADDR_I12_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I13_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__A2_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__B_ADDR_I_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__W_ADDR_I_I:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[DOTCOMPOUNDLITERAL_I_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__M_ADDR_I:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__V_ADDR_I:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: [[__T1_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T2_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T3_I:%.*]] = alloca <8 x float>, align 32 +// CHECK-NEXT: [[__T4_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T5_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T6_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T7_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T8_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T9_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__T10_I:%.*]] = alloca <4 x float>, align 16 +// CHECK-NEXT: [[__M_ADDR:%.*]] = alloca i16, align 2 +// CHECK-NEXT: [[__W_ADDR:%.*]] = alloca <16 x float>, align 64 +// CHECK-NEXT: store i16 [[__M:%.*]], i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: store <16 x float> [[__W:%.*]], <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[__M_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, <16 x float>* [[__W_ADDR]], align 64 +// CHECK-NEXT: store i16 [[TMP0]], i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP1]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store float 0x7FF0000000000000, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT_I_I:%.*]] = insertelement <16 x float> undef, float [[TMP2]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT1_I_I:%.*]] = insertelement <16 x float> [[VECINIT_I_I]], float [[TMP3]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT2_I_I:%.*]] = insertelement <16 x float> [[VECINIT1_I_I]], float [[TMP4]], i32 2 +// CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT3_I_I:%.*]] = insertelement <16 x float> [[VECINIT2_I_I]], float [[TMP5]], i32 3 +// CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT4_I_I:%.*]] = insertelement <16 x float> [[VECINIT3_I_I]], float [[TMP6]], i32 4 +// CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT5_I_I:%.*]] = insertelement <16 x float> [[VECINIT4_I_I]], float [[TMP7]], i32 5 +// CHECK-NEXT: [[TMP8:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT6_I_I:%.*]] = insertelement <16 x float> [[VECINIT5_I_I]], float [[TMP8]], i32 6 +// CHECK-NEXT: [[TMP9:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT7_I_I:%.*]] = insertelement <16 x float> [[VECINIT6_I_I]], float [[TMP9]], i32 7 +// CHECK-NEXT: [[TMP10:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT8_I_I:%.*]] = insertelement <16 x float> [[VECINIT7_I_I]], float [[TMP10]], i32 8 +// CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT9_I_I:%.*]] = insertelement <16 x float> [[VECINIT8_I_I]], float [[TMP11]], i32 9 +// CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT10_I_I:%.*]] = insertelement <16 x float> [[VECINIT9_I_I]], float [[TMP12]], i32 10 +// CHECK-NEXT: [[TMP13:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT11_I_I:%.*]] = insertelement <16 x float> [[VECINIT10_I_I]], float [[TMP13]], i32 11 +// CHECK-NEXT: [[TMP14:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT12_I_I:%.*]] = insertelement <16 x float> [[VECINIT11_I_I]], float [[TMP14]], i32 12 +// CHECK-NEXT: [[TMP15:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT13_I_I:%.*]] = insertelement <16 x float> [[VECINIT12_I_I]], float [[TMP15]], i32 13 +// CHECK-NEXT: [[TMP16:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT14_I_I:%.*]] = insertelement <16 x float> [[VECINIT13_I_I]], float [[TMP16]], i32 14 +// CHECK-NEXT: [[TMP17:%.*]] = load float, float* [[__W_ADDR_I_I]], align 4 +// CHECK-NEXT: [[VECINIT15_I_I:%.*]] = insertelement <16 x float> [[VECINIT14_I_I]], float [[TMP17]], i32 15 +// CHECK-NEXT: store <16 x float> [[VECINIT15_I_I]], <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP18:%.*]] = load <16 x float>, <16 x float>* [[DOTCOMPOUNDLITERAL_I_I]], align 64 +// CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* [[__M_ADDR_I]], align 2 +// CHECK-NEXT: [[TMP20:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: store <16 x float> [[TMP18]], <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: store i16 [[TMP19]], i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: store <16 x float> [[TMP20]], <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP21:%.*]] = load i16, i16* [[__U_ADDR_I_I]], align 2 +// CHECK-NEXT: [[TMP22:%.*]] = load <16 x float>, <16 x float>* [[__A_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP23:%.*]] = load <16 x float>, <16 x float>* [[__W2_ADDR_I_I]], align 64 +// CHECK-NEXT: [[TMP24:%.*]] = bitcast i16 [[TMP21]] to <16 x i1> +// CHECK-NEXT: [[TMP25:%.*]] = select <16 x i1> [[TMP24]], <16 x float> [[TMP22]], <16 x float> [[TMP23]] +// CHECK-NEXT: store <16 x float> [[TMP25]], <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP26:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP27:%.*]] = bitcast <16 x float> [[TMP26]] to <8 x double> +// CHECK-NEXT: [[EXTRACT_I:%.*]] = shufflevector <8 x double> [[TMP27]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP28:%.*]] = bitcast <4 x double> [[EXTRACT_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP28]], <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP29:%.*]] = load <16 x float>, <16 x float>* [[__V_ADDR_I]], align 64 +// CHECK-NEXT: [[TMP30:%.*]] = bitcast <16 x float> [[TMP29]] to <8 x double> +// CHECK-NEXT: [[EXTRACT4_I:%.*]] = shufflevector <8 x double> [[TMP30]], <8 x double> undef, <4 x i32> +// CHECK-NEXT: [[TMP31:%.*]] = bitcast <4 x double> [[EXTRACT4_I]] to <8 x float> +// CHECK-NEXT: store <8 x float> [[TMP31]], <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: [[TMP32:%.*]] = load <8 x float>, <8 x float>* [[__T1_I]], align 32 +// CHECK-NEXT: [[TMP33:%.*]] = load <8 x float>, <8 x float>* [[__T2_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP32]], <8 x float>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: store <8 x float> [[TMP33]], <8 x float>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP34:%.*]] = load <8 x float>, <8 x float>* [[__A_ADDR_I16_I]], align 32 +// CHECK-NEXT: [[TMP35:%.*]] = load <8 x float>, <8 x float>* [[__B_ADDR_I17_I]], align 32 +// CHECK-NEXT: [[TMP36:%.*]] = call <8 x float> @llvm.x86.avx.min.ps.256(<8 x float> [[TMP34]], <8 x float> [[TMP35]]) #2 +// CHECK-NEXT: store <8 x float> [[TMP36]], <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[TMP37:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT6_I:%.*]] = shufflevector <8 x float> [[TMP37]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT6_I]], <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP38:%.*]] = load <8 x float>, <8 x float>* [[__T3_I]], align 32 +// CHECK-NEXT: [[EXTRACT7_I:%.*]] = shufflevector <8 x float> [[TMP38]], <8 x float> undef, <4 x i32> +// CHECK-NEXT: store <4 x float> [[EXTRACT7_I]], <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: [[TMP39:%.*]] = load <4 x float>, <4 x float>* [[__T4_I]], align 16 +// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, <4 x float>* [[__T5_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP39]], <4 x float>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP40]], <4 x float>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP41:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I14_I]], align 16 +// CHECK-NEXT: [[TMP42:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I15_I]], align 16 +// CHECK-NEXT: [[TMP43:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP41]], <4 x float> [[TMP42]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP43]], <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP44:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP45:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> [[TMP44]], <4 x float> [[TMP45]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE_I]], <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: [[TMP46:%.*]] = load <4 x float>, <4 x float>* [[__T6_I]], align 16 +// CHECK-NEXT: [[TMP47:%.*]] = load <4 x float>, <4 x float>* [[__T7_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP46]], <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP47]], <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, <4 x float>* [[__A_ADDR_I12_I]], align 16 +// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I13_I]], align 16 +// CHECK-NEXT: [[TMP50:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP48]], <4 x float> [[TMP49]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP50]], <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[SHUFFLE10_I:%.*]] = shufflevector <4 x float> [[TMP51]], <4 x float> [[TMP52]], <4 x i32> +// CHECK-NEXT: store <4 x float> [[SHUFFLE10_I]], <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, <4 x float>* [[__T8_I]], align 16 +// CHECK-NEXT: [[TMP54:%.*]] = load <4 x float>, <4 x float>* [[__T9_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP53]], <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: store <4 x float> [[TMP54]], <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, <4 x float>* [[__A2_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP56:%.*]] = load <4 x float>, <4 x float>* [[__B_ADDR_I_I]], align 16 +// CHECK-NEXT: [[TMP57:%.*]] = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> [[TMP55]], <4 x float> [[TMP56]]) #2 +// CHECK-NEXT: store <4 x float> [[TMP57]], <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[TMP58:%.*]] = load <4 x float>, <4 x float>* [[__T10_I]], align 16 +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x float> [[TMP58]], i32 0 +// CHECK-NEXT: ret float [[VECEXT_I]] float test_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __W){ return _mm512_mask_reduce_min_ps(__M, __W); } -- GitLab From cd6d4e81a71e04a91eb93878a4668844e1d2162b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 19 Jun 2018 22:47:53 +0000 Subject: [PATCH 0186/1023] Recommit r335063: [Darwin] Add a warning for missing include path for libstdc++ The recommit ensures that the tests that failed on bots don't trigger the warning. Xcode 10 removes support for libstdc++, but the users just get a confusing include not file warning when including an STL header (when building for iOS6 which uses libstdc++ by default for example). This patch adds a new warning that lets the user know that the libstdc++ include path was not found to ensure that the user is more aware of why the error occurs. rdar://40830462 Differential Revision: https://reviews.llvm.org/D48297 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335081 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 5 ++ include/clang/Lex/HeaderSearch.h | 2 + lib/Frontend/InitHeaderSearch.cpp | 83 +++++++++++-------- test/CodeGenCXX/apple-kext-guard-variable.cpp | 2 +- test/Frontend/warning-stdlibcxx-darwin.cpp | 5 ++ test/Misc/backend-stack-frame-diagnostics.cpp | 4 +- 6 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 test/Frontend/warning-stdlibcxx-darwin.cpp diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 2211a92574..6add448871 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -236,4 +236,9 @@ def err_invalid_vfs_overlay : Error< def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup; + +def warn_stdlibcxx_not_found : Warning< + "include path for stdlibc++ headers not found; pass '-std=libc++' on the " + "command line to use the libc++ standard library instead">, + InGroup>; } diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 3d13162da7..fd52000954 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -272,6 +272,8 @@ public: FileManager &getFileMgr() const { return FileMgr; } + DiagnosticsEngine &getDiags() const { return Diags; } + /// Interface for setting the file search paths. void SetSearchPaths(const std::vector &dirs, unsigned angledDirIdx, unsigned systemDirIdx, diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d2fcc9a994..85aeec461b 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Config/config.h" // C_INCLUDE_DIRS +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/HeaderSearch.h" @@ -55,11 +56,13 @@ public: /// AddPath - Add the specified path to the specified group list, prefixing /// the sysroot if used. - void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); + /// Returns true if the path exists, false if it was ignored. + bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddUnmappedPath - Add the specified path to the specified group list, /// without performing any sysroot remapping. - void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, + /// Returns true if the path exists, false if it was ignored. + bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddSystemHeaderPrefix - Add the specified prefix to the system header @@ -70,10 +73,9 @@ public: /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu /// libstdc++. - void AddGnuCPlusPlusIncludePaths(StringRef Base, - StringRef ArchDir, - StringRef Dir32, - StringRef Dir64, + /// Returns true if the \p Base path was found, false if it does not exist. + bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, + StringRef Dir32, StringRef Dir64, const llvm::Triple &triple); /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW @@ -88,7 +90,8 @@ public: // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, + void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts, + const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); /// AddDefaultSystemIncludePaths - Adds the default system include paths so @@ -112,7 +115,7 @@ static bool CanPrefixSysroot(StringRef Path) { #endif } -void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { // Add the path with sysroot prepended, if desired and this is a system header // group. @@ -120,15 +123,14 @@ void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, SmallString<256> MappedPathStorage; StringRef MappedPathStr = Path.toStringRef(MappedPathStorage); if (CanPrefixSysroot(MappedPathStr)) { - AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); - return; + return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); } } - AddUnmappedPath(Path, Group, isFramework); + return AddUnmappedPath(Path, Group, isFramework); } -void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { assert(!Path.isTriviallyEmpty() && "can't handle empty path here"); @@ -150,7 +152,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) { IncludePath.push_back( std::make_pair(Group, DirectoryLookup(DE, Type, isFramework))); - return; + return true; } // Check to see if this is an apple-style headermap (which are not allowed to @@ -162,7 +164,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, IncludePath.push_back( std::make_pair(Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap))); - return; + return true; } } } @@ -170,15 +172,16 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (Verbose) llvm::errs() << "ignoring nonexistent directory \"" << MappedPathStr << "\"\n"; + return false; } -void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, +bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, StringRef Dir32, StringRef Dir64, const llvm::Triple &triple) { // Add the base dir - AddPath(Base, CXXSystem, false); + bool IsBaseFound = AddPath(Base, CXXSystem, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); @@ -190,6 +193,7 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, // Add the backward dir AddPath(Base + "/backward", CXXSystem, false); + return IsBaseFound; } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base, @@ -354,46 +358,55 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, } } -void InitHeaderSearch:: -AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { +void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( + const LangOptions &LangOpts, const llvm::Triple &triple, + const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); // FIXME: temporary hack: hard-coded paths. if (triple.isOSDarwin()) { + bool IsBaseFound = true; switch (triple.getArch()) { default: break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "powerpc-apple-darwin10", "", "ppc64", - triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "powerpc-apple-darwin10", "", "ppc64", - triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "powerpc-apple-darwin10", "", + "ppc64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "powerpc-apple-darwin10", "", + "ppc64", triple); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "i686-apple-darwin10", "", "x86_64", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "i686-apple-darwin8", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "i686-apple-darwin10", "", + "x86_64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); break; case llvm::Triple::arm: case llvm::Triple::thumb: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v7", "", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v6", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple); break; case llvm::Triple::aarch64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm64-apple-darwin10", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple); break; } + // Warn when compiling pure C++ / Objective-C++ only. + if (!IsBaseFound && + !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) { + Headers.getDiags().Report(SourceLocation(), + diag::warn_stdlibcxx_not_found); + } return; } @@ -478,7 +491,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, } AddPath("/usr/include/c++/v1", CXXSystem, false); } else { - AddDefaultCPlusPlusIncludePaths(triple, HSOpts); + AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts); } } diff --git a/test/CodeGenCXX/apple-kext-guard-variable.cpp b/test/CodeGenCXX/apple-kext-guard-variable.cpp index 76875a0b69..ea4c1483ce 100644 --- a/test/CodeGenCXX/apple-kext-guard-variable.cpp +++ b/test/CodeGenCXX/apple-kext-guard-variable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -mkernel -Xclang -verify %s +// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -Wno-stdlibcxx-not-found -mkernel -Xclang -verify %s // rdar://problem/9143356 diff --git a/test/Frontend/warning-stdlibcxx-darwin.cpp b/test/Frontend/warning-stdlibcxx-darwin.cpp new file mode 100644 index 0000000000..3c132b6a83 --- /dev/null +++ b/test/Frontend/warning-stdlibcxx-darwin.cpp @@ -0,0 +1,5 @@ +// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s +// RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify +// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead + +// expected-no-diagnostics diff --git a/test/Misc/backend-stack-frame-diagnostics.cpp b/test/Misc/backend-stack-frame-diagnostics.cpp index bb5566f1a4..e460294e1c 100644 --- a/test/Misc/backend-stack-frame-diagnostics.cpp +++ b/test/Misc/backend-stack-frame-diagnostics.cpp @@ -1,6 +1,6 @@ // REQUIRES: x86-registered-target -// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Xclang -verify -o /dev/null -c %s -// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Xclang -verify -o /dev/null -c %s -DIS_SYSHEADER +// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Wno-stdlibcxx-not-found -Xclang -verify -o /dev/null -c %s +// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Wno-stdlibcxx-not-found -Xclang -verify -o /dev/null -c %s -DIS_SYSHEADER // Test that: // * The driver passes the option through to the backend. -- GitLab From c3261ea295e010b1720e19b4ddd05b966366fea1 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 19 Jun 2018 23:19:34 +0000 Subject: [PATCH 0187/1023] clang-cl: Emit narrowing diag for initializer lists if -fmsc-version is at least 1900 (i.e. MSVC2015). Diagnostics for narrowing conversions in initializer lists are currently DefaultIgnored in Microsoft mode. But MSVC 2015 did add warnings about narrowing conversions (C2397), so clang-cl can remove its special case code if MSCompatibilityVersion is new enough. (In MSVC, C2397 is just a warning and in clang it's default-mapped to an error, but it can be remapped, and disabled with -Wno-c++11-narrowing, so that should be fine.) Fixes PR37314. https://reviews.llvm.org/D48296 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335082 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 42 ++++++++++++++------------ test/SemaCXX/ms-initlist-narrowing.cpp | 17 +++++++++++ 2 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 test/SemaCXX/ms-initlist-narrowing.cpp diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index dc9e29858d..cd6683e44f 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -8331,6 +8331,11 @@ void InitializationSequence::dump() const { dump(llvm::errs()); } +static bool NarrowingErrs(const LangOptions &L) { + return L.CPlusPlus11 && + (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015)); +} + static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, @@ -8364,35 +8369,34 @@ static void DiagnoseNarrowingInInitList(Sema &S, // This was a floating-to-integer conversion, which is always considered a // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. - S.Diag(PostInit->getLocStart(), - (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) - ? diag::warn_init_list_type_narrowing - : diag::ext_init_list_type_narrowing) - << PostInit->getSourceRange() - << PreNarrowingType.getLocalUnqualifiedType() - << EntityType.getLocalUnqualifiedType(); + S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) + ? diag::ext_init_list_type_narrowing + : diag::warn_init_list_type_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() + << EntityType.getLocalUnqualifiedType(); break; case NK_Constant_Narrowing: // A constant value was narrowed. S.Diag(PostInit->getLocStart(), - (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) - ? diag::warn_init_list_constant_narrowing - : diag::ext_init_list_constant_narrowing) - << PostInit->getSourceRange() - << ConstantValue.getAsString(S.getASTContext(), ConstantType) - << EntityType.getLocalUnqualifiedType(); + NarrowingErrs(S.getLangOpts()) + ? diag::ext_init_list_constant_narrowing + : diag::warn_init_list_constant_narrowing) + << PostInit->getSourceRange() + << ConstantValue.getAsString(S.getASTContext(), ConstantType) + << EntityType.getLocalUnqualifiedType(); break; case NK_Variable_Narrowing: // A variable's value may have been narrowed. S.Diag(PostInit->getLocStart(), - (S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11) - ? diag::warn_init_list_variable_narrowing - : diag::ext_init_list_variable_narrowing) - << PostInit->getSourceRange() - << PreNarrowingType.getLocalUnqualifiedType() - << EntityType.getLocalUnqualifiedType(); + NarrowingErrs(S.getLangOpts()) + ? diag::ext_init_list_variable_narrowing + : diag::warn_init_list_variable_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() + << EntityType.getLocalUnqualifiedType(); break; } diff --git a/test/SemaCXX/ms-initlist-narrowing.cpp b/test/SemaCXX/ms-initlist-narrowing.cpp new file mode 100644 index 0000000000..687a206d49 --- /dev/null +++ b/test/SemaCXX/ms-initlist-narrowing.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -fms-compatibility-version=19.0 -std=c++11 + +int ai[] = { 1, 2.0 }; // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{silence}} + +template +struct Agg { + T t; +}; + +void f(int i) { + // Constant expression. + Agg f8 = {1E50}; // expected-error {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{silence}} + + // Non-constant expression. + double d = 1.0; + Agg f2 = {d}; // expected-error {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{silence}} +} -- GitLab From c4f93467258f0fbdc966ffd42aead1e8da616572 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Tue, 19 Jun 2018 23:46:52 +0000 Subject: [PATCH 0188/1023] Append new attributes to the end of an AttributeList. ... instead of prepending it at the beginning (the original behavior since implemented in r122535 2010-12-23). This builds up an AttributeList in the the order in which the attributes appear in the source. The reverse order caused nodes for attributes in the AST (e.g. LoopHint) to be in the reverse, and therefore printed in the wrong order by -ast-dump. Some TODO comments mention this. The order was explicitly reversed for enable_if attribute overload resolution and name mangling, which is not necessary anymore with this patch. The change unfortunately has some secondary effects, especially for diagnostic output. In the simplest cases, the CHECK lines or expected diagnostic were changed to the the new output. If the kind of error/warning changed, the attribute's order was changed instead. It also causes some 'previous occurrence here' hints to be textually after the main marker. This typically happens when attributes are merged, but are incompatible. Interchanging the role of the the main and note SourceLocation will also cause the case where two different declaration's attributes (in contrast to multiple attributes of the same declaration) are merged to be reversed. There is no easy fix because sometimes previous attributes are merged into a new declaration's attribute list, sometimes new attributes are added to a previous declaration's attribute list. Since 'previous occurrence here' pointing to locations after the main marker is not rare, I left the markers as-is; it is only relevant when the attributes are declared in the same declaration anyway, which often is on the same line. Differential Revision: https://reviews.llvm.org/D48100 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335084 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/AttributeList.h | 7 ++- lib/AST/ItaniumMangle.cpp | 6 +- lib/Parse/ParseDecl.cpp | 4 +- lib/Sema/SemaOverload.cpp | 47 +++++---------- lib/Serialization/ASTReaderDecl.cpp | 33 ++++------- .../annotate-comments-availability-attrs.cpp | 2 +- test/Index/complete-with-annotations.cpp | 2 +- test/Misc/ast-print-pragmas.cpp | 17 +++--- test/PCH/pragma-loop.cpp | 21 +++---- test/Parser/pragma-loop-safety.cpp | 8 +-- test/Parser/pragma-loop.cpp | 57 +++++++++---------- test/Parser/pragma-unroll.cpp | 32 +++++------ test/Sema/attr-availability-tvos.c | 6 +- test/Sema/attr-availability.c | 4 +- test/Sema/attr-coldhot.c | 4 +- test/Sema/attr-disable-tail-calls.c | 4 +- test/Sema/attr-long-call.c | 4 +- test/Sema/attr-micromips.c | 4 +- test/Sema/attr-notail.c | 4 +- test/Sema/attr-ownership.c | 6 +- test/Sema/attr-ownership.cpp | 4 +- test/Sema/attr-print.c | 6 +- test/Sema/attr-swiftcall.c | 2 +- test/Sema/attr-target-mv.c | 2 +- test/Sema/attr-visibility.c | 4 +- test/Sema/internal_linkage.c | 4 +- test/Sema/mips-interrupt-attr.c | 8 +-- test/Sema/ms_abi-sysv_abi.c | 4 +- test/Sema/nullability.c | 4 +- test/Sema/stdcall-fastcall.c | 2 +- test/SemaCXX/attr-print.cpp | 2 +- test/SemaCXX/attr-swiftcall.cpp | 2 +- test/SemaCXX/decl-microsoft-call-conv.cpp | 2 +- test/SemaCXX/ms-uuid.cpp | 8 +-- test/SemaOpenCL/address-spaces.cl | 4 +- test/SemaTemplate/attributes.cpp | 4 +- 36 files changed, 146 insertions(+), 188 deletions(-) diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index dd15b7a2f5..dcbd116aa1 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -764,8 +764,11 @@ public: void add(AttributeList *newAttr) { assert(newAttr); assert(newAttr->getNext() == nullptr); - newAttr->setNext(list); - list = newAttr; + + // FIXME: AttributeList is a singly linked list, i.e. appending to the end + // requires walking to the last element. For adding n attributes, this + // requires O(n^2) time. However, AttributeLists should be very short. + addAllAtEnd(newAttr); } void addAll(AttributeList *newList) { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 380cfc47dd..54ceffa026 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -707,10 +707,8 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; - // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use - // it here. - for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(), - E = FD->getAttrs().rend(); + for (AttrVec::const_iterator I = FD->getAttrs().begin(), + E = FD->getAttrs().end(); I != E; ++I) { EnableIfAttr *EIA = dyn_cast(*I); if (!EIA) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9e4669a872..83bfd46d89 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1649,9 +1649,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, } // Find end of type attributes Attrs and add NewTypeAttributes in the same - // order they were in originally. (Remember, in AttributeList things earlier - // in source order are later in the list, since new attributes are added to - // the front of the list.) + // order they were in originally. Attrs.addAllAtEnd(TypeAttrHead); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 45639a718c..89cb9b53a4 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6189,24 +6189,6 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, return nullptr; } -// specific_attr_iterator iterates over enable_if attributes in reverse, and -// enable_if is order-sensitive. As a result, we need to reverse things -// sometimes. Size of 4 elements is arbitrary. -static SmallVector -getOrderedEnableIfAttrs(const FunctionDecl *Function) { - SmallVector Result; - if (!Function->hasAttrs()) - return Result; - - const auto &FuncAttrs = Function->getAttrs(); - for (Attr *Attr : FuncAttrs) - if (auto *EnableIf = dyn_cast(Attr)) - Result.push_back(EnableIf); - - std::reverse(Result.begin(), Result.end()); - return Result; -} - static bool convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, ArrayRef Args, Sema::SFINAETrap &Trap, @@ -6280,9 +6262,9 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef Args, bool MissingImplicitThis) { - SmallVector EnableIfAttrs = - getOrderedEnableIfAttrs(Function); - if (EnableIfAttrs.empty()) + auto EnableIfAttrs = Function->specific_attrs(); + + if (EnableIfAttrs.begin() == EnableIfAttrs.end()) return nullptr; SFINAETrap Trap(*this); @@ -6292,7 +6274,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef Args, if (!convertArgsForAvailabilityChecks( *this, Function, /*ThisArg=*/nullptr, Args, Trap, /*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs)) - return EnableIfAttrs[0]; + return *EnableIfAttrs.begin(); for (auto *EIA : EnableIfAttrs) { APValue Result; @@ -8943,24 +8925,21 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1Attr ? Comparison::Better : Comparison::Worse; } - // FIXME: The next several lines are just - // specific_attr_iterator but going in declaration order, - // instead of reverse order which is how they're stored in the AST. - auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1); - auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2); - - // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 - // has fewer enable_if attributes than Cand2. - if (Cand1Attrs.size() < Cand2Attrs.size()) - return Comparison::Worse; + auto Cand1Attrs = Cand1->specific_attrs(); + auto Cand2Attrs = Cand2->specific_attrs(); auto Cand1I = Cand1Attrs.begin(); llvm::FoldingSetNodeID Cand1ID, Cand2ID; - for (auto &Cand2A : Cand2Attrs) { + for (auto Cand2A : Cand2Attrs) { Cand1ID.clear(); Cand2ID.clear(); - auto &Cand1A = *Cand1I++; + // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 + // has fewer enable_if attributes than Cand2. + if (Cand1I == Cand1Attrs.end()) + return Comparison::Worse; + auto Cand1A = Cand1I++; + Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true); Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true); if (Cand1ID != Cand2ID) diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index a1ce26d27c..0daf1b3bdb 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2804,36 +2804,25 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, // Note that pass_object_size attributes are represented in the function's // ExtParameterInfo, so we don't need to check them here. - SmallVector AEnableIfs; - // Since this is an equality check, we can ignore that enable_if attrs show up - // in reverse order. - for (const auto *EIA : A->specific_attrs()) - AEnableIfs.push_back(EIA); - - SmallVector BEnableIfs; - for (const auto *EIA : B->specific_attrs()) - BEnableIfs.push_back(EIA); - - // Two very common cases: either we have 0 enable_if attrs, or we have an - // unequal number of enable_if attrs. - if (AEnableIfs.empty() && BEnableIfs.empty()) - return true; - - if (AEnableIfs.size() != BEnableIfs.size()) - return false; - + // Return false if any of the enable_if expressions of A and B are different. llvm::FoldingSetNodeID Cand1ID, Cand2ID; - for (unsigned I = 0, E = AEnableIfs.size(); I != E; ++I) { + auto AEnableIfAttrs = A->specific_attrs(); + auto BEnableIfAttrs = B->specific_attrs(); + auto AEnableIf = AEnableIfAttrs.begin(); + auto BEnableIf = BEnableIfAttrs.begin(); + for (; AEnableIf != AEnableIfAttrs.end() && BEnableIf != BEnableIfAttrs.end(); + ++BEnableIf, ++AEnableIf) { Cand1ID.clear(); Cand2ID.clear(); - AEnableIfs[I]->getCond()->Profile(Cand1ID, A->getASTContext(), true); - BEnableIfs[I]->getCond()->Profile(Cand2ID, B->getASTContext(), true); + AEnableIf->getCond()->Profile(Cand1ID, A->getASTContext(), true); + BEnableIf->getCond()->Profile(Cand2ID, B->getASTContext(), true); if (Cand1ID != Cand2ID) return false; } - return true; + // Return false if the number of enable_if attributes was different. + return AEnableIf == AEnableIfAttrs.end() && BEnableIf == BEnableIfAttrs.end(); } /// Determine whether the two declarations refer to the same entity. diff --git a/test/Index/annotate-comments-availability-attrs.cpp b/test/Index/annotate-comments-availability-attrs.cpp index f31c4e16cc..2722c06fc8 100644 --- a/test/Index/annotate-comments-availability-attrs.cpp +++ b/test/Index/annotate-comments-availability-attrs.cpp @@ -13,7 +13,7 @@ void attr_availability_1() __attribute__((availability(macosx,obsoleted=10.0,introduced=8.0,deprecated=9.0, message="use availability_test in "))) __attribute__((availability(ios,unavailable, message="not for iOS"))); -// CHECK: FullCommentAsXML=[attr_availability_1c:@F@attr_availability_1#void attr_availability_1() Aaa.not for iOS8.09.010.0use availability_test in <foo.h>] +// CHECK: FullCommentAsXML=[attr_availability_1c:@F@attr_availability_1#void attr_availability_1() Aaa.8.09.010.0use availability_test in <foo.h>not for iOS] /// Aaa. void attr_availability_2() __attribute__((availability(macosx,obsoleted=10.0.1,introduced=8.0.1,deprecated=9.0.1))); diff --git a/test/Index/complete-with-annotations.cpp b/test/Index/complete-with-annotations.cpp index 7bad8f1b7c..459bd9f573 100644 --- a/test/Index/complete-with-annotations.cpp +++ b/test/Index/complete-with-annotations.cpp @@ -14,7 +14,7 @@ void X::doSomething() { } // CHECK: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) -// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("three", "two", "one") +// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("one", "two", "three") // CHECK: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) ("some annotation") // CHECK: FieldDecl:{ResultType int}{TypedText member2} (35) ("another annotation", "some annotation") // CHECK: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) diff --git a/test/Misc/ast-print-pragmas.cpp b/test/Misc/ast-print-pragmas.cpp index f1a7b2479b..a87be2a340 100644 --- a/test/Misc/ast-print-pragmas.cpp +++ b/test/Misc/ast-print-pragmas.cpp @@ -1,11 +1,8 @@ // RUN: %clang_cc1 -ast-print %s -o - | FileCheck %s // RUN: %clang_cc1 -DMS_EXT -fsyntax-only -fms-extensions %s -triple x86_64-pc-win32 -ast-print | FileCheck %s --check-prefix=MS-EXT -// FIXME: A bug in ParsedAttributes causes the order of the attributes to be -// reversed. The checks are consequently in the reverse order below. - -// CHECK: #pragma clang loop interleave_count(8){{$}} -// CHECK-NEXT: #pragma clang loop vectorize_width(4) +// CHECK: #pragma clang loop vectorize_width(4) +// CHECK-NEXT: #pragma clang loop interleave_count(8){{$}} void test(int *List, int Length) { int i = 0; @@ -17,9 +14,9 @@ void test(int *List, int Length) { i++; } -// CHECK: #pragma clang loop interleave(disable) +// CHECK: #pragma clang loop distribute(disable) // CHECK-NEXT: #pragma clang loop vectorize(enable) -// CHECK-NEXT: #pragma clang loop distribute(disable) +// CHECK-NEXT: #pragma clang loop interleave(disable) #pragma clang loop distribute(disable) #pragma clang loop vectorize(enable) @@ -30,9 +27,9 @@ void test(int *List, int Length) { i++; } -// CHECK: #pragma clang loop interleave(enable) +// CHECK: #pragma clang loop distribute(enable) // CHECK-NEXT: #pragma clang loop vectorize(disable) -// CHECK-NEXT: #pragma clang loop distribute(enable) +// CHECK-NEXT: #pragma clang loop interleave(enable) #pragma clang loop distribute(enable) #pragma clang loop vectorize(disable) @@ -52,8 +49,8 @@ void test_nontype_template_param(int *List, int Length) { } } -// CHECK: #pragma clang loop interleave_count(I) // CHECK: #pragma clang loop vectorize_width(V) +// CHECK: #pragma clang loop interleave_count(I) void test_templates(int *List, int Length) { test_nontype_template_param<2, 4>(List, Length); diff --git a/test/PCH/pragma-loop.cpp b/test/PCH/pragma-loop.cpp index 7f443ddb03..b8079ff608 100644 --- a/test/PCH/pragma-loop.cpp +++ b/test/PCH/pragma-loop.cpp @@ -1,26 +1,23 @@ // RUN: %clang_cc1 -emit-pch -o %t.a %s // RUN: %clang_cc1 -include-pch %t.a %s -ast-print -o - | FileCheck %s -// FIXME: A bug in ParsedAttributes causes the order of the attributes to be -// reversed. The checks are consequently in the reverse order below. - -// CHECK: #pragma clang loop unroll_count(16){{$}} -// CHECK: #pragma clang loop interleave_count(8) // CHECK: #pragma clang loop vectorize_width(4) -// CHECK: #pragma clang loop distribute(enable) -// CHECK: #pragma clang loop unroll(disable) -// CHECK: #pragma clang loop interleave(disable) +// CHECK: #pragma clang loop interleave_count(8) +// CHECK: #pragma clang loop unroll_count(16){{$}} // CHECK: #pragma clang loop vectorize(enable) -// CHECK: #pragma clang loop distribute(disable) -// CHECK: #pragma clang loop unroll(full) -// CHECK: #pragma clang loop interleave(enable) +// CHECK: #pragma clang loop interleave(disable) +// CHECK: #pragma clang loop unroll(disable) +// CHECK: #pragma clang loop distribute(enable) // CHECK: #pragma clang loop vectorize(disable) +// CHECK: #pragma clang loop interleave(enable) +// CHECK: #pragma clang loop unroll(full) +// CHECK: #pragma clang loop distribute(disable) // FIXME: "#pragma unroll (enable)" is invalid and is not the input source. // CHECK: #pragma unroll (enable){{$}} // CHECK: #pragma unroll (32){{$}} // CHECK: #pragma nounroll{{$}} -// CHECK: #pragma clang loop interleave_count(I) // CHECK: #pragma clang loop vectorize_width(V) +// CHECK: #pragma clang loop interleave_count(I) #ifndef HEADER #define HEADER diff --git a/test/Parser/pragma-loop-safety.cpp b/test/Parser/pragma-loop-safety.cpp index ab87dcdcb6..1393cf7474 100644 --- a/test/Parser/pragma-loop-safety.cpp +++ b/test/Parser/pragma-loop-safety.cpp @@ -25,10 +25,10 @@ void test(int *List, int Length) { List[i] = i; } -/* expected-error {{duplicate directives 'vectorize(assume_safety)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable) -#pragma clang loop vectorize(assume_safety) -/* expected-error {{duplicate directives 'interleave(assume_safety)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable) -#pragma clang loop interleave(assume_safety) +#pragma clang loop vectorize(enable) +/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(assume_safety)'}} */ #pragma clang loop vectorize(assume_safety) +#pragma clang loop interleave(enable) +/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(assume_safety)'}} */ #pragma clang loop interleave(assume_safety) while (i-9 < Length) { List[i] = i; } diff --git a/test/Parser/pragma-loop.cpp b/test/Parser/pragma-loop.cpp index f42d196ce8..3db0fc4596 100644 --- a/test/Parser/pragma-loop.cpp +++ b/test/Parser/pragma-loop.cpp @@ -231,51 +231,50 @@ const int VV = 4; // of the next three tests rather than the last, and the order of the kinds // is also reversed. -/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) -#pragma clang loop vectorize(disable) -/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) -#pragma clang loop interleave(disable) -/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) -#pragma clang loop unroll(disable) +#pragma clang loop vectorize_width(4) +/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable) +#pragma clang loop interleave_count(4) +/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable) +#pragma clang loop unroll_count(4) +/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable) while (i-8 < Length) { List[i] = i; } -/* expected-error {{duplicate directives 'vectorize(disable)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable) -#pragma clang loop vectorize(disable) -/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable) -#pragma clang loop interleave(disable) -/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(full)'}} */ #pragma clang loop unroll(full) -#pragma clang loop unroll(disable) -/* expected-error {{duplicate directives 'distribute(disable)' and 'distribute(enable)'}} */ #pragma clang loop distribute(enable) -#pragma clang loop distribute(disable) +#pragma clang loop vectorize(enable) +/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable) +#pragma clang loop interleave(enable) +/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable) +#pragma clang loop unroll(full) +/* expected-error {{duplicate directives 'unroll(full)' and 'unroll(disable)'}} */ #pragma clang loop unroll(disable) +#pragma clang loop distribute(enable) +/* expected-error {{duplicate directives 'distribute(enable)' and 'distribute(disable)'}} */ #pragma clang loop distribute(disable) while (i-9 < Length) { List[i] = i; } -/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable) -#pragma clang loop vectorize_width(4) -/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable) -#pragma clang loop interleave_count(4) -/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable) -#pragma clang loop unroll_count(4) +#pragma clang loop vectorize(disable) +/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) +#pragma clang loop interleave(disable) +/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) +#pragma clang loop unroll(disable) +/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) while (i-10 < Length) { List[i] = i; } -/* expected-error {{duplicate directives 'vectorize_width(4)' and 'vectorize_width(8)'}} */ #pragma clang loop vectorize_width(8) -#pragma clang loop vectorize_width(4) -/* expected-error {{duplicate directives 'interleave_count(4)' and 'interleave_count(8)'}} */ #pragma clang loop interleave_count(8) -#pragma clang loop interleave_count(4) -/* expected-error {{duplicate directives 'unroll_count(4)' and 'unroll_count(8)'}} */ #pragma clang loop unroll_count(8) -#pragma clang loop unroll_count(4) +#pragma clang loop vectorize_width(8) +/* expected-error {{duplicate directives 'vectorize_width(8)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) +#pragma clang loop interleave_count(8) +/* expected-error {{duplicate directives 'interleave_count(8)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) +#pragma clang loop unroll_count(8) +/* expected-error {{duplicate directives 'unroll_count(8)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) while (i-11 < Length) { List[i] = i; } - -/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(full) -#pragma clang loop unroll_count(4) +#pragma clang loop unroll(full) +/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) while (i-11 < Length) { List[i] = i; } diff --git a/test/Parser/pragma-unroll.cpp b/test/Parser/pragma-unroll.cpp index b1d7798798..fb71381287 100644 --- a/test/Parser/pragma-unroll.cpp +++ b/test/Parser/pragma-unroll.cpp @@ -55,56 +55,56 @@ void test(int *List, int Length) { #pragma nounroll /* expected-error {{expected a for, while, or do-while loop to follow '#pragma nounroll'}} */ int l = Length; -/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma unroll 4 -#pragma clang loop unroll(disable) +#pragma unroll 4 +/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(disable) while (i-10 < Length) { List[i] = i; } -/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma unroll(4) -#pragma clang loop unroll(full) +#pragma unroll(4) +/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(full) while (i-11 < Length) { List[i] = i; } -/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma unroll(4) -#pragma clang loop unroll(enable) +#pragma unroll(4) +/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(enable) while (i-11 < Length) { List[i] = i; } -/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll(4) -#pragma unroll +#pragma unroll(4) +/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll while (i-11 < Length) { List[i] = i; } -/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) -#pragma nounroll +#pragma clang loop unroll_count(4) +/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma nounroll while (i-12 < Length) { List[i] = i; } -/* expected-error {{duplicate directives '#pragma nounroll' and '#pragma nounroll'}} */ #pragma nounroll #pragma nounroll +/* expected-error {{duplicate directives '#pragma nounroll' and '#pragma nounroll'}} */ #pragma nounroll while (i-13 < Length) { List[i] = i; } -/* expected-error {{duplicate directives '#pragma unroll' and '#pragma unroll'}} */ #pragma unroll #pragma unroll +/* expected-error {{duplicate directives '#pragma unroll' and '#pragma unroll'}} */ #pragma unroll while (i-14 < Length) { List[i] = i; } -/* expected-error {{duplicate directives 'unroll(full)' and '#pragma unroll'}} */ #pragma unroll -#pragma clang loop unroll(full) +#pragma unroll +/* expected-error {{duplicate directives '#pragma unroll' and 'unroll(full)'}} */ #pragma clang loop unroll(full) while (i-15 < Length) { List[i] = i; } -/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll 4 -#pragma unroll(4) +#pragma unroll 4 +/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll(4) while (i-16 < Length) { List[i] = i; } diff --git a/test/Sema/attr-availability-tvos.c b/test/Sema/attr-availability-tvos.c index 68337e49ce..4f8c4588ec 100644 --- a/test/Sema/attr-availability-tvos.c +++ b/test/Sema/attr-availability-tvos.c @@ -27,10 +27,8 @@ void test_transcribed_availability() { f9(0); } -__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-note{{previous attribute is here}} \ - // expected-note{{previous attribute is here}} -__attribute__((availability(ios,introduced=7_0))) // expected-warning{{availability does not match previous declaration}} \ - // expected-warning{{availability does not match previous declaration}} +__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-warning 2{{availability does not match previous declaration}} +__attribute__((availability(ios,introduced=7_0))) // expected-note 2{{previous attribute is here}} void f10(int); // Test tvOS specific attributes. diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c index 1b8cbd256c..4a26638252 100644 --- a/test/Sema/attr-availability.c +++ b/test/Sema/attr-availability.c @@ -64,8 +64,8 @@ enum { void f4(int) __attribute__((availability(ios,deprecated=3.0))); void f4(int) __attribute__((availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} -void f5(int) __attribute__((availability(ios,deprecated=3.0), - availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} +void f5(int) __attribute__((availability(ios,deprecated=3.0), // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} + availability(ios,introduced=4.0))); void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{previous attribute is here}} void f6(int) __attribute__((availability(ios,deprecated=4.0))); // expected-warning {{availability does not match previous declaration}} diff --git a/test/Sema/attr-coldhot.c b/test/Sema/attr-coldhot.c index 972f5a5266..a4b1582206 100644 --- a/test/Sema/attr-coldhot.c +++ b/test/Sema/attr-coldhot.c @@ -6,7 +6,7 @@ int bar() __attribute__((__cold__)); int var1 __attribute__((__cold__)); // expected-warning{{'__cold__' attribute only applies to functions}} int var2 __attribute__((__hot__)); // expected-warning{{'__hot__' attribute only applies to functions}} -int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \ +int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \ +int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} diff --git a/test/Sema/attr-disable-tail-calls.c b/test/Sema/attr-disable-tail-calls.c index e8f5bcc73e..0545e951e6 100644 --- a/test/Sema/attr-disable-tail-calls.c +++ b/test/Sema/attr-disable-tail-calls.c @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}} +void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}} __asm__(""); } -void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}} +void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}} __asm__(""); } diff --git a/test/Sema/attr-long-call.c b/test/Sema/attr-long-call.c index cd3de1bf9e..e80f8fdd52 100644 --- a/test/Sema/attr-long-call.c +++ b/test/Sema/attr-long-call.c @@ -19,8 +19,8 @@ __attribute((near)) void foo6(); __attribute((long_call, far)) void foo7(); __attribute((short_call, near)) void foo11(); -__attribute((far, near)) void foo8(); // expected-error {{'far' and 'near' attributes are not compatible}} \ +__attribute((far, near)) void foo8(); // expected-error {{'near' and 'far' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute((short_call, long_call)) void foo12(); // expected-error {{'short_call' and 'long_call' attributes are not compatible}} \ +__attribute((short_call, long_call)) void foo12(); // expected-error {{'long_call' and 'short_call' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} diff --git a/test/Sema/attr-micromips.c b/test/Sema/attr-micromips.c index fe587fa3db..27c9d3b54f 100644 --- a/test/Sema/attr-micromips.c +++ b/test/Sema/attr-micromips.c @@ -6,9 +6,9 @@ __attribute__((micromips(1))) void foo2(); // expected-error {{'micromips' at __attribute((nomicromips)) int a; // expected-error {{attribute only applies to functions}} __attribute((micromips)) int b; // expected-error {{attribute only applies to functions}} -__attribute__((micromips,mips16)) void foo5(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \ +__attribute__((micromips,mips16)) void foo5(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16,micromips)) void foo6(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \ +__attribute__((mips16,micromips)) void foo6(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} __attribute((micromips)) void foo7(); diff --git a/test/Sema/attr-notail.c b/test/Sema/attr-notail.c index 4d05fcf6f2..f65af47518 100644 --- a/test/Sema/attr-notail.c +++ b/test/Sema/attr-notail.c @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \ +int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \ +int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} int foo(int a) { diff --git a/test/Sema/attr-ownership.c b/test/Sema/attr-ownership.c index ff6c7197df..5ce758d9f4 100644 --- a/test/Sema/attr-ownership.c +++ b/test/Sema/attr-ownership.c @@ -16,11 +16,11 @@ void *f11(float i) __attribute__((ownership_returns(foo, 1))); // expected-erro void *f12(float i, int k, int f, int *j) __attribute__((ownership_returns(foo, 4))); // expected-error {{'ownership_returns' attribute only applies to integer arguments}} void f13(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_takes(foo, 2))); -void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_holds' and 'ownership_takes' attributes are not compatible}} +void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_takes' and 'ownership_holds' attributes are not compatible}} void f15(int, int) - __attribute__((ownership_returns(foo, 1))) // expected-note {{declared with index 1 here}} - __attribute__((ownership_returns(foo, 2))); // expected-error {{'ownership_returns' attribute index does not match; here it is 2}} + __attribute__((ownership_returns(foo, 1))) // expected-error {{'ownership_returns' attribute index does not match; here it is 1}} + __attribute__((ownership_returns(foo, 2))); // expected-note {{declared with index 2 here}} void f16(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_holds(foo, 1))); // OK, same index void f17(void*) __attribute__((ownership_takes(__, 1))); void f18() __attribute__((ownership_takes(foo, 1))); // expected-warning {{'ownership_takes' attribute only applies to non-K&R-style functions}} diff --git a/test/Sema/attr-ownership.cpp b/test/Sema/attr-ownership.cpp index cde195ff0a..7381285e2d 100644 --- a/test/Sema/attr-ownership.cpp +++ b/test/Sema/attr-ownership.cpp @@ -2,6 +2,6 @@ class C { void f(int, int) - __attribute__((ownership_returns(foo, 2))) // expected-note {{declared with index 2 here}} - __attribute__((ownership_returns(foo, 3))); // expected-error {{'ownership_returns' attribute index does not match; here it is 3}} + __attribute__((ownership_returns(foo, 2))) // expected-error {{'ownership_returns' attribute index does not match; here it is 2}} + __attribute__((ownership_returns(foo, 3))); // expected-note {{declared with index 3 here}} }; diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c index 16b440d5d7..645b8bc3e7 100644 --- a/test/Sema/attr-print.c +++ b/test/Sema/attr-print.c @@ -24,13 +24,13 @@ int * __ptr64 p64; // TODO: the Type Printer has no way to specify the order to print attributes // in, and so it currently always prints them in reverse order. Fix this. -// CHECK: int * __ptr32 __uptr p32_2; +// CHECK: int * __uptr __ptr32 p32_2; int * __uptr __ptr32 p32_2; -// CHECK: int * __ptr64 __sptr p64_2; +// CHECK: int * __sptr __ptr64 p64_2; int * __sptr __ptr64 p64_2; -// CHECK: int * __ptr32 __uptr p32_3; +// CHECK: int * __uptr __ptr32 p32_3; int * __uptr __ptr32 p32_3; // CHECK: int * __sptr * __ptr32 ppsp32; diff --git a/test/Sema/attr-swiftcall.c b/test/Sema/attr-swiftcall.c index 0323f059ba..77cf1b314d 100644 --- a/test/Sema/attr-swiftcall.c +++ b/test/Sema/attr-swiftcall.c @@ -9,7 +9,7 @@ int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} void unprototyped() SWIFTCALL; // expected-error {{function with no prototype cannot use the swiftcall calling convention}} -void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{swiftcall and vectorcall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} diff --git a/test/Sema/attr-target-mv.c b/test/Sema/attr-target-mv.c index 671adff5b0..e65f6486fb 100644 --- a/test/Sema/attr-target-mv.c +++ b/test/Sema/attr-target-mv.c @@ -95,7 +95,7 @@ void __attribute__((target("arch=sandybridge"))) addtl_attrs4(void); void __attribute__((used,target("arch=ivybridge"))) addtl_attrs4(void); int __attribute__((target("sse4.2"))) diff_cc(void); -// expected-error@+1 {{multiversioned function declaration has a different calling convention}} +// expected-error@+1 {{attribute 'target' multiversioning cannot be combined with other attributes}} __vectorcall int __attribute__((target("arch=sandybridge"))) diff_cc(void); int __attribute__((target("sse4.2"))) diff_ret(void); diff --git a/test/Sema/attr-visibility.c b/test/Sema/attr-visibility.c index ed52ec2743..798d6dcd78 100644 --- a/test/Sema/attr-visibility.c +++ b/test/Sema/attr-visibility.c @@ -15,8 +15,8 @@ struct test5; struct __attribute__((visibility("hidden"))) test5; // expected-note {{previous attribute is here}} struct __attribute__((visibility("default"))) test5; // expected-error {{visibility does not match previous declaration}} -void test6() __attribute__((visibility("hidden"), // expected-note {{previous attribute is here}} - visibility("default"))); // expected-error {{visibility does not match previous declaration}} +void test6() __attribute__((visibility("default"), // expected-error {{visibility does not match previous declaration}} + visibility("hidden"))); // expected-note {{previous attribute is here}} extern int test7 __attribute__((visibility("default"))); // expected-note {{previous attribute is here}} extern int test7 __attribute__((visibility("hidden"))); // expected-error {{visibility does not match previous declaration}} diff --git a/test/Sema/internal_linkage.c b/test/Sema/internal_linkage.c index 57315d826e..cc8039acd2 100644 --- a/test/Sema/internal_linkage.c +++ b/test/Sema/internal_linkage.c @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fdouble-square-bracket-attributes %s int var __attribute__((internal_linkage)); -int var2 __attribute__((internal_linkage,common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \ +int var2 __attribute__((internal_linkage,common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int var3 __attribute__((common,internal_linkage)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ +int var3 __attribute__((common,internal_linkage)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} int var4 __attribute__((common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ diff --git a/test/Sema/mips-interrupt-attr.c b/test/Sema/mips-interrupt-attr.c index 17344b6edc..7c5c9ddab5 100644 --- a/test/Sema/mips-interrupt-attr.c +++ b/test/Sema/mips-interrupt-attr.c @@ -19,11 +19,11 @@ __attribute__((interrupt(""))) void food() {} __attribute__((interrupt)) int foob() {return 0;} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have a 'void' return type}} __attribute__((interrupt())) void fooc(int a) {} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have no parameters}} -__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ +__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ +__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ +__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ +__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} diff --git a/test/Sema/ms_abi-sysv_abi.c b/test/Sema/ms_abi-sysv_abi.c index 35a5fad9ce..e97914d7dd 100644 --- a/test/Sema/ms_abi-sysv_abi.c +++ b/test/Sema/ms_abi-sysv_abi.c @@ -6,9 +6,9 @@ int __attribute__((sysv_abi)) var2; // expected-warning{{'sysv_abi' only applies // Different CC qualifiers are not compatible // FIXME: Should say 'sysv_abi' instead of 'cdecl' -void __attribute__((ms_abi, sysv_abi)) foo3(void); // expected-error{{cdecl and ms_abi attributes are not compatible}} +void __attribute__((ms_abi, sysv_abi)) foo3(void); // expected-error{{ms_abi and cdecl attributes are not compatible}} void __attribute__((ms_abi)) foo4(); // expected-note{{previous declaration is here}} void __attribute__((sysv_abi)) foo4(void); // expected-error{{function declared 'cdecl' here was previously declared 'ms_abi'}} -void bar(int i, int j) __attribute__((ms_abi, cdecl)); // expected-error{{cdecl and ms_abi attributes are not compatible}} +void bar(int i, int j) __attribute__((ms_abi, cdecl)); // expected-error{{ms_abi and cdecl attributes are not compatible}} void bar2(int i, int j) __attribute__((sysv_abi, cdecl)); // no-error diff --git a/test/Sema/nullability.c b/test/Sema/nullability.c index a0247e5af8..cc251257e4 100644 --- a/test/Sema/nullability.c +++ b/test/Sema/nullability.c @@ -20,8 +20,8 @@ typedef int * _Null_unspecified null_unspecified_int_ptr; typedef int * _Nonnull _Nonnull redundant_1; // expected-warning{{duplicate nullability specifier '_Nonnull'}} // Conflicting nullability type specifiers. -typedef int * _Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Nullable'}} -typedef int * _Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Null_unspecified' conflicts with existing specifier '_Nonnull'}} +typedef int *_Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}} +typedef int *_Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Null_unspecified'}} // Redundant nullability specifiers via a typedef are okay. typedef nonnull_int_ptr _Nonnull redundant_okay_1; diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c index 256f5588e6..e011b45518 100644 --- a/test/Sema/stdcall-fastcall.c +++ b/test/Sema/stdcall-fastcall.c @@ -5,7 +5,7 @@ int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies t int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}} // Different CC qualifiers are not compatible -void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{fastcall and stdcall attributes are not compatible}} +void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}} void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}} expected-warning{{function with no prototype cannot use the stdcall calling convention}} void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}} diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index 960050bc71..b741574b12 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -14,7 +14,7 @@ void foo() __attribute__((const)); void bar() __attribute__((__const)); // FIXME: Print this with correct format and order. -// CHECK: void foo1() __attribute__((pure)) __attribute__((noinline)); +// CHECK: void foo1() __attribute__((noinline)) __attribute__((pure)); void foo1() __attribute__((noinline, pure)); // CHECK: typedef int Small1 __attribute__((mode(byte))); diff --git a/test/SemaCXX/attr-swiftcall.cpp b/test/SemaCXX/attr-swiftcall.cpp index eb9538e310..be4d4e8f77 100644 --- a/test/SemaCXX/attr-swiftcall.cpp +++ b/test/SemaCXX/attr-swiftcall.cpp @@ -7,7 +7,7 @@ int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} -void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{swiftcall and vectorcall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index acd9b0720b..232549988e 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -161,7 +161,7 @@ void multi_attribute(int x) { __builtin_unreachable(); } // expected-error@+3 {{vectorcall and cdecl attributes are not compatible}} // expected-error@+2 {{stdcall and cdecl attributes are not compatible}} // expected-error@+1 {{fastcall and cdecl attributes are not compatible}} -void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x); +void __vectorcall __fastcall __cdecl __stdcall __cdecl __cdecl multi_cc(int x); template void __stdcall StdcallTemplate(T) {} template <> void StdcallTemplate(int) {} diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp index 624ac0541d..c177570682 100644 --- a/test/SemaCXX/ms-uuid.cpp +++ b/test/SemaCXX/ms-uuid.cpp @@ -62,14 +62,14 @@ class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2; [uuid("220000A0-0000-0000-C000-000000000049")] class C4 {}; // Both cl and clang-cl error out on this: -// expected-note@+1 {{previous uuid specified here}} -class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) // expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) +// expected-note@+1 {{previous uuid specified here}} __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5; -// expected-note@+1 {{previous uuid specified here}} -[uuid("000000A0-0000-0000-C000-000000000049"), // expected-error@+1 {{uuid does not match previous declaration}} +[uuid("000000A0-0000-0000-C000-000000000049"), +// expected-note@+1 {{previous uuid specified here}} uuid("110000A0-0000-0000-C000-000000000049")] class C6; // cl doesn't diagnose having one uuid each as []-style attributes and as diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl index 97dd1f4f90..2fec3e8647 100644 --- a/test/SemaOpenCL/address-spaces.cl +++ b/test/SemaOpenCL/address-spaces.cl @@ -58,8 +58,8 @@ __generic int func_return_generic(void); //expected-error {{return value cann void func_multiple_addr(void) { typedef __private int private_int_t; - __local __private int var1; // expected-error {{multiple address spaces specified for type}} - __local __private int *var2; // expected-error {{multiple address spaces specified for type}} + __private __local int var1; // expected-error {{multiple address spaces specified for type}} + __private __local int *var2; // expected-error {{multiple address spaces specified for type}} __local private_int_t var3; // expected-error {{multiple address spaces specified for type}} __local private_int_t *var4; // expected-error {{multiple address spaces specified for type}} } diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp index 7634b937c9..7a04c4705b 100644 --- a/test/SemaTemplate/attributes.cpp +++ b/test/SemaTemplate/attributes.cpp @@ -55,11 +55,11 @@ namespace PR9049 { } // CHECK: FunctionTemplateDecl {{.*}} HasAnnotations -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: FunctionDecl {{.*}} HasAnnotations // CHECK: TemplateArgument type 'int' -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations(); void UseAnnotations() { HasAnnotations(); } -- GitLab From 1e87a8a27becbed9809b99da7632ecd2a06bf22b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 20 Jun 2018 00:31:39 +0000 Subject: [PATCH 0189/1023] [X86] Undefine _mm512_mask_reduce_operator macro in avx512fintrin.h before redefining it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335086 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index ead3f8ef58..12b5f60405 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -9689,6 +9689,7 @@ _mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V); _mm512_mask_reduce_operator(min_epu32); } +#undef _mm512_mask_reduce_operator #define _mm512_mask_reduce_operator(op) \ __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \ -- GitLab From 2714dd09cfcf43203ed1165b36270dff363a3bab Mon Sep 17 00:00:00 2001 From: Douglas Yung Date: Wed, 20 Jun 2018 01:05:09 +0000 Subject: [PATCH 0190/1023] Add a test to verify the x86 intrinsic headers compile cleanly with no warnings or errors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335088 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Headers/x86-intrinsics-headers-clean.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/Headers/x86-intrinsics-headers-clean.cpp diff --git a/test/Headers/x86-intrinsics-headers-clean.cpp b/test/Headers/x86-intrinsics-headers-clean.cpp new file mode 100644 index 0000000000..c75f0910f5 --- /dev/null +++ b/test/Headers/x86-intrinsics-headers-clean.cpp @@ -0,0 +1,14 @@ +// Make sure the intrinsic headers compile cleanly with no warnings or errors. + +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wsystem-headers \ +// RUN: -fsyntax-only -x c++ -Wno-ignored-attributes -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wsystem-headers \ +// RUN: -fsyntax-only -x c++ -Wno-ignored-attributes -target-feature +f16c \ +// RUN: -verify %s + +// expected-no-diagnostics + +// Dont' include mm_malloc.h. It's system specific. +#define __MM_MALLOC_H + +#include -- GitLab From c6a83709c53cea66957b44d61f8773c187dd70fb Mon Sep 17 00:00:00 2001 From: Alexey Bader Date: Wed, 20 Jun 2018 08:31:24 +0000 Subject: [PATCH 0191/1023] [Sema] Allow creating types with multiple of the same addrspace. Summary: The comment with the OpenCL clause about this clearly says: "No type shall be qualified by qualifiers for two or more different address spaces." This must mean that two or more qualifiers for the _same_ address space is allowed. However, it is likely unintended by the programmer, so emit a warning. For dependent address space types, reject them like before since we cannot know what the address space will be. Patch by Bevin Hansson (ebevhan). Reviewers: Anastasia Reviewed By: Anastasia Subscribers: bader, cfe-commits Differential Revision: https://reviews.llvm.org/D47630 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335103 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 ++ lib/Sema/SemaType.cpp | 46 ++++++++++++++-------- test/Sema/address_spaces.c | 1 + test/SemaOpenCL/address-spaces.cl | 2 + 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9c1b549bdb..878443df4a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2576,6 +2576,9 @@ def err_attribute_address_space_too_high : Error< "address space is larger than the maximum supported (%0)">; def err_attribute_address_multiple_qualifiers : Error< "multiple address spaces specified for type">; +def warn_attribute_address_multiple_identical_qualifiers : Warning< + "multiple identical address spaces specified for type">, + InGroup; def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9ee947b80a..978c1cc015 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -5758,14 +5758,6 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { - // If this type is already address space qualified, reject it. - // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified - // by qualifiers for two or more different address spaces." - if (T.getAddressSpace() != LangAS::Default) { - Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); - return QualType(); - } - llvm::APSInt addrSpace(32); if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) { Diag(AttrLoc, diag::err_attribute_argument_type) @@ -5796,6 +5788,20 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, LangAS ASIdx = getLangASFromTargetAS(static_cast(addrSpace.getZExtValue())); + // If this type is already address space qualified with a different + // address space, reject it. + // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified + // by qualifiers for two or more different address spaces." + if (T.getAddressSpace() != LangAS::Default) { + if (T.getAddressSpace() != ASIdx) { + Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); + return QualType(); + } else + // Emit a warning if they are identical; it's likely unintended. + Diag(AttrLoc, + diag::warn_attribute_address_multiple_identical_qualifiers); + } + return Context.getAddrSpaceQualType(T, ASIdx); } @@ -5817,15 +5823,6 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, /// space for the type. static void HandleAddressSpaceTypeAttribute(QualType &Type, const AttributeList &Attr, Sema &S){ - // If this type is already address space qualified, reject it. - // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by - // qualifiers for two or more different address spaces." - if (Type.getAddressSpace() != LangAS::Default) { - S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); - Attr.setInvalid(); - return; - } - // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be // qualified by an address-space qualifier." if (Type->isFunctionType()) { @@ -5888,6 +5885,21 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, llvm_unreachable("Invalid address space"); } + // If this type is already address space qualified with a different + // address space, reject it. + // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by + // qualifiers for two or more different address spaces." + if (Type.getAddressSpace() != LangAS::Default) { + if (Type.getAddressSpace() != ASIdx) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); + Attr.setInvalid(); + return; + } else + // Emit a warning if they are identical; it's likely unintended. + S.Diag(Attr.getLoc(), + diag::warn_attribute_address_multiple_identical_qualifiers); + } + Type = S.Context.getAddrSpaceQualType(Type, ASIdx); } } diff --git a/test/Sema/address_spaces.c b/test/Sema/address_spaces.c index 018a8521bf..87707d7deb 100644 --- a/test/Sema/address_spaces.c +++ b/test/Sema/address_spaces.c @@ -14,6 +14,7 @@ void foo(_AS3 float *a, int _AS1 _AS2 *Y; // expected-error {{multiple address spaces specified for type}} int *_AS1 _AS2 *Z; // expected-error {{multiple address spaces specified for type}} + int *_AS1 _AS1 *M; // expected-warning {{multiple identical address spaces specified for type}} _AS1 int local; // expected-error {{automatic variable qualified with an address space}} _AS1 int array[5]; // expected-error {{automatic variable qualified with an address space}} diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl index 2fec3e8647..c5c58a6a30 100644 --- a/test/SemaOpenCL/address-spaces.cl +++ b/test/SemaOpenCL/address-spaces.cl @@ -62,4 +62,6 @@ void func_multiple_addr(void) { __private __local int *var2; // expected-error {{multiple address spaces specified for type}} __local private_int_t var3; // expected-error {{multiple address spaces specified for type}} __local private_int_t *var4; // expected-error {{multiple address spaces specified for type}} + __private private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}} + __private private_int_t *var6;// expected-warning {{multiple identical address spaces specified for type}} } -- GitLab From a746d868814a258db4c4ee3bdfd82ddfdcd50edf Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Wed, 20 Jun 2018 09:49:40 +0000 Subject: [PATCH 0192/1023] [SPIR] Prevent SPIR targets from using half conversion intrinsics The SPIR target currently allows for half precision floating point types to be emitted using the LLVM intrinsic functions which convert half types to floats and doubles. However, this is illegal in SPIR as the only intrinsic allowed by SPIR is memcpy, as per section 3 of the SPIR specification. Currently this is leading to an assert being hit in the Clang CodeGen when attempting to emit a constant or literal _Float16 type in a comparison operation on a SPIR or SPIR64 target. This assert stems from the CodeGen attempting to emit a constant half value as an integer because the backend has specified that it is using these half conversion intrinsics (which represents half as i16). This patch prevents SPIR targets from using these intrinsics by overloading the responsible target info method, marks SPIR targets as having a legal half type and provides additional regression testing for the _Float16 type on SPIR targets. Patch by: Stephen McGroarty Differential Revision: https://reviews.llvm.org/D48188 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335111 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/SPIR.h | 5 ++ test/CodeGen/spir-half-type.cpp | 146 ++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 test/CodeGen/spir-half-type.cpp diff --git a/lib/Basic/Targets/SPIR.h b/lib/Basic/Targets/SPIR.h index c384d4260c..9815292fc2 100644 --- a/lib/Basic/Targets/SPIR.h +++ b/lib/Basic/Targets/SPIR.h @@ -47,6 +47,7 @@ public: LongWidth = LongAlign = 64; AddrSpaceMap = &SPIRAddrSpaceMap; UseAddrSpaceMapMangling = true; + HasLegalHalfType = true; // Define available target features // These must be defined in sorted order! NoAsmVariants = true; @@ -59,6 +60,10 @@ public: return Feature == "spir"; } + // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is + // memcpy as per section 3 of the SPIR spec. + bool useFP16ConversionIntrinsics() const override { return false; } + ArrayRef getTargetBuiltins() const override { return None; } const char *getClobbers() const override { return ""; } diff --git a/test/CodeGen/spir-half-type.cpp b/test/CodeGen/spir-half-type.cpp new file mode 100644 index 0000000000..b60931fea6 --- /dev/null +++ b/test/CodeGen/spir-half-type.cpp @@ -0,0 +1,146 @@ +// RUN: %clang_cc1 -O0 -triple spir -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -O0 -triple spir64 -emit-llvm %s -o - | FileCheck %s + +// This file tests that using the _Float16 type with the spir target will not +// use the llvm intrinsics but instead will use the half arithmetic +// instructions directly. + +// Previously attempting to use a constant _Float16 with a comparison +// instruction when the target is spir or spir64 lead to an assert being hit. +bool fcmp_const() { + _Float16 a = 0.0f16; + const _Float16 b = 1.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp olt half [[REG1]], 0xH3C00 + + // CHECK: [[REG2:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp olt half [[REG2]], 0xH4000 + + // CHECK: [[REG3:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp ogt half [[REG3]], 0xH3C00 + + // CHECK: [[REG4:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp ogt half [[REG4]], 0xH4200 + + // CHECK: [[REG5:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp oeq half [[REG5]], 0xH3C00 + + // CHECK: [[REG7:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp oeq half [[REG7]], 0xH4400 + + // CHECK: [[REG8:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp une half [[REG8]], 0xH3C00 + + // CHECK: [[REG9:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp une half [[REG9]], 0xH4500 + + // CHECK: [[REG10:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp ole half [[REG10]], 0xH3C00 + + // CHECK: [[REG11:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp ole half [[REG11]], 0xH4600 + + // CHECK: [[REG12:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp oge half [[REG12]], 0xH3C00 + + // CHECK: [[REG13:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: fcmp oge half [[REG13]], 0xH4700 + return a < b || a < 2.0f16 || a > b || a > 3.0f16 || a == b || a == 4.0f16 || + a != b || a != 5.0f16 || a <= b || a <= 6.0f16 || a >= b || + a >= 7.0f16; +} + +bool fcmp() { + _Float16 a = 0.0f16; + _Float16 b = 1.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG2:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp olt half [[REG1]], [[REG2]] + + // CHECK: [[REG3:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG4:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp ogt half [[REG3]], [[REG4]] + + // CHECK: [[REG5:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG6:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp oeq half [[REG5]], [[REG6]] + + // CHECK: [[REG7:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp une half [[REG7]], [[REG8]] + + // CHECK: [[REG7:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp ole half [[REG7]], [[REG8]] + + // CHECK: [[REG7:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2 + // CHECK-NEXT: fcmp oge half [[REG7]], [[REG8]] + return a < b || a > b || a == b || a != b || a <= b || a >= b; +} + +_Float16 fadd() { + _Float16 a = 1.0f16; + const _Float16 b = 2.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG2:%.*]] = fadd half [[REG1]], 0xH4000 + // CHECK-NEXT: [[REG3:%.*]] = fadd half [[REG2]], 0xH4200 + // CHECK-NEXT: ret half [[REG3]] + return a + b + 3.0f16; +} + +_Float16 fsub() { + _Float16 a = 1.0f16; + const _Float16 b = 2.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG2:%.*]] = fsub half [[REG1]], 0xH4000 + // CHECK-NEXT: [[REG3:%.*]] = fsub half [[REG2]], 0xH4200 + // CHECK-NEXT: ret half [[REG3]] + return a - b - 3.0f16; +} + +// CHECK: define spir_func half @_Z4fmulDF16_(half %arg) +_Float16 fmul(_Float16 arg) { + _Float16 a = 1.0f16; + const _Float16 b = 2.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG2:%.*]] = load half, half* %arg.addr, align 2 + // CHECK-NEXT: [[REG3:%.*]] = fmul half [[REG1]], [[REG2]] + // CHECK-NEXT: [[REG4:%.*]] = fmul half [[REG3]], 0xH4000 + // CHECK-NEXT: [[REG5:%.*]] = fmul half [[REG4]], 0xH4200 + // CHECK-NEXT: ret half [[REG5]] + return a * arg * b * 3.0f16; +} + +_Float16 fdiv() { + _Float16 a = 1.0f16; + const _Float16 b = 2.0f16; + + // CHECK-NOT: llvm.convert.to.fp16 + // CHECK-NOT: llvm.convert.from.fp16 + + // CHECK: [[REG1:%.*]] = load half, half* %a, align 2 + // CHECK-NEXT: [[REG2:%.*]] = fdiv half [[REG1]], 0xH4000 + // CHECK-NEXT: [[REG3:%.*]] = fdiv half [[REG2]], 0xH4200 + // CHECK-NEXT: ret half [[REG3]] + return a / b / 3.0f16; +} -- GitLab From 5e8547baedb21953ae64b6eb2830dcf1ff0d8768 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 20 Jun 2018 11:42:12 +0000 Subject: [PATCH 0193/1023] [analyzer] Optimize constraint generation when the range is a concrete value Summary: If a constraint is something like: ``` $0 = [1,1] ``` it'll now be created as: ``` assert($0 == 1) ``` instead of: ``` assert($0 >= 1 && $0 <= 1) ``` In general, ~3% speedup when solving per query in my machine. Biggest improvement was when verifying sqlite3, total time went down from 3000s to 2200s. I couldn't create a test for this as there is no way to dump the formula yet. D48221 adds a method to dump the formula but there is no way to do it from the command line. Also, a test that prints the formula will most likely fail in the future, as different solvers print the formula in different formats. Reviewers: NoQ, george.karpenkov, ddcc Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D48227 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335116 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/Z3ConstraintManager.cpp | 99 +++++++++---------- 1 file changed, 47 insertions(+), 52 deletions(-) diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 0454825c6c..a47b7a2e70 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -994,6 +994,11 @@ private: BinaryOperator::Opcode Op, const Z3Expr &RHS, QualType RTy, QualType *RetTy) const; + // Wrapper to generate Z3Expr from a range. If From == To, an equality will + // be created instead. + Z3Expr getZ3RangeExpr(SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, bool InRange); + //===------------------------------------------------------------------===// // Helper functions. //===------------------------------------------------------------------===// @@ -1052,35 +1057,7 @@ ProgramStateRef Z3ConstraintManager::assumeSym(ProgramStateRef State, ProgramStateRef Z3ConstraintManager::assumeSymInclusiveRange( ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { - QualType RetTy; - // The expression may be casted, so we cannot call getZ3DataExpr() directly - Z3Expr Exp = getZ3Expr(Sym, &RetTy); - - QualType FromTy; - llvm::APSInt NewFromInt; - std::tie(NewFromInt, FromTy) = fixAPSInt(From); - Z3Expr FromExp = Z3Expr::fromAPSInt(NewFromInt); - - // Construct single (in)equality - if (From == To) - return assumeZ3Expr(State, Sym, - getZ3BinExpr(Exp, RetTy, InRange ? BO_EQ : BO_NE, - FromExp, FromTy, nullptr)); - - QualType ToTy; - llvm::APSInt NewToInt; - std::tie(NewToInt, ToTy) = fixAPSInt(To); - Z3Expr ToExp = Z3Expr::fromAPSInt(NewToInt); - assert(FromTy == ToTy && "Range values have different types!"); - // Construct two (in)equalities, and a logical and/or - Z3Expr LHS = getZ3BinExpr(Exp, RetTy, InRange ? BO_GE : BO_LT, FromExp, - FromTy, nullptr); - Z3Expr RHS = - getZ3BinExpr(Exp, RetTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, nullptr); - return assumeZ3Expr( - State, Sym, - Z3Expr::fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, - RetTy->isSignedIntegerOrEnumerationType())); + return assumeZ3Expr(State, Sym, getZ3RangeExpr(Sym, From, To, InRange)); } ProgramStateRef Z3ConstraintManager::assumeSymUnsupported(ProgramStateRef State, @@ -1264,31 +1241,14 @@ void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { SymbolRef Sym = I.first; Z3Expr Constraints = Z3Expr::fromBoolean(false); - for (const auto &Range : I.second) { - const llvm::APSInt &From = Range.From(); - const llvm::APSInt &To = Range.To(); - - QualType FromTy; - llvm::APSInt NewFromInt; - std::tie(NewFromInt, FromTy) = fixAPSInt(From); - Z3Expr FromExp = Z3Expr::fromAPSInt(NewFromInt); - QualType SymTy; - Z3Expr Exp = getZ3Expr(Sym, &SymTy); - bool IsSignedTy = SymTy->isSignedIntegerOrEnumerationType(); - QualType ToTy; - llvm::APSInt NewToInt; - std::tie(NewToInt, ToTy) = fixAPSInt(To); - Z3Expr ToExp = Z3Expr::fromAPSInt(NewToInt); - assert(FromTy == ToTy && "Range values have different types!"); - - Z3Expr LHS = - getZ3BinExpr(Exp, SymTy, BO_GE, FromExp, FromTy, /*RetTy=*/nullptr); - Z3Expr RHS = - getZ3BinExpr(Exp, SymTy, BO_LE, ToExp, FromTy, /*RetTy=*/nullptr); - Z3Expr SymRange = Z3Expr::fromBinOp(LHS, BO_LAnd, RHS, IsSignedTy); + Z3Expr SymRange = + getZ3RangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); + + // FIXME: the last argument (isSigned) is not used when generating the + // or expression, as both arguments are booleans Constraints = - Z3Expr::fromBinOp(Constraints, BO_LOr, SymRange, IsSignedTy); + Z3Expr::fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); } Solver.addConstraint(Constraints); } @@ -1466,6 +1426,41 @@ Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy, LTy->isSignedIntegerOrEnumerationType()); } +Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) { + // Convert lower bound + QualType FromTy; + llvm::APSInt NewFromInt; + std::tie(NewFromInt, FromTy) = fixAPSInt(From); + Z3Expr FromExp = Z3Expr::fromAPSInt(NewFromInt); + + // Convert symbol + QualType SymTy; + Z3Expr Exp = getZ3Expr(Sym, &SymTy); + + // Construct single (in)equality + if (From == To) + return getZ3BinExpr(Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, FromTy, + /*RetTy=*/nullptr); + + QualType ToTy; + llvm::APSInt NewToInt; + std::tie(NewToInt, ToTy) = fixAPSInt(To); + Z3Expr ToExp = Z3Expr::fromAPSInt(NewToInt); + assert(FromTy == ToTy && "Range values have different types!"); + + // Construct two (in)equalities, and a logical and/or + Z3Expr LHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, + FromTy, /*RetTy=*/nullptr); + Z3Expr RHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); + + return Z3Expr::fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, + SymTy->isSignedIntegerOrEnumerationType()); +} + //===------------------------------------------------------------------===// // Helper functions. //===------------------------------------------------------------------===// -- GitLab From 2e7bf27afabf7dd4fce58a26b0eee4b60c42f337 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 20 Jun 2018 15:57:38 +0000 Subject: [PATCH 0194/1023] Simplify. No behavior change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335139 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index cd6683e44f..b3f401e63a 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6446,13 +6446,7 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, // Find the std::move call and get the argument. const CallExpr *CE = dyn_cast(InitExpr->IgnoreParens()); - if (!CE || CE->getNumArgs() != 1) - return; - - const FunctionDecl *MoveFunction = CE->getDirectCallee(); - if (!MoveFunction || !MoveFunction->isInStdNamespace() || - !MoveFunction->getIdentifier() || - !MoveFunction->getIdentifier()->isStr("move")) + if (!CE || !CE->isCallToStdMove()) return; const Expr *Arg = CE->getArg(0)->IgnoreImplicit(); -- GitLab From 84dd23f357de28ff35ffb7343d72cbfc79e49130 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Wed, 20 Jun 2018 17:19:40 +0000 Subject: [PATCH 0195/1023] [Fixed Point Arithmetic] Fixed Point Precision Bits and Fixed Point Literals This diff includes the logic for setting the precision bits for each primary fixed point type in the target info and logic for initializing a fixed point literal. Fixed point literals are declared using the suffixes ``` hr: short _Fract uhr: unsigned short _Fract r: _Fract ur: unsigned _Fract lr: long _Fract ulr: unsigned long _Fract hk: short _Accum uhk: unsigned short _Accum k: _Accum uk: unsigned _Accum ``` Errors are also thrown for illegal literal values ``` unsigned short _Accum u_short_accum = 256.0uhk; // expected-error{{the integral part of this literal is too large for this unsigned _Accum type}} ``` Differential Revision: https://reviews.llvm.org/D46915 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335148 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 7 +- include/clang/AST/ASTContext.h | 3 + include/clang/AST/Expr.h | 41 +++++ include/clang/AST/RecursiveASTVisitor.h | 1 + include/clang/AST/Type.h | 7 + include/clang/Basic/DiagnosticCommonKinds.td | 2 + include/clang/Basic/LangOptions.def | 2 + include/clang/Basic/StmtNodes.td | 1 + include/clang/Basic/TargetInfo.h | 103 ++++++++++++ include/clang/Driver/Options.td | 4 + include/clang/Lex/LiteralSupport.h | 17 +- lib/AST/ASTContext.cpp | 89 ++++++++++ lib/AST/ASTDumper.cpp | 8 + lib/AST/Expr.cpp | 31 ++++ lib/AST/ExprClassification.cpp | 1 + lib/AST/ExprConstant.cpp | 101 ++++++++++++ lib/AST/ItaniumMangle.cpp | 1 + lib/AST/StmtPrinter.cpp | 22 +++ lib/AST/StmtProfile.cpp | 6 + lib/AST/Type.cpp | 16 ++ lib/Basic/TargetInfo.cpp | 83 +++++++++- lib/Basic/Targets.cpp | 2 + lib/CodeGen/CGExprAgg.cpp | 4 +- lib/CodeGen/CGExprScalar.cpp | 3 + lib/Driver/ToolChains/Clang.cpp | 5 + lib/Frontend/CompilerInvocation.cpp | 4 + lib/Lex/LiteralSupport.cpp | 153 +++++++++++++++++- lib/Sema/SemaExceptionSpec.cpp | 1 + lib/Sema/SemaExpr.cpp | 49 +++++- lib/Sema/TreeTransform.h | 6 + lib/Serialization/ASTReaderStmt.cpp | 6 + lib/Serialization/ASTWriterStmt.cpp | 7 + lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + test/Frontend/fixed_point.c | 162 ++++++++++++++++++- test/Frontend/fixed_point_bit_widths.c | 72 ++++----- test/Frontend/fixed_point_declarations.c | 113 +++++++++++++ test/Frontend/fixed_point_errors.c | 57 +++++++ test/Frontend/fixed_point_same_fbits.c | 28 ++++ tools/libclang/CIndex.cpp | 2 + tools/libclang/CXCursor.cpp | 4 + 40 files changed, 1175 insertions(+), 50 deletions(-) create mode 100644 test/Frontend/fixed_point_declarations.c create mode 100644 test/Frontend/fixed_point_same_fbits.c diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 4afcd2b1e3..0ad90010cc 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2170,7 +2170,12 @@ enum CXCursorKind { */ CXCursor_ObjCAvailabilityCheckExpr = 148, - CXCursor_LastExpr = CXCursor_ObjCAvailabilityCheckExpr, + /** + * Fixed point literal + */ + CXCursor_FixedPointLiteral = 149, + + CXCursor_LastExpr = CXCursor_FixedPointLiteral, /* Statements */ CXCursor_FirstStmt = 200, diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a488ff0ced..ac317a7769 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1947,6 +1947,9 @@ public: return getQualifiedType(type.getUnqualifiedType(), Qs); } + unsigned char getFixedPointScale(QualType Ty) const; + unsigned char getFixedPointIBits(QualType Ty) const; + DeclarationNameInfo getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index c51ba8ddc0..d71fda7430 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1351,6 +1351,47 @@ public: } }; +class FixedPointLiteral : public Expr, public APIntStorage { + SourceLocation Loc; + unsigned Scale; + + /// \brief Construct an empty integer literal. + explicit FixedPointLiteral(EmptyShell Empty) + : Expr(FixedPointLiteralClass, Empty) {} + + public: + FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, + SourceLocation l, unsigned Scale); + + // Store the int as is without any bit shifting. + static FixedPointLiteral *CreateFromRawInt(const ASTContext &C, + const llvm::APInt &V, + QualType type, SourceLocation l, + unsigned Scale); + + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + /// \brief Retrieve the location of the literal. + SourceLocation getLocation() const { return Loc; } + + void setLocation(SourceLocation Location) { Loc = Location; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == FixedPointLiteralClass; + } + + std::string getValueAsString(unsigned Radix) const; + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + class CharacterLiteral : public Expr { public: enum CharacterKind { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 1858de8e58..3e6090d312 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2585,6 +2585,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, { // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) +DEF_TRAVERSE_STMT(FixedPointLiteral, {}) DEF_TRAVERSE_STMT(CharacterLiteral, {}) DEF_TRAVERSE_STMT(FloatingLiteral, {}) DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ff26757b43..5e1fc372a0 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -30,6 +30,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" @@ -6546,6 +6547,12 @@ QualType DecayedType::getPointeeType() const { return cast(Decayed)->getPointeeType(); } +// Get the decimal string representation of a fixed point type, represented +// as a scaled integer. +void FixedPointValueToString(SmallVectorImpl &Str, + const llvm::APSInt &Val, + unsigned Scale, unsigned Radix); + } // namespace clang #endif // LLVM_CLANG_AST_TYPE_H diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 93f262361c..61a73541d0 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -168,6 +168,8 @@ def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">, InGroup; def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">, InGroup; +def err_too_large_for_fixed_point : Error< + "this value is too large for this fixed point type">; def err_fixed_point_not_enabled : Error<"compile with " "'-ffixed-point' to enable fixed point types">; diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index f9246bd893..d7d66be32d 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -305,6 +305,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions") LANGOPT(FixedPoint, 1, 0, "fixed point types") +LANGOPT(SameFBits, 1, 0, + "unsigned and signed fixed point type having the same number of fractional bits") #undef LANGOPT #undef COMPATIBLE_LANGOPT diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 0d21845fbf..506da07203 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -57,6 +57,7 @@ def Expr : Stmt<1>; def PredefinedExpr : DStmt; def DeclRefExpr : DStmt; def IntegerLiteral : DStmt; +def FixedPointLiteral : DStmt; def FloatingLiteral : DStmt; def ImaginaryLiteral : DStmt; def StringLiteral : DStmt; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 24eb67af41..9bb4db7205 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -74,12 +74,32 @@ protected: unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; + + // Fixed point bit widths unsigned char ShortAccumWidth, ShortAccumAlign; unsigned char AccumWidth, AccumAlign; unsigned char LongAccumWidth, LongAccumAlign; unsigned char ShortFractWidth, ShortFractAlign; unsigned char FractWidth, FractAlign; unsigned char LongFractWidth, LongFractAlign; + + // If true, unsigned fixed point types have the same number of fractional bits + // as their signed counterparts. Otherwise, unsigned fixed point types have + // one more fractional bit than its corresponding signed type. This is false + // by default. + bool SameFBits; + + // Fixed point integral and fractional bit sizes + // Saturated types share the same integral/fractional bits as their + // corresponding unsaturated types. + // For simplicity, the fractional bits in a _Fract type will be one less the + // width of that _Fract type. This leaves all signed _Fract types having no + // padding and unsigned _Fract types will only have 1 bit of padding after the + // sign if SameFBits is set. + unsigned char ShortAccumScale; + unsigned char AccumScale; + unsigned char LongAccumScale; + unsigned char SuitableAlign; unsigned char DefaultAlignForAttributeAligned; unsigned char MinGlobalAlign; @@ -394,6 +414,84 @@ public: unsigned getLongFractWidth() const { return LongFractWidth; } unsigned getLongFractAlign() const { return LongFractAlign; } + /// getShortAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed short _Accum' type. + unsigned getShortAccumScale() const { return ShortAccumScale; } + unsigned getShortAccumIBits() const { + return ShortAccumWidth - ShortAccumScale - 1; + } + + /// getAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed _Accum' type. + unsigned getAccumScale() const { return AccumScale; } + unsigned getAccumIBits() const { return AccumWidth - AccumScale - 1; } + + /// getLongAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed long _Accum' type. + unsigned getLongAccumScale() const { return LongAccumScale; } + unsigned getLongAccumIBits() const { + return LongAccumWidth - LongAccumScale - 1; + } + + /// getUnsignedShortAccumScale/IBits - Return the number of + /// fractional/integral bits in a 'unsigned short _Accum' type. + unsigned getUnsignedShortAccumScale() const { + return SameFBits ? ShortAccumScale : ShortAccumScale + 1; + } + unsigned getUnsignedShortAccumIBits() const { + return SameFBits ? getShortAccumIBits() + : ShortAccumWidth - getUnsignedShortAccumScale(); + } + + /// getUnsignedAccumScale/IBits - Return the number of fractional/integral + /// bits in a 'unsigned _Accum' type. + unsigned getUnsignedAccumScale() const { + return SameFBits ? AccumScale : AccumScale + 1; + } + unsigned getUnsignedAccumIBits() const { + return SameFBits ? getAccumIBits() : AccumWidth - getUnsignedAccumScale(); + } + + /// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral + /// bits in a 'unsigned long _Accum' type. + unsigned getUnsignedLongAccumScale() const { + return SameFBits ? LongAccumScale : LongAccumScale + 1; + } + unsigned getUnsignedLongAccumIBits() const { + return SameFBits ? getLongAccumIBits() + : LongAccumWidth - getUnsignedLongAccumScale(); + } + + /// getShortFractScale - Return the number of fractional bits + /// in a 'signed short _Fract' type. + unsigned getShortFractScale() const { return ShortFractWidth - 1; } + + /// getFractScale - Return the number of fractional bits + /// in a 'signed _Fract' type. + unsigned getFractScale() const { return FractWidth - 1; } + + /// getLongFractScale - Return the number of fractional bits + /// in a 'signed long _Fract' type. + unsigned getLongFractScale() const { return LongFractWidth - 1; } + + /// getUnsignedShortFractScale - Return the number of fractional bits + /// in a 'unsigned short _Fract' type. + unsigned getUnsignedShortFractScale() const { + return SameFBits ? getShortFractScale() : getShortFractScale() + 1; + } + + /// getUnsignedFractScale - Return the number of fractional bits + /// in a 'unsigned _Fract' type. + unsigned getUnsignedFractScale() const { + return SameFBits ? getFractScale() : getFractScale() + 1; + } + + /// getUnsignedLongFractScale - Return the number of fractional bits + /// in a 'unsigned long _Fract' type. + unsigned getUnsignedLongFractScale() const { + return SameFBits ? getLongFractScale() : getLongFractScale() + 1; + } + /// Determine whether the __int128 type is supported on this target. virtual bool hasInt128Type() const { return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; @@ -1189,6 +1287,11 @@ protected: virtual ArrayRef getGCCAddlRegNames() const { return None; } + + private: + // Assert the values for the fractional and integral bits for each fixed point + // type follow the restrictions given in clause 6.2.6.3 of N1169. + void CheckFixedPointBits() const; }; } // end namespace clang diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index cd02a5ab5b..089a9b3649 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -893,6 +893,10 @@ def ffixed_point : Flag<["-"], "ffixed-point">, Group, Flags<[CC1Option]>, HelpText<"Enable fixed point types">; def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group, HelpText<"Disable fixed point types">; +def fsame_fbits : Flag<["-"], "fsame-fbits">, Group, + Flags<[CC1Option]>, + HelpText<"Force each unsigned fixed point type to have the same number of fractional bits as its corresponding signed type">; +def fno_same_fbits : Flag<["-"], "fno-same-fbits">, Group; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 4f32fa8e73..1b6bf6bcff 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -50,7 +50,7 @@ class NumericLiteralParser { unsigned radix; - bool saw_exponent, saw_period, saw_ud_suffix; + bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix; SmallString<32> UDSuffixBuf; @@ -69,11 +69,16 @@ public: bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. + bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr + bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk + + bool isFixedPointLiteral() const { return saw_fixed_point_suffix; } + bool isIntegerLiteral() const { - return !saw_period && !saw_exponent; + return !saw_period && !saw_exponent && !isFixedPointLiteral(); } bool isFloatingLiteral() const { - return saw_period || saw_exponent; + return (saw_period || saw_exponent) && !isFixedPointLiteral(); } bool hasUDSuffix() const { @@ -105,6 +110,12 @@ public: /// literal exactly, and false otherwise. llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + /// GetFixedPointValue - Convert this numeric literal value into a + /// scaled integer that represents this value. Returns true if an overflow + /// occurred when calculating the integral part of the scaled integer or + /// calculating the digit sequence of the exponent. + bool GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale); + private: void ParseNumberStartingWithZero(SourceLocation TokLoc); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index de32de5dca..96b7b56c1c 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -10162,3 +10162,92 @@ clang::LazyGenerationalUpdatePtr< clang::LazyGenerationalUpdatePtr< const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue( const clang::ASTContext &Ctx, Decl *Value); + +unsigned char ASTContext::getFixedPointScale(QualType Ty) const { + assert(Ty->isFixedPointType()); + + const auto *BT = Ty->getAs(); + const TargetInfo &Target = getTargetInfo(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + case BuiltinType::SatShortAccum: + return Target.getShortAccumScale(); + case BuiltinType::Accum: + case BuiltinType::SatAccum: + return Target.getAccumScale(); + case BuiltinType::LongAccum: + case BuiltinType::SatLongAccum: + return Target.getLongAccumScale(); + case BuiltinType::UShortAccum: + case BuiltinType::SatUShortAccum: + return Target.getUnsignedShortAccumScale(); + case BuiltinType::UAccum: + case BuiltinType::SatUAccum: + return Target.getUnsignedAccumScale(); + case BuiltinType::ULongAccum: + case BuiltinType::SatULongAccum: + return Target.getUnsignedLongAccumScale(); + case BuiltinType::ShortFract: + case BuiltinType::SatShortFract: + return Target.getShortFractScale(); + case BuiltinType::Fract: + case BuiltinType::SatFract: + return Target.getFractScale(); + case BuiltinType::LongFract: + case BuiltinType::SatLongFract: + return Target.getLongFractScale(); + case BuiltinType::UShortFract: + case BuiltinType::SatUShortFract: + return Target.getUnsignedShortFractScale(); + case BuiltinType::UFract: + case BuiltinType::SatUFract: + return Target.getUnsignedFractScale(); + case BuiltinType::ULongFract: + case BuiltinType::SatULongFract: + return Target.getUnsignedLongFractScale(); + } +} + +unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { + assert(Ty->isFixedPointType()); + + const auto *BT = Ty->getAs(); + const TargetInfo &Target = getTargetInfo(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + case BuiltinType::SatShortAccum: + return Target.getShortAccumIBits(); + case BuiltinType::Accum: + case BuiltinType::SatAccum: + return Target.getAccumIBits(); + case BuiltinType::LongAccum: + case BuiltinType::SatLongAccum: + return Target.getLongAccumIBits(); + case BuiltinType::UShortAccum: + case BuiltinType::SatUShortAccum: + return Target.getUnsignedShortAccumIBits(); + case BuiltinType::UAccum: + case BuiltinType::SatUAccum: + return Target.getUnsignedAccumIBits(); + case BuiltinType::ULongAccum: + case BuiltinType::SatULongAccum: + return Target.getUnsignedLongAccumIBits(); + case BuiltinType::ShortFract: + case BuiltinType::SatShortFract: + case BuiltinType::Fract: + case BuiltinType::SatFract: + case BuiltinType::LongFract: + case BuiltinType::SatLongFract: + case BuiltinType::UShortFract: + case BuiltinType::SatUShortFract: + case BuiltinType::UFract: + case BuiltinType::SatUFract: + case BuiltinType::ULongFract: + case BuiltinType::SatULongFract: + return 0; + } +} diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index cf512b9bd3..6d9f24020f 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -525,6 +525,7 @@ namespace { void VisitPredefinedExpr(const PredefinedExpr *Node); void VisitCharacterLiteral(const CharacterLiteral *Node); void VisitIntegerLiteral(const IntegerLiteral *Node); + void VisitFixedPointLiteral(const FixedPointLiteral *Node); void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); void VisitInitListExpr(const InitListExpr *ILE); @@ -2177,6 +2178,13 @@ void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { OS << " " << Node->getValue().toString(10, isSigned); } +void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) { + VisitExpr(Node); + + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValueAsString(/*Radix=*/10); +} + void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { VisitExpr(Node); ColorScope Color(*this, ValueColor); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index b2593ef467..47cf026e28 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -755,6 +755,36 @@ IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) { return new (C) IntegerLiteral(Empty); } +FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, + QualType type, SourceLocation l, + unsigned Scale) + : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary, false, false, + false, false), + Loc(l), Scale(Scale) { + assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral"); + assert(V.getBitWidth() == C.getTypeInfo(type).Width && + "Fixed point type is not the correct size for constant."); + setValue(C, V); +} + +FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C, + const llvm::APInt &V, + QualType type, + SourceLocation l, + unsigned Scale) { + return new (C) FixedPointLiteral(C, V, type, l, Scale); +} + +std::string FixedPointLiteral::getValueAsString(unsigned Radix) const { + // Currently the longest decimal number that can be printed is the max for an + // unsigned long _Accum: 4294967295.99999999976716935634613037109375 + // which is 43 characters. + SmallString<64> S; + FixedPointValueToString( + S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale, Radix); + return S.str(); +} + FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, @@ -2991,6 +3021,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ObjCIvarRefExprClass: case PredefinedExprClass: case IntegerLiteralClass: + case FixedPointLiteralClass: case FloatingLiteralClass: case ImaginaryLiteralClass: case StringLiteralClass: diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 297267b521..c5b3b361a0 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -161,6 +161,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::IntegerLiteralClass: + case Expr::FixedPointLiteralClass: case Expr::CharacterLiteralClass: case Expr::AddrLabelExprClass: case Expr::CXXDeleteExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 2079f901ed..c700da635b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -7220,6 +7220,73 @@ public: // FIXME: Missing: array subscript of vector, member of vector }; + +class FixedPointExprEvaluator + : public ExprEvaluatorBase { + APValue &Result; + + public: + FixedPointExprEvaluator(EvalInfo &info, APValue &result) + : ExprEvaluatorBaseTy(info), Result(result) {} + + bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { + assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); + assert(SI.isSigned() == E->getType()->isSignedFixedPointType() && + "Invalid evaluation result."); + assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && + "Invalid evaluation result."); + Result = APValue(SI); + return true; + } + bool Success(const llvm::APSInt &SI, const Expr *E) { + return Success(SI, E, Result); + } + + bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { + assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); + assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && + "Invalid evaluation result."); + Result = APValue(APSInt(I)); + Result.getInt().setIsUnsigned(E->getType()->isUnsignedFixedPointType()); + return true; + } + bool Success(const llvm::APInt &I, const Expr *E) { + return Success(I, E, Result); + } + + bool Success(uint64_t Value, const Expr *E, APValue &Result) { + assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); + Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); + return true; + } + bool Success(uint64_t Value, const Expr *E) { + return Success(Value, E, Result); + } + + bool Success(CharUnits Size, const Expr *E) { + return Success(Size.getQuantity(), E); + } + + bool Success(const APValue &V, const Expr *E) { + if (V.isLValue() || V.isAddrLabelDiff()) { + Result = V; + return true; + } + return Success(V.getInt(), E); + } + + bool ZeroInitialization(const Expr *E) { return Success(0, E); } + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + bool VisitFixedPointLiteral(const FixedPointLiteral *E) { + return Success(E->getValue(), E); + } + + bool VisitUnaryOperator(const UnaryOperator *E); +}; } // end anonymous namespace /// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and @@ -9460,6 +9527,37 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { return Success(E->getValue(), E); } +bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + switch (E->getOpcode()) { + default: + // Invalid unary operators + return Error(E); + case UO_Plus: + // The result is just the value. + return Visit(E->getSubExpr()); + case UO_Minus: { + if (!Visit(E->getSubExpr())) return false; + if (!Result.isInt()) return Error(E); + const APSInt &Value = Result.getInt(); + if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { + SmallString<64> S; + FixedPointValueToString(S, Value, + Info.Ctx.getTypeInfo(E->getType()).Width, + /*Radix=*/10); + Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType(); + if (Info.noteUndefinedBehavior()) return false; + } + return Success(-Value, E); + } + case UO_LNot: { + bool bres; + if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) + return false; + return Success(!bres, E); + } + } +} + //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// @@ -10311,6 +10409,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { if (!EvaluateComplex(E, C, Info)) return false; C.moveInto(Result); + } else if (T->isFixedPointType()) { + if (!FixedPointExprEvaluator(Info, Result).Visit(E)) return false; } else if (T->isMemberPointerType()) { MemberPtr P; if (!EvaluateMemberPointer(E, P, Info)) @@ -10759,6 +10859,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::GenericSelectionExprClass: return CheckICE(cast(E)->getResultExpr(), Ctx); case Expr::IntegerLiteralClass: + case Expr::FixedPointLiteralClass: case Expr::CharacterLiteralClass: case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 54ceffa026..86b9fb5d6a 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -3501,6 +3501,7 @@ recurse: case Expr::AsTypeExprClass: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: + case Expr::FixedPointLiteralClass: { if (!NullOut) { // As bad as this diagnostic is, it's better than crashing. diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 38ec6632e7..dad57de894 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1529,6 +1529,28 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { } } +void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) { + if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context)) + return; + OS << Node->getValueAsString(/*Radix=*/10); + + switch (Node->getType()->getAs()->getKind()) { + default: llvm_unreachable("Unexpected type for fixed point literal!"); + case BuiltinType::ShortFract: OS << "hr"; break; + case BuiltinType::ShortAccum: OS << "hk"; break; + case BuiltinType::UShortFract: OS << "uhr"; break; + case BuiltinType::UShortAccum: OS << "uhk"; break; + case BuiltinType::Fract: OS << "r"; break; + case BuiltinType::Accum: OS << "k"; break; + case BuiltinType::UFract: OS << "ur"; break; + case BuiltinType::UAccum: OS << "uk"; break; + case BuiltinType::LongFract: OS << "lr"; break; + case BuiltinType::LongAccum: OS << "lk"; break; + case BuiltinType::ULongFract: OS << "ulr"; break; + case BuiltinType::ULongAccum: OS << "ulk"; break; + } +} + static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, bool PrintSuffix) { SmallString<16> Str; diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 91c7aa9f2f..791ec569cc 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -1007,6 +1007,12 @@ void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { ID.AddInteger(S->getType()->castAs()->getKind()); } +void StmtProfiler::VisitFixedPointLiteral(const FixedPointLiteral *S) { + VisitExpr(S); + S->getValue().Profile(ID); + ID.AddInteger(S->getType()->castAs()->getKind()); +} + void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) { VisitExpr(S); ID.AddInteger(S->getKind()); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5c37c10002..eb65220bc1 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3986,3 +3986,19 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { return getClass()->getAsCXXRecordDecl()->getMostRecentNonInjectedDecl(); } + +void clang::FixedPointValueToString(SmallVectorImpl &Str, + const llvm::APSInt &Val, unsigned Scale, + unsigned Radix) { + llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale); + llvm::APSInt IntPart = Val / ScaleVal; + llvm::APSInt FractPart = Val % ScaleVal; + llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix); + + IntPart.toString(Str, Radix); + Str.push_back('.'); + do { + (FractPart * RadixInt / ScaleVal).toString(Str, Radix); + FractPart = (FractPart * RadixInt) % ScaleVal; + } while (FractPart.getExtValue()); +} diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 8dfcbcc8e2..31bc7a44f8 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -40,12 +40,24 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; + + // Fixed point default bit widths ShortAccumWidth = ShortAccumAlign = 16; AccumWidth = AccumAlign = 32; LongAccumWidth = LongAccumAlign = 64; - ShortFractWidth = ShortFractAlign = 16; - FractWidth = FractAlign = 32; - LongFractWidth = LongFractAlign = 64; + ShortFractWidth = ShortFractAlign = 8; + FractWidth = FractAlign = 16; + LongFractWidth = LongFractAlign = 32; + + // Fixed point default integral and fractional bit sizes + // We give the _Accum 1 fewer fractional bits than their corresponding _Fract + // types by default to have the same number of fractional bits between _Accum + // and _Fract types. + SameFBits = false; + ShortAccumScale = 7; + AccumScale = 15; + LongAccumScale = 31; + SuitableAlign = 64; DefaultAlignForAttributeAligned = 128; MinGlobalAlign = 0; @@ -362,6 +374,11 @@ void TargetInfo::adjust(LangOptions &Opts) { if (Opts.NewAlignOverride) NewAlign = Opts.NewAlignOverride * getCharWidth(); + + // Each unsigned fixed point type has the same number of fractional bits as + // its corresponding signed type. + SameFBits |= Opts.SameFBits; + CheckFixedPointBits(); } bool TargetInfo::initFeatureMap( @@ -716,3 +733,63 @@ bool TargetInfo::validateInputConstraint( return true; } + +void TargetInfo::CheckFixedPointBits() const { + // Check that the number of fractional and integral bits (and maybe sign) can + // fit into the bits given for a fixed point type. + assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth); + assert(AccumScale + getAccumIBits() + 1 <= AccumWidth); + assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth); + assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <= + ShortAccumWidth); + assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth); + assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <= + LongAccumWidth); + + assert(getShortFractScale() + 1 <= ShortFractWidth); + assert(getFractScale() + 1 <= FractWidth); + assert(getLongFractScale() + 1 <= LongFractWidth); + assert(getUnsignedShortFractScale() <= ShortFractWidth); + assert(getUnsignedFractScale() <= FractWidth); + assert(getUnsignedLongFractScale() <= LongFractWidth); + + // Each unsigned fract type has either the same number of fractional bits + // as, or one more fractional bit than, its corresponding signed fract type. + assert(getShortFractScale() == getUnsignedShortFractScale() || + getShortFractScale() == getUnsignedShortFractScale() - 1); + assert(getFractScale() == getUnsignedFractScale() || + getFractScale() == getUnsignedFractScale() - 1); + assert(getLongFractScale() == getUnsignedLongFractScale() || + getLongFractScale() == getUnsignedLongFractScale() - 1); + + // When arranged in order of increasing rank (see 6.3.1.3a), the number of + // fractional bits is nondecreasing for each of the following sets of + // fixed-point types: + // - signed fract types + // - unsigned fract types + // - signed accum types + // - unsigned accum types. + assert(getLongFractScale() >= getFractScale() && + getFractScale() >= getShortFractScale()); + assert(getUnsignedLongFractScale() >= getUnsignedFractScale() && + getUnsignedFractScale() >= getUnsignedShortFractScale()); + assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale); + assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() && + getUnsignedAccumScale() >= getUnsignedShortAccumScale()); + + // When arranged in order of increasing rank (see 6.3.1.3a), the number of + // integral bits is nondecreasing for each of the following sets of + // fixed-point types: + // - signed accum types + // - unsigned accum types + assert(getLongAccumIBits() >= getAccumIBits() && + getAccumIBits() >= getShortAccumIBits()); + assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() && + getUnsignedAccumIBits() >= getUnsignedShortAccumIBits()); + + // Each signed accum type has at least as many integral bits as its + // corresponding unsigned accum type. + assert(getShortAccumIBits() >= getUnsignedShortAccumIBits()); + assert(getAccumIBits() >= getUnsignedAccumIBits()); + assert(getLongAccumIBits() >= getUnsignedLongAccumIBits()); +} diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 2e4b722b85..1ef2fe3b81 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -652,5 +652,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, if (!Target->validateTarget(Diags)) return nullptr; + Target->CheckFixedPointBits(); + return Target.release(); } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index d350a86a11..2917404783 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -684,12 +684,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { CGF.EmitDynamicCast(LV.getAddress(), cast(E)); else CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); - + if (!Dest.isIgnored()) CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); break; } - + case CK_ToUnion: { // Evaluate even if the destination is ignored. if (Dest.isIgnored()) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 0edd1cbdaf..f4c0c75c25 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -387,6 +387,9 @@ public: Value *VisitIntegerLiteral(const IntegerLiteral *E) { return Builder.getInt(E->getValue()); } + Value *VisitFixedPointLiteral(const FixedPointLiteral *E) { + return Builder.getInt(E->getValue()); + } Value *VisitFloatingLiteral(const FloatingLiteral *E) { return llvm::ConstantFP::get(VMContext, E->getValue()); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index a5943de993..bce2083051 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3766,6 +3766,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, /*Default=*/false)) Args.AddLastArg(CmdArgs, options::OPT_ffixed_point); + if (Args.hasFlag(options::OPT_fsame_fbits, + options::OPT_fno_same_fbits, + /*Default=*/false)) + Args.AddLastArg(CmdArgs, options::OPT_fsame_fbits); + // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 2aa74c38e2..1f9d6b0d7f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2338,6 +2338,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.FixedPoint = Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) && !Opts.CPlusPlus; + Opts.SameFBits = + Args.hasFlag(OPT_fsame_fbits, OPT_fno_same_fbits, + /*Default=*/false) && + Opts.FixedPoint; // Handle exception personalities Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index af64ffef6c..e414f85e02 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -538,6 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, saw_exponent = false; saw_period = false; saw_ud_suffix = false; + saw_fixed_point_suffix = false; isLong = false; isUnsigned = false; isLongLong = false; @@ -547,6 +548,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isFloat16 = false; isFloat128 = false; MicrosoftInteger = 0; + isFract = false; + isAccum = false; hadError = false; if (*s == '0') { // parse radix @@ -568,6 +571,14 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, SuffixBegin = s; checkSeparator(TokLoc, s, CSK_AfterDigits); + // Initial scan to lookahead for fixed point suffix. + for (const char *c = s; c != ThisTokEnd; ++c) { + if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') { + saw_fixed_point_suffix = true; + break; + } + } + // Parse the suffix. At this point we can classify whether we have an FP or // integer constant. bool isFPConstant = isFloatingLiteral(); @@ -576,11 +587,21 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // we break out of the loop. for (; s != ThisTokEnd; ++s) { switch (*s) { + case 'R': + case 'r': + if (isFract || isAccum) break; + isFract = true; + continue; + case 'K': + case 'k': + if (isFract || isAccum) break; + isAccum = true; + continue; case 'h': // FP Suffix for "half". case 'H': // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. - if (!PP.getLangOpts().Half) break; - if (!isFPConstant) break; // Error for integer constant. + if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break; + if (isIntegerLiteral()) break; // Error for integer constant. if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid. isHalf = true; continue; // Success. @@ -693,6 +714,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isHalf = false; isImaginary = false; MicrosoftInteger = 0; + saw_fixed_point_suffix = false; + isFract = false; + isAccum = false; } saw_ud_suffix = true; @@ -707,6 +731,11 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, hadError = true; } } + + if (!hadError && saw_fixed_point_suffix) { + assert(isFract || isAccum); + assert(radix == 16 || radix == 10); + } } /// ParseDecimalOrOctalCommon - This method is called for decimal or octal @@ -1012,6 +1041,126 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { return Result.convertFromString(Str, APFloat::rmNearestTiesToEven); } +static inline bool IsExponentPart(char c) { + return c == 'p' || c == 'P' || c == 'e' || c == 'E'; +} + +bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) { + assert(radix == 16 || radix == 10); + + // Find how many digits are needed to store the whole literal. + unsigned NumDigits = SuffixBegin - DigitsBegin; + if (saw_period) --NumDigits; + + // Initial scan of the exponent if it exists + bool ExpOverflowOccurred = false; + bool NegativeExponent = false; + const char *ExponentBegin; + uint64_t Exponent = 0; + int64_t BaseShift = 0; + if (saw_exponent) { + const char *Ptr = DigitsBegin; + + while (!IsExponentPart(*Ptr)) ++Ptr; + ExponentBegin = Ptr; + ++Ptr; + NegativeExponent = *Ptr == '-'; + if (NegativeExponent) ++Ptr; + + unsigned NumExpDigits = SuffixBegin - Ptr; + if (alwaysFitsInto64Bits(radix, NumExpDigits)) { + llvm::StringRef ExpStr(Ptr, NumExpDigits); + llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10); + Exponent = ExpInt.getZExtValue(); + } else { + ExpOverflowOccurred = true; + } + + if (NegativeExponent) BaseShift -= Exponent; + else BaseShift += Exponent; + } + + // Number of bits needed for decimal literal is + // ceil(NumDigits * log2(10)) Integral part + // + Scale Fractional part + // + ceil(Exponent * log2(10)) Exponent + // -------------------------------------------------- + // ceil((NumDigits + Exponent) * log2(10)) + Scale + // + // But for simplicity in handling integers, we can round up log2(10) to 4, + // making: + // 4 * (NumDigits + Exponent) + Scale + // + // Number of digits needed for hexadecimal literal is + // 4 * NumDigits Integral part + // + Scale Fractional part + // + Exponent Exponent + // -------------------------------------------------- + // (4 * NumDigits) + Scale + Exponent + uint64_t NumBitsNeeded; + if (radix == 10) + NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale; + else + NumBitsNeeded = 4 * NumDigits + Exponent + Scale; + + if (NumBitsNeeded > std::numeric_limits::max()) + ExpOverflowOccurred = true; + llvm::APInt Val(static_cast(NumBitsNeeded), 0, /*isSigned=*/false); + + bool FoundDecimal = false; + + int64_t FractBaseShift = 0; + const char *End = saw_exponent ? ExponentBegin : SuffixBegin; + for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) { + if (*Ptr == '.') { + FoundDecimal = true; + continue; + } + + // Normal reading of an integer + unsigned C = llvm::hexDigitValue(*Ptr); + assert(C < radix && "NumericLiteralParser ctor should have rejected this"); + + Val *= radix; + Val += C; + + if (FoundDecimal) + // Keep track of how much we will need to adjust this value by from the + // number of digits past the radix point. + --FractBaseShift; + } + + // For a radix of 16, we will be multiplying by 2 instead of 16. + if (radix == 16) FractBaseShift *= 4; + BaseShift += FractBaseShift; + + Val <<= Scale; + + uint64_t Base = (radix == 16) ? 2 : 10; + if (BaseShift > 0) { + for (int64_t i = 0; i < BaseShift; ++i) { + Val *= Base; + } + } else if (BaseShift < 0) { + for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i) + Val = Val.udiv(Base); + } + + bool IntOverflowOccurred = false; + auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth()); + if (Val.getBitWidth() > StoreVal.getBitWidth()) { + IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth())); + StoreVal = Val.trunc(StoreVal.getBitWidth()); + } else if (Val.getBitWidth() < StoreVal.getBitWidth()) { + IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal); + StoreVal = Val.zext(StoreVal.getBitWidth()); + } else { + StoreVal = Val; + } + + return IntOverflowOccurred || ExpOverflowOccurred; +} + /// \verbatim /// user-defined-character-literal: [C++11 lex.ext] /// character-literal ud-suffix diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index a81c17bb7f..8dce6d59c6 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -1258,6 +1258,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::ImaginaryLiteralClass: case Expr::ImplicitValueInitExprClass: case Expr::IntegerLiteralClass: + case Expr::FixedPointLiteralClass: case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::ObjCEncodeExprClass: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index aeedd6b169..88059e9466 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3326,7 +3326,52 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Expr *Res; - if (Literal.isFloatingLiteral()) { + if (Literal.isFixedPointLiteral()) { + QualType Ty; + + if (Literal.isAccum) { + if (Literal.isHalf) { + Ty = Context.ShortAccumTy; + } else if (Literal.isLong) { + Ty = Context.LongAccumTy; + } else { + Ty = Context.AccumTy; + } + } else if (Literal.isFract) { + if (Literal.isHalf) { + Ty = Context.ShortFractTy; + } else if (Literal.isLong) { + Ty = Context.LongFractTy; + } else { + Ty = Context.FractTy; + } + } + + if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty); + + bool isSigned = !Literal.isUnsigned; + unsigned scale = Context.getFixedPointScale(Ty); + unsigned ibits = Context.getFixedPointIBits(Ty); + unsigned bit_width = Context.getTypeInfo(Ty).Width; + + llvm::APInt Val(bit_width, 0, isSigned); + bool Overflowed = Literal.GetFixedPointValue(Val, scale); + + // Do not use bit_width since some types may have padding like _Fract or + // unsigned _Accums if SameFBits is set. + auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width); + if (Literal.isFract && Val == MaxVal + 1) + // Clause 6.4.4 - The value of a constant shall be in the range of + // representable values for its type, with exception for constants of a + // fract type with a value of exactly 1; such a constant shall denote + // the maximal value for the type. + --Val; + else if (Val.ugt(MaxVal) || Overflowed) + Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point); + + Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty, + Tok.getLocation(), scale); + } else if (Literal.isFloatingLiteral()) { QualType Ty; if (Literal.isHalf){ if (getOpenCLOptions().isEnabled("cl_khr_fp16")) @@ -13122,7 +13167,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, CondExpr = CondICE.get(); CondIsTrue = condEval.getZExtValue(); - // If the condition is > zero, then the AST type is the same as the LSHExpr. + // If the condition is > zero, then the AST type is the same as the LHSExpr. Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr; resType = ActiveExpr->getType(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index cdf7dc419f..66c947abb3 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -8888,6 +8888,12 @@ TreeTransform::TransformIntegerLiteral(IntegerLiteral *E) { return E; } +template +ExprResult TreeTransform::TransformFixedPointLiteral( + FixedPointLiteral *E) { + return E; +} + template ExprResult TreeTransform::TransformFloatingLiteral(FloatingLiteral *E) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 62d8cd088e..2b7de79841 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -533,6 +533,12 @@ void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { E->setValue(Record.getContext(), Record.readAPInt()); } +void ASTStmtReader::VisitFixedPointLiteral(FixedPointLiteral *E) { + VisitExpr(E); + E->setLocation(ReadSourceLocation()); + E->setValue(Record.getContext(), Record.readAPInt()); +} + void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); E->setRawSemantics(static_cast(Record.readInt())); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 665b87961d..b79e80e122 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -444,6 +444,13 @@ void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { Code = serialization::EXPR_INTEGER_LITERAL; } +void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getLocation()); + Record.AddAPInt(E->getValue()); + Code = serialization::EXPR_INTEGER_LITERAL; +} + void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { VisitExpr(E); Record.push_back(E->getRawSemantics()); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 939b21944d..8ec78cf810 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1297,6 +1297,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::AddrLabelExprClass: case Stmt::AttributedStmtClass: case Stmt::IntegerLiteralClass: + case Stmt::FixedPointLiteralClass: case Stmt::CharacterLiteralClass: case Stmt::ImplicitValueInitExprClass: case Stmt::CXXScalarValueInitExprClass: diff --git a/test/Frontend/fixed_point.c b/test/Frontend/fixed_point.c index bc8cf2dcd7..3a67718fba 100644 --- a/test/Frontend/fixed_point.c +++ b/test/Frontend/fixed_point.c @@ -236,4 +236,164 @@ SatlF_t SatlF_type; //CHECK-NEXT: |-VarDecl {{.*}} SatlA_type 'SatlA_t':'_Sat long _Accum' //CHECK-NEXT: |-VarDecl {{.*}} SatsF_type 'SatsF_t':'_Sat short _Fract' //CHECK-NEXT: |-VarDecl {{.*}} SatF_type 'SatF_t':'_Sat _Fract' -//CHECK-NEXT: `-VarDecl {{.*}} SatlF_type 'SatlF_t':'_Sat long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatlF_type 'SatlF_t':'_Sat long _Fract' + +// Fixed point literal exponent syntax +_Accum decexp1 = 1.575e1k; +_Accum decexp2 = 1.575E1k; +_Accum decexp3 = 1575e-2k; +_Accum decexp4 = 1575E-2k; + +_Accum hexexp1 = 0x0.3p10k; +_Accum hexexp2 = 0x0.3P10k; +_Accum hexexp3 = 0x30000p-10k; +_Accum hexexp4 = 0x30000P-10k; + +_Accum zeroexp1 = 1e0k; +_Accum zeroexp2 = 1e-0k; + +//CHECK-NEXT: |-VarDecl {{.*}} decexp1 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75 +//CHECK-NEXT: |-VarDecl {{.*}} decexp2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75 +//CHECK-NEXT: |-VarDecl {{.*}} decexp3 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75 +//CHECK-NEXT: |-VarDecl {{.*}} decexp4 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 15.75 + +//CHECK-NEXT: |-VarDecl {{.*}} hexexp1 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0 +//CHECK-NEXT: |-VarDecl {{.*}} hexexp2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0 +//CHECK-NEXT: |-VarDecl {{.*}} hexexp3 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0 +//CHECK-NEXT: |-VarDecl {{.*}} hexexp4 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 192.0 + +//CHECK-NEXT: |-VarDecl {{.*}} zeroexp1 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0 +//CHECK-NEXT: |-VarDecl {{.*}} zeroexp2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0 + +// Fixed point literal values +_Accum literal1 = 2.5k; // Precise decimal +_Accum literal2 = 0.0k; // Zero +_Accum literal3 = 1.1k; // Imprecise decimal +_Accum literal4 = 1.11k; +_Accum literal5 = 1.111k; +_Accum literal6 = 1.1111k; +_Accum literal7 = 1.11111k; // After some point after the radix, adding any more + // digits to the literal will not result in any + // further precision since the nth digit added may + // be less than the precision that can be + // represented by the fractional bits of the type. + // This results in the same value being stored for + // the type. + +//CHECK-NEXT: |-VarDecl {{.*}} literal1 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 2.5 +//CHECK-NEXT: |-VarDecl {{.*}} literal2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.0 +//CHECK-NEXT: |-VarDecl {{.*}} literal3 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0999755859375 +//CHECK-NEXT: |-VarDecl {{.*}} literal4 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.1099853515625 +//CHECK-NEXT: |-VarDecl {{.*}} literal5 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.110992431640625 +//CHECK-NEXT: |-VarDecl {{.*}} literal6 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375 +//CHECK-NEXT: |-VarDecl {{.*}} literal7 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375 + +long _Accum longaccumliteral = 0.99999999lk; +long _Accum longaccumliteral2 = 0.999999999lk; +long _Accum verylongaccumliteral = 0.99999999999999999999999999lk; +long _Fract longfractliteral = 0.99999999lr; +long _Fract longfractliteral2 = 0.999999999lr; +long _Fract verylongfractliteral = 0.99999999999999999999999999lr; + +//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.999999989755451679229736328125 +//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral2 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999986030161380767822265625 +//CHECK-NEXT: |-VarDecl {{.*}} verylongaccumliteral 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875 +//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral 'long _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.999999989755451679229736328125 +//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral2 'long _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999986030161380767822265625 +//CHECK-NEXT: |-VarDecl {{.*}} verylongfractliteral 'long _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875 + +unsigned _Accum uliteral1 = 2.5uk; // Unsigned +_Accum literal8 = -2.5k; // Negative + +//CHECK-NEXT: |-VarDecl {{.*}} uliteral1 'unsigned _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned _Accum' 2.5 +//CHECK-NEXT: |-VarDecl {{.*}} literal8 '_Accum' cinit +//CHECK-NEXT: `-UnaryOperator {{.*}} '_Accum' prefix '-' +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 2.5 + +short _Accum literalexact1 = 0.9921875hk; // Exact value +_Accum literalexact2 = 0.999969482421875k; + +//CHECK-NEXT: |-VarDecl {{.*}} literalexact1 'short _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.9921875 +//CHECK-NEXT: |-VarDecl {{.*}} literalexact2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.999969482421875 + +// Unfortunately we do not have enough space to store the exact decimal value of +// 0.9999999995343387126922607421875 ((1 << 31) - 1), but we can still use a +// large number of 9s to get the max fractional value. +long _Accum long_accum_max = 0.999999999999999999999999999lk; + +//CHECK-NEXT: |-VarDecl {{.*}} long_accum_max 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875 + +// Epsilon +short _Accum short_accum_eps = 0.0078125hk; +short _Accum short_accum_eps2 = 0.0078124hk; // Less than epsilon floors to zero +_Accum accum_eps = 0.000030517578125k; +_Accum accum_eps2 = 0.000030517578124k; +long _Accum long_accum_eps = 0x1p-31lk; +long _Accum long_accum_eps2 = 0x0.99999999p-31lk; + +//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps 'short _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.0078125 +//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps2 'short _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Accum' 0.0 +//CHECK-NEXT: |-VarDecl {{.*}} accum_eps '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.000030517578125 +//CHECK-NEXT: |-VarDecl {{.*}} accum_eps2 '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 0.0 +//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.0000000004656612873077392578125 +//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps2 'long _Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Accum' 0.0 + +// Fract literals can be one but evaluate to the respective Fract max +short _Fract short_fract_one = 1.0hr; +_Fract fract_one = 1.0r; +long _Fract long_fract_one = 1.0lr; +unsigned short _Fract u_short_fract_one = 1.0uhr; +unsigned _Fract u_fract_one = 1.0ur; +unsigned long _Fract u_long_fract_one = 1.0ulr; + +//CHECK-NEXT: |-VarDecl {{.*}} short_fract_one 'short _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'short _Fract' 0.9921875 +//CHECK-NEXT: |-VarDecl {{.*}} fract_one '_Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Fract' 0.999969482421875 +//CHECK-NEXT: |-VarDecl {{.*}} long_fract_one 'long _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875 + +//CHECK-NEXT: |-VarDecl {{.*}} u_short_fract_one 'unsigned short _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned short _Fract' 0.99609375 +//CHECK-NEXT: |-VarDecl {{.*}} u_fract_one 'unsigned _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned _Fract' 0.9999847412109375 +//CHECK-NEXT: |-VarDecl {{.*}} u_long_fract_one 'unsigned long _Fract' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} 'unsigned long _Fract' 0.99999999976716935634613037109375 + +_Accum literallast = 1.0k; // One + +//CHECK-NEXT: `-VarDecl {{.*}} literallast '_Accum' cinit +//CHECK-NEXT: `-FixedPointLiteral {{.*}} '_Accum' 1.0 diff --git a/test/Frontend/fixed_point_bit_widths.c b/test/Frontend/fixed_point_bit_widths.c index 8973a33666..ac8db49ed5 100644 --- a/test/Frontend/fixed_point_bit_widths.c +++ b/test/Frontend/fixed_point_bit_widths.c @@ -44,12 +44,12 @@ int align_SsF = __alignof(signed short _Fract); int align_SF = __alignof(signed _Fract); int align_SlF = __alignof(signed long _Fract); -// CHECK-NEXT: @size_SsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_SF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_SlF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_SF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_SlF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_SsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_SF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SlF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_SF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SlF = {{.*}}global i{{[0-9]+}} 4 /* Primary unsigned _Fract */ @@ -60,12 +60,12 @@ int align_UsF = __alignof(unsigned short _Fract); int align_UF = __alignof(unsigned _Fract); int align_UlF = __alignof(unsigned long _Fract); -// CHECK-NEXT: @size_UsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_UF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_UlF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_UF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_UlF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_UsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_UF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_UlF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_UF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_UlF = {{.*}}global i{{[0-9]+}} 4 /* Aliased _Accum */ @@ -92,12 +92,12 @@ int align_sF = __alignof(short _Fract); int align_F = __alignof(_Fract); int align_lF = __alignof(long _Fract); -// CHECK-NEXT: @size_sF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_F = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_lF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_sF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_F = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_lF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_sF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_F = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_lF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_sF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_F = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_lF = {{.*}}global i{{[0-9]+}} 4 /* Saturated signed _Accum */ @@ -140,12 +140,12 @@ int align_SatSsF = __alignof(_Sat signed short _Fract); int align_SatSF = __alignof(_Sat signed _Fract); int align_SatSlF = __alignof(_Sat signed long _Fract); -// CHECK-NEXT: @size_SatSsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_SatSF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_SatSlF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_SatSF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_SatSlF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_SatSsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_SatSF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatSlF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_SatSF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatSlF = {{.*}}global i{{[0-9]+}} 4 /* Saturated unsigned _Fract */ @@ -156,12 +156,12 @@ int align_SatUsF = __alignof(_Sat unsigned short _Fract); int align_SatUF = __alignof(_Sat unsigned _Fract); int align_SatUlF = __alignof(_Sat unsigned long _Fract); -// CHECK-NEXT: @size_SatUsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_SatUF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_SatUlF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_SatUF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_SatUlF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_SatUsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_SatUF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatUlF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_SatUF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatUlF = {{.*}}global i{{[0-9]+}} 4 /* Aliased saturated signed _Accum */ @@ -188,9 +188,9 @@ int align_SatsF = __alignof(_Sat short _Fract); int align_SatF = __alignof(_Sat _Fract); int align_SatlF = __alignof(_Sat long _Fract); -// CHECK-NEXT: @size_SatsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @size_SatF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @size_SatlF = {{.*}}global i{{[0-9]+}} 8 -// CHECK-NEXT: @align_SatsF = {{.*}}global i{{[0-9]+}} 2 -// CHECK-NEXT: @align_SatF = {{.*}}global i{{[0-9]+}} 4 -// CHECK-NEXT: @align_SatlF = {{.*}}global i{{[0-9]+}} 8 +// CHECK-NEXT: @size_SatsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @size_SatF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatlF = {{.*}}global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatsF = {{.*}}global i{{[0-9]+}} 1 +// CHECK-NEXT: @align_SatF = {{.*}}global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatlF = {{.*}}global i{{[0-9]+}} 4 diff --git a/test/Frontend/fixed_point_declarations.c b/test/Frontend/fixed_point_declarations.c new file mode 100644 index 0000000000..47f7e9f803 --- /dev/null +++ b/test/Frontend/fixed_point_declarations.c @@ -0,0 +1,113 @@ +// RUN: %clang -ffixed-point -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s + +// Primary fixed point types +signed short _Accum s_short_accum; // CHECK-DAG: @s_short_accum = {{.*}}global i16 0, align 2 +signed _Accum s_accum; // CHECK-DAG: @s_accum = {{.*}}global i32 0, align 4 +signed long _Accum s_long_accum; // CHECK-DAG: @s_long_accum = {{.*}}global i64 0, align 8 +unsigned short _Accum u_short_accum; // CHECK-DAG: @u_short_accum = {{.*}}global i16 0, align 2 +unsigned _Accum u_accum; // CHECK-DAG: @u_accum = {{.*}}global i32 0, align 4 +unsigned long _Accum u_long_accum; // CHECK-DAG: @u_long_accum = {{.*}}global i64 0, align 8 +signed short _Fract s_short_fract; // CHECK-DAG: @s_short_fract = {{.*}}global i8 0, align 1 +signed _Fract s_fract; // CHECK-DAG: @s_fract = {{.*}}global i16 0, align 2 +signed long _Fract s_long_fract; // CHECK-DAG: @s_long_fract = {{.*}}global i32 0, align 4 +unsigned short _Fract u_short_fract; // CHECK-DAG: @u_short_fract = {{.*}}global i8 0, align 1 +unsigned _Fract u_fract; // CHECK-DAG: @u_fract = {{.*}}global i16 0, align 2 +unsigned long _Fract u_long_fract; // CHECK-DAG: @u_long_fract = {{.*}}global i32 0, align 4 + +// Aliased +short _Accum short_accum; // CHECK-DAG: @short_accum = {{.*}}global i16 0, align 2 +_Accum accum; // CHECK-DAG: @accum = {{.*}}global i32 0, align 4 +long _Accum long_accum; // CHECK-DAG: @long_accum = {{.*}}global i64 0, align 8 +short _Fract short_fract; // CHECK-DAG: @short_fract = {{.*}}global i8 0, align 1 +_Fract fract; // CHECK-DAG: @fract = {{.*}}global i16 0, align 2 +long _Fract long_fract; // CHECK-DAG: @long_fract = {{.*}}global i32 0, align 4 + +// Primary saturated +_Sat signed short _Accum sat_s_short_accum; // CHECK-DAG: @sat_s_short_accum = {{.*}}global i16 0, align 2 +_Sat signed _Accum sat_s_accum; // CHECK-DAG: @sat_s_accum = {{.*}}global i32 0, align 4 +_Sat signed long _Accum sat_s_long_accum; // CHECK-DAG: @sat_s_long_accum = {{.*}}global i64 0, align 8 +_Sat unsigned short _Accum sat_u_short_accum; // CHECK-DAG: @sat_u_short_accum = {{.*}}global i16 0, align 2 +_Sat unsigned _Accum sat_u_accum; // CHECK-DAG: @sat_u_accum = {{.*}}global i32 0, align 4 +_Sat unsigned long _Accum sat_u_long_accum; // CHECK-DAG: @sat_u_long_accum = {{.*}}global i64 0, align 8 +_Sat signed short _Fract sat_s_short_fract; // CHECK-DAG: @sat_s_short_fract = {{.*}}global i8 0, align 1 +_Sat signed _Fract sat_s_fract; // CHECK-DAG: @sat_s_fract = {{.*}}global i16 0, align 2 +_Sat signed long _Fract sat_s_long_fract; // CHECK-DAG: @sat_s_long_fract = {{.*}}global i32 0, align 4 +_Sat unsigned short _Fract sat_u_short_fract; // CHECK-DAG: @sat_u_short_fract = {{.*}}global i8 0, align 1 +_Sat unsigned _Fract sat_u_fract; // CHECK-DAG: @sat_u_fract = {{.*}}global i16 0, align 2 +_Sat unsigned long _Fract sat_u_long_fract; // CHECK-DAG: @sat_u_long_fract = {{.*}}global i32 0, align 4 + +// Aliased saturated +_Sat short _Accum sat_short_accum; // CHECK-DAG: @sat_short_accum = {{.*}}global i16 0, align 2 +_Sat _Accum sat_accum; // CHECK-DAG: @sat_accum = {{.*}}global i32 0, align 4 +_Sat long _Accum sat_long_accum; // CHECK-DAG: @sat_long_accum = {{.*}}global i64 0, align 8 +_Sat short _Fract sat_short_fract; // CHECK-DAG: @sat_short_fract = {{.*}}global i8 0, align 1 +_Sat _Fract sat_fract; // CHECK-DAG: @sat_fract = {{.*}}global i16 0, align 2 +_Sat long _Fract sat_long_fract; // CHECK-DAG: @sat_long_fract = {{.*}}global i32 0, align 4 + +/* Fixed point literals */ +short _Accum short_accum_literal = 2.5hk; // CHECK-DAG: @short_accum_literal = {{.*}}global i16 320, align 2 +_Accum accum_literal = 2.5k; // CHECK-DAG: @accum_literal = {{.*}}global i32 81920, align 4 +long _Accum long_accum_literal = 2.5lk; // CHECK-DAG: @long_accum_literal = {{.*}}global i64 5368709120, align 8 +short _Fract short_fract_literal = 0.5hr; // CHECK-DAG: @short_fract_literal = {{.*}}global i8 64, align 1 +_Fract fract_literal = 0.5r; // CHECK-DAG: @fract_literal = {{.*}}global i16 16384, align 2 +long _Fract long_fract_literal = 0.5lr; // CHECK-DAG: @long_fract_literal = {{.*}}global i32 1073741824, align 4 + +unsigned short _Accum u_short_accum_literal = 2.5uhk; // CHECK-DAG: @u_short_accum_literal = {{.*}}global i16 640, align 2 +unsigned _Accum u_accum_literal = 2.5uk; // CHECK-DAG: @u_accum_literal = {{.*}}global i32 163840, align 4 +unsigned long _Accum u_long_accum_literal = 2.5ulk; // CHECK-DAG: @u_long_accum_literal = {{.*}}global i64 10737418240, align 8 +unsigned short _Fract u_short_fract_literal = 0.5uhr; // CHECK-DAG: @u_short_fract_literal = {{.*}}global i8 -128, align 1 +unsigned _Fract u_fract_literal = 0.5ur; // CHECK-DAG: @u_fract_literal = {{.*}}global i16 -32768, align 2 +unsigned long _Fract u_long_fract_literal = 0.5ulr; // CHECK-DAG: @u_long_fract_literal = {{.*}}global i32 -2147483648, align 4 + +// Max literal values +short _Accum short_accum_max = 255.9999999999999999hk; // CHECK-DAG: @short_accum_max = {{.*}}global i16 32767, align 2 +_Accum accum_max = 65535.9999999999999999k; // CHECK-DAG: @accum_max = {{.*}}global i32 2147483647, align 4 +long _Accum long_accum_max = 4294967295.9999999999999999lk; // CHECK-DAG: @long_accum_max = {{.*}}global i64 9223372036854775807, align 8 +unsigned short _Accum u_short_accum_max = 255.9999999999999999uhk; // CHECK-DAG: @u_short_accum_max = {{.*}}global i16 -1, align 2 +unsigned _Accum u_accum_max = 65535.9999999999999999uk; // CHECK-DAG: @u_accum_max = {{.*}}global i32 -1, align 4 +unsigned long _Accum u_long_accum_max = 4294967295.9999999999999999ulk; // CHECK-DAG: @u_long_accum_max = {{.*}}global i64 -1, align 8 + +short _Fract short_fract_max = 0.9999999999999999hr; // CHECK-DAG: @short_fract_max = {{.*}}global i8 127, align 1 +_Fract fract_max = 0.9999999999999999r; // CHECK-DAG: @fract_max = {{.*}}global i16 32767, align 2 +long _Fract long_fract_max = 0.9999999999999999lr; // CHECK-DAG: @long_fract_max = {{.*}}global i32 2147483647, align 4 +unsigned short _Fract u_short_fract_max = 0.9999999999999999uhr; // CHECK-DAG: @u_short_fract_max = {{.*}}global i8 -1, align 1 +unsigned _Fract u_fract_max = 0.9999999999999999ur; // CHECK-DAG: @u_fract_max = {{.*}}global i16 -1, align 2 +unsigned long _Fract u_long_fract_max = 0.9999999999999999ulr; // CHECK-DAG: @u_long_fract_max = {{.*}}global i32 -1, align 4 + +// Fracts may be exactly one but evaluate to the Fract max +short _Fract short_fract_one = 1.0hr; // CHECK-DAG: @short_fract_one = {{.*}}global i8 127, align 1 +_Fract fract_one = 1.0r; // CHECK-DAG: @fract_one = {{.*}}global i16 32767, align 2 +long _Fract long_fract_one = 1.0lr; // CHECK-DAG: @long_fract_one = {{.*}}global i32 2147483647, align 4 +unsigned short _Fract u_short_fract_one = 1.0uhr; // CHECK-DAG: @u_short_fract_one = {{.*}}global i8 -1, align 1 +unsigned _Fract u_fract_one = 1.0ur; // CHECK-DAG: @u_fract_one = {{.*}}global i16 -1, align 2 +unsigned long _Fract u_long_fract_one = 1.0ulr; // CHECK-DAG: @u_long_fract_one = {{.*}}global i32 -1, align 4 + +short _Fract short_fract_exp_one = 0.1e1hr; // CHECK-DAG: @short_fract_exp_one = {{.*}}global i8 127, align 1 +_Fract fract_exp_one = 0.1e1r; // CHECK-DAG: @fract_exp_one = {{.*}}global i16 32767, align 2 +long _Fract long_fract_exp_one = 0.1e1lr; // CHECK-DAG: @long_fract_exp_one = {{.*}}global i32 2147483647, align 4 +unsigned short _Fract u_short_fract_exp_one = 0.1e1uhr; // CHECK-DAG: @u_short_fract_exp_one = {{.*}}global i8 -1, align 1 +unsigned _Fract u_fract_exp_one = 0.1e1ur; // CHECK-DAG: @u_fract_exp_one = {{.*}}global i16 -1, align 2 +unsigned long _Fract u_long_fract_exp_one = 0.1e1ulr; // CHECK-DAG: @u_long_fract_exp_one = {{.*}}global i32 -1, align 4 + +short _Fract short_fract_hex_exp_one = 0x0.8p1hr; // CHECK-DAG: @short_fract_hex_exp_one = {{.*}}global i8 127, align 1 +_Fract fract_hex_exp_one = 0x0.8p1r; // CHECK-DAG: @fract_hex_exp_one = {{.*}}global i16 32767, align 2 +long _Fract long_fract_hex_exp_one = 0x0.8p1lr; // CHECK-DAG: @long_fract_hex_exp_one = {{.*}}global i32 2147483647, align 4 +unsigned short _Fract u_short_fract_hex_exp_one = 0x0.8p1uhr; // CHECK-DAG: @u_short_fract_hex_exp_one = {{.*}}global i8 -1, align 1 +unsigned _Fract u_fract_hex_exp_one = 0x0.8p1ur; // CHECK-DAG: @u_fract_hex_exp_one = {{.*}}global i16 -1, align 2 +unsigned long _Fract u_long_fract_hex_exp_one = 0x0.8p1ulr; // CHECK-DAG: @u_long_fract_hex_exp_one = {{.*}}global i32 -1, align 4 + +// Expsilon values +short _Accum short_accum_eps = 0x1p-7hk; // CHECK-DAG: @short_accum_eps = {{.*}}global i16 1, align 2 +_Accum accum_eps = 0x1p-15k; // CHECK-DAG: @accum_eps = {{.*}}global i32 1, align 4 +long _Accum long_accum_eps = 0x1p-31lk; // CHECK-DAG: @long_accum_eps = {{.*}}global i64 1, align 8 +unsigned short _Accum u_short_accum_eps = 0x1p-8uhk; // CHECK-DAG: @u_short_accum_eps = {{.*}}global i16 1, align 2 +unsigned _Accum u_accum_eps = 0x1p-16uk; // CHECK-DAG: @u_accum_eps = {{.*}}global i32 1, align 4 +unsigned long _Accum u_long_accum_eps = 0x1p-32ulk; // CHECK-DAG: @u_long_accum_eps = {{.*}}global i64 1, align 8 + +short _Fract short_fract_eps = 0x1p-7hr; // CHECK-DAG: @short_fract_eps = {{.*}}global i8 1, align 1 +_Fract fract_eps = 0x1p-15r; // CHECK-DAG: @fract_eps = {{.*}}global i16 1, align 2 +long _Fract long_fract_eps = 0x1p-31lr; // CHECK-DAG: @long_fract_eps = {{.*}}global i32 1, align 4 +unsigned short _Fract u_short_fract_eps = 0x1p-8uhr; // CHECK-DAG: @u_short_fract_eps = {{.*}}global i8 1, align 1 +unsigned _Fract u_fract_eps = 0x1p-16ur; // CHECK-DAG: @u_fract_eps = {{.*}}global i16 1, align 2 +unsigned long _Fract u_long_fract_eps = 0x1p-32ulr; // CHECK-DAG: @u_long_fract_eps = {{.*}}global i32 1, align 4 diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c index 7f0e009957..f55fc82f91 100644 --- a/test/Frontend/fixed_point_errors.c +++ b/test/Frontend/fixed_point_errors.c @@ -78,6 +78,50 @@ _Sat char c; // expected-error{{'_Sat' specifier is only valid on ' _Sat int i; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'int'}} _Sat _Sat _Fract fract; // expected-warning{{duplicate '_Sat' declaration specifier}} + +/* Literals that cannot fit into types */ +signed short _Accum s_short_accum = 256.0hk; // expected-error{{this value is too large for this fixed point type}} +unsigned short _Accum u_short_accum = 256.0uhk; // expected-error{{this value is too large for this fixed point type}} +signed _Accum s_accum = 65536.0k; // expected-error{{this value is too large for this fixed point type}} +unsigned _Accum u_accum = 65536.0uk; // expected-error{{this value is too large for this fixed point type}} +signed long _Accum s_long_accum = 4294967296.0lk; // expected-error{{this value is too large for this fixed point type}} +unsigned long _Accum u_long_accum = 4294967296.0ulk; // expected-error{{this value is too large for this fixed point type}} + +// Large values from decimal exponents +short _Accum short_accum_exp = 2.56e2hk; // expected-error{{this value is too large for this fixed point type}} +_Accum accum_exp = 6.5536e4k; // expected-error{{this value is too large for this fixed point type}} +long _Accum long_accum_exp = 4.294967296e9lk; // expected-error{{this value is too large for this fixed point type}} +unsigned short _Accum u_short_accum_exp = 2.56e2uhk; // expected-error{{this value is too large for this fixed point type}} +unsigned _Accum u_accum_exp = 6.5536e4uk; // expected-error{{this value is too large for this fixed point type}} +unsigned long _Accum u_long_accum_exp = 4.294967296e9ulk; // expected-error{{this value is too large for this fixed point type}} + +// Large value from hexidecimal exponents +short _Accum short_accum_hex_exp = 0x1p8hk; // expected-error{{this value is too large for this fixed point type}} +_Accum accum_hex_exp = 0x1p16k; // expected-error{{this value is too large for this fixed point type}} +long _Accum long_accum_hex_exp = 0x1p32lk; // expected-error{{this value is too large for this fixed point type}} +unsigned short _Accum u_short_accum_hex_exp = 0x1p8uhk; // expected-error{{this value is too large for this fixed point type}} +unsigned _Accum u_accum_hex_exp = 0x1p16uk; // expected-error{{this value is too large for this fixed point type}} +unsigned long _Accum u_long_accum_hex_exp = 0x1p32ulk; // expected-error{{this value is too large for this fixed point type}} + +// Very large exponent +_Accum x = 1e1000000000000000000000000000000000k; // expected-error{{this value is too large for this fixed point type}} + +/* Although _Fract's cannot equal 1, _Fract literals written as 1 are allowed + * and the underlying value represents the max value for that _Fract type. */ +short _Fract short_fract_above_1 = 1.1hr; // expected-error{{this value is too large for this fixed point type}} +_Fract fract_above_1 = 1.1r; // expected-error{{this value is too large for this fixed point type}} +long _Fract long_fract_above_1 = 1.1lr; // expected-error{{this value is too large for this fixed point type}} +unsigned short _Fract u_short_fract_above_1 = 1.1uhr; // expected-error{{this value is too large for this fixed point type}} +unsigned _Fract u_fract_above_1 = 1.1ur; // expected-error{{this value is too large for this fixed point type}} +unsigned long _Fract u_long_fract_above_1 = 1.1ulr; // expected-error{{this value is too large for this fixed point type}} + +short _Fract short_fract_hex_exp = 0x0.fp1hr; // expected-error{{this value is too large for this fixed point type}} +_Fract fract_hex_exp = 0x0.fp1r; // expected-error{{this value is too large for this fixed point type}} +long _Fract long_fract_hex_exp = 0x0.fp1lr; // expected-error{{this value is too large for this fixed point type}} +unsigned short _Fract u_short_fract_hex_exp = 0x0.fp1uhr; // expected-error{{this value is too large for this fixed point type}} +unsigned _Fract u_fract_hex_exp = 0x0.fp1ur; // expected-error{{this value is too large for this fixed point type}} +unsigned long _Fract u_long_fract_hex_exp = 0x0.fp1ulr; // expected-error{{this value is too large for this fixed point type}} + /* Do not allow typedef to be used with typedef'd types */ typedef short _Fract shortfract_t; typedef short _Accum shortaccum_t; @@ -91,3 +135,16 @@ _Sat fract_t td_sat_fract; // expected-error{{'_Sat' specifier _Sat accum_t td_sat_accum; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}} _Sat longfract_t td_sat_long_fract; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}} _Sat longaccum_t td_sat_long_accum; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}} + +/* Bad suffixes */ +_Accum fk = 1.0fk; // expected-error{{invalid suffix 'fk' on integer constant}} +_Accum kk = 1.0kk; // expected-error{{invalid suffix 'kk' on integer constant}} +_Accum rk = 1.0rk; // expected-error{{invalid suffix 'rk' on integer constant}} +_Accum rk = 1.0rr; // expected-error{{invalid suffix 'rr' on integer constant}} +_Accum qk = 1.0qr; // expected-error{{invalid suffix 'qr' on integer constant}} + +/* Using wrong exponent notation */ +_Accum dec_with_hex_exp1 = 0.1p10k; // expected-error{{invalid suffix 'p10k' on integer constant}} +_Accum dec_with_hex_exp2 = 0.1P10k; // expected-error{{invalid suffix 'P10k' on integer constant}} +_Accum hex_with_dex_exp1 = 0x0.1e10k; // expected-error{{hexadecimal floating constant requires an exponent}} +_Accum hex_with_dex_exp2 = 0x0.1E10k; // expected-error{{hexadecimal floating constant requires an exponent}} diff --git a/test/Frontend/fixed_point_same_fbits.c b/test/Frontend/fixed_point_same_fbits.c new file mode 100644 index 0000000000..ad88d1a73b --- /dev/null +++ b/test/Frontend/fixed_point_same_fbits.c @@ -0,0 +1,28 @@ +// RUN: %clang -ffixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=DEFAULT +// RUN: %clang -ffixed-point -fsame-fbits -S -emit-llvm -o - %s | FileCheck %s -check-prefix=SAME + +/* The scale for unsigned fixed point types should be the same as that of signed + * fixed point types when -fsame-fbits is enabled. */ + +void func() { + unsigned short _Accum u_short_accum = 0.5uhk; + unsigned _Accum u_accum = 0.5uk; + unsigned long _Accum u_long_accum = 0.5ulk; + unsigned short _Fract u_short_fract = 0.5uhr; + unsigned _Fract u_fract = 0.5ur; + unsigned long _Fract u_long_fract = 0.5ulr; + +// DEFAULT: store i16 128, i16* %u_short_accum, align 2 +// DEFAULT: store i32 32768, i32* %u_accum, align 4 +// DEFAULT: store i64 2147483648, i64* %u_long_accum, align 8 +// DEFAULT: store i8 -128, i8* %u_short_fract, align 1 +// DEFAULT: store i16 -32768, i16* %u_fract, align 2 +// DEFAULT: store i32 -2147483648, i32* %u_long_fract, align 4 + +// SAME: store i16 64, i16* %u_short_accum, align 2 +// SAME: store i32 16384, i32* %u_accum, align 4 +// SAME: store i64 1073741824, i64* %u_long_accum, align 8 +// SAME: store i8 64, i8* %u_short_fract, align 1 +// SAME: store i16 16384, i16* %u_fract, align 2 +// SAME: store i32 1073741824, i32* %u_long_fract, align 4 +} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 1c291d7332..c2aac1f102 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -5061,6 +5061,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("VariableRef"); case CXCursor_IntegerLiteral: return cxstring::createRef("IntegerLiteral"); + case CXCursor_FixedPointLiteral: + return cxstring::createRef("FixedPointLiteral"); case CXCursor_FloatingLiteral: return cxstring::createRef("FloatingLiteral"); case CXCursor_ImaginaryLiteral: diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index bce9351b94..b4ad0595cc 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -305,6 +305,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, K = CXCursor_IntegerLiteral; break; + case Stmt::FixedPointLiteralClass: + K = CXCursor_FixedPointLiteral; + break; + case Stmt::FloatingLiteralClass: K = CXCursor_FloatingLiteral; break; -- GitLab From 0fc71c52cfe2f8fdffe193d11ab60e714cc22e93 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Wed, 20 Jun 2018 18:48:05 +0000 Subject: [PATCH 0196/1023] Fixed test that failed when checking what variable a value was stored in for fixed point types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335155 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Frontend/fixed_point_same_fbits.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/Frontend/fixed_point_same_fbits.c b/test/Frontend/fixed_point_same_fbits.c index ad88d1a73b..255f7de89f 100644 --- a/test/Frontend/fixed_point_same_fbits.c +++ b/test/Frontend/fixed_point_same_fbits.c @@ -12,17 +12,17 @@ void func() { unsigned _Fract u_fract = 0.5ur; unsigned long _Fract u_long_fract = 0.5ulr; -// DEFAULT: store i16 128, i16* %u_short_accum, align 2 -// DEFAULT: store i32 32768, i32* %u_accum, align 4 -// DEFAULT: store i64 2147483648, i64* %u_long_accum, align 8 -// DEFAULT: store i8 -128, i8* %u_short_fract, align 1 -// DEFAULT: store i16 -32768, i16* %u_fract, align 2 -// DEFAULT: store i32 -2147483648, i32* %u_long_fract, align 4 +// DEFAULT: store i16 128, i16* {{.*}}, align 2 +// DEFAULT: store i32 32768, i32* {{.*}}, align 4 +// DEFAULT: store i64 2147483648, i64* {{.*}}, align 8 +// DEFAULT: store i8 -128, i8* {{.*}}, align 1 +// DEFAULT: store i16 -32768, i16* {{.*}}, align 2 +// DEFAULT: store i32 -2147483648, i32* {{.*}}, align 4 -// SAME: store i16 64, i16* %u_short_accum, align 2 -// SAME: store i32 16384, i32* %u_accum, align 4 -// SAME: store i64 1073741824, i64* %u_long_accum, align 8 -// SAME: store i8 64, i8* %u_short_fract, align 1 -// SAME: store i16 16384, i16* %u_fract, align 2 -// SAME: store i32 1073741824, i32* %u_long_fract, align 4 +// SAME: store i16 64, i16* {{.*}}, align 2 +// SAME: store i32 16384, i32* {{.*}}, align 4 +// SAME: store i64 1073741824, i64* {{.*}}, align 8 +// SAME: store i8 64, i8* {{.*}}, align 1 +// SAME: store i16 16384, i16* {{.*}}, align 2 +// SAME: store i32 1073741824, i32* {{.*}}, align 4 } -- GitLab From 222f69b5cc2a7701ac99d7906e85116ad3f5ebfa Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Wed, 20 Jun 2018 19:34:05 +0000 Subject: [PATCH 0197/1023] Fixed test in prior build where FileCheck tried to match against `common` when declaring a global variable when we primarily care about the value assigned in the test. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335159 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Frontend/fixed_point_declarations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Frontend/fixed_point_declarations.c b/test/Frontend/fixed_point_declarations.c index 47f7e9f803..5df54f38d7 100644 --- a/test/Frontend/fixed_point_declarations.c +++ b/test/Frontend/fixed_point_declarations.c @@ -1,4 +1,4 @@ -// RUN: %clang -ffixed-point -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-linux | FileCheck %s // RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s // Primary fixed point types -- GitLab From 0dbae3ef60d986835e2035443bdf5cee17940074 Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Wed, 20 Jun 2018 20:34:04 +0000 Subject: [PATCH 0198/1023] [CUDA] Removed unused __nvvm_* builtins with non-generic pointers. They were hot even hooked into CGBuiltin's machinery. Even if they were, CUDA does not support AS-specific pointers, so there would be no legal way no way to call these builtins. This came up in D47154. Differential Revision: https://reviews.llvm.org/D47845 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335168 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsNVPTX.def | 74 --------------------------- 1 file changed, 74 deletions(-) diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index 4e5d049930..08c6097977 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -475,191 +475,117 @@ BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "") // - they are used in address space analysis and optimization // So it does not hurt to expose them as builtins. // -BUILTIN(__nvvm_atom_add_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_add_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_add_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_add_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_add_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_add_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_add_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_add_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_add_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_add_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_add_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_add_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_add_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_add_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n") -BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n") BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n") TARGET_BUILTIN(__nvvm_atom_cta_add_gen_f, "ffD*f", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_add_gen_f, "ffD*f", "n", SM_60) -BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n") -BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n") TARGET_BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_cta_add_gen_d, "ddD*d", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_add_gen_d, "ddD*d", "n", SM_60) -BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_sub_gen_i, "iiD*i", "n") -BUILTIN(__nvvm_atom_sub_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_sub_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_sub_gen_l, "LiLiD*Li", "n") -BUILTIN(__nvvm_atom_sub_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_sub_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_sub_gen_ll, "LLiLLiD*LLi", "n") -BUILTIN(__nvvm_atom_xchg_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_xchg_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_xchg_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_xchg_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_xchg_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_xchg_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_xchg_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_xchg_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_xchg_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_max_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_max_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_max_s_ui, "UiUiD*3Ui", "n") BUILTIN(__nvvm_atom_max_gen_ui, "UiUiD*Ui", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ui, "UiUiD*Ui", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ui, "UiUiD*Ui", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_max_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_max_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_ul, "ULiULiD*1ULi", "n") -BUILTIN(__nvvm_atom_max_s_ul, "ULiULiD*3ULi", "n") BUILTIN(__nvvm_atom_max_gen_ul, "ULiULiD*ULi", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ul, "ULiULiD*ULi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ul, "ULiULiD*ULi", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_max_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_max_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_ull, "ULLiULLiD*1ULLi", "n") -BUILTIN(__nvvm_atom_max_s_ull, "ULLiULLiD*3ULLi", "n") BUILTIN(__nvvm_atom_max_gen_ull, "ULLiULLiD*ULLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_min_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_min_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_min_s_ui, "UiUiD*3Ui", "n") BUILTIN(__nvvm_atom_min_gen_ui, "UiUiD*Ui", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ui, "UiUiD*Ui", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ui, "UiUiD*Ui", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_min_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_min_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_ul, "ULiULiD*1ULi", "n") -BUILTIN(__nvvm_atom_min_s_ul, "ULiULiD*3ULi", "n") BUILTIN(__nvvm_atom_min_gen_ul, "ULiULiD*ULi", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ul, "ULiULiD*ULi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ul, "ULiULiD*ULi", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_min_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_min_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_ull, "ULLiULLiD*1ULLi", "n") -BUILTIN(__nvvm_atom_min_s_ull, "ULLiULLiD*3ULLi", "n") BUILTIN(__nvvm_atom_min_gen_ull, "ULLiULLiD*ULLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) -BUILTIN(__nvvm_atom_inc_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_inc_s_ui, "UiUiD*3Ui", "n") BUILTIN(__nvvm_atom_inc_gen_ui, "UiUiD*Ui", "n") TARGET_BUILTIN(__nvvm_atom_cta_inc_gen_ui, "UiUiD*Ui", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_inc_gen_ui, "UiUiD*Ui", "n", SM_60) -BUILTIN(__nvvm_atom_dec_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_dec_s_ui, "UiUiD*3Ui", "n") BUILTIN(__nvvm_atom_dec_gen_ui, "UiUiD*Ui", "n") TARGET_BUILTIN(__nvvm_atom_cta_dec_gen_ui, "UiUiD*Ui", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_dec_gen_ui, "UiUiD*Ui", "n", SM_60) -BUILTIN(__nvvm_atom_and_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_and_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_and_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_and_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_and_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_and_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_and_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_and_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_and_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_and_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_and_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_and_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_and_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_and_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_and_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_or_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_or_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_or_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_or_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_or_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_or_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_or_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_or_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_or_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_or_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_or_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_or_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_or_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_or_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_or_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_xor_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_xor_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_xor_gen_i, "iiD*i", "n") TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_i, "iiD*i", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_i, "iiD*i", "n", SM_60) -BUILTIN(__nvvm_atom_xor_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_xor_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_xor_gen_l, "LiLiD*Li", "n") TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_l, "LiLiD*Li", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_l, "LiLiD*Li", "n", SM_60) -BUILTIN(__nvvm_atom_xor_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_xor_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_xor_gen_ll, "LLiLLiD*LLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_cas_g_i, "iiD*1ii", "n") -BUILTIN(__nvvm_atom_cas_s_i, "iiD*3ii", "n") BUILTIN(__nvvm_atom_cas_gen_i, "iiD*ii", "n") TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_i, "iiD*ii", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_i, "iiD*ii", "n", SM_60) -BUILTIN(__nvvm_atom_cas_g_l, "LiLiD*1LiLi", "n") -BUILTIN(__nvvm_atom_cas_s_l, "LiLiD*3LiLi", "n") BUILTIN(__nvvm_atom_cas_gen_l, "LiLiD*LiLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_l, "LiLiD*LiLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_l, "LiLiD*LiLi", "n", SM_60) -BUILTIN(__nvvm_atom_cas_g_ll, "LLiLLiD*1LLiLLi", "n") -BUILTIN(__nvvm_atom_cas_s_ll, "LLiLLiD*3LLiLLi", "n") BUILTIN(__nvvm_atom_cas_gen_ll, "LLiLLiD*LLiLLi", "n") TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60) TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60) -- GitLab From 443ea9f82a450eca95affcddefed86a5aec03618 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 20 Jun 2018 21:12:20 +0000 Subject: [PATCH 0199/1023] [MS] Make sure __GetExceptionInfo works on types with no linkage Fixes PR36327 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335175 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.cpp | 2 ++ test/CodeGenCXX/microsoft-abi-throw.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index aa4f6461b6..7a8cd1ca4e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -645,6 +645,8 @@ void Sema::getUndefinedButUsed( !isExternalWithNoLinkageType(FD) && !FD->getMostRecentDecl()->isInlined()) continue; + if (FD->getBuiltinID()) + continue; } else { auto *VD = cast(ND); if (VD->hasDefinition() != VarDecl::DeclarationOnly) diff --git a/test/CodeGenCXX/microsoft-abi-throw.cpp b/test/CodeGenCXX/microsoft-abi-throw.cpp index 8800e97a03..cbbce2daaa 100644 --- a/test/CodeGenCXX/microsoft-abi-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-throw.cpp @@ -22,6 +22,7 @@ // CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1P6AXXZ to i8*) }, section ".xdata", comdat // CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.2* @_CTA2PAPFAH to i8*) }, section ".xdata", comdat // CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0PAPFAH@84", %eh.CatchableType* @"_CT??_R0PAX@84"] }, section ".xdata", comdat +// CHECK-DAG: @"_TI1?AUFoo@?A@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @"_CTA1?AUFoo@?A@@" to i8*) }, section ".xdata" struct N { ~N(); }; @@ -128,3 +129,12 @@ void *GetExceptionInfo_test1() { // CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1P6AXXZ to i8*) return __GetExceptionInfo(&h); } + +// PR36327: Try an exception type with no linkage. +namespace { struct Foo { } foo_exc; } + +void *GetExceptionInfo_test2() { +// CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ" +// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A@@" to i8*) + return __GetExceptionInfo(foo_exc); +} -- GitLab From fcfa2dd517ec1a6045a81e8247e346d630a22618 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 21:16:37 +0000 Subject: [PATCH 0200/1023] Add python tool to dump and construct header maps Header maps are binary files used by Xcode, which are used to map header names or paths to other locations. Clang has support for those since its inception, but there's not a lot of header map testing around. Since it's a binary format, testing becomes pretty much brittle and its hard to even know what's inside if you don't have the appropriate tools. Add a python based tool that allows creating and dumping header maps based on a json description of those. While here, rewrite tests to use the tool and remove the binary files from the tree. This tool was initially written by Daniel Dunbar. Differential Revision: https://reviews.llvm.org/D46485 rdar://problem/39994722 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335177 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 + test/CMakeLists.txt | 1 + test/Modules/crash-vfs-headermaps.m | 10 +- .../Inputs/headermap-rel/foo.hmap | Bin 804 -> 0 bytes .../Inputs/headermap-rel/foo.hmap.json | 6 + .../headermap-rel2/project-headers.hmap | Bin 108 -> 0 bytes .../headermap-rel2/project-headers.hmap.json | 6 + .../Inputs/nonportable-hmaps/foo.hmap | Bin 102 -> 0 bytes .../Inputs/nonportable-hmaps/foo.hmap.json | 6 + test/Preprocessor/headermap-rel.c | 8 +- test/Preprocessor/headermap-rel2.c | 9 +- .../nonportable-include-with-hmap.c | 4 +- utils/hmaptool/CMakeLists.txt | 16 + utils/hmaptool/hmaptool | 296 ++++++++++++++++++ 14 files changed, 344 insertions(+), 19 deletions(-) delete mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap.json delete mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json delete mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap create mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json create mode 100644 utils/hmaptool/CMakeLists.txt create mode 100755 utils/hmaptool/hmaptool diff --git a/CMakeLists.txt b/CMakeLists.txt index ab81ec34b0..ae8835d751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,6 +753,7 @@ endif() if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() +add_subdirectory(utils/hmaptool) configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8efe3600c5..8d6db5348e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff + hmaptool ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index 4f88f3ba11..d335346028 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -1,15 +1,9 @@ // REQUIRES: crash-recovery, shell, system-darwin -// This uses a headermap with this entry: -// Foo.h -> Foo/Foo.h - -// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid -// adding another binary format to the repository. - // RUN: rm -rf %t -// RUN: mkdir -p %t/m -// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i +// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h +// RUN: hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap deleted file mode 100644 index 783c64e67bb80a38f23845ed54fac43e2dc101a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 804 zcmXR&%*|kAU|^77W?%r(4h#$ooD9Pkfc(hL0P*Ya_2sC~C=LO){CvF(2DkiteFgxL C7zHB$ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json new file mode 100644 index 0000000000..ccfd911f0f --- /dev/null +++ b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "Foo.h" : "Foo/Foo.h" + } +} diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap deleted file mode 100644 index a0770fb251242a3eec33dda98beab4f3d38adef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmXR&%*|kAU|{fIU|;~zEDQ_`A`HX Foo/Foo.h - -// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap +// RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i // CHECK: Foo.h is parsed diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index d61f3385b2..172821efa4 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,8 +1,7 @@ -// This uses a headermap with this entry: -// someheader.h -> Product/someheader.h - -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap +// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H +// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index fc958e7e5e..0190d13498 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,5 +1,7 @@ +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ -// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \ +// RUN: -I%t.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ // RUN: %s -verify // diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt new file mode 100644 index 0000000000..f5cc7d856a --- /dev/null +++ b/utils/hmaptool/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CLANG_HMAPTOOL hmaptool) + +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} + ${CMAKE_BINARY_DIR}/bin/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) + +list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) +install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) + +add_custom_target(hmaptool ALL DEPENDS ${Depends}) +set_target_properties(hmaptool PROPERTIES FOLDER "Utils") + diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool new file mode 100755 index 0000000000..2b1ca7436c --- /dev/null +++ b/utils/hmaptool/hmaptool @@ -0,0 +1,296 @@ +#!/usr/bin/env python +from __future__ import print_function + +import json +import optparse +import os +import struct +import sys + +### + +k_header_magic_LE = 'pamh' +k_header_magic_BE = 'hmap' + +def hmap_hash(str): + """hash(str) -> int + + Apply the "well-known" headermap hash function. + """ + + return sum((ord(c.lower()) * 13 + for c in str), 0) + +class HeaderMap(object): + @staticmethod + def frompath(path): + with open(path, 'rb') as f: + magic = f.read(4) + if magic == k_header_magic_LE: + endian_code = '<' + elif magic == k_header_magic_BE: + endian_code = '>' + else: + raise SystemExit("error: %s: not a headermap" % ( + path,)) + + # Read the header information. + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + data = f.read(header_size) + if len(data) != header_size: + raise SystemExit("error: %s: truncated headermap header" % ( + path,)) + + (version, reserved, strtable_offset, num_entries, + num_buckets, max_value_len) = struct.unpack(header_fmt, data) + + if version != 1: + raise SystemExit("error: %s: unknown headermap version: %r" % ( + path, version)) + if reserved != 0: + raise SystemExit("error: %s: invalid reserved value in header" % ( + path,)) + + # The number of buckets must be a power of two. + if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0: + raise SystemExit("error: %s: invalid number of buckets" % ( + path,)) + + # Read all of the buckets. + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + buckets_data = f.read(num_buckets * bucket_size) + if len(buckets_data) != num_buckets * bucket_size: + raise SystemExit("error: %s: truncated headermap buckets" % ( + path,)) + buckets = [struct.unpack(bucket_fmt, + buckets_data[i*bucket_size:(i+1)*bucket_size]) + for i in range(num_buckets)] + + # Read the string table; the format doesn't explicitly communicate the + # size of the string table (which is dumb), so assume it is the rest of + # the file. + f.seek(0, 2) + strtable_size = f.tell() - strtable_offset + f.seek(strtable_offset) + + if strtable_size == 0: + raise SystemExit("error: %s: unable to read zero-sized string table"%( + path,)) + strtable = f.read(strtable_size) + + if len(strtable) != strtable_size: + raise SystemExit("error: %s: unable to read complete string table"%( + path,)) + if strtable[-1] != '\0': + raise SystemExit("error: %s: invalid string table in headermap" % ( + path,)) + + return HeaderMap(num_entries, buckets, strtable) + + def __init__(self, num_entries, buckets, strtable): + self.num_entries = num_entries + self.buckets = buckets + self.strtable = strtable + + def get_string(self, idx): + if idx >= len(self.strtable): + raise SystemExit("error: %s: invalid string index" % ( + path,)) + end_idx = self.strtable.index('\0', idx) + return self.strtable[idx:end_idx] + + @property + def mappings(self): + for key_idx,prefix_idx,suffix_idx in self.buckets: + if key_idx == 0: + continue + yield (self.get_string(key_idx), + self.get_string(prefix_idx) + self.get_string(suffix_idx)) + +### + +def action_dump(name, args): + "dump a headermap file" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("-v", "--verbose", dest="verbose", + help="show more verbose output [%default]", + action="store_true", default=False) + (opts, args) = parser.parse_args(args) + + if len(args) != 1: + parser.error("invalid number of arguments") + + path, = args + + hmap = HeaderMap.frompath(path) + + # Dump all of the buckets. + print ('Header Map: %s' % (path,)) + if opts.verbose: + print ('headermap: %r' % (path,)) + print (' num entries: %d' % (hmap.num_entries,)) + print (' num buckets: %d' % (len(hmap.buckets),)) + print (' string table size: %d' % (len(hmap.strtable),)) + for i,bucket in enumerate(hmap.buckets): + key_idx,prefix_idx,suffix_idx = bucket + + if key_idx == 0: + continue + + # Get the strings. + key = hmap.get_string(key_idx) + prefix = hmap.get_string(prefix_idx) + suffix = hmap.get_string(suffix_idx) + + print (" bucket[%d]: %r -> (%r, %r) -- %d" % ( + i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1)))) + else: + mappings = sorted(hmap.mappings) + for key,value in mappings: + print ("%s -> %s" % (key, value)) + print () + +def next_power_of_two(value): + if value < 0: + raise ArgumentError + return 1 if value == 0 else 2**(value - 1).bit_length() + +def action_write(name, args): + "write a headermap file from a JSON definition" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + + input_path,output_path = args + + with open(input_path, "r") as f: + input_data = json.load(f) + + # Compute the headermap contents, we make a table that is 1/3 full. + mappings = input_data['mappings'] + num_buckets = next_power_of_two(len(mappings) * 3) + + table = [(0, 0, 0) + for i in range(num_buckets)] + max_value_len = 0 + strtable = "\0" + for key,value in mappings.items(): + if not isinstance(key, str): + key = key.decode('utf-8') + if not isinstance(value, str): + value = value.decode('utf-8') + max_value_len = max(max_value_len, len(value)) + + key_idx = len(strtable) + strtable += key + '\0' + prefix = os.path.dirname(value) + '/' + suffix = os.path.basename(value) + prefix_idx = len(strtable) + strtable += prefix + '\0' + suffix_idx = len(strtable) + strtable += suffix + '\0' + + hash = hmap_hash(key) + for i in range(num_buckets): + idx = (hash + i) % num_buckets + if table[idx][0] == 0: + table[idx] = (key_idx, prefix_idx, suffix_idx) + break + else: + raise RuntimeError + + endian_code = '<' + magic = k_header_magic_LE + magic_size = 4 + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + strtable_offset = magic_size + header_size + num_buckets * bucket_size + header = (1, 0, strtable_offset, len(mappings), + num_buckets, max_value_len) + + # Write out the headermap. + with open(output_path, 'wb') as f: + f.write(magic.encode()) + f.write(struct.pack(header_fmt, *header)) + for bucket in table: + f.write(struct.pack(bucket_fmt, *bucket)) + f.write(strtable.encode()) + +def action_tovfs(name, args): + "convert a headermap to a VFS layout" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("", "--build-path", dest="build_path", + help="build path prefix", + action="store", type=str) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + if opts.build_path is None: + parser.error("--build-path is required") + + input_path,output_path = args + + hmap = HeaderMap.frompath(input_path) + + # Create the table for all the objects. + vfs = {} + vfs['version'] = 0 + build_dir_contents = [] + vfs['roots'] = [{ + 'name' : opts.build_path, + 'type' : 'directory', + 'contents' : build_dir_contents }] + + # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to + # "/Foo.framework/Headers/Bar.h". + for key,value in hmap.mappings: + # If this isn't a framework style mapping, ignore it. + components = key.split('/') + if len(components) != 2: + continue + framework_name,header_name = components + build_dir_contents.append({ + 'name' : '%s.framework/Headers/%s' % (framework_name, + header_name), + 'type' : 'file', + 'external-contents' : value }) + + with open(output_path, 'w') as f: + json.dump(vfs, f, indent=2) + +commands = dict((name[7:].replace("_","-"), f) + for name,f in locals().items() + if name.startswith('action_')) + +def usage(): + print ("Usage: %s command [options]" % ( + os.path.basename(sys.argv[0])), file=sys.stderr) + print (file=sys.stderr) + print ("Available commands:", file=sys.stderr) + cmds_width = max(map(len, commands)) + for name,func in sorted(commands.items()): + print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr) + sys.exit(1) + +def main(): + if len(sys.argv) < 2 or sys.argv[1] not in commands: + usage() + + cmd = sys.argv[1] + commands[cmd](cmd, sys.argv[2:]) + +if __name__ == '__main__': + main() -- GitLab From 39990b1e95721caf4dbe0cee68a46552f7f03dd1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 20 Jun 2018 21:58:20 +0000 Subject: [PATCH 0201/1023] Related to PR37768: improve diagnostics for class name shadowing. Diagnose the name of the class being shadowed by using declarations, and improve the diagnostics for the case where the name of the class is shadowed by a non-static data member in a class with constructors. In the latter case, we now always give the "member with the same name as its class" diagnostic regardless of the relative order of the member and the constructor, rather than giving an inscrutible diagnostic if the constructor appears second. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335182 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++ lib/Parse/ParseDecl.cpp | 14 ++++---- lib/Parse/ParseExprCXX.cpp | 16 ++++----- lib/Sema/SemaDeclCXX.cpp | 58 +++++++++++++++++++++++--------- lib/Sema/SemaExprCXX.cpp | 33 ++++++++++++++++++ test/CXX/class/class.mem/p13.cpp | 47 ++++++++++++++++++++++++++ test/CXX/class/class.mem/p14.cpp | 5 ++- test/CXX/drs/dr0xx.cpp | 5 ++- 8 files changed, 143 insertions(+), 38 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7641814319..8b4cf02fde 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4984,6 +4984,8 @@ public: SourceLocation NameLoc, IdentifierInfo &Name); + ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec &SS, @@ -5704,6 +5706,7 @@ public: //===--------------------------------------------------------------------===// // C++ Classes // + CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 83bfd46d89..e369156548 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3250,6 +3250,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } + // If we're in a context where the identifier could be a class name, + // check whether this is a constructor declaration. + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && + isConstructorDeclarator(/*Unqualified*/true)) + goto DoneWithDeclSpec; + ParsedType TypeRep = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr, false, false, nullptr, false, false, @@ -3269,13 +3276,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; } - // If we're in a context where the identifier could be a class name, - // check whether this is a constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && - isConstructorDeclarator(/*Unqualified*/true)) - goto DoneWithDeclSpec; - // Likewise, if this is a context where the identifier could be a template // name, check whether this is a deduction guide declaration. if (getLangOpts().CPlusPlus17 && diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index ad91ff0021..26b8a0f779 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2505,10 +2505,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. - ParsedType Ty = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, false, - false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NonTrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS); + if (!Ty) + return true; Result.setConstructorName(Ty, IdLoc, IdLoc); } else if (getLangOpts().CPlusPlus17 && AllowDeductionGuide && SS.isEmpty() && @@ -2555,11 +2554,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, << TemplateId->Name << FixItHint::CreateRemoval( SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); - ParsedType Ty = - Actions.getTypeName(*TemplateId->Name, TemplateId->TemplateNameLoc, - getCurScope(), &SS, false, false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NontrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName( + *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS); + if (!Ty) + return true; Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); ConsumeAnnotationToken(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 7a7e0378cf..f397949964 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2059,24 +2059,36 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { return true; } +/// Get the class that is directly named by the current context. This is the +/// class for which an unqualified-id in this scope could name a constructor +/// or destructor. +/// +/// If the scope specifier denotes a class, this will be that class. +/// If the scope specifier is empty, this will be the class whose +/// member-specification we are currently within. Otherwise, there +/// is no such class. +CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { + assert(getLangOpts().CPlusPlus && "No class names in C!"); + + if (SS && SS->isInvalid()) + return nullptr; + + if (SS && SS->isNotEmpty()) { + DeclContext *DC = computeDeclContext(*SS, true); + return dyn_cast_or_null(DC); + } + + return dyn_cast_or_null(CurContext); +} + /// isCurrentClassName - Determine whether the identifier II is the /// name of the class type currently being defined. In the case of /// nested classes, this will only return true if II is the name of /// the innermost class. -bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, +bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS) { - assert(getLangOpts().CPlusPlus && "No class names in C!"); - - CXXRecordDecl *CurDecl; - if (SS && SS->isSet() && !SS->isInvalid()) { - DeclContext *DC = computeDeclContext(*SS, true); - CurDecl = dyn_cast_or_null(DC); - } else - CurDecl = dyn_cast_or_null(CurContext); - - if (CurDecl && CurDecl->getIdentifier()) - return &II == CurDecl->getIdentifier(); - return false; + CXXRecordDecl *CurDecl = getCurrentClass(S, SS); + return CurDecl && &II == CurDecl->getIdentifier(); } /// Determine whether the identifier II is a typo for the name of @@ -5991,10 +6003,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; - if ((isa(D) && Record->hasUserDeclaredConstructor()) || + NamedDecl *D = (*I)->getUnderlyingDecl(); + if (((isa(D) || isa(D)) && + Record->hasUserDeclaredConstructor()) || isa(D)) { - Diag(D->getLocation(), diag::err_member_name_of_class) + Diag((*I)->getLocation(), diag::err_member_name_of_class) << D->getDeclName(); break; } @@ -9538,6 +9551,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (isa(D) || isa(D)) continue; + if (auto *RD = dyn_cast(D)) { + // C++ [class.mem]p19: + // If T is the name of a class, then [every named member other than + // a non-static data member] shall have a name different from T + if (RD->isInjectedClassName() && !isa(Target) && + !isa(Target) && + !isa(Target) && + DiagnoseClassNameShadow( + CurContext, + DeclarationNameInfo(Using->getDeclName(), Using->getLocation()))) + return true; + } + if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast(*I)) PrevShadow = Shadow; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5d1001dc84..d977ea3453 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -80,6 +80,39 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, Context.getTrivialTypeSourceInfo(Type, NameLoc)); } +ParsedType Sema::getConstructorName(IdentifierInfo &II, + SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS) { + CXXRecordDecl *CurClass = getCurrentClass(S, &SS); + assert(CurClass && &II == CurClass->getIdentifier() && + "not a constructor name"); + + if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass)) + return ParsedType(); + + // Find the injected-class-name declaration. Note that we make no attempt to + // diagnose cases where the injected-class-name is shadowed: the only + // declaration that can validly shadow the injected-class-name is a + // non-static data member, and if the class contains both a non-static data + // member and a constructor then it is ill-formed (we check that in + // CheckCompletedCXXClass). + CXXRecordDecl *InjectedClassName = nullptr; + for (NamedDecl *ND : CurClass->lookup(&II)) { + auto *RD = dyn_cast(ND); + if (RD && RD->isInjectedClassName()) { + InjectedClassName = RD; + break; + } + } + assert(InjectedClassName && "couldn't find injected class name"); + + QualType T = Context.getTypeDeclType(InjectedClassName); + DiagnoseUseOfDecl(InjectedClassName, NameLoc); + MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false); + + return ParsedType::make(T); +} + ParsedType Sema::getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp index bc01fd4d30..1b1c0c7f8f 100644 --- a/test/CXX/class/class.mem/p13.cpp +++ b/test/CXX/class/class.mem/p13.cpp @@ -67,3 +67,50 @@ struct X4 { // expected-note{{previous}} }; }; }; + +// This includes such things inherited from base classes. +struct B { + static int D0; + int Da() {}; + enum D1 {}; + struct D1a; + typedef int D2; + using D2a = int; + template struct D2b; + template void D2c(); + template static int D2d; + template using D2e = int; + union { int D4; }; + int Dtemplate; + int Dtemplate_with_ctors; +}; +struct B2 { int Dtemplate(); }; + +struct D0 : B { using B::D0; }; // expected-error {{member 'D0' has the same name as its class}} +struct Da : B { using B::Da; }; // expected-error {{member 'Da' has the same name as its class}} +struct D1 : B { using B::D1; }; // expected-error {{member 'D1' has the same name as its class}} +struct D1a : B { using B::D1a; }; // expected-error {{member 'D1a' has the same name as its class}} +struct D2 : B { using B::D2; }; // expected-error {{member 'D2' has the same name as its class}} +struct D2a : B { using B::D2a; }; // expected-error {{member 'D2a' has the same name as its class}} +struct D2b : B { using B::D2b; }; // expected-error {{member 'D2b' has the same name as its class}} +struct D2c : B { using B::D2c; }; // expected-error {{member 'D2c' has the same name as its class}} +struct D2d : B { using B::D2d; }; // expected-error {{member 'D2d' has the same name as its class}} +struct D2e : B { using B::D2e; }; // expected-error {{member 'D2e' has the same name as its class}} +struct D4 : B { using B::D4; }; // expected-error {{member 'D4' has the same name as its class}} + +template struct Dtemplate : B { + using B::Dtemplate; // expected-error {{member 'Dtemplate' has the same name as its class}} +}; +Dtemplate ok; +Dtemplate error; // expected-note {{in instantiation of}} + +template struct Dtemplate_with_ctors : B { + Dtemplate_with_ctors(); + using B::Dtemplate_with_ctors; // expected-error {{member 'Dtemplate_with_ctors' has the same name as its class}} +}; + +template struct CtorDtorName : B { + using B::CtorDtorName; // expected-error {{member 'CtorDtorName' has the same name as its class}} + CtorDtorName(); + ~CtorDtorName(); // expected-error {{expected the class name after '~' to name a destructor}} +}; diff --git a/test/CXX/class/class.mem/p14.cpp b/test/CXX/class/class.mem/p14.cpp index 3f14099ef8..a2f6061856 100644 --- a/test/CXX/class/class.mem/p14.cpp +++ b/test/CXX/class/class.mem/p14.cpp @@ -9,9 +9,8 @@ struct X0 { }; struct X1 { - int X1; // expected-note{{hidden by a non-type declaration of 'X1' here}} - X1(); // expected-error{{must use 'struct' tag to refer to type 'X1' in this scope}} \ - // expected-error{{expected member name or ';' after declaration specifiers}} + int X1; // expected-error{{member 'X1' has the same name as its class}} + X1(); }; struct X2 { diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index a311d8f339..048187814d 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -911,9 +911,8 @@ namespace dr80 { // dr80: yes static int B; // expected-error {{same name as its class}} }; struct C { - int C; // expected-note {{hidden by}} - // FIXME: These diagnostics aren't very good. - C(); // expected-error {{must use 'struct' tag to refer to}} expected-error {{expected member name}} + int C; // expected-error {{same name as its class}} + C(); }; struct D { D(); -- GitLab From 9b5ff2db7e31c4bb11a7d468260b068b41c7c285 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 22:11:59 +0000 Subject: [PATCH 0202/1023] Warning for framework headers using double quote includes Introduce -Wquoted-include-in-framework-header, which should fire a warning whenever a quote include appears in a framework header and suggest a fix-it. For instance, for header A.h added in the tests, this is how the warning looks like: ./A.framework/Headers/A.h:2:10: warning: double-quoted include "A0.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "A0.h" ^~~~~~ ./A.framework/Headers/A.h:3:10: warning: double-quoted include "B.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "B.h" ^~~~~ This helps users to prevent frameworks from using local headers when in fact they should be targetting system level ones. The warning is off by default. Differential Revision: https://reviews.llvm.org/D47157 rdar://problem/37077034 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335184 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticLexKinds.td | 5 ++ lib/Lex/HeaderSearch.cpp | 65 ++++++++++++++++++- .../double-quotes/A.framework/Headers/A.h | 6 ++ .../double-quotes/A.framework/Headers/A0.h | 1 + .../A.framework/Modules/module.modulemap | 5 ++ test/Modules/Inputs/double-quotes/B.h | 1 + .../double-quotes/X.framework/Headers/X.h | 1 + .../X.framework/Modules/module.modulemap | 4 ++ test/Modules/Inputs/double-quotes/a.hmap.json | 6 ++ .../Inputs/double-quotes/flat-header-path/Z.h | 1 + .../flat-header-path/Z.modulemap | 4 ++ test/Modules/Inputs/double-quotes/x.hmap.json | 7 ++ test/Modules/Inputs/double-quotes/z.yaml | 28 ++++++++ test/Modules/double-quotes.m | 39 +++++++++++ 15 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/B.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Headers/X.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/a.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.h create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap create mode 100644 test/Modules/Inputs/double-quotes/x.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/z.yaml create mode 100644 test/Modules/double-quotes.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 643c178743..7cc9967738 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; +def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 9b7f7e6777..de6bffcdca 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -714,6 +714,11 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; +def warn_quoted_include_in_framework_header : Warning< + "double-quoted include \"%0\" in framework header, " + "expected angle-bracketed instead" + >, InGroup, DefaultIgnore; + def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup, DefaultIgnore; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 1f2c339ea3..757cd097e4 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,6 +621,59 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } +static bool isFrameworkStylePath(StringRef Path, + SmallVectorImpl &FrameworkName) { + using namespace llvm::sys; + path::const_iterator I = path::begin(Path); + path::const_iterator E = path::end(Path); + + // Detect different types of framework style paths: + // + // ...Foo.framework/{Headers,PrivateHeaders} + // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} + // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} + // ... + // + // and some other variations among these lines. + int FoundComp = 0; + while (I != E) { + if (I->endswith(".framework")) { + FrameworkName.append(I->begin(), I->end()); + ++FoundComp; + } + if (*I == "Headers" || *I == "PrivateHeaders") + ++FoundComp; + ++I; + } + + return FoundComp >= 2; +} + +static void +diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, + StringRef Includer, StringRef IncludeFilename, + const FileEntry *IncludeFE, bool isAngled = false, + bool FoundByHeaderMap = false) { + SmallString<128> FromFramework, ToFramework; + if (!isFrameworkStylePath(Includer, FromFramework)) + return; + bool IsIncludeeInFramework = + isFrameworkStylePath(IncludeFE->getName(), ToFramework); + + if (!isAngled && !FoundByHeaderMap) { + SmallString<128> NewInclude("<"); + if (IsIncludeeInFramework) { + NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework + NewInclude += "/"; + } + NewInclude += IncludeFilename; + NewInclude += ">"; + Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) + << IncludeFilename + << FixItHint::CreateReplacement(IncludeLoc, NewInclude); + } +} + /// LookupFile - Given a "foo" or \ reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -722,8 +775,12 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) + if (First) { + diagnoseFrameworkInclude(Diags, IncludeLoc, + IncluderAndDir.second->getName(), Filename, + FE); return FE; + } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -834,6 +891,12 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } + bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; + if (!Includers.empty()) + diagnoseFrameworkInclude(Diags, IncludeLoc, + Includers.front().second->getName(), Filename, + FE, isAngled, FoundByHeaderMap); + // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h new file mode 100644 index 0000000000..17ceb83bb9 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h @@ -0,0 +1,6 @@ +#include "A0.h" +#include "B.h" + +#include "X.h" + +int foo(); diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h new file mode 100644 index 0000000000..79c6b8893b --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h @@ -0,0 +1 @@ +// double-quotes/A.framework/Headers/A0.h diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..09a887a8f4 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +// double-quotes/A.framework/Modules/module.modulemap +framework module A { + header "A.h" + header "A0.h" +} diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h new file mode 100644 index 0000000000..724faaef80 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/B.h @@ -0,0 +1 @@ +// double-quotes/B.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h new file mode 100644 index 0000000000..0185751299 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h @@ -0,0 +1 @@ +// double-quotes/X.framework/Headers/X.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap new file mode 100644 index 0000000000..95524704c6 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +// double-quotes/X.framework/Modules/module.modulemap +framework module X { + header "X.h" +} diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json new file mode 100644 index 0000000000..bdd383ce41 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/a.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "A.h" : "A/A.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h new file mode 100644 index 0000000000..db96b64962 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h @@ -0,0 +1 @@ +#import "B.h" // Included from Z.h & A.h diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap new file mode 100644 index 0000000000..34441b0701 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap @@ -0,0 +1,4 @@ +// double-quotes/flat-header-path/Z.modulemap +framework module Z { + header "Z.h" +} diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json new file mode 100644 index 0000000000..2b6a059564 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/x.hmap.json @@ -0,0 +1,7 @@ + +{ + "mappings" : + { + "X.h" : "X/X.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml new file mode 100644 index 0000000000..242f821346 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/z.yaml @@ -0,0 +1,28 @@ +{ + 'version': 0, + 'case-sensitive': 'false', + 'roots': [ + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Headers", + 'contents': [ + { + 'type': 'file', + 'name': "Z.h", + 'external-contents': "TEST_DIR/flat-header-path/Z.h" + } + ] + }, + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Modules", + 'contents': [ + { + 'type': 'file', + 'name': "module.modulemap", + 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" + } + ] + } + ] +} diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m new file mode 100644 index 0000000000..b0dbf662a1 --- /dev/null +++ b/test/Modules/double-quotes.m @@ -0,0 +1,39 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap +// RUN: hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap + +// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \ +// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml + +// The output with and without modules should be the same + +// RUN: %clang_cc1 \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \ +// RUN: 2>%t/stderr + +// The same warnings show up when modules is on but -verify doesn't get it +// because they only show up under the module A building context. +// RUN: FileCheck --input-file=%t/stderr %s +// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead + +#import "A.h" +#import + +int bar() { return foo(); } + +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} -- GitLab From 1cb0fd412f8bb6259cd621e3899f3617478653d7 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 20 Jun 2018 22:56:59 +0000 Subject: [PATCH 0203/1023] Use cast instead of dyn_cast_or_null. This addresses John's post-commit review feedback. https://reviews.llvm.org/rC335021#inline-2038 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335189 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f397949964..822d5ef254 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7832,7 +7832,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, reinterpret_cast(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(dyn_cast_or_null(TagDecl)); + CheckCompletedCXXClass(cast(TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared -- GitLab From 63711c3cd337a0d22617579a904af07481139611 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 23:08:43 +0000 Subject: [PATCH 0204/1023] Fix hmaptool cmake file to work on Windows Unbreak a few windows buildbots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335190 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/hmaptool/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt index f5cc7d856a..5573009d34 100644 --- a/utils/hmaptool/CMakeLists.txt +++ b/utils/hmaptool/CMakeLists.txt @@ -1,14 +1,14 @@ set(CLANG_HMAPTOOL hmaptool) -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL} COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/bin + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/bin/ + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) -list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) +list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}) install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) add_custom_target(hmaptool ALL DEPENDS ${Depends}) -- GitLab From fc8d6b0b1110ed2dfdf4c9196500306f84db6b3f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 20 Jun 2018 23:36:55 +0000 Subject: [PATCH 0205/1023] When a dependent alignas is applied to a non-dependent typedef, prioritize the error for the bad subject over the error for the dependent / non-dependent mismatch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335191 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclAttr.cpp | 23 +++++++++++----------- test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp | 6 ++++++ 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 779192b865..614432b0e2 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3440,16 +3440,6 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &AL) { if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; - if (E->isValueDependent()) { - if (const auto *TND = dyn_cast(D)) { - if (!TND->getUnderlyingType()->isDependentType()) { - S.Diag(AL.getLoc(), diag::err_alignment_dependent_typedef_name) - << E->getSourceRange(); - return; - } - } - } - S.AddAlignedAttr(AL.getRange(), D, E, AL.getAttributeSpellingListIndex(), AL.isPackExpansion()); } @@ -3496,7 +3486,18 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, } } - if (E->isTypeDependent() || E->isValueDependent()) { + if (E->isValueDependent()) { + // We can't support a dependent alignment on a non-dependent type, + // because we have no way to model that a type is "alignment-dependent" + // but not dependent in any other way. + if (const auto *TND = dyn_cast(D)) { + if (!TND->getUnderlyingType()->isDependentType()) { + Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) + << E->getSourceRange(); + return; + } + } + // Save dependent expressions in the AST to be instantiated. AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); AA->setPackExpansion(IsPackExpansion); diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp new file mode 100644 index 0000000000..ec7b22f753 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +typedef int A alignas(4); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} +template void f() { + typedef int B alignas(N); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} +} -- GitLab From 938c027c694efcb11be392ac8f9d0127a91cc1ef Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 21 Jun 2018 00:16:32 +0000 Subject: [PATCH 0206/1023] ASan docs: no_sanitize("address") works on globals. Summary: Mention that no_sanitize attribute can be used with globals. Reviewers: alekseyshl Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48390 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335193 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/AddressSanitizer.rst | 14 +++++++++----- include/clang/Basic/AttrDocs.td | 21 +++++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst index f58995576f..20cf699ac0 100644 --- a/docs/AddressSanitizer.rst +++ b/docs/AddressSanitizer.rst @@ -197,13 +197,17 @@ this purpose. Disabling Instrumentation with ``__attribute__((no_sanitize("address")))`` -------------------------------------------------------------------------- -Some code should not be instrumented by AddressSanitizer. One may use the -function attribute ``__attribute__((no_sanitize("address")))`` (which has -deprecated synonyms `no_sanitize_address` and `no_address_safety_analysis`) to -disable instrumentation of a particular function. This attribute may not be -supported by other compilers, so we suggest to use it together with +Some code should not be instrumented by AddressSanitizer. One may use +the attribute ``__attribute__((no_sanitize("address")))`` (which has +deprecated synonyms `no_sanitize_address` and +`no_address_safety_analysis`) to disable instrumentation of a +particular function. This attribute may not be supported by other +compilers, so we suggest to use it together with ``__has_feature(address_sanitizer)``. +The same attribute used on a global variable prevents AddressSanitizer +from adding redzones around it and detecting out of bounds accesses. + Suppressing Errors in Recompiled Code (Blacklist) ------------------------------------------------- diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 1cb510560d..8210bf0a86 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -1804,13 +1804,14 @@ This attribute accepts a single parameter that must be one of the following: def NoSanitizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ -Use the ``no_sanitize`` attribute on a function declaration to specify -that a particular instrumentation or set of instrumentations should not be -applied to that function. The attribute takes a list of string literals, -which have the same meaning as values accepted by the ``-fno-sanitize=`` -flag. For example, ``__attribute__((no_sanitize("address", "thread")))`` -specifies that AddressSanitizer and ThreadSanitizer should not be applied -to the function. +Use the ``no_sanitize`` attribute on a function or a global variable +declaration to specify that a particular instrumentation or set of +instrumentations should not be applied. The attribute takes a list of +string literals, which have the same meaning as values accepted by the +``-fno-sanitize=`` flag. For example, +``__attribute__((no_sanitize("address", "thread")))`` specifies that +AddressSanitizer and ThreadSanitizer should not be applied to the +function or variable. See :ref:`Controlling Code Generation ` for a full list of supported sanitizer flags. @@ -1825,9 +1826,9 @@ def NoSanitizeAddressDocs : Documentation { let Content = [{ .. _langext-address_sanitizer: -Use ``__attribute__((no_sanitize_address))`` on a function declaration to -specify that address safety instrumentation (e.g. AddressSanitizer) should -not be applied to that function. +Use ``__attribute__((no_sanitize_address))`` on a function or a global +variable declaration to specify that address safety instrumentation +(e.g. AddressSanitizer) should not be applied. }]; } -- GitLab From e642afa2d9a93ed56722d74ed06402995f8b5b18 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:42 +0000 Subject: [PATCH 0207/1023] Revert "Fix hmaptool cmake file to work on Windows" This reverts commit 63711c3cd337a0d22617579a904af07481139611, due to breaking bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335194 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/hmaptool/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt index 5573009d34..f5cc7d856a 100644 --- a/utils/hmaptool/CMakeLists.txt +++ b/utils/hmaptool/CMakeLists.txt @@ -1,14 +1,14 @@ set(CLANG_HMAPTOOL hmaptool) -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL} +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin + ${CMAKE_BINARY_DIR}/bin COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/ + ${CMAKE_BINARY_DIR}/bin/ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) -list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}) +list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) add_custom_target(hmaptool ALL DEPENDS ${Depends}) -- GitLab From 62edf8185082bbf882f74ee7aae04c91f93e92f8 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:51 +0000 Subject: [PATCH 0208/1023] Revert "Warning for framework headers using double quote includes" This reverts commit 9b5ff2db7e31c4bb11a7d468260b068b41c7c285. Broke bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335195 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 - include/clang/Basic/DiagnosticLexKinds.td | 5 -- lib/Lex/HeaderSearch.cpp | 65 +------------------ .../double-quotes/A.framework/Headers/A.h | 6 -- .../double-quotes/A.framework/Headers/A0.h | 1 - .../A.framework/Modules/module.modulemap | 5 -- test/Modules/Inputs/double-quotes/B.h | 1 - .../double-quotes/X.framework/Headers/X.h | 1 - .../X.framework/Modules/module.modulemap | 4 -- test/Modules/Inputs/double-quotes/a.hmap.json | 6 -- .../Inputs/double-quotes/flat-header-path/Z.h | 1 - .../flat-header-path/Z.modulemap | 4 -- test/Modules/Inputs/double-quotes/x.hmap.json | 7 -- test/Modules/Inputs/double-quotes/z.yaml | 28 -------- test/Modules/double-quotes.m | 39 ----------- 15 files changed, 1 insertion(+), 173 deletions(-) delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A.h delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/B.h delete mode 100644 test/Modules/Inputs/double-quotes/X.framework/Headers/X.h delete mode 100644 test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/a.hmap.json delete mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.h delete mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/x.hmap.json delete mode 100644 test/Modules/Inputs/double-quotes/z.yaml delete mode 100644 test/Modules/double-quotes.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 7cc9967738..643c178743 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,7 +31,6 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; -def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index de6bffcdca..9b7f7e6777 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -714,11 +714,6 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; -def warn_quoted_include_in_framework_header : Warning< - "double-quoted include \"%0\" in framework header, " - "expected angle-bracketed instead" - >, InGroup, DefaultIgnore; - def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup, DefaultIgnore; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 757cd097e4..1f2c339ea3 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,59 +621,6 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } -static bool isFrameworkStylePath(StringRef Path, - SmallVectorImpl &FrameworkName) { - using namespace llvm::sys; - path::const_iterator I = path::begin(Path); - path::const_iterator E = path::end(Path); - - // Detect different types of framework style paths: - // - // ...Foo.framework/{Headers,PrivateHeaders} - // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} - // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} - // ... - // - // and some other variations among these lines. - int FoundComp = 0; - while (I != E) { - if (I->endswith(".framework")) { - FrameworkName.append(I->begin(), I->end()); - ++FoundComp; - } - if (*I == "Headers" || *I == "PrivateHeaders") - ++FoundComp; - ++I; - } - - return FoundComp >= 2; -} - -static void -diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, - StringRef Includer, StringRef IncludeFilename, - const FileEntry *IncludeFE, bool isAngled = false, - bool FoundByHeaderMap = false) { - SmallString<128> FromFramework, ToFramework; - if (!isFrameworkStylePath(Includer, FromFramework)) - return; - bool IsIncludeeInFramework = - isFrameworkStylePath(IncludeFE->getName(), ToFramework); - - if (!isAngled && !FoundByHeaderMap) { - SmallString<128> NewInclude("<"); - if (IsIncludeeInFramework) { - NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework - NewInclude += "/"; - } - NewInclude += IncludeFilename; - NewInclude += ">"; - Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) - << IncludeFilename - << FixItHint::CreateReplacement(IncludeLoc, NewInclude); - } -} - /// LookupFile - Given a "foo" or \ reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -775,12 +722,8 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) { - diagnoseFrameworkInclude(Diags, IncludeLoc, - IncluderAndDir.second->getName(), Filename, - FE); + if (First) return FE; - } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -891,12 +834,6 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } - bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; - if (!Includers.empty()) - diagnoseFrameworkInclude(Diags, IncludeLoc, - Includers.front().second->getName(), Filename, - FE, isAngled, FoundByHeaderMap); - // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h deleted file mode 100644 index 17ceb83bb9..0000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "A0.h" -#include "B.h" - -#include "X.h" - -int foo(); diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h deleted file mode 100644 index 79c6b8893b..0000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/A.framework/Headers/A0.h diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap deleted file mode 100644 index 09a887a8f4..0000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -// double-quotes/A.framework/Modules/module.modulemap -framework module A { - header "A.h" - header "A0.h" -} diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h deleted file mode 100644 index 724faaef80..0000000000 --- a/test/Modules/Inputs/double-quotes/B.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/B.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h deleted file mode 100644 index 0185751299..0000000000 --- a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/X.framework/Headers/X.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap deleted file mode 100644 index 95524704c6..0000000000 --- a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -// double-quotes/X.framework/Modules/module.modulemap -framework module X { - header "X.h" -} diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json deleted file mode 100644 index bdd383ce41..0000000000 --- a/test/Modules/Inputs/double-quotes/a.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "A.h" : "A/A.h" - } -} diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h deleted file mode 100644 index db96b64962..0000000000 --- a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h +++ /dev/null @@ -1 +0,0 @@ -#import "B.h" // Included from Z.h & A.h diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap deleted file mode 100644 index 34441b0701..0000000000 --- a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -// double-quotes/flat-header-path/Z.modulemap -framework module Z { - header "Z.h" -} diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json deleted file mode 100644 index 2b6a059564..0000000000 --- a/test/Modules/Inputs/double-quotes/x.hmap.json +++ /dev/null @@ -1,7 +0,0 @@ - -{ - "mappings" : - { - "X.h" : "X/X.h" - } -} diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml deleted file mode 100644 index 242f821346..0000000000 --- a/test/Modules/Inputs/double-quotes/z.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{ - 'version': 0, - 'case-sensitive': 'false', - 'roots': [ - { - 'type': 'directory', - 'name': "TEST_DIR/Z.framework/Headers", - 'contents': [ - { - 'type': 'file', - 'name': "Z.h", - 'external-contents': "TEST_DIR/flat-header-path/Z.h" - } - ] - }, - { - 'type': 'directory', - 'name': "TEST_DIR/Z.framework/Modules", - 'contents': [ - { - 'type': 'file', - 'name': "module.modulemap", - 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" - } - ] - } - ] -} diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m deleted file mode 100644 index b0dbf662a1..0000000000 --- a/test/Modules/double-quotes.m +++ /dev/null @@ -1,39 +0,0 @@ -// REQUIRES: shell - -// RUN: rm -rf %t -// RUN: mkdir %t - -// RUN: hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap -// RUN: hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap - -// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \ -// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml - -// The output with and without modules should be the same - -// RUN: %clang_cc1 \ -// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ -// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ -// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify - -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ -// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ -// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ -// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \ -// RUN: 2>%t/stderr - -// The same warnings show up when modules is on but -verify doesn't get it -// because they only show up under the module A building context. -// RUN: FileCheck --input-file=%t/stderr %s -// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead -// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead -// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead - -#import "A.h" -#import - -int bar() { return foo(); } - -// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}} -// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} -// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} -- GitLab From db9cf08b1f1519fc74c87b8fe3f13226e4cd80ac Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:58 +0000 Subject: [PATCH 0209/1023] Revert "Add python tool to dump and construct header maps" This reverts commit fcfa2dd517ec1a6045a81e8247e346d630a22618. Broke bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335196 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 - test/CMakeLists.txt | 1 - test/Modules/crash-vfs-headermaps.m | 10 +- .../Inputs/headermap-rel/foo.hmap | Bin 0 -> 804 bytes .../Inputs/headermap-rel/foo.hmap.json | 6 - .../headermap-rel2/project-headers.hmap | Bin 0 -> 108 bytes .../headermap-rel2/project-headers.hmap.json | 6 - .../Inputs/nonportable-hmaps/foo.hmap | Bin 0 -> 102 bytes .../Inputs/nonportable-hmaps/foo.hmap.json | 6 - test/Preprocessor/headermap-rel.c | 8 +- test/Preprocessor/headermap-rel2.c | 9 +- .../nonportable-include-with-hmap.c | 4 +- utils/hmaptool/CMakeLists.txt | 16 - utils/hmaptool/hmaptool | 296 ------------------ 14 files changed, 19 insertions(+), 344 deletions(-) create mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap delete mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap.json create mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap delete mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json create mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap delete mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json delete mode 100644 utils/hmaptool/CMakeLists.txt delete mode 100755 utils/hmaptool/hmaptool diff --git a/CMakeLists.txt b/CMakeLists.txt index ae8835d751..ab81ec34b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,7 +753,6 @@ endif() if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() -add_subdirectory(utils/hmaptool) configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d6db5348e..8efe3600c5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,7 +54,6 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff - hmaptool ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index d335346028..4f88f3ba11 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -1,9 +1,15 @@ // REQUIRES: crash-recovery, shell, system-darwin +// This uses a headermap with this entry: +// Foo.h -> Foo/Foo.h + +// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid +// adding another binary format to the repository. + // RUN: rm -rf %t -// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers +// RUN: mkdir -p %t/m +// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h -// RUN: hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap new file mode 100644 index 0000000000000000000000000000000000000000..783c64e67bb80a38f23845ed54fac43e2dc101a4 GIT binary patch literal 804 zcmXR&%*|kAU|^77W?%r(4h#$ooD9Pkfc(hL0P*Ya_2sC~C=LO){CvF(2DkiteFgxL C7zHB$ literal 0 HcmV?d00001 diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json deleted file mode 100644 index ccfd911f0f..0000000000 --- a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "Foo.h" : "Foo/Foo.h" - } -} diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap new file mode 100644 index 0000000000000000000000000000000000000000..a0770fb251242a3eec33dda98beab4f3d38adef8 GIT binary patch literal 108 zcmXR&%*|kAU|{fIU|;~zEDQ_`A`HX Foo/Foo.h + +// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i // CHECK: Foo.h is parsed diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index 172821efa4..d61f3385b2 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,7 +1,8 @@ -// RUN: rm -f %t.hmap -// RUN: hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// This uses a headermap with this entry: +// someheader.h -> Product/someheader.h + +// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H +// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index 0190d13498..fc958e7e5e 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,7 +1,5 @@ -// RUN: rm -f %t.hmap -// RUN: hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ -// RUN: -I%t.hmap \ +// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ // RUN: %s -verify // diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt deleted file mode 100644 index f5cc7d856a..0000000000 --- a/utils/hmaptool/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(CLANG_HMAPTOOL hmaptool) - -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} - COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/bin - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/bin/ - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) - -list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) -install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) - -add_custom_target(hmaptool ALL DEPENDS ${Depends}) -set_target_properties(hmaptool PROPERTIES FOLDER "Utils") - diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool deleted file mode 100755 index 2b1ca7436c..0000000000 --- a/utils/hmaptool/hmaptool +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -import json -import optparse -import os -import struct -import sys - -### - -k_header_magic_LE = 'pamh' -k_header_magic_BE = 'hmap' - -def hmap_hash(str): - """hash(str) -> int - - Apply the "well-known" headermap hash function. - """ - - return sum((ord(c.lower()) * 13 - for c in str), 0) - -class HeaderMap(object): - @staticmethod - def frompath(path): - with open(path, 'rb') as f: - magic = f.read(4) - if magic == k_header_magic_LE: - endian_code = '<' - elif magic == k_header_magic_BE: - endian_code = '>' - else: - raise SystemExit("error: %s: not a headermap" % ( - path,)) - - # Read the header information. - header_fmt = endian_code + 'HHIIII' - header_size = struct.calcsize(header_fmt) - data = f.read(header_size) - if len(data) != header_size: - raise SystemExit("error: %s: truncated headermap header" % ( - path,)) - - (version, reserved, strtable_offset, num_entries, - num_buckets, max_value_len) = struct.unpack(header_fmt, data) - - if version != 1: - raise SystemExit("error: %s: unknown headermap version: %r" % ( - path, version)) - if reserved != 0: - raise SystemExit("error: %s: invalid reserved value in header" % ( - path,)) - - # The number of buckets must be a power of two. - if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0: - raise SystemExit("error: %s: invalid number of buckets" % ( - path,)) - - # Read all of the buckets. - bucket_fmt = endian_code + 'III' - bucket_size = struct.calcsize(bucket_fmt) - buckets_data = f.read(num_buckets * bucket_size) - if len(buckets_data) != num_buckets * bucket_size: - raise SystemExit("error: %s: truncated headermap buckets" % ( - path,)) - buckets = [struct.unpack(bucket_fmt, - buckets_data[i*bucket_size:(i+1)*bucket_size]) - for i in range(num_buckets)] - - # Read the string table; the format doesn't explicitly communicate the - # size of the string table (which is dumb), so assume it is the rest of - # the file. - f.seek(0, 2) - strtable_size = f.tell() - strtable_offset - f.seek(strtable_offset) - - if strtable_size == 0: - raise SystemExit("error: %s: unable to read zero-sized string table"%( - path,)) - strtable = f.read(strtable_size) - - if len(strtable) != strtable_size: - raise SystemExit("error: %s: unable to read complete string table"%( - path,)) - if strtable[-1] != '\0': - raise SystemExit("error: %s: invalid string table in headermap" % ( - path,)) - - return HeaderMap(num_entries, buckets, strtable) - - def __init__(self, num_entries, buckets, strtable): - self.num_entries = num_entries - self.buckets = buckets - self.strtable = strtable - - def get_string(self, idx): - if idx >= len(self.strtable): - raise SystemExit("error: %s: invalid string index" % ( - path,)) - end_idx = self.strtable.index('\0', idx) - return self.strtable[idx:end_idx] - - @property - def mappings(self): - for key_idx,prefix_idx,suffix_idx in self.buckets: - if key_idx == 0: - continue - yield (self.get_string(key_idx), - self.get_string(prefix_idx) + self.get_string(suffix_idx)) - -### - -def action_dump(name, args): - "dump a headermap file" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - parser.add_option("-v", "--verbose", dest="verbose", - help="show more verbose output [%default]", - action="store_true", default=False) - (opts, args) = parser.parse_args(args) - - if len(args) != 1: - parser.error("invalid number of arguments") - - path, = args - - hmap = HeaderMap.frompath(path) - - # Dump all of the buckets. - print ('Header Map: %s' % (path,)) - if opts.verbose: - print ('headermap: %r' % (path,)) - print (' num entries: %d' % (hmap.num_entries,)) - print (' num buckets: %d' % (len(hmap.buckets),)) - print (' string table size: %d' % (len(hmap.strtable),)) - for i,bucket in enumerate(hmap.buckets): - key_idx,prefix_idx,suffix_idx = bucket - - if key_idx == 0: - continue - - # Get the strings. - key = hmap.get_string(key_idx) - prefix = hmap.get_string(prefix_idx) - suffix = hmap.get_string(suffix_idx) - - print (" bucket[%d]: %r -> (%r, %r) -- %d" % ( - i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1)))) - else: - mappings = sorted(hmap.mappings) - for key,value in mappings: - print ("%s -> %s" % (key, value)) - print () - -def next_power_of_two(value): - if value < 0: - raise ArgumentError - return 1 if value == 0 else 2**(value - 1).bit_length() - -def action_write(name, args): - "write a headermap file from a JSON definition" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - (opts, args) = parser.parse_args(args) - - if len(args) != 2: - parser.error("invalid number of arguments") - - input_path,output_path = args - - with open(input_path, "r") as f: - input_data = json.load(f) - - # Compute the headermap contents, we make a table that is 1/3 full. - mappings = input_data['mappings'] - num_buckets = next_power_of_two(len(mappings) * 3) - - table = [(0, 0, 0) - for i in range(num_buckets)] - max_value_len = 0 - strtable = "\0" - for key,value in mappings.items(): - if not isinstance(key, str): - key = key.decode('utf-8') - if not isinstance(value, str): - value = value.decode('utf-8') - max_value_len = max(max_value_len, len(value)) - - key_idx = len(strtable) - strtable += key + '\0' - prefix = os.path.dirname(value) + '/' - suffix = os.path.basename(value) - prefix_idx = len(strtable) - strtable += prefix + '\0' - suffix_idx = len(strtable) - strtable += suffix + '\0' - - hash = hmap_hash(key) - for i in range(num_buckets): - idx = (hash + i) % num_buckets - if table[idx][0] == 0: - table[idx] = (key_idx, prefix_idx, suffix_idx) - break - else: - raise RuntimeError - - endian_code = '<' - magic = k_header_magic_LE - magic_size = 4 - header_fmt = endian_code + 'HHIIII' - header_size = struct.calcsize(header_fmt) - bucket_fmt = endian_code + 'III' - bucket_size = struct.calcsize(bucket_fmt) - strtable_offset = magic_size + header_size + num_buckets * bucket_size - header = (1, 0, strtable_offset, len(mappings), - num_buckets, max_value_len) - - # Write out the headermap. - with open(output_path, 'wb') as f: - f.write(magic.encode()) - f.write(struct.pack(header_fmt, *header)) - for bucket in table: - f.write(struct.pack(bucket_fmt, *bucket)) - f.write(strtable.encode()) - -def action_tovfs(name, args): - "convert a headermap to a VFS layout" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - parser.add_option("", "--build-path", dest="build_path", - help="build path prefix", - action="store", type=str) - (opts, args) = parser.parse_args(args) - - if len(args) != 2: - parser.error("invalid number of arguments") - if opts.build_path is None: - parser.error("--build-path is required") - - input_path,output_path = args - - hmap = HeaderMap.frompath(input_path) - - # Create the table for all the objects. - vfs = {} - vfs['version'] = 0 - build_dir_contents = [] - vfs['roots'] = [{ - 'name' : opts.build_path, - 'type' : 'directory', - 'contents' : build_dir_contents }] - - # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to - # "/Foo.framework/Headers/Bar.h". - for key,value in hmap.mappings: - # If this isn't a framework style mapping, ignore it. - components = key.split('/') - if len(components) != 2: - continue - framework_name,header_name = components - build_dir_contents.append({ - 'name' : '%s.framework/Headers/%s' % (framework_name, - header_name), - 'type' : 'file', - 'external-contents' : value }) - - with open(output_path, 'w') as f: - json.dump(vfs, f, indent=2) - -commands = dict((name[7:].replace("_","-"), f) - for name,f in locals().items() - if name.startswith('action_')) - -def usage(): - print ("Usage: %s command [options]" % ( - os.path.basename(sys.argv[0])), file=sys.stderr) - print (file=sys.stderr) - print ("Available commands:", file=sys.stderr) - cmds_width = max(map(len, commands)) - for name,func in sorted(commands.items()): - print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr) - sys.exit(1) - -def main(): - if len(sys.argv) < 2 or sys.argv[1] not in commands: - usage() - - cmd = sys.argv[1] - commands[cmd](cmd, sys.argv[2:]) - -if __name__ == '__main__': - main() -- GitLab From 3cf091f2774c4050a4f6b8fccc5bbb1c856aff50 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 05:01:01 +0000 Subject: [PATCH 0210/1023] [X86] Remove masking from the 512-bit floating point max/min builtins. Use select in IR instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335200 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 8 +- lib/Headers/avx512fintrin.h | 204 +++++++++++----------------- lib/Sema/SemaChecking.cpp | 10 +- test/CodeGen/avx512f-builtins.c | 55 +++++--- 4 files changed, 121 insertions(+), 156 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index c044a78757..2128c37139 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -908,10 +908,10 @@ TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "nc", "avx51 TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "nc", "avx512f") diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 12b5f60405..b2f6e28031 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -944,104 +944,78 @@ _mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } +#define _mm512_max_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_maxpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) + #define _mm512_mask_max_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_max_round_pd((A), (B), (R)), \ + (__v8df)(W)) #define _mm512_maskz_max_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) - -#define _mm512_max_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_undefined_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_max_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_max_pd(__m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_maxpd512((__v8df) __A, (__v8df) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_max_pd(__A, __B), + (__v8df)__W); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_max_pd(__A, __B), + (__v8df)_mm512_setzero_pd()); } +#define _mm512_max_round_ps(A, B, R) \ + (__m512)__builtin_ia32_maxps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) + #define _mm512_mask_max_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_max_round_ps((A), (B), (R)), \ + (__v16sf)(W)) #define _mm512_maskz_max_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) - -#define _mm512_max_round_ps(A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_undefined_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_max_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_max_ps(__m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_maxps512((__v16sf) __A, (__v16sf) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __W, - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_max_ps(__A, __B), + (__v16sf)__W); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_max_ps(__A, __B), + (__v16sf)_mm512_setzero_ps()); } static __inline__ __m128 __DEFAULT_FN_ATTRS @@ -1205,104 +1179,78 @@ _mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } +#define _mm512_min_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_minpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) + #define _mm512_mask_min_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_min_round_pd((A), (B), (R)), \ + (__v8df)(W)) #define _mm512_maskz_min_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) - -#define _mm512_min_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_undefined_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_min_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_min_pd(__m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_minpd512((__v8df) __A, (__v8df) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_min_pd(__A, __B), + (__v8df)__W); } -#define _mm512_mask_min_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) - -#define _mm512_maskz_min_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) - -#define _mm512_min_round_ps(A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_undefined_ps(), \ - (__mmask16)-1, (int)(R)) - static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_min_pd(__A, __B), + (__v8df)_mm512_setzero_pd()); } +#define _mm512_min_round_ps(A, B, R) \ + (__m512)__builtin_ia32_minps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) + +#define _mm512_mask_min_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_min_round_ps((A), (B), (R)), \ + (__v16sf)(W)) + +#define _mm512_maskz_min_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_min_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()) + static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_min_ps(__m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_minps512((__v16sf) __A, (__v16sf) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __W, - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_min_ps(__A, __B), + (__v16sf)__W); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_min_ps(__A, __B), + (__v16sf)_mm512_setzero_ps()); } static __inline__ __m128 __DEFAULT_FN_ATTRS diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 237484a4ca..9a05d9f00e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2298,6 +2298,12 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vcvttss2usi64: ArgNum = 1; break; + case X86::BI__builtin_ia32_maxpd512: + case X86::BI__builtin_ia32_maxps512: + case X86::BI__builtin_ia32_minpd512: + case X86::BI__builtin_ia32_minps512: + ArgNum = 2; + break; case X86::BI__builtin_ia32_cvtps2pd512_mask: case X86::BI__builtin_ia32_cvttpd2dq512_mask: case X86::BI__builtin_ia32_cvttpd2qq512_mask: @@ -2327,12 +2333,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_cvtss2sd_round_mask: case X86::BI__builtin_ia32_getexpsd128_round_mask: case X86::BI__builtin_ia32_getexpss128_round_mask: - case X86::BI__builtin_ia32_maxpd512_mask: - case X86::BI__builtin_ia32_maxps512_mask: case X86::BI__builtin_ia32_maxsd_round_mask: case X86::BI__builtin_ia32_maxss_round_mask: - case X86::BI__builtin_ia32_minpd512_mask: - case X86::BI__builtin_ia32_minps512_mask: case X86::BI__builtin_ia32_minsd_round_mask: case X86::BI__builtin_ia32_minss_round_mask: case X86::BI__builtin_ia32_rcp28sd_round_mask: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 3942daa5c5..16ad425255 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -8354,140 +8354,155 @@ float test_mm512_cvtss_f32(__m512 A) { __m512d test_mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_max_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_max_pd (__W,__U,__A,__B); } __m512d test_mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_max_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_max_pd (__U,__A,__B); } __m512 test_mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_max_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_max_ps (__W,__U,__A,__B); } __m512d test_mm512_mask_max_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_mask_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_max_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_maskz_max_round_pd(__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_maskz_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_max_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_max_round_pd(__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 return _mm512_max_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_max_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_max_ps (__U,__A,__B); } __m512 test_mm512_mask_max_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_mask_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_max_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_max_round_ps(__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_maskz_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_max_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_max_round_ps(__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 return _mm512_max_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_min_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_min_pd (__W,__U,__A,__B); } __m512d test_mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_min_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 return _mm512_maskz_min_pd (__U,__A,__B); } __m512d test_mm512_mask_min_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_mask_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_min_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_maskz_min_round_pd(__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_maskz_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_min_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_min_round_pd( __m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 return _mm512_min_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_min_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_min_ps (__W,__U,__A,__B); } __m512 test_mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_min_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_min_ps (__U,__A,__B); } __m512 test_mm512_mask_min_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_mask_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_min_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_min_round_ps(__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_maskz_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_min_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_min_round_ps(__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 return _mm512_min_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION); } -- GitLab From 61f72dee117ea4f68a1154057eaf060978e76b97 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Jun 2018 08:34:50 +0000 Subject: [PATCH 0211/1023] [Sema] Fix overloaded static functions for templates Apply almost the same fix as https://reviews.llvm.org/D36390 but for templates. Differential Revision: https://reviews.llvm.org/D43453 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335211 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 80 ++++++++++++++++++------------------ test/Index/complete-call.cpp | 68 ++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 50 deletions(-) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 89cb9b53a4..b1df8f6232 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6363,63 +6363,61 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, /// the overload candidate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef Args, - OverloadCandidateSet& CandidateSet, + OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, bool PartialOverloading, bool FirstArgumentIsBase) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); - if (FunctionDecl *FD = dyn_cast(D)) { - ArrayRef FunctionArgs = Args; - if (isa(FD) && !cast(FD)->isStatic()) { - QualType ObjectType; - Expr::Classification ObjectClassification; - if (Args.size() > 0) { - if (Expr *E = Args[0]) { - // Use the explicit base to restrict the lookup: - ObjectType = E->getType(); - ObjectClassification = E->Classify(Context); - } // .. else there is an implit base. - FunctionArgs = Args.slice(1); - } - AddMethodCandidate(cast(FD), F.getPair(), - cast(FD)->getParent(), ObjectType, - ObjectClassification, FunctionArgs, CandidateSet, - SuppressUserConversions, PartialOverloading); - } else { - // Slice the first argument (which is the base) when we access - // static method as non-static - if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa(FD) && - !isa(FD)))) { - assert(cast(FD)->isStatic()); - FunctionArgs = Args.slice(1); - } - AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, - SuppressUserConversions, PartialOverloading); - } - } else { - FunctionTemplateDecl *FunTmpl = cast(D); - if (isa(FunTmpl->getTemplatedDecl()) && - !cast(FunTmpl->getTemplatedDecl())->isStatic()) { - QualType ObjectType; - Expr::Classification ObjectClassification; + ArrayRef FunctionArgs = Args; + + FunctionTemplateDecl *FunTmpl = dyn_cast(D); + FunctionDecl *FD = + FunTmpl ? FunTmpl->getTemplatedDecl() : cast(D); + + if (isa(FD) && !cast(FD)->isStatic()) { + QualType ObjectType; + Expr::Classification ObjectClassification; + if (Args.size() > 0) { if (Expr *E = Args[0]) { // Use the explicit base to restrict the lookup: ObjectType = E->getType(); ObjectClassification = E->Classify(Context); - } // .. else there is an implit base. + } // .. else there is an implicit base. + FunctionArgs = Args.slice(1); + } + if (FunTmpl) { AddMethodTemplateCandidate( FunTmpl, F.getPair(), cast(FunTmpl->getDeclContext()), ExplicitTemplateArgs, ObjectType, ObjectClassification, - Args.slice(1), CandidateSet, SuppressUserConversions, + FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); } else { - AddTemplateOverloadCandidate(FunTmpl, F.getPair(), - ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions, - PartialOverloading); + AddMethodCandidate(cast(FD), F.getPair(), + cast(FD)->getParent(), ObjectType, + ObjectClassification, FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); + } + } else { + // This branch handles both standalone functions and static methods. + + // Slice the first argument (which is the base) when we access + // static method as non-static. + if (Args.size() > 0 && + (!Args[0] || (FirstArgumentIsBase && isa(FD) && + !isa(FD)))) { + assert(cast(FD)->isStatic()); + FunctionArgs = Args.slice(1); + } + if (FunTmpl) { + AddTemplateOverloadCandidate( + FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, + CandidateSet, SuppressUserConversions, PartialOverloading); + } else { + AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); } } } diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp index ca116485ac..84189a2aab 100644 --- a/test/Index/complete-call.cpp +++ b/test/Index/complete-call.cpp @@ -109,12 +109,39 @@ void test() { struct Bar2 : public Bar { Bar2() { Bar::foo_1(); - } -}; - -// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s -// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC1: Completion contexts: + } +}; + +struct BarTemplates { + static void foo_1() {} + void foo_1(float) {} + static void foo_1(int) {} + + template + static void foo_1(T1 a, T2 b) { a + b; } + + template + void foo_1(T1 a, T2 b, float c) { a + b + c; } + + template + static void foo_1(T2 a, int b, T1 c) { a + b + c; } +}; + +void testTemplates() { + BarTemplates::foo_1(); + BarTemplates b; + b.foo_1(); +} + +struct Bar2Template : public BarTemplates { + Bar2Template() { + BarTemplates::foo_1(); + } +}; + +// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC1: Completion contexts: // CHECK-CC1-NEXT: Any type // CHECK-CC1-NEXT: Any value // CHECK-CC1-NEXT: Enum tag @@ -860,7 +887,30 @@ struct Bar2 : public Bar { // CHECK-CC62-NEXT: Enum tag // CHECK-CC62-NEXT: Union tag // CHECK-CC62-NEXT: Struct tag -// CHECK-CC62-NEXT: Class name -// CHECK-CC62-NEXT: Nested name specifier -// CHECK-CC62-NEXT: Objective-C interface +// CHECK-CC62-NEXT: Class name +// CHECK-CC62-NEXT: Nested name specifier +// CHECK-CC62-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) -- GitLab From bba6b10856dab9699654e2c2ca19c4d2a01f238e Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Thu, 21 Jun 2018 12:39:24 +0000 Subject: [PATCH 0212/1023] Fix line endings in recently updated test file git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335220 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/complete-call.cpp | 118 +++++++++++++++++------------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp index 84189a2aab..95bc8d49b2 100644 --- a/test/Index/complete-call.cpp +++ b/test/Index/complete-call.cpp @@ -109,39 +109,39 @@ void test() { struct Bar2 : public Bar { Bar2() { Bar::foo_1(); - } -}; - -struct BarTemplates { - static void foo_1() {} - void foo_1(float) {} - static void foo_1(int) {} - - template - static void foo_1(T1 a, T2 b) { a + b; } - - template - void foo_1(T1 a, T2 b, float c) { a + b + c; } - - template - static void foo_1(T2 a, int b, T1 c) { a + b + c; } -}; - -void testTemplates() { - BarTemplates::foo_1(); - BarTemplates b; - b.foo_1(); -} - -struct Bar2Template : public BarTemplates { - Bar2Template() { - BarTemplates::foo_1(); - } -}; - -// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s -// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC1: Completion contexts: + } +}; + +struct BarTemplates { + static void foo_1() {} + void foo_1(float) {} + static void foo_1(int) {} + + template + static void foo_1(T1 a, T2 b) { a + b; } + + template + void foo_1(T1 a, T2 b, float c) { a + b + c; } + + template + static void foo_1(T2 a, int b, T1 c) { a + b + c; } +}; + +void testTemplates() { + BarTemplates::foo_1(); + BarTemplates b; + b.foo_1(); +} + +struct Bar2Template : public BarTemplates { + Bar2Template() { + BarTemplates::foo_1(); + } +}; + +// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC1: Completion contexts: // CHECK-CC1-NEXT: Any type // CHECK-CC1-NEXT: Any value // CHECK-CC1-NEXT: Enum tag @@ -887,30 +887,30 @@ struct Bar2Template : public BarTemplates { // CHECK-CC62-NEXT: Enum tag // CHECK-CC62-NEXT: Union tag // CHECK-CC62-NEXT: Struct tag -// CHECK-CC62-NEXT: Class name -// CHECK-CC62-NEXT: Nested name specifier -// CHECK-CC62-NEXT: Objective-C interface - -// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) -// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) - -// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s -// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) -// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) -// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) -// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) - -// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) -// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) +// CHECK-CC62-NEXT: Class name +// CHECK-CC62-NEXT: Nested name specifier +// CHECK-CC62-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) -- GitLab From 41e20a3f297fbf794689979fad39a2cc77e5aafb Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Thu, 21 Jun 2018 13:40:50 +0000 Subject: [PATCH 0213/1023] [liblang] Remove DOS line endings in libclang.exports Undefined first referenced symbol in file clang_getCompletionFixIt /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getTokenLocation /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getToken /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getTemplateCursorKind /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getTUResourceUsageName /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionChunkKind /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionChunkText /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getSpellingLocation /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionParent /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionChunkCompletionString /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionPriority /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionNumFixIts /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getTokenExtent /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getCompletionNumAnnotations /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports clang_getTokenKind /var/gcc/llvm/obj/local/tools/clang/tools/libclang/libclang.exports ld: fatal: symbol referencing errors collect2: error: ld returned 1 exit status make[2]: *** [tools/clang/tools/libclang/CMakeFiles/libclang.dir/build.make:651: lib/libclang.so.7] Error 1 It turns out that this is caused by https://reviews.llvm.org/D46862: it added a couple of CRs (^M) to some lines. Solaris ld takes them to be part of the symbol names, which of course are missing from the input objects. GNU ld handles this just fine. Fixed by removing the CRs. Bootstrapped on i386-pc-solaris2.11. I guess this is obvious. Differential Revision: https://reviews.llvm.org/D48423 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335234 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/libclang.exports | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index a185bc7845..95a42712c4 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -168,14 +168,14 @@ clang_getClangVersion clang_getCompletionAnnotation clang_getCompletionAvailability clang_getCompletionBriefComment -clang_getCompletionChunkCompletionString -clang_getCompletionChunkKind -clang_getCompletionChunkText -clang_getCompletionNumFixIts -clang_getCompletionFixIt -clang_getCompletionNumAnnotations -clang_getCompletionParent -clang_getCompletionPriority +clang_getCompletionChunkCompletionString +clang_getCompletionChunkKind +clang_getCompletionChunkText +clang_getCompletionNumFixIts +clang_getCompletionFixIt +clang_getCompletionNumAnnotations +clang_getCompletionParent +clang_getCompletionPriority clang_getCursor clang_getCursorAvailability clang_getCursorCompletionString @@ -259,13 +259,13 @@ clang_getRemappingsFromFileList clang_getResultType clang_getSkippedRanges clang_getSpecializedCursorTemplate -clang_getSpellingLocation -clang_getTUResourceUsageName -clang_getTemplateCursorKind -clang_getToken -clang_getTokenExtent -clang_getTokenKind -clang_getTokenLocation +clang_getSpellingLocation +clang_getTUResourceUsageName +clang_getTemplateCursorKind +clang_getToken +clang_getTokenExtent +clang_getTokenKind +clang_getTokenLocation clang_getTokenSpelling clang_getTranslationUnitCursor clang_getTranslationUnitSpelling -- GitLab From 0be86b8c934425669a4da497cbc08425370fda0a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 16:41:28 +0000 Subject: [PATCH 0214/1023] [X86] Rewrite the add/mul/or/and reduction intrinsics to make better use of other intrinsics and remove undef shuffle indices. Similar to what was done to max/min recently. These already reduced the vector width to 256 and 128 bit as we go unlike the original max/min code. Differential Revision: https://reviews.llvm.org/D48346 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335253 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 266 +++++-------- test/CodeGen/avx512-reduceIntrin.c | 618 ++++++++++++++--------------- 2 files changed, 406 insertions(+), 478 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index b2f6e28031..534007b69f 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -9281,251 +9281,185 @@ _mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A) * Used bisection method. At each step, we partition the vector with previous * step in half, and the operation is performed on its two halves. * This takes log2(n) steps where n is the number of elements in the vector. - - * Vec512 - Vector with size 512. - * Operator - Can be one of following: +,*,&,| - * T2 - Can get 'i' for int and 'f' for float. - * T1 - Can get 'i' for int and 'd' for double. */ -#define _mm512_reduce_operator_64bit(Vec512, Operator, T2, T1) \ - __extension__({ \ - __m256##T1 Vec256 = __builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 0, 1, 2, 3) \ - Operator \ - __builtin_shufflevector( \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512, \ - 4, 5, 6, 7); \ - __m128##T1 Vec128 = __builtin_shufflevector( \ - (__v4d##T2)Vec256, \ - (__v4d##T2)Vec256, \ - 0, 1) \ - Operator \ - __builtin_shufflevector( \ - (__v4d##T2)Vec256, \ - (__v4d##T2)Vec256, \ - 2, 3); \ - Vec128 = __builtin_shufflevector((__v2d##T2)Vec128, \ - (__v2d##T2)Vec128, 0, -1) \ - Operator \ - __builtin_shufflevector((__v2d##T2)Vec128, \ - (__v2d##T2)Vec128, 1, -1); \ - return Vec128[0]; \ - }) +#define _mm512_mask_reduce_operator(op) \ + __v4du __t1 = (__v4du)_mm512_extracti64x4_epi64(__W, 0); \ + __v4du __t2 = (__v4du)_mm512_extracti64x4_epi64(__W, 1); \ + __m256i __t3 = (__m256i)(__t1 op __t2); \ + __v2du __t4 = (__v2du)_mm256_extracti128_si256(__t3, 0); \ + __v2du __t5 = (__v2du)_mm256_extracti128_si256(__t3, 1); \ + __v2du __t6 = __t4 op __t5; \ + __v2du __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \ + __v2du __t8 = __t6 op __t7; \ + return __t8[0]; static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_add_epi64(__m512i __W) { - _mm512_reduce_operator_64bit(__W, +, i, i); + _mm512_mask_reduce_operator(+); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_mul_epi64(__m512i __W) { - _mm512_reduce_operator_64bit(__W, *, i, i); + _mm512_mask_reduce_operator(*); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_and_epi64(__m512i __W) { - _mm512_reduce_operator_64bit(__W, &, i, i); + _mm512_mask_reduce_operator(&); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_or_epi64(__m512i __W) { - _mm512_reduce_operator_64bit(__W, |, i, i); -} - -static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_add_pd(__m512d __W) { - _mm512_reduce_operator_64bit(__W, +, f, d); + _mm512_mask_reduce_operator(|); } -static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_mul_pd(__m512d __W) { - _mm512_reduce_operator_64bit(__W, *, f, d); -} - -/* Vec512 - Vector with size 512. - * Vec512Neutral - All vector elements set to the identity element. - * Identity element: {+,0},{*,1},{&,0xFFFFFFFFFFFFFFFF},{|,0} - * Operator - Can be one of following: +,*,&,| - * Mask - Intrinsic Mask - * T2 - Can get 'i' for int and 'f' for float. - * T1 - Can get 'i' for int and 'd' for packed double-precision. - * T3 - Can be Pd for packed double or q for q-word. - */ - -#define _mm512_mask_reduce_operator_64bit(Vec512, Vec512Neutral, Operator, \ - Mask, T2, T1, T3) \ - __extension__({ \ - Vec512 = __builtin_ia32_select##T3##_512( \ - (__mmask8)Mask, \ - (__v8d##T2)Vec512, \ - (__v8d##T2)Vec512Neutral); \ - _mm512_reduce_operator_64bit(Vec512, Operator, T2, T1); \ - }) - static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), +, __M, i, i, q); + __W = _mm512_maskz_mov_epi64(__M, __W); + _mm512_mask_reduce_operator(+); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(1), *, __M, i, i, q); + __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(1), __M, __W); + _mm512_mask_reduce_operator(*); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF), - &, __M, i, i, q); + __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __W); + _mm512_mask_reduce_operator(&); } static __inline__ long long __DEFAULT_FN_ATTRS _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), |, __M, - i, i, q); + __W = _mm512_maskz_mov_epi64(__M, __W); + _mm512_mask_reduce_operator(|); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256d __t1 = _mm512_extractf64x4_pd(__W, 0); \ + __m256d __t2 = _mm512_extractf64x4_pd(__W, 1); \ + __m256d __t3 = __t1 op __t2; \ + __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \ + __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \ + __m128d __t6 = __t4 op __t5; \ + __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \ + __m128d __t8 = __t6 op __t7; \ + return __t8[0]; + +static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_add_pd(__m512d __W) { + _mm512_mask_reduce_operator(+); +} + +static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_mul_pd(__m512d __W) { + _mm512_mask_reduce_operator(*); } static __inline__ double __DEFAULT_FN_ATTRS _mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(0), +, __M, - f, d, pd); + __W = _mm512_maskz_mov_pd(__M, __W); + _mm512_mask_reduce_operator(+); } static __inline__ double __DEFAULT_FN_ATTRS _mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W) { - _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(1), *, __M, - f, d, pd); + __W = _mm512_mask_mov_pd(_mm512_set1_pd(1.0), __M, __W); + _mm512_mask_reduce_operator(*); } -#undef _mm512_reduce_operator_64bit -#undef _mm512_mask_reduce_operator_64bit - -/* Vec512 - Vector with size 512. - * Operator - Can be one of following: +,*,&,| - * T2 - Can get 'i' for int and ' ' for packed single. - * T1 - Can get 'i' for int and 'f' for float. - */ +#undef _mm512_mask_reduce_operator -#define _mm512_reduce_operator_32bit(Vec512, Operator, T2, T1) __extension__({ \ - __m256##T1 Vec256 = \ - (__m256##T1)(__builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 0, 1, 2, 3, 4, 5, 6, 7) \ - Operator \ - __builtin_shufflevector( \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512, \ - 8, 9, 10, 11, 12, 13, 14, 15)); \ - __m128##T1 Vec128 = \ - (__m128##T1)(__builtin_shufflevector( \ - (__v8s##T2)Vec256, \ - (__v8s##T2)Vec256, \ - 0, 1, 2, 3) \ - Operator \ - __builtin_shufflevector( \ - (__v8s##T2)Vec256, \ - (__v8s##T2)Vec256, \ - 4, 5, 6, 7)); \ - Vec128 = (__m128##T1)(__builtin_shufflevector( \ - (__v4s##T2)Vec128, \ - (__v4s##T2)Vec128, \ - 0, 1, -1, -1) \ - Operator \ - __builtin_shufflevector( \ - (__v4s##T2)Vec128, \ - (__v4s##T2)Vec128, \ - 2, 3, -1, -1)); \ - Vec128 = (__m128##T1)(__builtin_shufflevector( \ - (__v4s##T2)Vec128, \ - (__v4s##T2)Vec128, \ - 0, -1, -1, -1) \ - Operator \ - __builtin_shufflevector( \ - (__v4s##T2)Vec128, \ - (__v4s##T2)Vec128, \ - 1, -1, -1, -1)); \ - return Vec128[0]; \ - }) +#define _mm512_mask_reduce_operator(op) \ + __v8su __t1 = (__v8su)_mm512_extracti64x4_epi64(__W, 0); \ + __v8su __t2 = (__v8su)_mm512_extracti64x4_epi64(__W, 1); \ + __m256i __t3 = (__m256i)(__t1 op __t2); \ + __v4su __t4 = (__v4su)_mm256_extracti128_si256(__t3, 0); \ + __v4su __t5 = (__v4su)_mm256_extracti128_si256(__t3, 1); \ + __v4su __t6 = __t4 op __t5; \ + __v4su __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \ + __v4su __t8 = __t6 op __t7; \ + __v4su __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \ + __v4su __t10 = __t8 op __t9; \ + return __t10[0]; static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_add_epi32(__m512i __W) { - _mm512_reduce_operator_32bit(__W, +, i, i); + _mm512_mask_reduce_operator(+); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_mul_epi32(__m512i __W) { - _mm512_reduce_operator_32bit(__W, *, i, i); + _mm512_mask_reduce_operator(*); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_and_epi32(__m512i __W) { - _mm512_reduce_operator_32bit(__W, &, i, i); + _mm512_mask_reduce_operator(&); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_reduce_or_epi32(__m512i __W) { - _mm512_reduce_operator_32bit(__W, |, i, i); -} - -static __inline__ float __DEFAULT_FN_ATTRS -_mm512_reduce_add_ps(__m512 __W) { - _mm512_reduce_operator_32bit(__W, +, f, ); + _mm512_mask_reduce_operator(|); } -static __inline__ float __DEFAULT_FN_ATTRS -_mm512_reduce_mul_ps(__m512 __W) { - _mm512_reduce_operator_32bit(__W, *, f, ); -} - -/* Vec512 - Vector with size 512. - * Vec512Neutral - All vector elements set to the identity element. - * Identity element: {+,0},{*,1},{&,0xFFFFFFFF},{|,0} - * Operator - Can be one of following: +,*,&,| - * Mask - Intrinsic Mask - * T2 - Can get 'i' for int and 'f' for float. - * T1 - Can get 'i' for int and 'd' for double. - * T3 - Can be Ps for packed single or d for d-word. - */ - -#define _mm512_mask_reduce_operator_32bit(Vec512, Vec512Neutral, Operator, \ - Mask, T2, T1, T3) \ - __extension__({ \ - Vec512 = (__m512##T1)__builtin_ia32_select##T3##_512( \ - (__mmask16)Mask, \ - (__v16s##T2)Vec512, \ - (__v16s##T2)Vec512Neutral); \ - _mm512_reduce_operator_32bit(Vec512, Operator, T2, T1); \ - }) - static __inline__ int __DEFAULT_FN_ATTRS _mm512_mask_reduce_add_epi32( __mmask16 __M, __m512i __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), +, __M, i, i, d); + __W = _mm512_maskz_mov_epi32(__M, __W); + _mm512_mask_reduce_operator(+); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_mask_reduce_mul_epi32( __mmask16 __M, __m512i __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(1), *, __M, i, i, d); + __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(1), __M, __W); + _mm512_mask_reduce_operator(*); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_mask_reduce_and_epi32( __mmask16 __M, __m512i __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0xFFFFFFFF), &, __M, - i, i, d); + __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __W); + _mm512_mask_reduce_operator(&); } static __inline__ int __DEFAULT_FN_ATTRS _mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), |, __M, i, i, d); + __W = _mm512_maskz_mov_epi32(__M, __W); + _mm512_mask_reduce_operator(|); +} +#undef _mm512_mask_reduce_operator + +#define _mm512_mask_reduce_operator(op) \ + __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__W, 0); \ + __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__W, 1); \ + __m256 __t3 = __t1 op __t2; \ + __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \ + __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \ + __m128 __t6 = __t4 op __t5; \ + __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \ + __m128 __t8 = __t6 op __t7; \ + __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \ + __m128 __t10 = __t8 op __t9; \ + return __t10[0]; + +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_reduce_add_ps(__m512 __W) { + _mm512_mask_reduce_operator(+); +} + +static __inline__ float __DEFAULT_FN_ATTRS +_mm512_reduce_mul_ps(__m512 __W) { + _mm512_mask_reduce_operator(*); } static __inline__ float __DEFAULT_FN_ATTRS _mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_ps(0), +, __M, f, , ps); + __W = _mm512_maskz_mov_ps(__M, __W); + _mm512_mask_reduce_operator(+); } static __inline__ float __DEFAULT_FN_ATTRS _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { - _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_ps(1), *, __M, f, , ps); + __W = _mm512_mask_mov_ps(_mm512_set1_ps(1.0f), __M, __W); + _mm512_mask_reduce_operator(*); } -#undef _mm512_reduce_operator_32bit -#undef _mm512_mask_reduce_operator_32bit +#undef _mm512_mask_reduce_operator #define _mm512_mask_reduce_operator(op) \ __m512i __t1 = (__m512i)__builtin_shufflevector((__v8di)__V, (__v8di)__V, 4, 5, 6, 7, 0, 1, 2, 3); \ diff --git a/test/CodeGen/avx512-reduceIntrin.c b/test/CodeGen/avx512-reduceIntrin.c index d24cd0e563..8157095fc6 100644 --- a/test/CodeGen/avx512-reduceIntrin.c +++ b/test/CodeGen/avx512-reduceIntrin.c @@ -1,410 +1,404 @@ -// RUN: %clang_cc1 -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -ffreestanding %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s #include long long test_mm512_reduce_add_epi64(__m512i __W){ - // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %add.i = add <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> - // CHECK: %add4.i = add <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %add4.i, <2 x i64> undef, <2 x i32> - // CHECK: %add7.i = add <2 x i64> %shuffle6.i, %add4.i - // CHECK: %vecext.i = extractelement <2 x i64> %add7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_reduce_add_epi64( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: add <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: add <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: add <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_reduce_add_epi64(__W); } long long test_mm512_reduce_mul_epi64(__m512i __W){ - // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %mul.i = mul <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> - // CHECK: %mul4.i = mul <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %mul4.i, <2 x i64> undef, <2 x i32> - // CHECK: %mul7.i = mul <2 x i64> %shuffle6.i, %mul4.i - // CHECK: %vecext.i = extractelement <2 x i64> %mul7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_reduce_mul_epi64( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: mul <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: mul <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: mul <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_reduce_mul_epi64(__W); } long long test_mm512_reduce_or_epi64(__m512i __W){ - // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %or.i = or <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> - // CHECK: %or4.i = or <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %or4.i, <2 x i64> undef, <2 x i32> - // CHECK: %or7.i = or <2 x i64> %shuffle6.i, %or4.i - // CHECK: %vecext.i = extractelement <2 x i64> %or7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_reduce_or_epi64( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: or <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: or <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: or <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_reduce_or_epi64(__W); } long long test_mm512_reduce_and_epi64(__m512i __W){ - // CHECK: %shuffle.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <4 x i32> - // CHECK: %and.i = and <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> - // CHECK: %and4.i = and <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %and4.i, <2 x i64> undef, <2 x i32> - // CHECK: %and7.i = and <2 x i64> %shuffle6.i, %and4.i - // CHECK: %vecext.i = extractelement <2 x i64> %and7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_reduce_and_epi64( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: and <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: and <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: and <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_reduce_and_epi64(__W); } long long test_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> zeroinitializer - // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %add.i = add <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %add.i, <4 x i64> undef, <2 x i32> - // CHECK: %add4.i = add <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %add4.i, <2 x i64> undef, <2 x i32> - // CHECK: %add7.i = add <2 x i64> %shuffle6.i, %add4.i - // CHECK: %vecext.i = extractelement <2 x i64> %add7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_add_epi64( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: add <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: add <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: add <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_mask_reduce_add_epi64(__M, __W); } long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> - // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %mul.i = mul <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %mul.i, <4 x i64> undef, <2 x i32> - // CHECK: %mul4.i = mul <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %mul4.i, <2 x i64> undef, <2 x i32> - // CHECK: %mul7.i = mul <2 x i64> %shuffle6.i, %mul4.i - // CHECK: %vecext.i = extractelement <2 x i64> %mul7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_mul_epi64( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: mul <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: mul <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: mul <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_mask_reduce_mul_epi64(__M, __W); } long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> - // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %and.i = and <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %and.i, <4 x i64> undef, <2 x i32> - // CHECK: %and4.i = and <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %and4.i, <2 x i64> undef, <2 x i32> - // CHECK: %and7.i = and <2 x i64> %shuffle6.i, %and4.i - // CHECK: %vecext.i = extractelement <2 x i64> %and7.i, i32 0 +// CHECK-LABEL: @test_mm512_mask_reduce_and_epi64( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: and <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: and <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: and <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_mask_reduce_and_epi64(__M, __W); } long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x i64> %__W, <8 x i64> zeroinitializer - // CHECK: %shuffle.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x i64> {{.*}}, <8 x i64> undef, <4 x i32> - // CHECK: %or.i = or <4 x i64> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x i64> %or.i, <4 x i64> undef, <2 x i32> - // CHECK: %or4.i = or <2 x i64> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x i64> %or4.i, <2 x i64> undef, <2 x i32> - // CHECK: %or7.i = or <2 x i64> %shuffle6.i, %or4.i - // CHECK: %vecext.i = extractelement <2 x i64> %or7.i, i32 0 - // CHECK: ret i64 %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_or_epi64( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: or <4 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: or <2 x i64> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> +// CHECK: or <2 x i64> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x i64> %{{.*}}, i32 0 return _mm512_mask_reduce_or_epi64(__M, __W); } int test_mm512_reduce_add_epi32(__m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %add.i = add <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> - // CHECK: %add4.i = add <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %add4.i, <4 x i32> undef, <4 x i32> - // CHECK: %add7.i = add <4 x i32> %shuffle6.i, %add4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %add7.i, <4 x i32> undef, <4 x i32> - // CHECK: %add10.i = add <4 x i32> %shuffle9.i, %add7.i - // CHECK: {{.*}} = bitcast <4 x i32> %add10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_reduce_add_epi32( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: add <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_reduce_add_epi32(__W); } int test_mm512_reduce_mul_epi32(__m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %mul.i = mul <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> - // CHECK: %mul4.i = mul <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %mul4.i, <4 x i32> undef, <4 x i32> - // CHECK: %mul7.i = mul <4 x i32> %shuffle6.i, %mul4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %mul7.i, <4 x i32> undef, <4 x i32> - // CHECK: %mul10.i = mul <4 x i32> %shuffle9.i, %mul7.i - // CHECK: {{.*}} = bitcast <4 x i32> %mul10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_reduce_mul_epi32( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: mul <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_reduce_mul_epi32(__W); } int test_mm512_reduce_or_epi32(__m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %or.i = or <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> - // CHECK: %or4.i = or <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %or4.i, <4 x i32> undef, <4 x i32> - // CHECK: %or7.i = or <4 x i32> %shuffle6.i, %or4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %or7.i, <4 x i32> undef, <4 x i32> - // CHECK: %or10.i = or <4 x i32> %shuffle9.i, %or7.i - // CHECK: {{.*}} = bitcast <4 x i32> %or10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_reduce_or_epi32( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: or <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_reduce_or_epi32(__W); } int test_mm512_reduce_and_epi32(__m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %and.i = and <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> - // CHECK: %and4.i = and <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %and4.i, <4 x i32> undef, <4 x i32> - // CHECK: %and7.i = and <4 x i32> %shuffle6.i, %and4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %and7.i, <4 x i32> undef, <4 x i32> - // CHECK: %and10.i = and <4 x i32> %shuffle9.i, %and7.i - // CHECK: {{.*}} = bitcast <4 x i32> %and10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_reduce_and_epi32( +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: and <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_reduce_and_epi32(__W); } int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> zeroinitializer - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %add.i = add <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %add.i, <8 x i32> undef, <4 x i32> - // CHECK: %add4.i = add <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %add4.i, <4 x i32> undef, <4 x i32> - // CHECK: %add7.i = add <4 x i32> %shuffle6.i, %add4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %add7.i, <4 x i32> undef, <4 x i32> - // CHECK: %add10.i = add <4 x i32> %shuffle9.i, %add7.i - // CHECK: {{.*}} = bitcast <4 x i32> %add10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_mask_reduce_add_epi32( +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} +// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: add <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: add <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_mask_reduce_add_epi32(__M, __W); } int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %mul.i = mul <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %mul.i, <8 x i32> undef, <4 x i32> - // CHECK: %mul4.i = mul <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %mul4.i, <4 x i32> undef, <4 x i32> - // CHECK: %mul7.i = mul <4 x i32> %shuffle6.i, %mul4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %mul7.i, <4 x i32> undef, <4 x i32> - // CHECK: %mul10.i = mul <4 x i32> %shuffle9.i, %mul7.i - // CHECK: {{.*}} = bitcast <4 x i32> %mul10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_mask_reduce_mul_epi32( +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} +// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: mul <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: mul <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_mask_reduce_mul_epi32(__M, __W); } int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %and.i = and <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %and.i, <8 x i32> undef, <4 x i32> - // CHECK: %and4.i = and <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %and4.i, <4 x i32> undef, <4 x i32> - // CHECK: %and7.i = and <4 x i32> %shuffle6.i, %and4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %and7.i, <4 x i32> undef, <4 x i32> - // CHECK: %and10.i = and <4 x i32> %shuffle9.i, %and7.i - // CHECK: {{.*}} = bitcast <4 x i32> %and10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_mask_reduce_and_epi32( +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} +// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: and <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: and <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_mask_reduce_and_epi32(__M, __W); } int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){ - // CHECK: {{.*}} = bitcast <8 x i64> %__W to <16 x i32> - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x i32> {{.*}}, <16 x i32> zeroinitializer - // CHECK: %shuffle.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x i32> {{.*}}, <16 x i32> undef, <8 x i32> - // CHECK: %or.i = or <8 x i32> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x i32> %or.i, <8 x i32> undef, <4 x i32> - // CHECK: %or4.i = or <4 x i32> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x i32> %or4.i, <4 x i32> undef, <4 x i32> - // CHECK: %or7.i = or <4 x i32> %shuffle6.i, %or4.i - // CHECK: %shuffle9.i = shufflevector <4 x i32> %or7.i, <4 x i32> undef, <4 x i32> - // CHECK: %or10.i = or <4 x i32> %shuffle9.i, %or7.i - // CHECK: {{.*}} = bitcast <4 x i32> %or10.i to <2 x i64> - // CHECK: %vecext.i = extractelement <2 x i64> {{.*}}, i32 0 - // CHECK: %conv.i = trunc i64 %vecext.i to i32 - // CHECK: ret i32 %conv.i +// CHECK-LABEL: @test_mm512_mask_reduce_or_epi32( +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} +// CHECK: bitcast <16 x i32> %{{.*}} to <8 x i64> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> undef, <4 x i32> +// CHECK: or <8 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> undef, <2 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> +// CHECK: or <4 x i32> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x i32> %{{.*}}, i32 0 return _mm512_mask_reduce_or_epi32(__M, __W); } double test_mm512_reduce_add_pd(__m512d __W){ - // CHECK: %shuffle.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> - // CHECK: %add.i = fadd <4 x double> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> - // CHECK: %add4.i = fadd <2 x double> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x double> %add4.i, <2 x double> undef, <2 x i32> - // CHECK: %add7.i = fadd <2 x double> %add4.i, %shuffle6.i - // CHECK: %vecext.i = extractelement <2 x double> %add7.i, i32 0 - // CHECK: ret double %vecext.i +// CHECK-LABEL: @test_mm512_reduce_add_pd( +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: fadd <4 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: fadd <2 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> +// CHECK: fadd <2 x double> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x double> %{{.*}}, i32 0 return _mm512_reduce_add_pd(__W); } double test_mm512_reduce_mul_pd(__m512d __W){ - // CHECK: %shuffle.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <4 x i32> - // CHECK: %mul.i = fmul <4 x double> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> - // CHECK: %mul4.i = fmul <2 x double> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x double> %mul4.i, <2 x double> undef, <2 x i32> - // CHECK: %mul7.i = fmul <2 x double> %mul4.i, %shuffle6.i - // CHECK: %vecext.i = extractelement <2 x double> %mul7.i, i32 0 - // CHECK: ret double %vecext.i +// CHECK-LABEL: @test_mm512_reduce_mul_pd( +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: fmul <4 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: fmul <2 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> +// CHECK: fmul <2 x double> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x double> %{{.*}}, i32 0 return _mm512_reduce_mul_pd(__W); } float test_mm512_reduce_add_ps(__m512 __W){ - // CHECK: %shuffle.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> - // CHECK: %add.i = fadd <8 x float> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> - // CHECK: %add4.i = fadd <4 x float> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x float> %add4.i, <4 x float> undef, <4 x i32> - // CHECK: %add7.i = fadd <4 x float> %add4.i, %shuffle6.i - // CHECK: %shuffle9.i = shufflevector <4 x float> %add7.i, <4 x float> undef, <4 x i32> - // CHECK: %add10.i = fadd <4 x float> %add7.i, %shuffle9.i - // CHECK: %vecext.i = extractelement <4 x float> %add10.i, i32 0 - // CHECK: ret float %vecext.i +// CHECK-LABEL: @test_mm512_reduce_add_ps( +// CHECK: bitcast <16 x float> %{{.*}} to <8 x double> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: fadd <8 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x float> %{{.*}}, i32 0 return _mm512_reduce_add_ps(__W); } float test_mm512_reduce_mul_ps(__m512 __W){ - // CHECK: %shuffle.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <8 x i32> - // CHECK: %mul.i = fmul <8 x float> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> - // CHECK: %mul4.i = fmul <4 x float> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x float> %mul4.i, <4 x float> undef, <4 x i32> - // CHECK: %mul7.i = fmul <4 x float> %mul4.i, %shuffle6.i - // CHECK: %shuffle9.i = shufflevector <4 x float> %mul7.i, <4 x float> undef, <4 x i32> - // CHECK: %mul10.i = fmul <4 x float> %mul7.i, %shuffle9.i - // CHECK: %vecext.i = extractelement <4 x float> %mul10.i, i32 0 - // CHECK: ret float %vecext.i +// CHECK-LABEL: @test_mm512_reduce_mul_ps( +// CHECK: bitcast <16 x float> %{{.*}} to <8 x double> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: fmul <8 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x float> %{{.*}}, i32 0 return _mm512_reduce_mul_ps(__W); } double test_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x double> %__W, <8 x double> zeroinitializer - // CHECK: %shuffle.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> - // CHECK: %add.i = fadd <4 x double> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x double> %add.i, <4 x double> undef, <2 x i32> - // CHECK: %add4.i = fadd <2 x double> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x double> %add4.i, <2 x double> undef, <2 x i32> - // CHECK: %add7.i = fadd <2 x double> %add4.i, %shuffle6.i - // CHECK: %vecext.i = extractelement <2 x double> %add7.i, i32 0 - // CHECK: ret double %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_add_pd( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: fadd <4 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: fadd <2 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> +// CHECK: fadd <2 x double> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x double> %{{.*}}, i32 0 return _mm512_mask_reduce_add_pd(__M, __W); } double test_mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W){ - // CHECK: {{.*}} = bitcast i8 %__M to <8 x i1> - // CHECK: {{.*}} = select <8 x i1> {{.*}}, <8 x double> %__W, <8 x double> - // CHECK: %shuffle.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> - // CHECK: %shuffle1.i = shufflevector <8 x double> {{.*}}, <8 x double> undef, <4 x i32> - // CHECK: %mul.i = fmul <4 x double> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> - // CHECK: %shuffle3.i = shufflevector <4 x double> %mul.i, <4 x double> undef, <2 x i32> - // CHECK: %mul4.i = fmul <2 x double> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <2 x double> %mul4.i, <2 x double> undef, <2 x i32> - // CHECK: %mul7.i = fmul <2 x double> %mul4.i, %shuffle6.i - // CHECK: %vecext.i = extractelement <2 x double> %mul7.i, i32 0 - // CHECK: ret double %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_mul_pd( +// CHECK: bitcast i8 %{{.*}} to <8 x i1> +// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: fmul <4 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> undef, <2 x i32> +// CHECK: fmul <2 x double> %{{.*}}, %{{.*}} +// CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x i32> +// CHECK: fmul <2 x double> %{{.*}}, %{{.*}} +// CHECK: extractelement <2 x double> %{{.*}}, i32 0 return _mm512_mask_reduce_mul_pd(__M, __W); } float test_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W){ - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x float> %__W, <16 x float> zeroinitializer - // CHECK: %shuffle.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> - // CHECK: %add.i = fadd <8 x float> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x float> %add.i, <8 x float> undef, <4 x i32> - // CHECK: %add4.i = fadd <4 x float> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x float> %add4.i, <4 x float> undef, <4 x i32> - // CHECK: %add7.i = fadd <4 x float> %add4.i, %shuffle6.i - // CHECK: %shuffle9.i = shufflevector <4 x float> %add7.i, <4 x float> undef, <4 x i32> - // CHECK: %add10.i = fadd <4 x float> %add7.i, %shuffle9.i - // CHECK: %vecext.i = extractelement <4 x float> %add10.i, i32 0 - // CHECK: ret float %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_add_ps( +// CHECK-NEXT: entry: +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}} +// CHECK: bitcast <16 x float> %{{.*}} to <8 x double> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: fadd <8 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x float> %{{.*}}, i32 0 return _mm512_mask_reduce_add_ps(__M, __W); } float test_mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W){ - // CHECK: {{.*}} = bitcast i16 %__M to <16 x i1> - // CHECK: {{.*}} = select <16 x i1> {{.*}}, <16 x float> %__W, <16 x float> - // CHECK: %shuffle.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> - // CHECK: %shuffle1.i = shufflevector <16 x float> {{.*}}, <16 x float> undef, <8 x i32> - // CHECK: %mul.i = fmul <8 x float> %shuffle.i, %shuffle1.i - // CHECK: %shuffle2.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> - // CHECK: %shuffle3.i = shufflevector <8 x float> %mul.i, <8 x float> undef, <4 x i32> - // CHECK: %mul4.i = fmul <4 x float> %shuffle2.i, %shuffle3.i - // CHECK: %shuffle6.i = shufflevector <4 x float> %mul4.i, <4 x float> undef, <4 x i32> - // CHECK: %mul7.i = fmul <4 x float> %mul4.i, %shuffle6.i - // CHECK: %shuffle9.i = shufflevector <4 x float> %mul7.i, <4 x float> undef, <4 x i32> - // CHECK: %mul10.i = fmul <4 x float> %mul7.i, %shuffle9.i - // CHECK: %vecext.i = extractelement <4 x float> %mul10.i, i32 0 - // CHECK: ret float %vecext.i +// CHECK-LABEL: @test_mm512_mask_reduce_mul_ps( +// CHECK: bitcast i16 %{{.*}} to <16 x i1> +// CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> %{{.*}} +// CHECK: bitcast <16 x float> %{{.*}} to <8 x double> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> undef, <4 x i32> +// CHECK: bitcast <4 x double> %{{.*}} to <8 x float> +// CHECK: fmul <8 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> undef, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> +// CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +// CHECK: extractelement <4 x float> %{{.*}}, i32 0 return _mm512_mask_reduce_mul_ps(__M, __W); } -- GitLab From 4cf0c3e56c85f0a38f92434d074a6d43165d16a7 Mon Sep 17 00:00:00 2001 From: Anastasis Grammenos Date: Thu, 21 Jun 2018 16:53:48 +0000 Subject: [PATCH 0215/1023] [DebugInfo] Inline for without DebugLocation Summary: This test is a strip down version of a function inside the amalgamated sqlite source. When converted to IR clang produces a phi instruction without debug location. This patch fixes the above issue. Differential Revision: https://reviews.llvm.org/D47720 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335255 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprScalar.cpp | 6 ++++++ test/CodeGen/debug-info-inline-for.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 test/CodeGen/debug-info-inline-for.c diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index f4c0c75c25..10c59a2cb8 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -3431,6 +3431,12 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // Insert an entry into the phi node for the edge with the value of RHSCond. PN->addIncoming(RHSCond, RHSBlock); + // Artificial location to preserve the scope information + { + auto NL = ApplyDebugLocation::CreateArtificial(CGF); + PN->setDebugLoc(Builder.getCurrentDebugLocation()); + } + // ZExt result to int. return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext"); } diff --git a/test/CodeGen/debug-info-inline-for.c b/test/CodeGen/debug-info-inline-for.c new file mode 100644 index 0000000000..55066b28a1 --- /dev/null +++ b/test/CodeGen/debug-info-inline-for.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s +// Check that clang emits Debug location in the phi instruction + +int func(int n) { + int a; + for(a = 10; a>0 && n++; a--); + return n; +} + +// CHECK: land.end: +// CHECK-NEXT: {{.*}} = phi i1 {{.*}} !dbg ![[DbgLoc:[0-9]+]] + +// CHECK: ![[DbgLoc]] = !DILocation(line: 0 -- GitLab From 8b6d5a07b8dbd5377cc9c8bdaa4b24cd6f18f0dd Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 17:07:04 +0000 Subject: [PATCH 0216/1023] [Intrinsics] Add/move some builtin declarations in intrin.h to get ms-intrinsics.c to not issue warnings ud2 and int2c were missing declarations entirely. And the bitscans were only under x86_64, but they seem to be in BuiltinsARM.def as well and are tested by ms_intrinsics.c Differential Revision: https://reviews.llvm.org/D48187 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335259 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/intrin.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index 5ac8e30087..cf6e25a49a 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -83,6 +83,7 @@ void __incfsdword(unsigned long); void __incfsword(unsigned long); unsigned long __indword(unsigned short); void __indwordstring(unsigned short, unsigned long *, unsigned long); +void __int2c(void); void __invlpg(void *); unsigned short __inword(unsigned short); void __inwordstring(unsigned short, unsigned short *, unsigned long); @@ -140,6 +141,7 @@ void __svm_stgi(void); void __svm_vmload(size_t); void __svm_vmrun(size_t); void __svm_vmsave(size_t); +void __ud2(void); unsigned __int64 __ull_rshift(unsigned __int64, int); void __vmx_off(void); void __vmx_vmptrst(unsigned __int64 *); @@ -246,10 +248,6 @@ void __writegsbyte(unsigned long, unsigned char); void __writegsdword(unsigned long, unsigned long); void __writegsqword(unsigned long, unsigned __int64); void __writegsword(unsigned long, unsigned short); -static __inline__ -unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); -static __inline__ -unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); unsigned char _bittest64(__int64 const *, __int64); unsigned char _bittestandcomplement64(__int64 *, __int64); unsigned char _bittestandreset64(__int64 *, __int64); @@ -303,6 +301,11 @@ unsigned __int64 _umul128(unsigned __int64, #if defined(__x86_64__) || defined(__arm__) +static __inline__ +unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); +static __inline__ +unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); + static __inline__ __int64 _InterlockedDecrement64(__int64 volatile *_Addend); static __inline__ -- GitLab From 878659b4b1a0215d2ce51b68be22f0cb02389a50 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 18:56:30 +0000 Subject: [PATCH 0217/1023] [X86] Correct the inline assembly implementations of __movsb/w/d/q and __stosw/d/q to mark registers/memory as modified The inline assembly for these didn't mark that edi, esi, ecx are modified by movs/stos instruction. It also didn't mark that memory is modified. This issue was reported to llvm-dev last year http://lists.llvm.org/pipermail/cfe-dev/2017-November/055863.html but no bug was ever filed. Differential Revision: https://reviews.llvm.org/D48448 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335270 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/intrin.h | 21 ++++++--- test/CodeGen/ms-intrinsics.c | 83 ++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index cf6e25a49a..7dd70acc37 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -797,33 +797,40 @@ _InterlockedCompareExchange64_rel(__int64 volatile *_Destination, #if defined(__i386__) || defined(__x86_64__) static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst, unsigned char const *__src, size_t __n) { - __asm__("rep movsb" : : "D"(__dst), "S"(__src), "c"(__n)); + __asm__ __volatile__("rep movsb" : "+D"(__dst), "+S"(__src), "+c"(__n) + : : "memory"); } static __inline__ void __DEFAULT_FN_ATTRS __movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) { - __asm__("rep movsl" : : "D"(__dst), "S"(__src), "c"(__n)); + __asm__ __volatile__("rep movsl" : "+D"(__dst), "+S"(__src), "+c"(__n) + : : "memory"); } static __inline__ void __DEFAULT_FN_ATTRS __movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) { - __asm__("rep movsw" : : "D"(__dst), "S"(__src), "c"(__n)); + __asm__ __volatile__("rep movsw" : "+D"(__dst), "+S"(__src), "+c"(__n) + : : "memory"); } static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst, unsigned long __x, size_t __n) { - __asm__("rep stosl" : : "D"(__dst), "a"(__x), "c"(__n)); + __asm__ __volatile__("rep stosl" : "+D"(__dst), "+c"(__n) : "a"(__x) + : "memory"); } static __inline__ void __DEFAULT_FN_ATTRS __stosw(unsigned short *__dst, unsigned short __x, size_t __n) { - __asm__("rep stosw" : : "D"(__dst), "a"(__x), "c"(__n)); + __asm__ __volatile__("rep stosw" : "+D"(__dst), "+c"(__n) : "a"(__x) + : "memory"); } #endif #ifdef __x86_64__ static __inline__ void __DEFAULT_FN_ATTRS __movsq(unsigned long long *__dst, unsigned long long const *__src, size_t __n) { - __asm__("rep movsq" : : "D"(__dst), "S"(__src), "c"(__n)); + __asm__ __volatile__("rep movsq" : "+D"(__dst), "+S"(__src), "+c"(__n) + : : "memory"); } static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) { - __asm__("rep stosq" : : "D"(__dst), "a"(__x), "c"(__n)); + __asm__ __volatile__("rep stosq" : "+D"(__dst), "+c"(__n) : "a"(__x) + : "memory"); } #endif diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c index a9902b2f21..2e85be8926 100644 --- a/test/CodeGen/ms-intrinsics.c +++ b/test/CodeGen/ms-intrinsics.c @@ -29,6 +29,89 @@ void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) { // CHECK-X64: ret void // CHECK-X64: } +void test__movsb(unsigned char *Dest, unsigned char *Src, size_t Count) { + return __movsb(Dest, Src, Count); +} +// CHECK-I386-LABEL: define{{.*}} void @test__movsb +// CHECK-I386: call { i8*, i8*, i32 } asm sideeffect "rep movsb", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i32 %Count) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64-LABEL: define{{.*}} void @test__movsb +// CHECK-X64: call { i8*, i8*, i64 } asm sideeffect "rep movsb", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +void test__stosw(unsigned short *Dest, unsigned short Data, size_t Count) { + return __stosw(Dest, Data, Count); +} +// CHECK-I386-LABEL: define{{.*}} void @test__stosw +// CHECK-I386: call { i16*, i32 } asm sideeffect "rep stosw", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i16 %Data, i16* %Dest, i32 %Count) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64-LABEL: define{{.*}} void @test__stosw +// CHECK-X64: call { i16*, i64 } asm sideeffect "rep stosw", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i16 %Data, i16* %Dest, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +void test__movsw(unsigned short *Dest, unsigned short *Src, size_t Count) { + return __movsw(Dest, Src, Count); +} +// CHECK-I386-LABEL: define{{.*}} void @test__movsw +// CHECK-I386: call { i16*, i16*, i32 } asm sideeffect "rep movsw", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i32 %Count) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64-LABEL: define{{.*}} void @test__movsw +// CHECK-X64: call { i16*, i16*, i64 } asm sideeffect "rep movsw", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +void test__stosd(unsigned long *Dest, unsigned long Data, size_t Count) { + return __stosd(Dest, Data, Count); +} +// CHECK-I386-LABEL: define{{.*}} void @test__stosd +// CHECK-I386: call { i32*, i32 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i32 %Count) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64-LABEL: define{{.*}} void @test__stosd +// CHECK-X64: call { i32*, i64 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +void test__movsd(unsigned long *Dest, unsigned long *Src, size_t Count) { + return __movsd(Dest, Src, Count); +} +// CHECK-I386-LABEL: define{{.*}} void @test__movsd +// CHECK-I386: call { i32*, i32*, i32 } asm sideeffect "rep movsl", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i32 %Count) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64-LABEL: define{{.*}} void @test__movsd +// CHECK-X64: call { i32*, i32*, i64 } asm sideeffect "rep movsl", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +#ifdef __x86_64__ +void test__stosq(unsigned __int64 *Dest, unsigned __int64 Data, size_t Count) { + return __stosq(Dest, Data, Count); +} +// CHECK-X64-LABEL: define{{.*}} void @test__stosq +// CHECK-X64: call { i64*, i64 } asm sideeffect "rep stosq", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i64 %Data, i64* %Dest, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } + +void test__movsq(unsigned __int64 *Dest, unsigned __int64 *Src, size_t Count) { + return __movsq(Dest, Src, Count); +} +// CHECK-X64-LABEL: define{{.*}} void @test__movsq +// CHECK-X64: call { i64*, i64*, i64 } asm sideeffect "rep movsq", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Dest, i64* %Src, i64 %Count) +// CHECK-X64: ret void +// CHECK-X64: } +#endif + void test__ud2(void) { __ud2(); } -- GitLab From bd45a59072ca7d5b4b03e13919d3ac1f294fd361 Mon Sep 17 00:00:00 2001 From: Jonathan Coe Date: Thu, 21 Jun 2018 20:07:03 +0000 Subject: [PATCH 0218/1023] [bindings] Fix most Python binding unittests on Windows Summary: This fixes all but one of the test cases for Windows. TestCDB will take more work to debug, as CompilationDatabase seems not to work correctly. Reviewers: bkramer, wanders, jbcoe Reviewed By: bkramer, jbcoe Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47864 Patch written by ethanhs (Ethan) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335282 91177308-0d34-0410-b5e6-96231b3b80d8 --- bindings/python/tests/cindex/test_cdb.py | 2 + bindings/python/tests/cindex/test_cursor.py | 4 +- .../tests/cindex/test_translation_unit.py | 37 +++++++++---------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py index bd6e77329f..64651af317 100644 --- a/bindings/python/tests/cindex/test_cdb.py +++ b/bindings/python/tests/cindex/test_cdb.py @@ -5,11 +5,13 @@ from clang.cindex import CompileCommand import os import gc import unittest +import sys kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') +@unittest.skipIf(sys.platform == 'win32', "TODO: Fix these tests on Windows") class TestCDB(unittest.TestCase): def test_create_fail(self): """Check we fail loading a database with an assertion""" diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py index 2575ffb8a5..f5733fd158 100644 --- a/bindings/python/tests/cindex/test_cursor.py +++ b/bindings/python/tests/cindex/test_cursor.py @@ -335,7 +335,7 @@ class TestCursor(unittest.TestCase): self.assertEqual(enum.kind, CursorKind.ENUM_DECL) enum_type = enum.enum_type - self.assertEqual(enum_type.kind, TypeKind.UINT) + self.assertIn(enum_type.kind, (TypeKind.UINT, TypeKind.INT)) def test_enum_type_cpp(self): tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") @@ -561,4 +561,4 @@ class TestCursor(unittest.TestCase): # all valid manglings. # [c-index-test handles this by running the source through clang, emitting # an AST file and running libclang on that AST file] - self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH')) + self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH', '?foo@@YAHHH@Z')) diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py index 09230d1da2..d3ee535f4d 100644 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ b/bindings/python/tests/cindex/test_translation_unit.py @@ -1,3 +1,4 @@ +from contextlib import contextmanager import gc import os import tempfile @@ -19,15 +20,15 @@ from .util import get_tu kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') +@contextmanager def save_tu(tu): """Convenience API to save a TranslationUnit to a file. Returns the filename it was saved to. """ - _, path = tempfile.mkstemp() - tu.save(path) - - return path + with tempfile.NamedTemporaryFile() as t: + tu.save(t.name) + yield t.name class TestTranslationUnit(unittest.TestCase): @@ -125,10 +126,9 @@ int SOME_DEFINE; tu = get_tu('int foo();') - path = save_tu(tu) - self.assertTrue(os.path.exists(path)) - self.assertGreater(os.path.getsize(path), 0) - os.unlink(path) + with save_tu(tu) as path: + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) def test_save_translation_errors(self): """Ensure that saving to an invalid directory raises.""" @@ -149,21 +149,18 @@ int SOME_DEFINE; tu = get_tu('int foo();') self.assertEqual(len(tu.diagnostics), 0) - path = save_tu(tu) - - self.assertTrue(os.path.exists(path)) - self.assertGreater(os.path.getsize(path), 0) - - tu2 = TranslationUnit.from_ast_file(filename=path) - self.assertEqual(len(tu2.diagnostics), 0) + with save_tu(tu) as path: + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) - foo = get_cursor(tu2, 'foo') - self.assertIsNotNone(foo) + tu2 = TranslationUnit.from_ast_file(filename=path) + self.assertEqual(len(tu2.diagnostics), 0) - # Just in case there is an open file descriptor somewhere. - del tu2 + foo = get_cursor(tu2, 'foo') + self.assertIsNotNone(foo) - os.unlink(path) + # Just in case there is an open file descriptor somewhere. + del tu2 def test_index_parse(self): path = os.path.join(kInputsDir, 'hello.cpp') -- GitLab From 044f47d77bf408702f9270dd154beeb6f0d6ccd5 Mon Sep 17 00:00:00 2001 From: Tobias Edler von Koch Date: Thu, 21 Jun 2018 20:20:41 +0000 Subject: [PATCH 0219/1023] [LTO] Enable module summary emission by default for regular LTO Summary: With D33921, we gained the ability to have module summaries in regular LTO modules without triggering ThinLTO compilation. Module summaries in regular LTO allow garbage collection (dead stripping) before LTO compilation and thus open up additional optimization opportunities. This patch enables summary emission in regular LTO for all targets except ld64-based ones (which use the legacy LTO API). Reviewers: pcc, tejohnson, mehdi_amini Subscribers: inglorion, eraman, cfe-commits Differential Revision: https://reviews.llvm.org/D34156 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335284 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/CodeGenOptions.def | 2 +- lib/CodeGen/BackendUtil.cpp | 38 +++++++++++++++++------ lib/CodeGen/CGDebugInfo.cpp | 2 +- lib/Frontend/CompilerInvocation.cpp | 4 +-- test/CodeGen/emit-summary-index.c | 17 ++++++++++ test/Misc/thinlto.c | 4 --- 6 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 test/CodeGen/emit-summary-index.c delete mode 100644 test/Misc/thinlto.c diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 019425d194..99567e04ba 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -110,7 +110,7 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. -CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the +CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 4125d507a1..b06c68fe74 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -524,7 +524,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.Inliner = createFunctionInliningPass( CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, (!CodeGenOpts.SampleProfileFile.empty() && - CodeGenOpts.EmitSummaryIndex)); + CodeGenOpts.PrepareForThinLTO)); } PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; @@ -534,7 +534,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; - PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex; + PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO; PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; @@ -776,7 +776,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -784,10 +784,20 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, } PerModulePasses.add(createWriteThinLTOBitcodePass( *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); - } - else + } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + PerModulePasses.add( - createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists)); + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + EmitLTOSummary)); + } break; case Backend_EmitLL: @@ -935,7 +945,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( ModulePassManager MPM(CodeGenOpts.DebugPassManager); if (!CodeGenOpts.DisableLLVMPasses) { - bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; + bool IsThinLTO = CodeGenOpts.PrepareForThinLTO; bool IsLTO = CodeGenOpts.PrepareForLTO; if (CodeGenOpts.OptimizationLevel == 0) { @@ -996,7 +1006,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -1005,9 +1015,17 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + EmitLTOSummary)); } break; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3ca6459a6a..a0d5fd6236 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -578,7 +578,7 @@ void CGDebugInfo::CreateCompileUnit() { CSInfo, getSource(SM, SM.getMainFileID())), CGOpts.EmitVersionIdentMetadata ? Producer : "", - LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex, + LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind, 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1f9d6b0d7f..60ed5fdf70 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -749,11 +749,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - Opts.EmitSummaryIndex = false; + Opts.PrepareForThinLTO = false; if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { StringRef S = A->getValue(); if (S == "thin") - Opts.EmitSummaryIndex = true; + Opts.PrepareForThinLTO = true; else if (S != "full") Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; } diff --git a/test/CodeGen/emit-summary-index.c b/test/CodeGen/emit-summary-index.c new file mode 100644 index 0000000000..6126410206 --- /dev/null +++ b/test/CodeGen/emit-summary-index.c @@ -0,0 +1,17 @@ +// ; Check that the -flto=thin option emits a ThinLTO summary +// RUN: %clang_cc1 -flto=thin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck %s +// CHECK: Date: Thu, 21 Jun 2018 20:26:33 +0000 Subject: [PATCH 0220/1023] [OPENMP, NVPTX] Fix globalization of the variables passed to orphaned parallel region. If the current construct requires sharing of the local variable in the inner parallel region, this variable must be globalized to avoid runtime crash. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335285 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 98 +++++++++++++++----------- lib/CodeGen/CGOpenMPRuntimeNVPTX.h | 12 ++-- test/OpenMP/nvptx_parallel_codegen.cpp | 9 +++ 3 files changed, 70 insertions(+), 49 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 9452bdea4c..e3cec13f7d 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -184,9 +184,10 @@ class CheckVarsEscapingDeclContext final llvm::SetVector EscapedDecls; llvm::SetVector EscapedVariableLengthDecls; llvm::SmallPtrSet EscapedParameters; - bool AllEscaped = false; RecordDecl *GlobalizedRD = nullptr; llvm::SmallDenseMap MappedDeclsFields; + bool AllEscaped = false; + bool IsForParallelRegion = false; static llvm::Optional isDeclareTargetDeclaration(const ValueDecl *VD) { @@ -207,23 +208,32 @@ class CheckVarsEscapingDeclContext final // Variables captured by value must be globalized. if (auto *CSI = CGF.CapturedStmtInfo) { if (const FieldDecl *FD = CSI->lookup(cast(VD))) { - if (!FD->hasAttrs()) - return; - const auto *Attr = FD->getAttr(); - if (!Attr) - return; - if (!isOpenMPPrivate( - static_cast(Attr->getCaptureKind())) || - Attr->getCaptureKind() == OMPC_map) - return; - if (FD->getType()->isReferenceType()) + // Check if need to capture the variable that was already captured by + // value in the outer region. + if (!IsForParallelRegion) { + if (!FD->hasAttrs()) + return; + const auto *Attr = FD->getAttr(); + if (!Attr) + return; + if (!isOpenMPPrivate( + static_cast(Attr->getCaptureKind())) || + Attr->getCaptureKind() == OMPC_map) + return; + } + if (!FD->getType()->isReferenceType()) { + assert(!VD->getType()->isVariablyModifiedType() && + "Parameter captured by value with variably modified type"); + EscapedParameters.insert(VD); + } else if (!IsForParallelRegion) { return; - assert(!VD->getType()->isVariablyModifiedType() && - "Parameter captured by value with variably modified type"); - EscapedParameters.insert(VD); + } } - } else if (VD->getType()->isReferenceType()) - // Do not globalize variables with reference or pointer type. + } + if ((!CGF.CapturedStmtInfo || + (IsForParallelRegion && CGF.CapturedStmtInfo)) && + VD->getType()->isReferenceType()) + // Do not globalize variables with reference type. return; if (VD->getType()->isVariablyModifiedType()) EscapedVariableLengthDecls.insert(VD); @@ -243,15 +253,18 @@ class CheckVarsEscapingDeclContext final } } } - void VisitOpenMPCapturedStmt(const CapturedStmt *S) { + void VisitOpenMPCapturedStmt(const CapturedStmt *S, bool IsParallelRegion) { if (!S) return; for (const CapturedStmt::Capture &C : S->captures()) { if (C.capturesVariable() && !C.capturesVariableByCopy()) { const ValueDecl *VD = C.getCapturedVar(); + bool SavedIsParallelRegion = IsForParallelRegion; + IsForParallelRegion = IsParallelRegion; markAsEscaped(VD); if (isa(VD)) VisitValueDecl(VD); + IsForParallelRegion = SavedIsParallelRegion; } } } @@ -316,20 +329,19 @@ public: void VisitOMPExecutableDirective(const OMPExecutableDirective *D) { if (!D) return; - if (D->hasAssociatedStmt()) { - if (const auto *S = - dyn_cast_or_null(D->getAssociatedStmt())) { - // Do not analyze directives that do not actually require capturing, - // like `omp for` or `omp simd` directives. - llvm::SmallVector CaptureRegions; - getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind()); - if (CaptureRegions.size() == 1 && - CaptureRegions.back() == OMPD_unknown) { - VisitStmt(S->getCapturedStmt()); - return; - } - VisitOpenMPCapturedStmt(S); + if (!D->hasAssociatedStmt()) + return; + if (const auto *S = + dyn_cast_or_null(D->getAssociatedStmt())) { + // Do not analyze directives that do not actually require capturing, + // like `omp for` or `omp simd` directives. + llvm::SmallVector CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind()); + if (CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown) { + VisitStmt(S->getCapturedStmt()); + return; } + VisitOpenMPCapturedStmt(S, CaptureRegions.back() == OMPD_parallel); } } void VisitCapturedStmt(const CapturedStmt *S) { @@ -551,9 +563,9 @@ static void syncParallelThreads(CodeGenFunction &CGF, llvm::Value *NumThreads) { /// CTA. The threads in the last warp are reserved for master execution. /// For the 'spmd' execution mode, all threads in a CTA are part of the team. static llvm::Value *getThreadLimit(CodeGenFunction &CGF, - bool IsInSpmdExecutionMode = false) { + bool IsInSPMDExecutionMode = false) { CGBuilderTy &Bld = CGF.Builder; - return IsInSpmdExecutionMode + return IsInSPMDExecutionMode ? getNVPTXNumThreads(CGF) : Bld.CreateNUWSub(getNVPTXNumThreads(CGF), getNVPTXWarpSize(CGF), "thread_limit"); @@ -930,7 +942,7 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDEntryFooter(CodeGenFunction &CGF, EST.ExitBB = nullptr; } -void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D, +void CGOpenMPRuntimeNVPTX::emitSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, @@ -951,10 +963,10 @@ void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D, const OMPExecutableDirective &D) : RT(RT), EST(EST), D(D) {} void Enter(CodeGenFunction &CGF) override { - RT.emitSpmdEntryHeader(CGF, EST, D); + RT.emitSPMDEntryHeader(CGF, EST, D); } void Exit(CodeGenFunction &CGF) override { - RT.emitSpmdEntryFooter(CGF, EST); + RT.emitSPMDEntryFooter(CGF, EST); } } Action(*this, EST, D); CodeGen.setAction(Action); @@ -962,7 +974,7 @@ void CGOpenMPRuntimeNVPTX::emitSpmdKernel(const OMPExecutableDirective &D, IsOffloadEntry, CodeGen); } -void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader( +void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader( CodeGenFunction &CGF, EntryFunctionState &EST, const OMPExecutableDirective &D) { CGBuilderTy &Bld = CGF.Builder; @@ -974,7 +986,7 @@ void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader( // Initialize the OMP state in the runtime; called by all active threads. // TODO: Set RequiresOMPRuntime and RequiresDataSharing parameters // based on code analysis of the target region. - llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSpmdExecutionMode=*/true), + llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSPMDExecutionMode=*/true), /*RequiresOMPRuntime=*/Bld.getInt16(1), /*RequiresDataSharing=*/Bld.getInt16(1)}; CGF.EmitRuntimeCall( @@ -986,7 +998,7 @@ void CGOpenMPRuntimeNVPTX::emitSpmdEntryHeader( IsInTargetMasterThreadRegion = true; } -void CGOpenMPRuntimeNVPTX::emitSpmdEntryFooter(CodeGenFunction &CGF, +void CGOpenMPRuntimeNVPTX::emitSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST) { IsInTargetMasterThreadRegion = false; if (!CGF.HaveInsertPoint()) @@ -1465,7 +1477,7 @@ void CGOpenMPRuntimeNVPTX::emitTargetOutlinedFunction( bool Mode = supportsSPMDExecutionMode(CGM.getContext(), D); if (Mode) - emitSpmdKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, + emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, CodeGen); else emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, @@ -1483,7 +1495,7 @@ CGOpenMPRuntimeNVPTX::CGOpenMPRuntimeNVPTX(CodeGenModule &CGM) void CGOpenMPRuntimeNVPTX::emitProcBindClause(CodeGenFunction &CGF, OpenMPProcBindClauseKind ProcBind, SourceLocation Loc) { - // Do nothing in case of Spmd mode and L0 parallel. + // Do nothing in case of SPMD mode and L0 parallel. if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) return; @@ -1493,7 +1505,7 @@ void CGOpenMPRuntimeNVPTX::emitProcBindClause(CodeGenFunction &CGF, void CGOpenMPRuntimeNVPTX::emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc) { - // Do nothing in case of Spmd mode and L0 parallel. + // Do nothing in case of SPMD mode and L0 parallel. if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) return; @@ -1718,7 +1730,7 @@ void CGOpenMPRuntimeNVPTX::emitParallelCall( return; if (getExecutionMode() == CGOpenMPRuntimeNVPTX::EM_SPMD) - emitSpmdParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); + emitSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); else emitNonSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond); } @@ -1904,7 +1916,7 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( } } -void CGOpenMPRuntimeNVPTX::emitSpmdParallelCall( +void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall( CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, ArrayRef CapturedVars, const Expr *IfCond) { // Just call the outlined function to execute the parallel region. diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h index c7d647bfdb..f83e99f8a3 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h @@ -77,12 +77,12 @@ private: /// Helper for generic variables globalization epilog. void emitGenericVarsEpilog(CodeGenFunction &CGF); - /// Helper for Spmd mode target directive's entry function. - void emitSpmdEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST, + /// Helper for SPMD mode target directive's entry function. + void emitSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST, const OMPExecutableDirective &D); - /// Signal termination of Spmd mode execution. - void emitSpmdEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST); + /// Signal termination of SPMD mode execution. + void emitSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST); // // Base class overrides. @@ -119,7 +119,7 @@ private: /// \param CodeGen Object containing the target statements. /// An outlined function may not be an entry if, e.g. the if clause always /// evaluates to false. - void emitSpmdKernel(const OMPExecutableDirective &D, StringRef ParentName, + void emitSPMDKernel(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen); @@ -166,7 +166,7 @@ private: /// \param IfCond Condition in the associated 'if' clause, if it was /// specified, nullptr otherwise. /// - void emitSpmdParallelCall(CodeGenFunction &CGF, SourceLocation Loc, + void emitSPMDParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn, ArrayRef CapturedVars, const Expr *IfCond); diff --git a/test/OpenMP/nvptx_parallel_codegen.cpp b/test/OpenMP/nvptx_parallel_codegen.cpp index 8f496eb80e..d1a3104407 100644 --- a/test/OpenMP/nvptx_parallel_codegen.cpp +++ b/test/OpenMP/nvptx_parallel_codegen.cpp @@ -315,6 +315,15 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}_worker() // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l54}}( +// CHECK-32: [[A_ADDR:%.+]] = alloca i32, +// CHECK-64: [[A_ADDR:%.+]] = alloca i64, +// CHECK-64: [[CONV:%.+]] = bitcast i64* [[A_ADDR]] to i32* +// CHECK: [[STACK:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0) +// CHECK: [[BC:%.+]] = bitcast i8* [[STACK]] to %struct._globalized_locals_ty* +// CHECK-32: [[A:%.+]] = load i32, i32* [[A_ADDR]], +// CHECK-64: [[A:%.+]] = load i32, i32* [[CONV]], +// CHECK: [[GLOBAL_A_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[BC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: store i32 [[A]], i32* [[GLOBAL_A_ADDR]], // CHECK-LABEL: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.*}}) // CHECK: [[CC:%.+]] = alloca i32, -- GitLab From 72c90200a6e12dea433ab55f338412374da8e5f1 Mon Sep 17 00:00:00 2001 From: Konstantin Zhuravlyov Date: Thu, 21 Jun 2018 20:27:47 +0000 Subject: [PATCH 0221/1023] AMDGPU: Remove amdgpu-debugger-reserve-regs feature git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335287 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/AMDGPU.cpp | 1 - test/Driver/amdgpu-features.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp index a313bc5c35..6b673feead 100644 --- a/lib/Driver/ToolChains/AMDGPU.cpp +++ b/lib/Driver/ToolChains/AMDGPU.cpp @@ -43,7 +43,6 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D, StringRef value = dAbi->getValue(); if (value == "1.0") { Features.push_back("+amdgpu-debugger-insert-nops"); - Features.push_back("+amdgpu-debugger-reserve-regs"); Features.push_back("+amdgpu-debugger-emit-prologue"); } else { D.Diag(diag::err_drv_clang_unsupported) << dAbi->getAsString(Args); diff --git a/test/Driver/amdgpu-features.c b/test/Driver/amdgpu-features.c index 23ba72b26d..0e54a5e251 100644 --- a/test/Driver/amdgpu-features.c +++ b/test/Driver/amdgpu-features.c @@ -4,7 +4,7 @@ // RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=1.0 %s -o - 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MAMDGPU-DEBUGGER-ABI-1-0 %s -// CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-reserve-regs" "-target-feature" "+amdgpu-debugger-emit-prologue" +// CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-emit-prologue" // RUN: %clang -### -target amdgcn -mcpu=gfx700 -mxnack %s 2>&1 | FileCheck --check-prefix=XNACK %s // XNACK: "-target-feature" "+xnack" -- GitLab From 16a4b693139b7675bf95e82b436fe386988d577c Mon Sep 17 00:00:00 2001 From: Tobias Edler von Koch Date: Thu, 21 Jun 2018 21:24:30 +0000 Subject: [PATCH 0222/1023] Revert "[LTO] Enable module summary emission by default for regular LTO" This is breaking a couple of buildbots. We need to run the NameAnonGlobal pass for regular LTO now as well (since we're producing a summary). I'll post a separate patch for review to make this happen and then re-commit. This reverts commit c0759b7b1f4a81ff9021b952aa38a222d5fa4dfd. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335291 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/CodeGenOptions.def | 2 +- lib/CodeGen/BackendUtil.cpp | 38 ++++++----------------- lib/CodeGen/CGDebugInfo.cpp | 2 +- lib/Frontend/CompilerInvocation.cpp | 4 +-- test/CodeGen/emit-summary-index.c | 17 ---------- test/Misc/thinlto.c | 4 +++ 6 files changed, 18 insertions(+), 49 deletions(-) delete mode 100644 test/CodeGen/emit-summary-index.c create mode 100644 test/Misc/thinlto.c diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 99567e04ba..019425d194 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -110,7 +110,7 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. -CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the +CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index b06c68fe74..4125d507a1 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -524,7 +524,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.Inliner = createFunctionInliningPass( CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, (!CodeGenOpts.SampleProfileFile.empty() && - CodeGenOpts.PrepareForThinLTO)); + CodeGenOpts.EmitSummaryIndex)); } PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; @@ -534,7 +534,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; - PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO; + PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex; PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; @@ -776,7 +776,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, break; case Backend_EmitBC: - if (CodeGenOpts.PrepareForThinLTO) { + if (CodeGenOpts.EmitSummaryIndex) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -784,20 +784,10 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, } PerModulePasses.add(createWriteThinLTOBitcodePass( *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); - } else { - // Emit a module summary by default for Regular LTO except for ld64 - // targets - bool EmitLTOSummary = - (CodeGenOpts.PrepareForLTO && - llvm::Triple(TheModule->getTargetTriple()).getVendor() != - llvm::Triple::Apple); - if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); - - PerModulePasses.add( - createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - EmitLTOSummary)); } + else + PerModulePasses.add( + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists)); break; case Backend_EmitLL: @@ -945,7 +935,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( ModulePassManager MPM(CodeGenOpts.DebugPassManager); if (!CodeGenOpts.DisableLLVMPasses) { - bool IsThinLTO = CodeGenOpts.PrepareForThinLTO; + bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; bool IsLTO = CodeGenOpts.PrepareForLTO; if (CodeGenOpts.OptimizationLevel == 0) { @@ -1006,7 +996,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - if (CodeGenOpts.PrepareForThinLTO) { + if (CodeGenOpts.EmitSummaryIndex) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -1015,17 +1005,9 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); } else { - // Emit a module summary by default for Regular LTO except for ld64 - // targets - bool EmitLTOSummary = - (CodeGenOpts.PrepareForLTO && - llvm::Triple(TheModule->getTargetTriple()).getVendor() != - llvm::Triple::Apple); - if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); - MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - EmitLTOSummary)); + CodeGenOpts.EmitSummaryIndex, + CodeGenOpts.EmitSummaryIndex)); } break; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index a0d5fd6236..3ca6459a6a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -578,7 +578,7 @@ void CGDebugInfo::CreateCompileUnit() { CSInfo, getSource(SM, SM.getMainFileID())), CGOpts.EmitVersionIdentMetadata ? Producer : "", - LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, + LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind, 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 60ed5fdf70..1f9d6b0d7f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -749,11 +749,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - Opts.PrepareForThinLTO = false; + Opts.EmitSummaryIndex = false; if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { StringRef S = A->getValue(); if (S == "thin") - Opts.PrepareForThinLTO = true; + Opts.EmitSummaryIndex = true; else if (S != "full") Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; } diff --git a/test/CodeGen/emit-summary-index.c b/test/CodeGen/emit-summary-index.c deleted file mode 100644 index 6126410206..0000000000 --- a/test/CodeGen/emit-summary-index.c +++ /dev/null @@ -1,17 +0,0 @@ -// ; Check that the -flto=thin option emits a ThinLTO summary -// RUN: %clang_cc1 -flto=thin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck %s -// CHECK: Date: Thu, 21 Jun 2018 21:45:24 +0000 Subject: [PATCH 0223/1023] Re-apply: Add python tool to dump and construct header maps Header maps are binary files used by Xcode, which are used to map header names or paths to other locations. Clang has support for those since its inception, but there's not a lot of header map testing around. Since it's a binary format, testing becomes pretty much brittle and its hard to even know what's inside if you don't have the appropriate tools. Add a python based tool that allows creating and dumping header maps based on a json description of those. While here, rewrite tests to use the tool and remove the binary files from the tree. This tool was initially written by Daniel Dunbar. Thanks to Stella Stamenova for helping make this work on Windows. Differential Revision: https://reviews.llvm.org/D46485 rdar://problem/39994722 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335295 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 + test/CMakeLists.txt | 1 + test/Modules/crash-vfs-headermaps.m | 10 +- .../Inputs/headermap-rel/foo.hmap | Bin 804 -> 0 bytes .../Inputs/headermap-rel/foo.hmap.json | 6 + .../headermap-rel2/project-headers.hmap | Bin 108 -> 0 bytes .../headermap-rel2/project-headers.hmap.json | 6 + .../Inputs/nonportable-hmaps/foo.hmap | Bin 102 -> 0 bytes .../Inputs/nonportable-hmaps/foo.hmap.json | 6 + test/Preprocessor/headermap-rel.c | 8 +- test/Preprocessor/headermap-rel2.c | 9 +- .../nonportable-include-with-hmap.c | 4 +- test/lit.cfg.py | 2 +- utils/hmaptool/CMakeLists.txt | 16 + utils/hmaptool/hmaptool | 296 ++++++++++++++++++ 15 files changed, 345 insertions(+), 20 deletions(-) delete mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap.json delete mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json delete mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap create mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json create mode 100644 utils/hmaptool/CMakeLists.txt create mode 100755 utils/hmaptool/hmaptool diff --git a/CMakeLists.txt b/CMakeLists.txt index ab81ec34b0..ae8835d751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,6 +753,7 @@ endif() if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() +add_subdirectory(utils/hmaptool) configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8efe3600c5..8d6db5348e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff + hmaptool ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index 4f88f3ba11..c340d268ea 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -1,15 +1,9 @@ // REQUIRES: crash-recovery, shell, system-darwin -// This uses a headermap with this entry: -// Foo.h -> Foo/Foo.h - -// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid -// adding another binary format to the repository. - // RUN: rm -rf %t -// RUN: mkdir -p %t/m -// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i +// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h +// RUN: '%python' hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap deleted file mode 100644 index 783c64e67bb80a38f23845ed54fac43e2dc101a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 804 zcmXR&%*|kAU|^77W?%r(4h#$ooD9Pkfc(hL0P*Ya_2sC~C=LO){CvF(2DkiteFgxL C7zHB$ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json new file mode 100644 index 0000000000..ccfd911f0f --- /dev/null +++ b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "Foo.h" : "Foo/Foo.h" + } +} diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap deleted file mode 100644 index a0770fb251242a3eec33dda98beab4f3d38adef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmXR&%*|kAU|{fIU|;~zEDQ_`A`HX Foo/Foo.h - -// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel +// RUN: rm -f %t.hmap +// RUN: '%python' hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap +// RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i // CHECK: Foo.h is parsed diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index d61f3385b2..af12bf3949 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,8 +1,7 @@ -// This uses a headermap with this entry: -// someheader.h -> Product/someheader.h - -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// RUN: rm -f %t.hmap +// RUN: '%python' hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap +// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H +// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index fc958e7e5e..f2c279f36c 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,5 +1,7 @@ +// RUN: rm -f %t.hmap +// RUN: '%python' hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ -// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \ +// RUN: -I%t.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ // RUN: %s -verify // diff --git a/test/lit.cfg.py b/test/lit.cfg.py index f5cc72bdf5..6fa7ef66fc 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -58,7 +58,7 @@ tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir] tools = [ 'c-index-test', 'clang-check', 'clang-diff', 'clang-format', 'clang-tblgen', - 'opt', + 'opt', 'hmaptool', ToolSubst('%clang_func_map', command=FindTool( 'clang-func-mapping'), unresolved='ignore'), ] diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt new file mode 100644 index 0000000000..5573009d34 --- /dev/null +++ b/utils/hmaptool/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CLANG_HMAPTOOL hmaptool) + +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) + +list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}) +install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) + +add_custom_target(hmaptool ALL DEPENDS ${Depends}) +set_target_properties(hmaptool PROPERTIES FOLDER "Utils") + diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool new file mode 100755 index 0000000000..2b1ca7436c --- /dev/null +++ b/utils/hmaptool/hmaptool @@ -0,0 +1,296 @@ +#!/usr/bin/env python +from __future__ import print_function + +import json +import optparse +import os +import struct +import sys + +### + +k_header_magic_LE = 'pamh' +k_header_magic_BE = 'hmap' + +def hmap_hash(str): + """hash(str) -> int + + Apply the "well-known" headermap hash function. + """ + + return sum((ord(c.lower()) * 13 + for c in str), 0) + +class HeaderMap(object): + @staticmethod + def frompath(path): + with open(path, 'rb') as f: + magic = f.read(4) + if magic == k_header_magic_LE: + endian_code = '<' + elif magic == k_header_magic_BE: + endian_code = '>' + else: + raise SystemExit("error: %s: not a headermap" % ( + path,)) + + # Read the header information. + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + data = f.read(header_size) + if len(data) != header_size: + raise SystemExit("error: %s: truncated headermap header" % ( + path,)) + + (version, reserved, strtable_offset, num_entries, + num_buckets, max_value_len) = struct.unpack(header_fmt, data) + + if version != 1: + raise SystemExit("error: %s: unknown headermap version: %r" % ( + path, version)) + if reserved != 0: + raise SystemExit("error: %s: invalid reserved value in header" % ( + path,)) + + # The number of buckets must be a power of two. + if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0: + raise SystemExit("error: %s: invalid number of buckets" % ( + path,)) + + # Read all of the buckets. + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + buckets_data = f.read(num_buckets * bucket_size) + if len(buckets_data) != num_buckets * bucket_size: + raise SystemExit("error: %s: truncated headermap buckets" % ( + path,)) + buckets = [struct.unpack(bucket_fmt, + buckets_data[i*bucket_size:(i+1)*bucket_size]) + for i in range(num_buckets)] + + # Read the string table; the format doesn't explicitly communicate the + # size of the string table (which is dumb), so assume it is the rest of + # the file. + f.seek(0, 2) + strtable_size = f.tell() - strtable_offset + f.seek(strtable_offset) + + if strtable_size == 0: + raise SystemExit("error: %s: unable to read zero-sized string table"%( + path,)) + strtable = f.read(strtable_size) + + if len(strtable) != strtable_size: + raise SystemExit("error: %s: unable to read complete string table"%( + path,)) + if strtable[-1] != '\0': + raise SystemExit("error: %s: invalid string table in headermap" % ( + path,)) + + return HeaderMap(num_entries, buckets, strtable) + + def __init__(self, num_entries, buckets, strtable): + self.num_entries = num_entries + self.buckets = buckets + self.strtable = strtable + + def get_string(self, idx): + if idx >= len(self.strtable): + raise SystemExit("error: %s: invalid string index" % ( + path,)) + end_idx = self.strtable.index('\0', idx) + return self.strtable[idx:end_idx] + + @property + def mappings(self): + for key_idx,prefix_idx,suffix_idx in self.buckets: + if key_idx == 0: + continue + yield (self.get_string(key_idx), + self.get_string(prefix_idx) + self.get_string(suffix_idx)) + +### + +def action_dump(name, args): + "dump a headermap file" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("-v", "--verbose", dest="verbose", + help="show more verbose output [%default]", + action="store_true", default=False) + (opts, args) = parser.parse_args(args) + + if len(args) != 1: + parser.error("invalid number of arguments") + + path, = args + + hmap = HeaderMap.frompath(path) + + # Dump all of the buckets. + print ('Header Map: %s' % (path,)) + if opts.verbose: + print ('headermap: %r' % (path,)) + print (' num entries: %d' % (hmap.num_entries,)) + print (' num buckets: %d' % (len(hmap.buckets),)) + print (' string table size: %d' % (len(hmap.strtable),)) + for i,bucket in enumerate(hmap.buckets): + key_idx,prefix_idx,suffix_idx = bucket + + if key_idx == 0: + continue + + # Get the strings. + key = hmap.get_string(key_idx) + prefix = hmap.get_string(prefix_idx) + suffix = hmap.get_string(suffix_idx) + + print (" bucket[%d]: %r -> (%r, %r) -- %d" % ( + i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1)))) + else: + mappings = sorted(hmap.mappings) + for key,value in mappings: + print ("%s -> %s" % (key, value)) + print () + +def next_power_of_two(value): + if value < 0: + raise ArgumentError + return 1 if value == 0 else 2**(value - 1).bit_length() + +def action_write(name, args): + "write a headermap file from a JSON definition" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + + input_path,output_path = args + + with open(input_path, "r") as f: + input_data = json.load(f) + + # Compute the headermap contents, we make a table that is 1/3 full. + mappings = input_data['mappings'] + num_buckets = next_power_of_two(len(mappings) * 3) + + table = [(0, 0, 0) + for i in range(num_buckets)] + max_value_len = 0 + strtable = "\0" + for key,value in mappings.items(): + if not isinstance(key, str): + key = key.decode('utf-8') + if not isinstance(value, str): + value = value.decode('utf-8') + max_value_len = max(max_value_len, len(value)) + + key_idx = len(strtable) + strtable += key + '\0' + prefix = os.path.dirname(value) + '/' + suffix = os.path.basename(value) + prefix_idx = len(strtable) + strtable += prefix + '\0' + suffix_idx = len(strtable) + strtable += suffix + '\0' + + hash = hmap_hash(key) + for i in range(num_buckets): + idx = (hash + i) % num_buckets + if table[idx][0] == 0: + table[idx] = (key_idx, prefix_idx, suffix_idx) + break + else: + raise RuntimeError + + endian_code = '<' + magic = k_header_magic_LE + magic_size = 4 + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + strtable_offset = magic_size + header_size + num_buckets * bucket_size + header = (1, 0, strtable_offset, len(mappings), + num_buckets, max_value_len) + + # Write out the headermap. + with open(output_path, 'wb') as f: + f.write(magic.encode()) + f.write(struct.pack(header_fmt, *header)) + for bucket in table: + f.write(struct.pack(bucket_fmt, *bucket)) + f.write(strtable.encode()) + +def action_tovfs(name, args): + "convert a headermap to a VFS layout" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("", "--build-path", dest="build_path", + help="build path prefix", + action="store", type=str) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + if opts.build_path is None: + parser.error("--build-path is required") + + input_path,output_path = args + + hmap = HeaderMap.frompath(input_path) + + # Create the table for all the objects. + vfs = {} + vfs['version'] = 0 + build_dir_contents = [] + vfs['roots'] = [{ + 'name' : opts.build_path, + 'type' : 'directory', + 'contents' : build_dir_contents }] + + # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to + # "/Foo.framework/Headers/Bar.h". + for key,value in hmap.mappings: + # If this isn't a framework style mapping, ignore it. + components = key.split('/') + if len(components) != 2: + continue + framework_name,header_name = components + build_dir_contents.append({ + 'name' : '%s.framework/Headers/%s' % (framework_name, + header_name), + 'type' : 'file', + 'external-contents' : value }) + + with open(output_path, 'w') as f: + json.dump(vfs, f, indent=2) + +commands = dict((name[7:].replace("_","-"), f) + for name,f in locals().items() + if name.startswith('action_')) + +def usage(): + print ("Usage: %s command [options]" % ( + os.path.basename(sys.argv[0])), file=sys.stderr) + print (file=sys.stderr) + print ("Available commands:", file=sys.stderr) + cmds_width = max(map(len, commands)) + for name,func in sorted(commands.items()): + print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr) + sys.exit(1) + +def main(): + if len(sys.argv) < 2 or sys.argv[1] not in commands: + usage() + + cmd = sys.argv[1] + commands[cmd](cmd, sys.argv[2:]) + +if __name__ == '__main__': + main() -- GitLab From 8fa8ac3e9e950d0e7b9419df7040c84da6e2504d Mon Sep 17 00:00:00 2001 From: Emmett Neyman Date: Thu, 21 Jun 2018 22:08:20 +0000 Subject: [PATCH 0224/1023] Test commit, made a minor change to a comment git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335299 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp index 69fa31f170..3640be13fa 100644 --- a/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp +++ b/tools/clang-fuzzer/ExampleClangLoopProtoFuzzer.cpp @@ -11,7 +11,7 @@ /// This file implements a function that runs Clang on a single /// input and uses libprotobuf-mutator to find new inputs. This function is /// then linked into the Fuzzer library. This file differs from -/// ExampleClangProtoFuzzer in that it uses the new protobuf that includes +/// ExampleClangProtoFuzzer in that it uses a different protobuf that includes /// C++ code with a single for loop. /// //===----------------------------------------------------------------------===// -- GitLab From ae3ac6af8dbb69611d941cb3705145e77577d871 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 21 Jun 2018 23:22:37 +0000 Subject: [PATCH 0225/1023] Ignore blacklist when generating __cfi_check_fail. Summary: Fixes PR37898. Reviewers: pcc, vlad.tsyrklevich Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48454 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335305 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 5 +++++ test/CodeGen/cfi-check-fail2.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c1b30500a7..12b30936dc 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -3075,6 +3075,11 @@ void CodeGenFunction::EmitCfiCheckFail() { StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, SourceLocation()); + // This function should not be affected by blacklist. This function does + // not have a source location, but "src:*" would still apply. Revert any + // changes to SanOpts made in StartFunction. + SanOpts = CGM.getLangOpts().Sanitize; + llvm::Value *Data = EmitLoadOfScalar(GetAddrOfLocalVar(&ArgData), /*Volatile=*/false, CGM.getContext().VoidPtrTy, ArgData.getLocation()); diff --git a/test/CodeGen/cfi-check-fail2.c b/test/CodeGen/cfi-check-fail2.c index 5340871c2e..9c4d0ac2ea 100644 --- a/test/CodeGen/cfi-check-fail2.c +++ b/test/CodeGen/cfi-check-fail2.c @@ -3,6 +3,12 @@ // RUN: -fsanitize=cfi-vcall \ // RUN: -emit-llvm -o - %s | FileCheck %s +// Check that blacklist does not affect generated code. +// RUN: echo "src:*" > %t-all.blacklist +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O0 -fsanitize-cfi-cross-dso \ +// RUN: -fsanitize=cfi-vcall -fsanitize-blacklist=%t-all.blacklist \ +// RUN: -emit-llvm -o - %s | FileCheck %s + void caller(void (*f)()) { f(); } -- GitLab From b3f7cdc3d9fa8c24f3ef87f15876ee143428883c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 23:39:47 +0000 Subject: [PATCH 0226/1023] [X86] Update handling in CGBuiltin to be tolerant of out of range immediates. D48464 contains changes that will loosen some of the range checks in SemaChecking to a DefaultError warning that can be disabled. This patch adds explicit masking to avoid using the upper bits of immediates to gracefully handle the warning being disabled. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335308 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 42 ++++++++++++++++++++++++----------- test/CodeGen/avx-builtins.c | 16 ++++++------- test/CodeGen/sse2-builtins.c | 4 ++-- test/CodeGen/sse41-builtins.c | 14 ++++++------ test/CodeGen/vector.c | 4 ++-- 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 739f2341d9..b9430e6fc9 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9031,10 +9031,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_vec_ext_v32qi: case X86::BI__builtin_ia32_vec_ext_v16hi: case X86::BI__builtin_ia32_vec_ext_v8si: - case X86::BI__builtin_ia32_vec_ext_v4di: + case X86::BI__builtin_ia32_vec_ext_v4di: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + uint64_t Index = cast(Ops[1])->getZExtValue(); + Index &= NumElts - 1; // These builtins exist so we can ensure the index is an ICE and in range. // Otherwise we could just do this in the header file. - return Builder.CreateExtractElement(Ops[0], Ops[1]); + return Builder.CreateExtractElement(Ops[0], Index); + } case X86::BI__builtin_ia32_vec_set_v16qi: case X86::BI__builtin_ia32_vec_set_v8hi: case X86::BI__builtin_ia32_vec_set_v4si: @@ -9042,10 +9046,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_vec_set_v32qi: case X86::BI__builtin_ia32_vec_set_v16hi: case X86::BI__builtin_ia32_vec_set_v8si: - case X86::BI__builtin_ia32_vec_set_v4di: + case X86::BI__builtin_ia32_vec_set_v4di: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + unsigned Index = cast(Ops[2])->getZExtValue(); + Index &= NumElts - 1; // These builtins exist so we can ensure the index is an ICE and in range. // Otherwise we could just do this in the header file. - return Builder.CreateInsertElement(Ops[0], Ops[1], Ops[2]); + return Builder.CreateInsertElement(Ops[0], Ops[1], Index); + } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { Address Tmp = CreateMemTemp(E->getArg(0)->getType()); @@ -9311,8 +9319,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // extract (0, 1) unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1; - llvm::Value *Idx = llvm::ConstantInt::get(SizeTy, Index); - Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract"); + Ops[1] = Builder.CreateExtractElement(Ops[1], Index, "extract"); // cast pointer to i64 & store Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); @@ -9336,7 +9343,12 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_extracti64x2_512_mask: { llvm::Type *DstTy = ConvertType(E->getType()); unsigned NumElts = DstTy->getVectorNumElements(); - unsigned Index = cast(Ops[1])->getZExtValue() * NumElts; + unsigned SrcNumElts = Ops[0]->getType()->getVectorNumElements(); + unsigned SubVectors = SrcNumElts / NumElts; + unsigned Index = cast(Ops[1])->getZExtValue(); + assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors"); + Index &= SubVectors - 1; // Remove any extra bits. + Index *= NumElts; uint32_t Indices[16]; for (unsigned i = 0; i != NumElts; ++i) @@ -9370,7 +9382,11 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_inserti64x2_512: { unsigned DstNumElts = Ops[0]->getType()->getVectorNumElements(); unsigned SrcNumElts = Ops[1]->getType()->getVectorNumElements(); - unsigned Index = cast(Ops[2])->getZExtValue() * SrcNumElts; + unsigned SubVectors = DstNumElts / SrcNumElts; + unsigned Index = cast(Ops[2])->getZExtValue(); + assert(llvm::isPowerOf2_32(SubVectors) && "Expected power of 2 subvectors"); + Index &= SubVectors - 1; // Remove any extra bits. + Index *= SrcNumElts; uint32_t Indices[16]; for (unsigned i = 0; i != DstNumElts; ++i) @@ -9571,7 +9587,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr256: case X86::BI__builtin_ia32_palignr512: { - unsigned ShiftVal = cast(Ops[2])->getZExtValue(); + unsigned ShiftVal = cast(Ops[2])->getZExtValue() & 0xff; unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); assert(NumElts % 16 == 0); @@ -9611,7 +9627,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_alignq256: case X86::BI__builtin_ia32_alignq512: { unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - unsigned ShiftVal = cast(Ops[2])->getZExtValue(); + unsigned ShiftVal = cast(Ops[2])->getZExtValue() & 0xff; // Mask the shift amount to width of two vectors. ShiftVal &= (2 * NumElts) - 1; @@ -9696,7 +9712,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_pslldqi128_byteshift: case X86::BI__builtin_ia32_pslldqi256_byteshift: case X86::BI__builtin_ia32_pslldqi512_byteshift: { - unsigned ShiftVal = cast(Ops[1])->getZExtValue(); + unsigned ShiftVal = cast(Ops[1])->getZExtValue() & 0xff; llvm::Type *ResultType = Ops[0]->getType(); // Builtin type is vXi64 so multiply by 8 to get bytes. unsigned NumElts = ResultType->getVectorNumElements() * 8; @@ -9726,7 +9742,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_psrldqi128_byteshift: case X86::BI__builtin_ia32_psrldqi256_byteshift: case X86::BI__builtin_ia32_psrldqi512_byteshift: { - unsigned ShiftVal = cast(Ops[1])->getZExtValue(); + unsigned ShiftVal = cast(Ops[1])->getZExtValue() & 0xff; llvm::Type *ResultType = Ops[0]->getType(); // Builtin type is vXi64 so multiply by 8 to get bytes. unsigned NumElts = ResultType->getVectorNumElements() * 8; @@ -10170,7 +10186,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_cmpps256: case X86::BI__builtin_ia32_cmppd: case X86::BI__builtin_ia32_cmppd256: { - unsigned CC = cast(Ops[2])->getZExtValue(); + unsigned CC = cast(Ops[2])->getZExtValue() & 0x1f; // If this one of the SSE immediates, we can use native IR. if (CC < 8) { FCmpInst::Predicate Pred; diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index bd72dcaae5..67632e9dde 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -316,27 +316,27 @@ __m256 test_mm256_dp_ps(__m256 A, __m256 B) { int test_mm256_extract_epi8(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi8 - // CHECK: extractelement <32 x i8> %{{.*}}, i32 31 + // CHECK: extractelement <32 x i8> %{{.*}}, {{i32|i64}} 31 // CHECK: zext i8 %{{.*}} to i32 return _mm256_extract_epi8(A, 31); } int test_mm256_extract_epi16(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi16 - // CHECK: extractelement <16 x i16> %{{.*}}, i32 15 + // CHECK: extractelement <16 x i16> %{{.*}}, {{i32|i64}} 15 // CHECK: zext i16 %{{.*}} to i32 return _mm256_extract_epi16(A, 15); } int test_mm256_extract_epi32(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi32 - // CHECK: extractelement <8 x i32> %{{.*}}, i32 7 + // CHECK: extractelement <8 x i32> %{{.*}}, {{i32|i64}} 7 return _mm256_extract_epi32(A, 7); } long long test_mm256_extract_epi64(__m256i A) { // CHECK-LABEL: test_mm256_extract_epi64 - // CHECK: extractelement <4 x i64> %{{.*}}, i32 3 + // CHECK: extractelement <4 x i64> %{{.*}}, {{i32|i64}} 3 return _mm256_extract_epi64(A, 3); } @@ -396,25 +396,25 @@ __m256 test_mm256_hsub_ps(__m256 A, __m256 B) { __m256i test_mm256_insert_epi8(__m256i x, char b) { // CHECK-LABEL: test_mm256_insert_epi8 - // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, i32 14 + // CHECK: insertelement <32 x i8> %{{.*}}, i8 %{{.*}}, {{i32|i64}} 14 return _mm256_insert_epi8(x, b, 14); } __m256i test_mm256_insert_epi16(__m256i x, int b) { // CHECK-LABEL: test_mm256_insert_epi16 - // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, i32 4 + // CHECK: insertelement <16 x i16> %{{.*}}, i16 %{{.*}}, {{i32|i64}} 4 return _mm256_insert_epi16(x, b, 4); } __m256i test_mm256_insert_epi32(__m256i x, int b) { // CHECK-LABEL: test_mm256_insert_epi32 - // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, i32 5 + // CHECK: insertelement <8 x i32> %{{.*}}, i32 %{{.*}}, {{i32|i64}} 5 return _mm256_insert_epi32(x, b, 5); } __m256i test_mm256_insert_epi64(__m256i x, long long b) { // CHECK-LABEL: test_mm256_insert_epi64 - // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, i32 2 + // CHECK: insertelement <4 x i64> %{{.*}}, i64 %{{.*}}, {{i32|i64}} 2 return _mm256_insert_epi64(x, b, 2); } diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index 35554bc187..dbf79c4736 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -613,14 +613,14 @@ __m128d test_mm_div_sd(__m128d A, __m128d B) { // Lowering to pextrw requires optimization. int test_mm_extract_epi16(__m128i A) { // CHECK-LABEL: test_mm_extract_epi16 - // CHECK: extractelement <8 x i16> %{{.*}}, i32 1 + // CHECK: extractelement <8 x i16> %{{.*}}, {{i32|i64}} 1 // CHECK: zext i16 %{{.*}} to i32 return _mm_extract_epi16(A, 1); } __m128i test_mm_insert_epi16(__m128i A, int B) { // CHECK-LABEL: test_mm_insert_epi16 - // CHECK: insertelement <8 x i16> %{{.*}}, i32 0 + // CHECK: insertelement <8 x i16> %{{.*}}, {{i32|i64}} 0 return _mm_insert_epi16(A, B, 0); } diff --git a/test/CodeGen/sse41-builtins.c b/test/CodeGen/sse41-builtins.c index 6d6e11e962..2d9da07330 100644 --- a/test/CodeGen/sse41-builtins.c +++ b/test/CodeGen/sse41-builtins.c @@ -171,26 +171,26 @@ __m128 test_mm_dp_ps(__m128 x, __m128 y) { int test_mm_extract_epi8(__m128i x) { // CHECK-LABEL: test_mm_extract_epi8 - // CHECK: extractelement <16 x i8> %{{.*}}, i32 1 + // CHECK: extractelement <16 x i8> %{{.*}}, {{i32|i64}} 1 // CHECK: zext i8 %{{.*}} to i32 return _mm_extract_epi8(x, 1); } int test_mm_extract_epi32(__m128i x) { // CHECK-LABEL: test_mm_extract_epi32 - // CHECK: extractelement <4 x i32> %{{.*}}, i32 1 + // CHECK: extractelement <4 x i32> %{{.*}}, {{i32|i64}} 1 return _mm_extract_epi32(x, 1); } long long test_mm_extract_epi64(__m128i x) { // CHECK-LABEL: test_mm_extract_epi64 - // CHECK: extractelement <2 x i64> %{{.*}}, i32 1 + // CHECK: extractelement <2 x i64> %{{.*}}, {{i32|i64}} 1 return _mm_extract_epi64(x, 1); } int test_mm_extract_ps(__m128 x) { // CHECK-LABEL: test_mm_extract_ps - // CHECK: extractelement <4 x float> %{{.*}}, i32 1 + // CHECK: extractelement <4 x float> %{{.*}}, {{i32|i64}} 1 return _mm_extract_ps(x, 1); } @@ -220,19 +220,19 @@ __m128 test_mm_floor_ss(__m128 x, __m128 y) { __m128i test_mm_insert_epi8(__m128i x, char b) { // CHECK-LABEL: test_mm_insert_epi8 - // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, i32 1 + // CHECK: insertelement <16 x i8> %{{.*}}, i8 %{{.*}}, {{i32|i64}} 1 return _mm_insert_epi8(x, b, 1); } __m128i test_mm_insert_epi32(__m128i x, int b) { // CHECK-LABEL: test_mm_insert_epi32 - // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, i32 1 + // CHECK: insertelement <4 x i32> %{{.*}}, i32 %{{.*}}, {{i32|i64}} 1 return _mm_insert_epi32(x, b, 1); } __m128i test_mm_insert_epi64(__m128i x, long long b) { // CHECK-LABEL: test_mm_insert_epi64 - // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, i32 1 + // CHECK: insertelement <2 x i64> %{{.*}}, i64 %{{.*}}, {{i32|i64}} 1 return _mm_insert_epi64(x, b, 1); } diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c index 98dd82a28a..c79cd84f7e 100644 --- a/test/CodeGen/vector.c +++ b/test/CodeGen/vector.c @@ -45,13 +45,13 @@ int test4(int argc, char *argv[]) { unsigned long test_epi8(__m128i x) { return _mm_extract_epi8(x, 4); } // CHECK: @test_epi8 -// CHECK: extractelement <16 x i8> {{.*}}, i32 4 +// CHECK: extractelement <16 x i8> {{.*}}, {{i32|i64}} 4 // CHECK: zext i8 {{.*}} to i32 unsigned long test_epi16(__m128i x) { return _mm_extract_epi16(x, 3); } // CHECK: @test_epi16 -// CHECK: extractelement <8 x i16> {{.*}}, i32 3 +// CHECK: extractelement <8 x i16> {{.*}}, {{i32|i64}} 3 // CHECK: zext i16 {{.*}} to i32 void extractinttypes() { -- GitLab From 6fe85e4ee4ab061034a40341cb1ab729895c72be Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 21 Jun 2018 23:46:09 +0000 Subject: [PATCH 0227/1023] [x86] Teach the builtin argument range check to allow invalid ranges in dead code. This is important for C++ templates that essentially compute the valid input in a way that is constant and will cause all the invalid cases to be dead code that is deleted. Code in the wild actually does this and GCC also accepts these kinds of patterns so it is important to support it. To make this work, we provide a non-error path to diagnose these issues, and use a default-error warning instead. This keeps the relatively strict handling but prevents nastiness like SFINAE on these errors. It also allows us to safely use the system to diagnose this only when it occurs at runtime (in emitted code). Entertainingly, this required fixing the syntax in various other ways for the x86 test because we never bothered to diagnose that the returns were invalid. Since debugging these compile failures was super confusing, I've also improved the diagnostic to actually say what the value was. Most of the checks I've made ignore this to simplify maintenance, but I've checked it in a few places to make sure the diagnsotic is working. Depends on D48462. Without that, we might actually crash some part of the compiler after bypassing the error here. Thanks to Richard, Ben Kramer, and especially Craig Topper for all the help here. Differential Revision: https://reviews.llvm.org/D48464 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335309 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 5 +- include/clang/Sema/Sema.h | 4 +- lib/Sema/SemaChecking.cpp | 24 ++- test/CodeGen/builtins-mips-args.c | 28 ++-- test/CodeGen/builtins-systemz-vector-error.c | 140 ++++++++-------- test/CodeGen/builtins-systemz-vector2-error.c | 32 ++-- test/CodeGen/builtins-systemz-zvector-error.c | 4 +- .../CodeGen/builtins-systemz-zvector2-error.c | 4 +- test/CodeGen/hexagon-check-builtins.c | 16 +- test/Sema/aarch64-neon-fp16-ranges.c | 40 ++--- test/Sema/aarch64-neon-ranges.c | 150 +++++++++--------- test/Sema/arm-neon-types.c | 2 +- test/Sema/builtin-object-size.c | 6 +- test/Sema/builtin-prefetch.c | 6 +- test/Sema/builtins-arm.c | 32 ++-- test/Sema/builtins-arm64.c | 14 +- test/Sema/builtins-ppc.c | 34 ++-- test/Sema/builtins-x86.c | 74 ++++----- test/Sema/builtins-x86.cpp | 23 +++ test/SemaCXX/neon-vector-types.cpp | 2 +- 20 files changed, 340 insertions(+), 300 deletions(-) create mode 100644 test/Sema/builtins-x86.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 878443df4a..454aa53774 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8132,7 +8132,10 @@ def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< - "argument should be a value from %0 to %1">; + "argument value %0 is outside the valid range [%1, %2]">; +def warn_argument_invalid_range : Warning< + "argument value %0 is outside the valid range [%1, %2]">, DefaultError, + InGroup>; def err_argument_not_multiple : Error< "argument should be a multiple of %0">; def warn_neon_vector_initializer_non_portable : Warning< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 8b4cf02fde..5d2f4f0811 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -10431,8 +10431,8 @@ private: bool IsDelete); bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); - bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, - int Low, int High); + bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, + int High, bool RangeIsError = true); bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple); bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 9a05d9f00e..53be0f6d9f 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2937,7 +2937,12 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { i = 4; l = 0; u = 255; break; } - return SemaBuiltinConstantArgRange(TheCall, i, l, u); + + // Note that we don't force a hard error on the range check here, allowing + // template-generated or macro-generated dead code to potentially have out-of- + // range values. These need to code generate, but don't need to necessarily + // make any sense. We use a warning that defaults to an error. + return SemaBuiltinConstantArgRange(TheCall, i, l, u, /*RangeIsError*/ false); } /// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo @@ -5005,7 +5010,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, /// SemaBuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr /// TheCall is a constant expression in the range [Low, High]. bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, - int Low, int High) { + int Low, int High, bool RangeIsError) { llvm::APSInt Result; // We can't check the value of a dependent argument. @@ -5017,9 +5022,18 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) return true; - if (Result.getSExtValue() < Low || Result.getSExtValue() > High) - return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << Low << High << Arg->getSourceRange(); + if (Result.getSExtValue() < Low || Result.getSExtValue() > High) { + if (RangeIsError) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << Result.toString(10) << Low << High << Arg->getSourceRange(); + else + // Defer the warning until we know if the code will be emitted so that + // dead code can ignore this. + DiagRuntimeBehavior(TheCall->getLocStart(), TheCall, + PDiag(diag::warn_argument_invalid_range) + << Result.toString(10) << Low << High + << Arg->getSourceRange()); + } return false; } diff --git a/test/CodeGen/builtins-mips-args.c b/test/CodeGen/builtins-mips-args.c index fd3e31443e..cdb42af4a5 100644 --- a/test/CodeGen/builtins-mips-args.c +++ b/test/CodeGen/builtins-mips-args.c @@ -7,10 +7,10 @@ void foo() { int a = 3; __builtin_mips_wrdsp(2052, a); // expected-error{{argument to '__builtin_mips_wrdsp' must be a constant integer}} __builtin_mips_rddsp(a); // expected-error{{argument to '__builtin_mips_rddsp' must be a constant integer}} - __builtin_mips_wrdsp(2052, -1); // expected-error{{argument should be a value from 0 to 63}} - __builtin_mips_rddsp(-1); // expected-error{{argument should be a value from 0 to 63}} - __builtin_mips_wrdsp(2052, 64); // expected-error{{argument should be a value from 0 to 63}} - __builtin_mips_rddsp(64); // expected-error{{argument should be a value from 0 to 63}} + __builtin_mips_wrdsp(2052, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_rddsp(-1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_wrdsp(2052, 64); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_rddsp(64); // expected-error-re{{argument value {{.*}} is outside the valid range}} // MIPS DSP Rev 2 @@ -20,18 +20,18 @@ void foo() { __builtin_mips_precr_sra_r_ph_w(1, 2, a); // expected-error{{argument to '__builtin_mips_precr_sra_r_ph_w' must be a constant integer}} __builtin_mips_prepend(1, 2, a); // expected-error{{argument to '__builtin_mips_prepend' must be a constant integer}} - __builtin_mips_append(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}} - __builtin_mips_append(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}} + __builtin_mips_append(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_append(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}} - __builtin_mips_balign(1, 2, -1); // expected-error{{argument should be a value from 0 to 3}} - __builtin_mips_balign(1, 2, 4); // expected-error{{argument should be a value from 0 to 3}} + __builtin_mips_balign(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_balign(1, 2, 4); // expected-error-re{{argument value {{.*}} is outside the valid range}} - __builtin_mips_precr_sra_ph_w(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}} - __builtin_mips_precr_sra_ph_w(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}} + __builtin_mips_precr_sra_ph_w(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_precr_sra_ph_w(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}} - __builtin_mips_precr_sra_r_ph_w(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}} - __builtin_mips_precr_sra_r_ph_w(1, 2, 32); // expected-error{{argument should be a value from 0 to 31}} + __builtin_mips_precr_sra_r_ph_w(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_precr_sra_r_ph_w(1, 2, 32); // expected-error-re{{argument value {{.*}} is outside the valid range}} - __builtin_mips_prepend(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}} - __builtin_mips_prepend(1, 2, -1); // expected-error{{argument should be a value from 0 to 31}} + __builtin_mips_prepend(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} + __builtin_mips_prepend(1, 2, -1); // expected-error-re{{argument value {{.*}} is outside the valid range}} } diff --git a/test/CodeGen/builtins-systemz-vector-error.c b/test/CodeGen/builtins-systemz-vector-error.c index 6f4ecc2aca..f0db901082 100644 --- a/test/CodeGen/builtins-systemz-vector-error.c +++ b/test/CodeGen/builtins-systemz-vector-error.c @@ -27,148 +27,148 @@ const void * volatile cptr; int cc; void test_core(void) { - __builtin_s390_lcbb(cptr, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_lcbb(cptr, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_lcbb(cptr, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_lcbb(cptr, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_lcbb(cptr, len); // expected-error {{must be a constant integer}} - __builtin_s390_vlbb(cptr, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vlbb(cptr, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vlbb(cptr, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vlbb(cptr, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vlbb(cptr, len); // expected-error {{must be a constant integer}} - __builtin_s390_vpdi(vul, vul, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vpdi(vul, vul, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vpdi(vul, vul, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vpdi(vul, vul, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vpdi(vul, vul, len); // expected-error {{must be a constant integer}} } void test_integer(void) { - __builtin_s390_verimb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 255}} - __builtin_s390_verimb(vuc, vuc, vuc, 256); // expected-error {{argument should be a value from 0 to 255}} + __builtin_s390_verimb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_verimb(vuc, vuc, vuc, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_verimb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}} - __builtin_s390_verimh(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 255}} - __builtin_s390_verimh(vus, vus, vus, 256); // expected-error {{argument should be a value from 0 to 255}} + __builtin_s390_verimh(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_verimh(vus, vus, vus, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_verimh(vus, vus, vus, len); // expected-error {{must be a constant integer}} - __builtin_s390_verimf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 255}} - __builtin_s390_verimf(vui, vui, vui, 256); // expected-error {{argument should be a value from 0 to 255}} + __builtin_s390_verimf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_verimf(vui, vui, vui, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_verimf(vui, vui, vui, len); // expected-error {{must be a constant integer}} - __builtin_s390_verimg(vul, vul, vul, -1); // expected-error {{argument should be a value from 0 to 255}} - __builtin_s390_verimg(vul, vul, vul, 256); // expected-error {{argument should be a value from 0 to 255}} + __builtin_s390_verimg(vul, vul, vul, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_verimg(vul, vul, vul, 256); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_verimg(vul, vul, vul, len); // expected-error {{must be a constant integer}} - __builtin_s390_vsldb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vsldb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vsldb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vsldb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vsldb(vuc, vuc, len); // expected-error {{must be a constant integer}} } void test_string(void) { - __builtin_s390_vfaeb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaeb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaeb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaeb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaeb(vuc, vuc, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaeh(vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaeh(vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaeh(vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaeh(vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaeh(vus, vus, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaef(vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaef(vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaef(vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaef(vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaef(vui, vui, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezb(vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezb(vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezb(vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezb(vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezb(vuc, vuc, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezh(vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezh(vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezh(vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezh(vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezh(vus, vus, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezf(vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezf(vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezf(vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezf(vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezf(vui, vui, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrcb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrcb(vuc, vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrcb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrcb(vuc, vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrcb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrch(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrch(vus, vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrch(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrch(vus, vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrch(vus, vus, vus, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrcf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrcf(vui, vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrcf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrcf(vui, vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrcf(vui, vui, vui, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczb(vuc, vuc, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczb(vuc, vuc, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczb(vuc, vuc, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczb(vuc, vuc, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczb(vuc, vuc, vuc, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczh(vus, vus, vus, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczh(vus, vus, vus, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczh(vus, vus, vus, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczh(vus, vus, vus, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczh(vus, vus, vus, len); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczf(vui, vui, vui, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczf(vui, vui, vui, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczf(vui, vui, vui, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczf(vui, vui, vui, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczf(vui, vui, vui, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfaebs(vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaebs(vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaebs(vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaebs(vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaebs(vuc, vuc, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfaehs(vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaehs(vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaehs(vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaehs(vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaehs(vus, vus, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfaefs(vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaefs(vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaefs(vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaefs(vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaefs(vui, vui, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezbs(vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezbs(vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezbs(vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezbs(vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezbs(vuc, vuc, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezhs(vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezhs(vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezhs(vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezhs(vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezhs(vus, vus, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfaezfs(vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfaezfs(vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfaezfs(vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfaezfs(vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfaezfs(vui, vui, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrcbs(vuc, vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrcbs(vuc, vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrcbs(vuc, vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrcbs(vuc, vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrcbs(vuc, vuc, vuc, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrchs(vus, vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrchs(vus, vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrchs(vus, vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrchs(vus, vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrchs(vus, vus, vus, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrcfs(vui, vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrcfs(vui, vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrcfs(vui, vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrcfs(vui, vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrcfs(vui, vui, vui, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczbs(vuc, vuc, vuc, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczbs(vuc, vuc, vuc, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczbs(vuc, vuc, vuc, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczbs(vuc, vuc, vuc, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczbs(vuc, vuc, vuc, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczhs(vus, vus, vus, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczhs(vus, vus, vus, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczhs(vus, vus, vus, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczhs(vus, vus, vus, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczhs(vus, vus, vus, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vstrczfs(vui, vui, vui, -1, &cc); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vstrczfs(vui, vui, vui, 16, &cc); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vstrczfs(vui, vui, vui, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vstrczfs(vui, vui, vui, 16, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vstrczfs(vui, vui, vui, len, &cc); // expected-error {{must be a constant integer}} } void test_float(void) { - __builtin_s390_vftcidb(vd, -1, &cc); // expected-error {{argument should be a value from 0 to 4095}} - __builtin_s390_vftcidb(vd, 4096, &cc); // expected-error {{argument should be a value from 0 to 4095}} + __builtin_s390_vftcidb(vd, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vftcidb(vd, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vftcidb(vd, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfidb(vd, -1, 0); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfidb(vd, 16, 0); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfidb(vd, -1, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfidb(vd, 16, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfidb(vd, len, 0); // expected-error {{must be a constant integer}} - __builtin_s390_vfidb(vd, 0, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfidb(vd, 0, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfidb(vd, 0, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfidb(vd, 0, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfidb(vd, 0, len); // expected-error {{must be a constant integer}} } diff --git a/test/CodeGen/builtins-systemz-vector2-error.c b/test/CodeGen/builtins-systemz-vector2-error.c index ceebaf8cc7..cd27ac79e1 100644 --- a/test/CodeGen/builtins-systemz-vector2-error.c +++ b/test/CodeGen/builtins-systemz-vector2-error.c @@ -28,34 +28,34 @@ volatile unsigned int len; int cc; void test_integer(void) { - __builtin_s390_vmslg(vul, vul, vuc, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vmslg(vul, vul, vuc, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vmslg(vul, vul, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vmslg(vul, vul, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vmslg(vul, vul, vuc, len); // expected-error {{must be a constant integer}} } void test_float(void) { - __builtin_s390_vfmaxdb(vd, vd, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfmaxdb(vd, vd, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfmaxdb(vd, vd, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfmaxdb(vd, vd, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfmaxdb(vd, vd, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfmindb(vd, vd, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfmindb(vd, vd, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfmindb(vd, vd, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfmindb(vd, vd, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfmindb(vd, vd, len); // expected-error {{must be a constant integer}} - __builtin_s390_vftcisb(vf, -1, &cc); // expected-error {{argument should be a value from 0 to 4095}} - __builtin_s390_vftcisb(vf, 4096, &cc); // expected-error {{argument should be a value from 0 to 4095}} + __builtin_s390_vftcisb(vf, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vftcisb(vf, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vftcisb(vf, len, &cc); // expected-error {{must be a constant integer}} - __builtin_s390_vfisb(vf, -1, 0); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfisb(vf, 16, 0); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfisb(vf, -1, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfisb(vf, 16, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfisb(vf, len, 0); // expected-error {{must be a constant integer}} - __builtin_s390_vfisb(vf, 0, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfisb(vf, 0, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfisb(vf, 0, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfisb(vf, 0, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfisb(vf, 0, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfmaxsb(vf, vf, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfmaxsb(vf, vf, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfmaxsb(vf, vf, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfmaxsb(vf, vf, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfmaxsb(vf, vf, len); // expected-error {{must be a constant integer}} - __builtin_s390_vfminsb(vf, vf, -1); // expected-error {{argument should be a value from 0 to 15}} - __builtin_s390_vfminsb(vf, vf, 16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_s390_vfminsb(vf, vf, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_s390_vfminsb(vf, vf, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_s390_vfminsb(vf, vf, len); // expected-error {{must be a constant integer}} } diff --git a/test/CodeGen/builtins-systemz-zvector-error.c b/test/CodeGen/builtins-systemz-zvector-error.c index 8d5aaabfba..cb60ea495e 100644 --- a/test/CodeGen/builtins-systemz-zvector-error.c +++ b/test/CodeGen/builtins-systemz-zvector-error.c @@ -560,6 +560,6 @@ void test_float(void) { // expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 31}} vbl = vec_fp_test_data_class(vd, idx, &cc); // expected-error {{must be a constant integer}} - vbl = vec_fp_test_data_class(vd, -1, &cc); // expected-error {{should be a value from 0 to 4095}} - vbl = vec_fp_test_data_class(vd, 4096, &cc); // expected-error {{should be a value from 0 to 4095}} + vbl = vec_fp_test_data_class(vd, -1, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vbl = vec_fp_test_data_class(vd, 4096, &cc); // expected-error-re {{argument value {{.*}} is outside the valid range}} } diff --git a/test/CodeGen/builtins-systemz-zvector2-error.c b/test/CodeGen/builtins-systemz-zvector2-error.c index 823d6374dc..3b890b9d09 100644 --- a/test/CodeGen/builtins-systemz-zvector2-error.c +++ b/test/CodeGen/builtins-systemz-zvector2-error.c @@ -127,8 +127,8 @@ void test_integer(void) { // expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 15}} vuc = vec_msum_u128(vul, vul, vuc, idx); // expected-error {{must be a constant integer}} - vuc = vec_msum_u128(vul, vul, vuc, -1); // expected-error {{should be a value from 0 to 15}} - vuc = vec_msum_u128(vul, vul, vuc, 16); // expected-error {{should be a value from 0 to 15}} + vuc = vec_msum_u128(vul, vul, vuc, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vuc = vec_msum_u128(vul, vul, vuc, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_float(void) { diff --git a/test/CodeGen/hexagon-check-builtins.c b/test/CodeGen/hexagon-check-builtins.c index 97118d5ead..a9294362f6 100644 --- a/test/CodeGen/hexagon-check-builtins.c +++ b/test/CodeGen/hexagon-check-builtins.c @@ -2,13 +2,13 @@ // RUN: %clang_cc1 -fsyntax-only -triple hexagon-unknown-elf -verify %s int foo(int x) { - // expected-error@+2 {{argument should be a value from 0 to 31}} - // expected-error@+1 {{argument should be a value from 0 to 31}} + // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}} + // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}} return __builtin_HEXAGON_S4_extract(x, 33, -1) + - // expected-error@+1 {{argument should be a value from 0 to 31}} + // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}} __builtin_HEXAGON_S4_extract(x, 3, 91) + - // expected-error@+2 {{argument should be a value from 0 to 31}} - // expected-error@+1 {{argument should be a value from 0 to 31}} + // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}} + // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}} __builtin_HEXAGON_S4_extract(x, -1, 35) + __builtin_HEXAGON_S4_extract(x, 0, 31) + __builtin_HEXAGON_S4_extract(x, 31, 0); @@ -17,13 +17,13 @@ int foo(int x) { int bar(void *p, void *q, int x) { // expected-error@+1 {{argument should be a multiple of 4}} return __builtin_HEXAGON_L2_loadri_pci(p, -1, x, q) + - // expected-error@+2 {{argument should be a value from -32 to 28}} + // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}} // expected-error@+1 {{argument should be a multiple of 4}} __builtin_HEXAGON_L2_loadri_pci(p, -99, x, q) + - // expected-error@+1 {{argument should be a value from -32 to 28}} + // expected-error-re@+1 {{argument value {{.*}} is outside the valid range}} __builtin_HEXAGON_L2_loadri_pci(p, -132, x, q) + __builtin_HEXAGON_L2_loadri_pci(p, 28, x, q) + - // expected-error@+2 {{argument should be a value from -32 to 28}} + // expected-error-re@+2 {{argument value {{.*}} is outside the valid range}} // expected-error@+1 {{argument should be a multiple of 4}} __builtin_HEXAGON_L2_loadri_pci(p, 29, x, q); } diff --git a/test/Sema/aarch64-neon-fp16-ranges.c b/test/Sema/aarch64-neon-fp16-ranges.c index acd6947446..60190525e0 100644 --- a/test/Sema/aarch64-neon-fp16-ranges.c +++ b/test/Sema/aarch64-neon-fp16-ranges.c @@ -7,58 +7,58 @@ void test_vcvt_f16_16(int16_t a){ vcvth_n_f16_s16(a, 1); vcvth_n_f16_s16(a, 16); - vcvth_n_f16_s16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_f16_s16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_f16_s16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_f16_u16(a, 1); vcvth_n_f16_u16(a, 16); - vcvth_n_f16_u16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_f16_u16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_u16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_f16_u16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vcvt_f16_32(int32_t a){ vcvth_n_f16_u32(a, 1); vcvth_n_f16_u32(a, 16); - vcvth_n_f16_u32(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_f16_u32(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_u32(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_f16_u32(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_f16_s32(a, 1); vcvth_n_f16_s32(a, 16); - vcvth_n_f16_s32(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_f16_s32(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s32(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_f16_s32(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vcvt_f16_64(int64_t a){ vcvth_n_f16_s64(a, 1); vcvth_n_f16_s64(a, 16); - vcvth_n_f16_s64(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_f16_s64(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_f16_s64(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_f16_s64(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_vcvt_su_f(float16_t a){ vcvth_n_s16_f16(a, 1); vcvth_n_s16_f16(a, 16); - vcvth_n_s16_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_s16_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s16_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_s16_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_s32_f16(a, 1); vcvth_n_s32_f16(a, 16); - vcvth_n_s32_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_s32_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s32_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_s32_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_s64_f16(a, 1); vcvth_n_s64_f16(a, 16); - vcvth_n_s64_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_s64_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_s64_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_s64_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_u16_f16(a, 1); vcvth_n_u16_f16(a, 16); - vcvth_n_u16_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_u16_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_u16_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_u16_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} vcvth_n_u32_f16(a, 1); vcvth_n_u32_f16(a, 16); - vcvth_n_u32_f16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - vcvth_n_u32_f16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + vcvth_n_u32_f16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vcvth_n_u32_f16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} } diff --git a/test/Sema/aarch64-neon-ranges.c b/test/Sema/aarch64-neon-ranges.c index 3a170b8f4c..f9b652fc9b 100644 --- a/test/Sema/aarch64-neon-ranges.c +++ b/test/Sema/aarch64-neon-ranges.c @@ -11,12 +11,12 @@ void test_vext_8bit(int8x8_t small, int8x16_t big) { vextq_u8(big, big, 15); vextq_p8(big, big, 15); - vext_s8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}} - vext_u8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}} - vext_p8(small, small, 8); // expected-error {{argument should be a value from 0 to 7}} - vextq_s8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}} - vextq_u8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}} - vextq_p8(big, big, 16); // expected-error {{argument should be a value from 0 to 15}} + vext_s8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vext_u8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vext_p8(small, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vextq_s8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vextq_u8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vextq_p8(big, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_mul_lane_f64(float64x1_t small, float64x2_t big, float64x2_t rhs) { @@ -29,11 +29,11 @@ void test_mul_lane_f64(float64x1_t small, float64x2_t big, float64x2_t rhs) { vfmaq_lane_f64(big, big, small, 0); vfmaq_laneq_f64(big, big, big, 1); - vmul_lane_f64(small, small, 1); // expected-error {{argument should be a value from 0 to 0}} - vmul_laneq_f64(small, big, 2); // expected-error {{argument should be a value from 0 to 1}} - vfma_lane_f64(small, small, small, 1); // expected-error {{argument should be a value from 0 to 0}} - vfma_laneq_f64(small, small, big, 2); // expected-error {{argument should be a value from 0 to 1}} - vfmaq_laneq_f64(big, big, big, 2); // expected-error {{argument should be a value from 0 to 1}} + vmul_lane_f64(small, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vmul_laneq_f64(small, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vfma_lane_f64(small, small, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vfma_laneq_f64(small, small, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vfmaq_laneq_f64(big, big, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) { @@ -47,15 +47,15 @@ void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) { vld1q_lane_s32(addr, big, 3); vld1q_lane_s64(addr, big, 1); - vld1_lane_s8(addr, small, 8); // expected-error {{argument should be a value from 0 to 7}} - vld1_lane_s16(addr, small, 4); // expected-error {{argument should be a value from 0 to 3}} - vld1_lane_s32(addr, small, 2); // expected-error {{argument should be a value from 0 to 1}} - vld1_lane_s64(addr, small, 1); // expected-error {{argument should be a value from 0 to 0}} + vld1_lane_s8(addr, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1_lane_s16(addr, small, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1_lane_s32(addr, small, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1_lane_s64(addr, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vld1q_lane_s8(addr, big, 16); // expected-error {{argument should be a value from 0 to 15}} - vld1q_lane_s16(addr, big, 8); // expected-error {{argument should be a value from 0 to 7}} - vld1q_lane_s32(addr, big, 4); // expected-error {{argument should be a value from 0 to 3}} - vld1q_lane_s64(addr, big, 2); // expected-error {{argument should be a value from 0 to 1}} + vld1q_lane_s8(addr, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1q_lane_s16(addr, big, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1q_lane_s32(addr, big, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld1q_lane_s64(addr, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} vst1_lane_s8(addr, small, 7); vst1_lane_s16(addr, small, 3); @@ -67,15 +67,15 @@ void test_ld1st1(int8x8_t small, int8x16_t big, void *addr) { vst1q_lane_s32(addr, big, 3); vst1q_lane_s64(addr, big, 1); - vst1_lane_s8(addr, small, 8); // expected-error {{argument should be a value from 0 to 7}} - vst1_lane_s16(addr, small, 4); // expected-error {{argument should be a value from 0 to 3}} - vst1_lane_s32(addr, small, 2); // expected-error {{argument should be a value from 0 to 1}} - vst1_lane_s64(addr, small, 1); // expected-error {{argument should be a value from 0 to 0}} + vst1_lane_s8(addr, small, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1_lane_s16(addr, small, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1_lane_s32(addr, small, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1_lane_s64(addr, small, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vst1q_lane_s8(addr, big, 16); // expected-error {{argument should be a value from 0 to 15}} - vst1q_lane_s16(addr, big, 8); // expected-error {{argument should be a value from 0 to 7}} - vst1q_lane_s32(addr, big, 4); // expected-error {{argument should be a value from 0 to 3}} - vst1q_lane_s64(addr, big, 2); // expected-error {{argument should be a value from 0 to 1}} + vst1q_lane_s8(addr, big, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1q_lane_s16(addr, big, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1q_lane_s32(addr, big, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst1q_lane_s64(addr, big, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8, @@ -93,15 +93,15 @@ void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8, vld2q_lane_s32(addr, big32, 3); vld2q_lane_s64(addr, big64, 1); - vld2_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vld2_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vld2_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vld2_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vld2_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vld2q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vld2q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vld2q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vld2q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vld2q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld2q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} vst2_lane_s8(addr, small8, 7); vst2_lane_s16(addr, small16, 3); @@ -113,15 +113,15 @@ void test_ld2st2(int8x8x2_t small8, int8x16x2_t big8, vst2q_lane_s32(addr, big32, 3); vst2q_lane_s64(addr, big64, 1); - vst2_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vst2_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vst2_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vst2_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vst2_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vst2q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vst2q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vst2q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vst2q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vst2q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst2q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8, @@ -139,15 +139,15 @@ void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8, vld3q_lane_s32(addr, big32, 3); vld3q_lane_s64(addr, big64, 1); - vld3_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vld3_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vld3_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vld3_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vld3_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vld3q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vld3q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vld3q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vld3q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vld3q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld3q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} vst3_lane_s8(addr, small8, 7); vst3_lane_s16(addr, small16, 3); @@ -159,15 +159,15 @@ void test_ld3st3(int8x8x3_t small8, int8x16x3_t big8, vst3q_lane_s32(addr, big32, 3); vst3q_lane_s64(addr, big64, 1); - vst3_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vst3_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vst3_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vst3_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vst3_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vst3q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vst3q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vst3q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vst3q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vst3q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst3q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8, @@ -185,15 +185,15 @@ void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8, vld4q_lane_s32(addr, big32, 3); vld4q_lane_s64(addr, big64, 1); - vld4_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vld4_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vld4_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vld4_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vld4_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vld4q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vld4q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vld4q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vld4q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vld4q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vld4q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} vst4_lane_s8(addr, small8, 7); vst4_lane_s16(addr, small16, 3); @@ -205,14 +205,14 @@ void test_ld4st4(int8x8x4_t small8, int8x16x4_t big8, vst4q_lane_s32(addr, big32, 3); vst4q_lane_s64(addr, big64, 1); - vst4_lane_s8(addr, small8, 8); // expected-error {{argument should be a value from 0 to 7}} - vst4_lane_s16(addr, small16, 4); // expected-error {{argument should be a value from 0 to 3}} - vst4_lane_s32(addr, small32, 2); // expected-error {{argument should be a value from 0 to 1}} - vst4_lane_s64(addr, small64, 1); // expected-error {{argument should be a value from 0 to 0}} + vst4_lane_s8(addr, small8, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4_lane_s16(addr, small16, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4_lane_s32(addr, small32, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4_lane_s64(addr, small64, 1); // expected-error-re {{argument value {{.*}} is outside the valid range}} - vst4q_lane_s8(addr, big8, 16); // expected-error {{argument should be a value from 0 to 15}} - vst4q_lane_s16(addr, big16, 8); // expected-error {{argument should be a value from 0 to 7}} - vst4q_lane_s32(addr, big32, 4); // expected-error {{argument should be a value from 0 to 3}} - vst4q_lane_s64(addr, big64, 2); // expected-error {{argument should be a value from 0 to 1}} + vst4q_lane_s8(addr, big8, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4q_lane_s16(addr, big16, 8); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4q_lane_s32(addr, big32, 4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vst4q_lane_s64(addr, big64, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } diff --git a/test/Sema/arm-neon-types.c b/test/Sema/arm-neon-types.c index a5ee708b50..989f20ab20 100644 --- a/test/Sema/arm-neon-types.c +++ b/test/Sema/arm-neon-types.c @@ -17,7 +17,7 @@ float32x2_t test2(uint32x2_t x) { float32x2_t test3(uint32x2_t x) { // FIXME: The "incompatible result type" error is due to pr10112 and should be // removed when that is fixed. - return vcvt_n_f32_u32(x, 0); // expected-error {{argument should be a value from 1 to 32}} + return vcvt_n_f32_u32(x, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} } typedef signed int vSInt32 __attribute__((__vector_size__(16))); diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c index 096882a088..436e99d9ab 100644 --- a/test/Sema/builtin-object-size.c +++ b/test/Sema/builtin-object-size.c @@ -13,10 +13,10 @@ int f1() { __builtin_object_size(&a, 3)); } int f2() { - return __builtin_object_size(&a, -1); // expected-error {{argument should be a value from 0 to 3}} + return __builtin_object_size(&a, -1); // expected-error {{argument value -1 is outside the valid range [0, 3]}} } int f3() { - return __builtin_object_size(&a, 4); // expected-error {{argument should be a value from 0 to 3}} + return __builtin_object_size(&a, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} } @@ -41,7 +41,7 @@ void f5(void) char buf[10]; memset((void *)0x100000000ULL, 0, 0x1000); memcpy((char *)NULL + 0x10000, buf, 0x10); - memcpy1((char *)NULL + 0x10000, buf, 0x10); // expected-error {{argument should be a value from 0 to 3}} + memcpy1((char *)NULL + 0x10000, buf, 0x10); // expected-error {{argument value 4 is outside the valid range [0, 3]}} } // rdar://18431336 diff --git a/test/Sema/builtin-prefetch.c b/test/Sema/builtin-prefetch.c index c5fa792a56..478c85b756 100644 --- a/test/Sema/builtin-prefetch.c +++ b/test/Sema/builtin-prefetch.c @@ -8,7 +8,7 @@ void foo() { __builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}} __builtin_prefetch(&a, "hello", 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}} __builtin_prefetch(&a, a, 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}} - __builtin_prefetch(&a, 2); // expected-error{{argument should be a value from 0 to 1}} - __builtin_prefetch(&a, 0, 4); // expected-error{{argument should be a value from 0 to 3}} - __builtin_prefetch(&a, -1, 4); // expected-error{{argument should be a value from 0 to 1}} + __builtin_prefetch(&a, 2); // expected-error{{argument value 2 is outside the valid range [0, 1]}} + __builtin_prefetch(&a, 0, 4); // expected-error{{argument value 4 is outside the valid range [0, 3]}} + __builtin_prefetch(&a, -1, 4); // expected-error{{argument value -1 is outside the valid range [0, 1]}} } diff --git a/test/Sema/builtins-arm.c b/test/Sema/builtins-arm.c index 22572e0c3e..f34499123c 100644 --- a/test/Sema/builtins-arm.c +++ b/test/Sema/builtins-arm.c @@ -35,18 +35,18 @@ void test2() { #endif void test3() { - __builtin_arm_dsb(16); // expected-error {{argument should be a value from 0 to 15}} - __builtin_arm_dmb(17); // expected-error {{argument should be a value from 0 to 15}} - __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}} + __builtin_arm_dsb(16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_dmb(17); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_isb(18); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test4() { - __builtin_arm_prefetch(0, 2, 0); // expected-error {{argument should be a value from 0 to 1}} - __builtin_arm_prefetch(0, 0, 2); // expected-error {{argument should be a value from 0 to 1}} + __builtin_arm_prefetch(0, 2, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_prefetch(0, 0, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test5() { - __builtin_arm_dbg(16); // expected-error {{argument should be a value from 0 to 15}} + __builtin_arm_dbg(16); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test6(int a, int b, int c) { @@ -168,14 +168,14 @@ void test_9_4_1_width_specified_saturation(int a, int b) { s = __builtin_arm_ssat(8, 2); s = __builtin_arm_ssat(a, 1); s = __builtin_arm_ssat(a, 32); - s = __builtin_arm_ssat(a, 0); // expected-error {{argument should be a value from 1 to 32}} - s = __builtin_arm_ssat(a, 33); // expected-error {{argument should be a value from 1 to 32}} + s = __builtin_arm_ssat(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + s = __builtin_arm_ssat(a, 33); // expected-error-re {{argument value {{.*}} is outside the valid range}} s = __builtin_arm_ssat(a, b); // expected-error {{argument to '__builtin_arm_ssat' must be a constant integer}} u = __builtin_arm_usat(8, 2); u = __builtin_arm_usat(a, 0); u = __builtin_arm_usat(a, 31); - u = __builtin_arm_usat(a, 32); // expected-error {{argument should be a value from 0 to 31}} + u = __builtin_arm_usat(a, 32); // expected-error-re {{argument value {{.*}} is outside the valid range}} u = __builtin_arm_usat(a, b); // expected-error {{argument to '__builtin_arm_usat' must be a constant integer}} } @@ -215,12 +215,12 @@ void test_9_5_4_parallel_16bit_saturation(int16x2_t a) { s = __builtin_arm_ssat16(a, 1); s = __builtin_arm_ssat16(a, 16); - s = __builtin_arm_ssat16(a, 0); // expected-error {{argument should be a value from 1 to 16}} - s = __builtin_arm_ssat16(a, 17); // expected-error {{argument should be a value from 1 to 16}} + s = __builtin_arm_ssat16(a, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + s = __builtin_arm_ssat16(a, 17); // expected-error-re {{argument value {{.*}} is outside the valid range}} u = __builtin_arm_usat16(a, 0); u = __builtin_arm_usat16(a, 15); - u = __builtin_arm_usat16(a, 16); // expected-error {{argument should be a value from 0 to 15}} + u = __builtin_arm_usat16(a, 16); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_9_5_5_packing_and_unpacking(int16x2_t a, int8x4_t b, uint16x2_t c, uint8x4_t d) { @@ -327,11 +327,11 @@ void test_VFP(float f, double d) { fr = __builtin_arm_vcvtr_f(f, 0); fr = __builtin_arm_vcvtr_f(f, 1); - fr = __builtin_arm_vcvtr_f(f, -1); // expected-error {{argument should be a value from 0 to 1}} - fr = __builtin_arm_vcvtr_f(f, 2); // expected-error {{argument should be a value from 0 to 1}} + fr = __builtin_arm_vcvtr_f(f, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + fr = __builtin_arm_vcvtr_f(f, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} dr = __builtin_arm_vcvtr_f(d, 0); dr = __builtin_arm_vcvtr_f(d, 1); - dr = __builtin_arm_vcvtr_f(d, -1); // expected-error {{argument should be a value from 0 to 1}} - dr = __builtin_arm_vcvtr_f(d, 2); // expected-error {{argument should be a value from 0 to 1}} + dr = __builtin_arm_vcvtr_f(d, -1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + dr = __builtin_arm_vcvtr_f(d, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } diff --git a/test/Sema/builtins-arm64.c b/test/Sema/builtins-arm64.c index 2779984680..27144a18cd 100644 --- a/test/Sema/builtins-arm64.c +++ b/test/Sema/builtins-arm64.c @@ -18,14 +18,14 @@ void test_clear_cache_no_args() { } void test_memory_barriers() { - __builtin_arm_dmb(16); // expected-error {{argument should be a value from 0 to 15}} - __builtin_arm_dsb(17); // expected-error {{argument should be a value from 0 to 15}} - __builtin_arm_isb(18); // expected-error {{argument should be a value from 0 to 15}} + __builtin_arm_dmb(16); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_dsb(17); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_isb(18); // expected-error-re {{argument value {{.*}} is outside the valid range}} } void test_prefetch() { - __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error {{argument should be a value from 0 to 1}} - __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error {{argument should be a value from 0 to 2}} - __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error {{argument should be a value from 0 to 1}} - __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error {{argument should be a value from 0 to 1}} + __builtin_arm_prefetch(0, 2, 0, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_prefetch(0, 0, 3, 0, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } diff --git a/test/Sema/builtins-ppc.c b/test/Sema/builtins-ppc.c index 5c45d02b41..aa6e9843f6 100644 --- a/test/Sema/builtins-ppc.c +++ b/test/Sema/builtins-ppc.c @@ -9,15 +9,15 @@ #ifdef TEST_HTM void test_htm() { - __builtin_tbegin(4); // expected-error {{argument should be a value from 0 to 1}} - __builtin_tend(-1); // expected-error {{argument should be a value from 0 to 1}} - __builtin_tsr(55); // expected-error {{argument should be a value from 0 to 7}} - __builtin_tabortwc(-5, 2, 3); // expected-error {{argument should be a value from 0 to 31}} - __builtin_tabortdc(55, 2, 3); // expected-error {{argument should be a value from 0 to 31}} - __builtin_tabortwci(-5, 2, 5); // expected-error {{argument should be a value from 0 to 31}} - __builtin_tabortwci(5, 2, 55); // expected-error {{argument should be a value from 0 to 31}} - __builtin_tabortdci(-5, 2, 5); // expected-error {{argument should be a value from 0 to 31}} - __builtin_tabortdci(5, 2, 55); // expected-error {{argument should be a value from 0 to 31}} + __builtin_tbegin(4); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tend(-1); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tsr(55); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortwc(-5, 2, 3); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortdc(55, 2, 3); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortwci(-5, 2, 5); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortwci(5, 2, 55); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortdci(-5, 2, 5); // expected-error-re {{argument value {{.*}} is outside the valid range}} + __builtin_tabortdci(5, 2, 55); // expected-error-re {{argument value {{.*}} is outside the valid range}} } #endif @@ -30,20 +30,20 @@ void test_htm() { vector unsigned int test_vshasigmaw_or(void) { vector unsigned int a = W_INIT - vector unsigned int b = __builtin_crypto_vshasigmaw(a, 2, 15); // expected-error {{argument should be a value from 0 to 1}} - vector unsigned int c = __builtin_crypto_vshasigmaw(a, -1, 15); // expected-error {{argument should be a value from 0 to 1}} - vector unsigned int d = __builtin_crypto_vshasigmaw(a, 0, 85); // expected-error {{argument should be a value from 0 to 15}} - vector unsigned int e = __builtin_crypto_vshasigmaw(a, 1, -15); // expected-error {{argument should be a value from 0 to 15}} + vector unsigned int b = __builtin_crypto_vshasigmaw(a, 2, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned int c = __builtin_crypto_vshasigmaw(a, -1, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned int d = __builtin_crypto_vshasigmaw(a, 0, 85); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned int e = __builtin_crypto_vshasigmaw(a, 1, -15); // expected-error-re {{argument value {{.*}} is outside the valid range}} return __builtin_crypto_vshasigmaw(a, 1, 15); } vector unsigned long long test_vshasigmad_or(void) { vector unsigned long long a = D_INIT - vector unsigned long long b = __builtin_crypto_vshasigmad(a, 2, 15); // expected-error {{argument should be a value from 0 to 1}} - vector unsigned long long c = __builtin_crypto_vshasigmad(a, -1, 15); // expected-error {{argument should be a value from 0 to 1}} - vector unsigned long long d = __builtin_crypto_vshasigmad(a, 0, 85); // expected-error {{argument should be a value from 0 to 1}} - vector unsigned long long e = __builtin_crypto_vshasigmad(a, 1, -15); // expected-error {{argument should be a value from 0 to 1}} + vector unsigned long long b = __builtin_crypto_vshasigmad(a, 2, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned long long c = __builtin_crypto_vshasigmad(a, -1, 15); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned long long d = __builtin_crypto_vshasigmad(a, 0, 85); // expected-error-re {{argument value {{.*}} is outside the valid range}} + vector unsigned long long e = __builtin_crypto_vshasigmad(a, 1, -15); // expected-error-re {{argument value {{.*}} is outside the valid range}} return __builtin_crypto_vshasigmad(a, 0, 15); } diff --git a/test/Sema/builtins-x86.c b/test/Sema/builtins-x86.c index e96caf2d79..9872a64f18 100644 --- a/test/Sema/builtins-x86.c +++ b/test/Sema/builtins-x86.c @@ -22,145 +22,145 @@ void call_x86_32_builtins(void) { } __m128 test__builtin_ia32_cmpps(__m128 __a, __m128 __b) { - __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128d test__builtin_ia32_cmppd(__m128d __a, __m128d __b) { - __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128 test__builtin_ia32_cmpss(__m128 __a, __m128 __b) { - __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128d test__builtin_ia32_cmpsd(__m128d __a, __m128d __b) { - __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __mmask16 test__builtin_ia32_cmpps512_mask(__m512d __a, __m512d __b) { - __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 4); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __mmask8 test__builtin_ia32_cmppd512_mask(__m512d __a, __m512d __b) { - __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}} + return __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 4); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128i test__builtin_ia32_vpcomub(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomuw(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomud(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomuq(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomb(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomub(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomw(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomuw(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomd(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomud(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __m128i test__builtin_ia32_vpcomq(__m128i __a, __m128i __b) { - __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument should be a value from 0 to 7}} + return __builtin_ia32_vpcomuq(__a, __b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } __mmask16 test__builtin_ia32_cmpps512_mask_rounding(__m512 __a, __m512 __b, __mmask16 __u) { - __builtin_ia32_cmpps512_mask(__a, __b, 0, __u, 0); // expected-error {{invalid rounding argument}} + return __builtin_ia32_cmpps512_mask(__a, __b, 0, __u, 0); // expected-error {{invalid rounding argument}} } __m128i test_mm_mask_i32gather_epi32(__m128i a, int const *b, __m128i c, __m128i mask) { return __builtin_ia32_gatherd_d(a, b, c, mask, 5); // expected-error {{scale argument must be 1, 2, 4, or 8}} } -__m512i _mm512_mask_prefetch_i32gather_ps(__m512i index, __mmask16 mask, int const *addr) { - return __builtin_ia32_gatherpfdps(mask, index, addr, 5, 1); // expected-error {{scale argument must be 1, 2, 4, or 8}} +void _mm512_mask_prefetch_i32gather_ps(__m512i index, __mmask16 mask, int const *addr) { + __builtin_ia32_gatherpfdps(mask, index, addr, 5, 1); // expected-error {{scale argument must be 1, 2, 4, or 8}} } -__m512 _mm512_mask_prefetch_i32gather_ps_2(__m512i index, __mmask16 mask, int const *addr) { - return __builtin_ia32_gatherpfdps(mask, index, addr, 1, 1); // expected-error {{argument should be a value from 2 to 3}} +void _mm512_mask_prefetch_i32gather_ps_2(__m512i index, __mmask16 mask, int const *addr) { + __builtin_ia32_gatherpfdps(mask, index, addr, 1, 1); // expected-error {{argument value 1 is outside the valid range [2, 3]}} } __m512i test_mm512_shldi_epi64(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshldq512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldq512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m512i test_mm512_shldi_epi32(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshldd512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldd512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m512i test_mm512_shldi_epi16(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshldw512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldw512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m512i test_mm512_shrdi_epi64(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdq512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdq512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m512i test_mm512_shrdi_epi32(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdd512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdd512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m512i test_mm512_shrdi_epi16(__m512i __A, __m512i __B) { - return __builtin_ia32_vpshrdw512(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdw512(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shldi_epi64(__m256i __A, __m256i __B) { - return __builtin_ia32_vpshldq256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldq256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shldi_epi64( __m128i __A, __m128i __B) { - return __builtin_ia32_vpshldq128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldq128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shldi_epi32(__m256i __A, __m256i __B) { - return __builtin_ia32_vpshldd256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldd256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shldi_epi32(__m128i __A, __m128i __B) { - return __builtin_ia32_vpshldd128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldd128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shldi_epi16( __m256i __A, __m256i __B) { - return __builtin_ia32_vpshldw256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldw256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shldi_epi16(__m128i __A, __m128i __B) { - return __builtin_ia32_vpshldw128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshldw128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shrdi_epi64(__m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdq256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdq256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shrdi_epi64(__m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdq128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdq128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shrdi_epi32(__m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdd256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdd256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shrdi_epi32(__m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdd128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdd128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m256i test_mm256_shrdi_epi16(__m256i __A, __m256i __B) { - return __builtin_ia32_vpshrdw256(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdw256(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } __m128i test_mm128_shrdi_epi16(__m128i __A, __m128i __B) { - return __builtin_ia32_vpshrdw128(__A, __B, 1024); // expected-error {{argument should be a value from 0 to 255}} + return __builtin_ia32_vpshrdw128(__A, __B, 1024); // expected-error {{argument value 1024 is outside the valid range [0, 255]}} } diff --git a/test/Sema/builtins-x86.cpp b/test/Sema/builtins-x86.cpp new file mode 100644 index 0000000000..d6c03a8999 --- /dev/null +++ b/test/Sema/builtins-x86.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin -fsyntax-only -verify %s +// +// Ensure that when we use builtins in C++ code with templates that compute the +// valid immediate, the dead code with the invalid immediate doesn't error. + +typedef short __v8hi __attribute__((__vector_size__(16))); + +template +__v8hi test(__v8hi a) { + if (Imm < 4) + return __builtin_ia32_pshuflw(a, 0x55 * Imm); + else + return __builtin_ia32_pshuflw(a, 0x55 * (Imm - 4)); +} + +template __v8hi test<0>(__v8hi); +template __v8hi test<1>(__v8hi); +template __v8hi test<2>(__v8hi); +template __v8hi test<3>(__v8hi); +template __v8hi test<4>(__v8hi); +template __v8hi test<5>(__v8hi); +template __v8hi test<6>(__v8hi); +template __v8hi test<7>(__v8hi); \ No newline at end of file diff --git a/test/SemaCXX/neon-vector-types.cpp b/test/SemaCXX/neon-vector-types.cpp index c2953d713b..aaf4af18e2 100644 --- a/test/SemaCXX/neon-vector-types.cpp +++ b/test/SemaCXX/neon-vector-types.cpp @@ -35,7 +35,7 @@ namespace rdar11688587 { extern float32x4_t vec; return __extension__ ({ float32x4_t __a = (vec); - (float32_t)__builtin_neon_vgetq_lane_f32(__a, I); // expected-error{{argument should be a value from 0 to 3}} + (float32_t)__builtin_neon_vgetq_lane_f32(__a, I); // expected-error-re{{argument value {{.*}} is outside the valid range}} }); } -- GitLab From b88a7c539369de2defd02c780f60e402003de865 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 21 Jun 2018 23:52:36 +0000 Subject: [PATCH 0228/1023] [x86] Fix a tiny bug in my test case in r335309 by marking that we don't expect any diagnostics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335310 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Sema/builtins-x86.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Sema/builtins-x86.cpp b/test/Sema/builtins-x86.cpp index d6c03a8999..0f37f4a346 100644 --- a/test/Sema/builtins-x86.cpp +++ b/test/Sema/builtins-x86.cpp @@ -2,6 +2,7 @@ // // Ensure that when we use builtins in C++ code with templates that compute the // valid immediate, the dead code with the invalid immediate doesn't error. +// expected-no-diagnostics typedef short __v8hi __attribute__((__vector_size__(16))); @@ -20,4 +21,4 @@ template __v8hi test<3>(__v8hi); template __v8hi test<4>(__v8hi); template __v8hi test<5>(__v8hi); template __v8hi test<6>(__v8hi); -template __v8hi test<7>(__v8hi); \ No newline at end of file +template __v8hi test<7>(__v8hi); -- GitLab From 7e77eaa2364878aa9ec10b7628d53555e5fd88d5 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 22 Jun 2018 09:46:40 +0000 Subject: [PATCH 0229/1023] [hmaptool] Turn %hmaptool into a proper substitution This is still super ugly, but at least it doesn't require working directories to just line up perfectly for python to find the tool. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335330 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Modules/crash-vfs-headermaps.m | 2 +- test/Preprocessor/headermap-rel.c | 2 +- test/Preprocessor/headermap-rel2.c | 2 +- test/Preprocessor/nonportable-include-with-hmap.c | 2 +- test/lit.cfg.py | 6 +++++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index c340d268ea..118537ba2a 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -3,7 +3,7 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/m %t/i/Foo.framework/Headers // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h -// RUN: '%python' hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap +// RUN: %hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/headermap-rel.c b/test/Preprocessor/headermap-rel.c index 4c67186830..db57534c1c 100644 --- a/test/Preprocessor/headermap-rel.c +++ b/test/Preprocessor/headermap-rel.c @@ -1,5 +1,5 @@ // RUN: rm -f %t.hmap -// RUN: '%python' hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap +// RUN: %hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap // RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index af12bf3949..83e89f0a49 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,5 +1,5 @@ // RUN: rm -f %t.hmap -// RUN: '%python' hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap +// RUN: %hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap // RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H // RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index f2c279f36c..bbbd669a0f 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,5 +1,5 @@ // RUN: rm -f %t.hmap -// RUN: '%python' hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap +// RUN: %hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ // RUN: -I%t.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 6fa7ef66fc..5b11691f44 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -58,7 +58,7 @@ tool_dirs = [config.clang_tools_dir, config.llvm_tools_dir] tools = [ 'c-index-test', 'clang-check', 'clang-diff', 'clang-format', 'clang-tblgen', - 'opt', 'hmaptool', + 'opt', ToolSubst('%clang_func_map', command=FindTool( 'clang-func-mapping'), unresolved='ignore'), ] @@ -69,6 +69,10 @@ if config.clang_examples: llvm_config.add_tool_substitutions(tools, tool_dirs) +config.substitutions.append( + ('%hmaptool', '%s %s' % (config.python_executable, + os.path.join(config.llvm_tools_dir, 'hmaptool')))) + # Plugins (loadable modules) # TODO: This should be supplied by Makefile or autoconf. if sys.platform in ['win32', 'cygwin']: -- GitLab From b24220e585d72689df6497374bae709708e76316 Mon Sep 17 00:00:00 2001 From: Jacek Olesiak Date: Fri, 22 Jun 2018 11:57:55 +0000 Subject: [PATCH 0230/1023] [clang-format] Add AlwaysBreakBeforeMultilineString tests Summary: Followup to D47393. Reviewers: stephanemoore Reviewed By: stephanemoore Subscribers: benhamilton, cfe-commits Differential Revision: https://reviews.llvm.org/D48432 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335338 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Format/FormatTestObjC.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index fc1ee2574c..58559eabe8 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -1227,6 +1227,15 @@ TEST_F(FormatTestObjC, AlwaysBreakBeforeMultilineStrings) { " @\"cccc\");"); verifyFormat("aaaa(qqq, @\"bbbb\"\n" " @\"cccc\");"); + verifyFormat("[aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"];"); + verifyFormat("aaaa = [aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"];"); + verifyFormat("[aaaa qqqq:@\"bbbb\"\n" + " @\"cccc\"\n" + " rr:42\n" + " ssssss:@\"ee\"\n" + " @\"fffff\"];"); } } // end namespace -- GitLab From 84dae0555379696bff8fe6472ba402223ef04608 Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Fri, 22 Jun 2018 11:59:16 +0000 Subject: [PATCH 0231/1023] [X86] Lower _mm[256|512]_cmp[.]_mask intrinsics to native llvm IR Summary: Lowering some vector comparision builtins to fcmp IR instructions. This ignores the signaling behaviour specified in the predicate argument of said builtins. Affected AVX512 builtins: __builtin_ia32_cmpps128_mask __builtin_ia32_cmpps256_mask __builtin_ia32_cmpps512_mask __builtin_ia32_cmppd128_mask __builtin_ia32_cmppd256_mask __builtin_ia32_cmppd512_mask Reviewers: craig.topper, uriel.k, RKSimon, andrew.w.kaylor, spatel, scanon, efriedma Reviewed By: craig.topper, spatel, efriedma Differential Revision: https://reviews.llvm.org/D45616 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335339 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 165 ++++++++++++++----------------- test/CodeGen/avx-builtins.c | 114 ++++++++++++++------- test/CodeGen/avx-cmp-builtins.c | 24 ----- test/CodeGen/avx2-builtins.c | 4 +- test/CodeGen/avx512f-builtins.c | 152 ++++++++++++++++++++-------- test/CodeGen/avx512vl-builtins.c | 139 +++++++++++++++++++++++--- 6 files changed, 395 insertions(+), 203 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index b9430e6fc9..de96127987 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10120,44 +10120,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return Builder.CreateExtractValue(Call, 1); } - case X86::BI__builtin_ia32_cmpps128_mask: - case X86::BI__builtin_ia32_cmpps256_mask: - case X86::BI__builtin_ia32_cmpps512_mask: - case X86::BI__builtin_ia32_cmppd128_mask: - case X86::BI__builtin_ia32_cmppd256_mask: - case X86::BI__builtin_ia32_cmppd512_mask: { - unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); - Value *MaskIn = Ops[3]; - Ops.erase(&Ops[3]); - - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_cmpps128_mask: - ID = Intrinsic::x86_avx512_mask_cmp_ps_128; - break; - case X86::BI__builtin_ia32_cmpps256_mask: - ID = Intrinsic::x86_avx512_mask_cmp_ps_256; - break; - case X86::BI__builtin_ia32_cmpps512_mask: - ID = Intrinsic::x86_avx512_mask_cmp_ps_512; - break; - case X86::BI__builtin_ia32_cmppd128_mask: - ID = Intrinsic::x86_avx512_mask_cmp_pd_128; - break; - case X86::BI__builtin_ia32_cmppd256_mask: - ID = Intrinsic::x86_avx512_mask_cmp_pd_256; - break; - case X86::BI__builtin_ia32_cmppd512_mask: - ID = Intrinsic::x86_avx512_mask_cmp_pd_512; - break; - } - - Value *Cmp = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); - return EmitX86MaskedCompareResult(*this, Cmp, NumElts, MaskIn); - } - - // SSE packed comparison intrinsics + // packed comparison intrinsics case X86::BI__builtin_ia32_cmpeqps: case X86::BI__builtin_ia32_cmpeqpd: return getVectorFCmpIR(CmpInst::FCMP_OEQ); @@ -10185,64 +10148,84 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_cmpps: case X86::BI__builtin_ia32_cmpps256: case X86::BI__builtin_ia32_cmppd: - case X86::BI__builtin_ia32_cmppd256: { + case X86::BI__builtin_ia32_cmppd256: + case X86::BI__builtin_ia32_cmpps128_mask: + case X86::BI__builtin_ia32_cmpps256_mask: + case X86::BI__builtin_ia32_cmpps512_mask: + case X86::BI__builtin_ia32_cmppd128_mask: + case X86::BI__builtin_ia32_cmppd256_mask: + case X86::BI__builtin_ia32_cmppd512_mask: { + // Lowering vector comparisons to fcmp instructions, while + // ignoring signalling behaviour requested + // ignoring rounding mode requested + // This is is only possible as long as FENV_ACCESS is not implemented. + // See also: https://reviews.llvm.org/D45616 + + // The third argument is the comparison condition, and integer in the + // range [0, 31] unsigned CC = cast(Ops[2])->getZExtValue() & 0x1f; - // If this one of the SSE immediates, we can use native IR. - if (CC < 8) { - FCmpInst::Predicate Pred; - switch (CC) { - case 0: Pred = FCmpInst::FCMP_OEQ; break; - case 1: Pred = FCmpInst::FCMP_OLT; break; - case 2: Pred = FCmpInst::FCMP_OLE; break; - case 3: Pred = FCmpInst::FCMP_UNO; break; - case 4: Pred = FCmpInst::FCMP_UNE; break; - case 5: Pred = FCmpInst::FCMP_UGE; break; - case 6: Pred = FCmpInst::FCMP_UGT; break; - case 7: Pred = FCmpInst::FCMP_ORD; break; - } - return getVectorFCmpIR(Pred); + + // Lowering to IR fcmp instruction. + // Ignoring requested signaling behaviour, + // e.g. both _CMP_GT_OS & _CMP_GT_OQ are translated to FCMP_OGT. + FCmpInst::Predicate Pred; + switch (CC) { + case 0x00: Pred = FCmpInst::FCMP_OEQ; break; + case 0x01: Pred = FCmpInst::FCMP_OLT; break; + case 0x02: Pred = FCmpInst::FCMP_OLE; break; + case 0x03: Pred = FCmpInst::FCMP_UNO; break; + case 0x04: Pred = FCmpInst::FCMP_UNE; break; + case 0x05: Pred = FCmpInst::FCMP_UGE; break; + case 0x06: Pred = FCmpInst::FCMP_UGT; break; + case 0x07: Pred = FCmpInst::FCMP_ORD; break; + case 0x08: Pred = FCmpInst::FCMP_UEQ; break; + case 0x09: Pred = FCmpInst::FCMP_ULT; break; + case 0x0a: Pred = FCmpInst::FCMP_ULE; break; + case 0x0c: Pred = FCmpInst::FCMP_ONE; break; + case 0x0d: Pred = FCmpInst::FCMP_OGE; break; + case 0x0e: Pred = FCmpInst::FCMP_OGT; break; + case 0x10: Pred = FCmpInst::FCMP_OEQ; break; + case 0x11: Pred = FCmpInst::FCMP_OLT; break; + case 0x12: Pred = FCmpInst::FCMP_OLE; break; + case 0x13: Pred = FCmpInst::FCMP_UNO; break; + case 0x14: Pred = FCmpInst::FCMP_UNE; break; + case 0x15: Pred = FCmpInst::FCMP_UGE; break; + case 0x16: Pred = FCmpInst::FCMP_UGT; break; + case 0x17: Pred = FCmpInst::FCMP_ORD; break; + case 0x18: Pred = FCmpInst::FCMP_UEQ; break; + case 0x19: Pred = FCmpInst::FCMP_ULT; break; + case 0x1a: Pred = FCmpInst::FCMP_ULE; break; + case 0x1c: Pred = FCmpInst::FCMP_ONE; break; + case 0x1d: Pred = FCmpInst::FCMP_OGE; break; + case 0x1e: Pred = FCmpInst::FCMP_OGT; break; + // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector + // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... + case 0x0b: // FALSE_OQ + case 0x1b: // FALSE_OS + return llvm::Constant::getNullValue(ConvertType(E->getType())); + case 0x0f: // TRUE_UQ + case 0x1f: // TRUE_US + return llvm::Constant::getAllOnesValue(ConvertType(E->getType())); + + default: llvm_unreachable("Unhandled CC"); } - // We can't handle 8-31 immediates with native IR, use the intrinsic. - // Except for predicates that create constants. - Intrinsic::ID ID; + // Builtins without the _mask suffix return a vector of integers + // of the same width as the input vectors switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_cmpps: - ID = Intrinsic::x86_sse_cmp_ps; - break; - case X86::BI__builtin_ia32_cmpps256: - // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector - // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... - if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) { - Value *Constant = (CC == 0xf || CC == 0x1f) ? - llvm::Constant::getAllOnesValue(Builder.getInt32Ty()) : - llvm::Constant::getNullValue(Builder.getInt32Ty()); - Value *Vec = Builder.CreateVectorSplat( - Ops[0]->getType()->getVectorNumElements(), Constant); - return Builder.CreateBitCast(Vec, Ops[0]->getType()); - } - ID = Intrinsic::x86_avx_cmp_ps_256; - break; - case X86::BI__builtin_ia32_cmppd: - ID = Intrinsic::x86_sse2_cmp_pd; - break; - case X86::BI__builtin_ia32_cmppd256: - // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector - // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... - if (CC == 0xf || CC == 0xb || CC == 0x1b || CC == 0x1f) { - Value *Constant = (CC == 0xf || CC == 0x1f) ? - llvm::Constant::getAllOnesValue(Builder.getInt64Ty()) : - llvm::Constant::getNullValue(Builder.getInt64Ty()); - Value *Vec = Builder.CreateVectorSplat( - Ops[0]->getType()->getVectorNumElements(), Constant); - return Builder.CreateBitCast(Vec, Ops[0]->getType()); - } - ID = Intrinsic::x86_avx_cmp_pd_256; - break; + case X86::BI__builtin_ia32_cmpps512_mask: + case X86::BI__builtin_ia32_cmppd512_mask: + case X86::BI__builtin_ia32_cmpps128_mask: + case X86::BI__builtin_ia32_cmpps256_mask: + case X86::BI__builtin_ia32_cmppd128_mask: + case X86::BI__builtin_ia32_cmppd256_mask: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + Value *Cmp = Builder.CreateFCmp(Pred, Ops[0], Ops[1]); + return EmitX86MaskedCompareResult(*this, Cmp, NumElts, Ops[3]); + } + default: + return getVectorFCmpIR(Pred); } - - return Builder.CreateCall(CGM.getIntrinsic(ID), Ops); } // SSE scalar comparison intrinsics diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index 67632e9dde..cbed537127 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -214,25 +214,25 @@ __m256 test_mm_ceil_ps(__m256 x) { __m128d test_mm_cmp_pd(__m128d A, __m128d B) { // CHECK-LABEL: test_mm_cmp_pd - // CHECK: call <2 x double> @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 13) + // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd(A, B, _CMP_GE_OS); } __m256d test_mm256_cmp_pd(__m256d A, __m256d B) { // CHECK-LABEL: test_mm256_cmp_pd - // CHECK: call <4 x double> @llvm.x86.avx.cmp.pd.256(<4 x double> %{{.*}}, <4 x double> %{{.*}}, i8 13) + // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd(A, B, _CMP_GE_OS); } __m128 test_mm_cmp_ps(__m128 A, __m128 B) { // CHECK-LABEL: test_mm_cmp_ps - // CHECK: call <4 x float> @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 13) + // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps(A, B, _CMP_GE_OS); } __m256 test_mm256_cmp_ps(__m256d A, __m256d B) { // CHECK-LABEL: test_mm256_cmp_ps - // CHECK: call <8 x float> @llvm.x86.avx.cmp.ps.256(<8 x float> %{{.*}}, <8 x float> %{{.*}}, i8 13) + // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps(A, B, _CMP_GE_OS); } @@ -1401,69 +1401,117 @@ __m256i test_mm256_zextsi128_si256(__m128i A) { double test_mm256_cvtsd_f64(__m256d __a) { - // CHECK-LABEL: @test_mm256_cvtsd_f64 - // CHECK: extractelement <4 x double> %{{.*}}, i32 0 - return _mm256_cvtsd_f64(__a); + // CHECK-LABEL: @test_mm256_cvtsd_f64 + // CHECK: extractelement <4 x double> %{{.*}}, i32 0 + return _mm256_cvtsd_f64(__a); } int test_mm256_cvtsi256_si32(__m256i __a) { - // CHECK-LABEL: @test_mm256_cvtsi256_si32 - // CHECK: extractelement <8 x i32> %{{.*}}, i32 0 - return _mm256_cvtsi256_si32(__a); + // CHECK-LABEL: @test_mm256_cvtsi256_si32 + // CHECK: extractelement <8 x i32> %{{.*}}, i32 0 + return _mm256_cvtsi256_si32(__a); } float test_mm256_cvtss_f32(__m256 __a) { - // CHECK-LABEL: @test_mm256_cvtss_f32 - // CHECK: extractelement <8 x float> %{{.*}}, i32 0 - return _mm256_cvtss_f32(__a); + // CHECK-LABEL: @test_mm256_cvtss_f32 + // CHECK: extractelement <8 x float> %{{.*}}, i32 0 + return _mm256_cvtss_f32(__a); } __m256 test_mm256_cmp_ps_true(__m256 a, __m256 b) { - // CHECK-LABEL: @test_mm256_cmp_ps_true - // CHECK: ret <8 x float> zeroinitializer - return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); + // CHECK-LABEL: @test_mm256_cmp_ps_false + // CHECK: ret <8 x float> zeroinitializer + return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); } __m256d test_mm256_cmp_pd_false(__m256d a, __m256d b) { - // CHECK-LABEL: @test_mm256_cmp_pd_false - // CHECK: ret <4 x double> zeroinitializer + // CHECK-LABEL: @test_mm256_cmp_pd_false + // CHECK: ret <4 x double> zeroinitializer return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ); } __m256 test_mm256_cmp_ps_strue(__m256 a, __m256 b) { - // CHECK-LABEL: @test_mm256_cmp_ps_strue - // CHECK: ret <8 x float> zeroinitializer - return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); + // CHECK-LABEL: @test_mm256_cmp_ps_sfalse + // CHECK: ret <8 x float> zeroinitializer + return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); } __m256d test_mm256_cmp_pd_sfalse(__m256d a, __m256d b) { - // CHECK-LABEL: @test_mm256_cmp_pd_sfalse - // CHECK: ret <4 x double> zeroinitializer + // CHECK-LABEL: @test_mm256_cmp_pd_sfalse + // CHECK: ret <4 x double> zeroinitializer return _mm256_cmp_pd(a, b, _CMP_FALSE_OS); } + +__m128 test_mm_cmp_ps_true(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_ps_true + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_ps(a, b, _CMP_FALSE_OQ); +} + +__m128 test_mm_cmp_pd_false(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_pd_false + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_pd(a, b, _CMP_FALSE_OQ); +} + +__m128 test_mm_cmp_ps_strue(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_ps_strue + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_ps(a, b, _CMP_FALSE_OS); +} + +__m128 test_mm_cmp_pd_sfalse(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_pd_sfalse + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_pd(a, b, _CMP_FALSE_OS); +} diff --git a/test/CodeGen/avx-cmp-builtins.c b/test/CodeGen/avx-cmp-builtins.c index 7d61942665..38d3ae24cd 100644 --- a/test/CodeGen/avx-cmp-builtins.c +++ b/test/CodeGen/avx-cmp-builtins.c @@ -8,30 +8,6 @@ // Test LLVM IR codegen of cmpXY instructions // -__m128d test_cmp_pd(__m128d a, __m128d b) { - // Expects that the third argument in LLVM IR is immediate expression - // CHECK: @llvm.x86.sse2.cmp.pd({{.*}}, i8 13) - return _mm_cmp_pd(a, b, _CMP_GE_OS); -} - -__m128d test_cmp_ps(__m128 a, __m128 b) { - // Expects that the third argument in LLVM IR is immediate expression - // CHECK: @llvm.x86.sse.cmp.ps({{.*}}, i8 13) - return _mm_cmp_ps(a, b, _CMP_GE_OS); -} - -__m256d test_cmp_pd256(__m256d a, __m256d b) { - // Expects that the third argument in LLVM IR is immediate expression - // CHECK: @llvm.x86.avx.cmp.pd.256({{.*}}, i8 13) - return _mm256_cmp_pd(a, b, _CMP_GE_OS); -} - -__m256d test_cmp_ps256(__m256 a, __m256 b) { - // Expects that the third argument in LLVM IR is immediate expression - // CHECK: @llvm.x86.avx.cmp.ps.256({{.*}}, i8 13) - return _mm256_cmp_ps(a, b, _CMP_GE_OS); -} - __m128d test_cmp_sd(__m128d a, __m128d b) { // Expects that the third argument in LLVM IR is immediate expression // CHECK: @llvm.x86.sse2.cmp.sd({{.*}}, i8 13) diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index 73b18c2e60..b0f4b5e6b5 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -612,9 +612,7 @@ __m128d test_mm_mask_i64gather_pd(__m128d a, double const *b, __m128i c, __m128d __m256d test_mm256_i64gather_pd(double const *b, __m256i c) { // CHECK-LABEL: test_mm256_i64gather_pd - // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double> - // CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i64> - // CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i64> [[SEXT]] to <4 x double> + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} // CHECK: call <4 x double> @llvm.x86.avx2.gather.q.pd.256(<4 x double> zeroinitializer, i8* %{{.*}}, <4 x i64> %{{.*}}, <4 x double> %{{.*}}, i8 2) return _mm256_i64gather_pd(b, c, 2); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 16ad425255..93cbcbe938 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1279,245 +1279,317 @@ __m512 test_mm512_unpacklo_ps(__m512 a, __m512 b) __mmask16 test_mm512_cmp_round_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmp_round_ps_mask - // CHECK: call <16 x i1> @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_round_ps_mask(a, b, 0, _MM_FROUND_CUR_DIRECTION); } __mmask16 test_mm512_mask_cmp_round_ps_mask(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmp_round_ps_mask - // CHECK: [[CMP:%.*]] = call <16 x i1> @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_round_ps_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION); } __mmask16 test_mm512_cmp_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmp_ps_mask - // CHECK: call <16 x i1> @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_ps_mask(a, b, 0); } +__mmask16 test_mm512_cmp_ps_mask_true_uq(__m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_cmp_ps_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i16 -1 + return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_true_us(__m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_cmp_ps_mask_true_us + // CHECK-NOT: call + // CHECK: ret i16 -1 + return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_US); +} + +__mmask16 test_mm512_cmp_ps_mask_false_oq(__m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i16 0 + return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_false_os(__m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i16 0 + return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OS); +} + __mmask16 test_mm512_mask_cmp_ps_mask(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = call <16 x i1> @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_ps_mask(m, a, b, 0); } __mmask8 test_mm512_cmp_round_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmp_round_pd_mask - // CHECK: call <8 x i1> @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_round_pd_mask(a, b, 0, _MM_FROUND_CUR_DIRECTION); } __mmask8 test_mm512_mask_cmp_round_pd_mask(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmp_round_pd_mask - // CHECK: [[CMP:%.*]] = call <8 x i1> @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_round_pd_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION); } __mmask8 test_mm512_cmp_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmp_pd_mask - // CHECK: call <8 x i1> @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_pd_mask(a, b, 0); } +__mmask8 test_mm512_cmp_pd_mask_true_uq(__m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_cmp_pd_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_true_us(__m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_cmp_pd_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm512_cmp_pd_mask_false_oq(__m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_false_os(__m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OS); +} + __mmask8 test_mm512_mask_cmp_pd_mask(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmp_pd_mask - // CHECK: [[CMP:%.*]] = call <8 x i1> @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_pd_mask(m, a, b, 0); } __mmask8 test_mm512_cmpeq_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpeq_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpeq_pd_mask(a, b); } __mmask8 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpeq_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpeq_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpeq_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpeq_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpeq_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpeq_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpeq_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpeq_ps_mask(k, a, b); } __mmask8 test_mm512_cmple_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmple_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}} return _mm512_cmple_pd_mask(a, b); } __mmask8 test_mm512_cmple_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmple_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}} return _mm512_cmple_ps_mask(a, b); } __mmask8 test_mm512_mask_cmple_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmple_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmple_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmple_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmple_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmple_ps_mask(k, a, b); } __mmask8 test_mm512_cmplt_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmplt_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}} return _mm512_cmplt_pd_mask(a, b); } __mmask8 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmplt_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}} return _mm512_cmplt_ps_mask(a, b); } __mmask8 test_mm512_mask_cmplt_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmplt_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmplt_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmplt_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmplt_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmplt_ps_mask(k, a, b); } __mmask8 test_mm512_cmpneq_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpneq_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpneq_pd_mask(a, b); } __mmask8 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpneq_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpneq_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpneq_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpneq_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpneq_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpneq_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpneq_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpneq_ps_mask(k, a, b); } __mmask8 test_mm512_cmpnle_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpnle_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpnle_pd_mask(a, b); } __mmask8 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpnle_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpnle_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpnle_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpnle_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpnle_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpnle_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpnle_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpnle_ps_mask(k, a, b); } __mmask8 test_mm512_cmpnlt_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpnlt_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpnlt_pd_mask(a, b); } __mmask8 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpnlt_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpnlt_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpnlt_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpnlt_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpnlt_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpnlt_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpnlt_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpnlt_ps_mask(k, a, b); } __mmask8 test_mm512_cmpord_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpord_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpord_pd_mask(a, b); } __mmask8 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpord_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpord_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpord_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpord_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpord_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpord_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpord_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpord_ps_mask(k, a, b); } __mmask8 test_mm512_cmpunord_pd_mask(__m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_cmpunord_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}} return _mm512_cmpunord_pd_mask(a, b); } __mmask8 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpunord_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpunord_ps_mask(a, b); } __mmask8 test_mm512_mask_cmpunord_pd_mask(__mmask8 k, __m512d a, __m512d b) { // CHECK-LABEL: @test_mm512_mask_cmpunord_pd_mask - // CHECK: @llvm.x86.avx512.mask.cmp.pd.512 + // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpunord_pd_mask(k, a, b); } __mmask8 test_mm512_mask_cmpunord_ps_mask(__mmask8 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpunord_ps_mask - // CHECK: @llvm.x86.avx512.mask.cmp.ps.512 + // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmpunord_ps_mask(k, a, b); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 295796089f..3e68d7091f 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -1073,53 +1073,168 @@ __m128i test_mm_maskz_xor_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { __mmask8 test_mm256_cmp_ps_mask(__m256 __A, __m256 __B) { // CHECK-LABEL: @test_mm256_cmp_ps_mask - // CHECK: call <8 x i1> @llvm.x86.avx512.mask.cmp.ps.256 + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} return (__mmask8)_mm256_cmp_ps_mask(__A, __B, 0); } +__mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_true_us(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_false_os(__m256 __A, __m256 __B) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm256_mask_cmp_ps_mask(__mmask8 m, __m256 __A, __m256 __B) { // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = call <8 x i1> @llvm.x86.avx512.mask.cmp.ps.256 - // CHECK: and <8 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> %{{.*}}, %{{.*}} return _mm256_mask_cmp_ps_mask(m, __A, __B, 0); } __mmask8 test_mm_cmp_ps_mask(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_cmp_ps_mask - // CHECK: call <4 x i1> @llvm.x86.avx512.mask.cmp.ps.128 + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} return (__mmask8)_mm_cmp_ps_mask(__A, __B, 0); } +__mmask8 test_mm_cmp_ps_mask_true_uq(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_true_us(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm_cmp_ps_mask_false_oq(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_false_os(__m128 __A, __m128 __B) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm_mask_cmp_ps_mask(__mmask8 m, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = call <4 x i1> @llvm.x86.avx512.mask.cmp.ps.128 - // CHECK: and <4 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> + // CHECK: and <4 x i1> %{{.*}}, %{{.*}} return _mm_mask_cmp_ps_mask(m, __A, __B, 0); } __mmask8 test_mm256_cmp_pd_mask(__m256d __A, __m256d __B) { // CHECK-LABEL: @test_mm256_cmp_pd_mask - // CHECK: call <4 x i1> @llvm.x86.avx512.mask.cmp.pd.256 + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} return (__mmask8)_mm256_cmp_pd_mask(__A, __B, 0); } +__mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_true_us(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_false_os(__m256d __A, __m256d __B) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm256_mask_cmp_pd_mask(__mmask8 m, __m256d __A, __m256d __B) { // CHECK-LABEL: @test_mm256_mask_cmp_pd_mask - // CHECK: [[CMP:%.*]] = call <4 x i1> @llvm.x86.avx512.mask.cmp.pd.256 - // CHECK: and <4 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} + // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> + // CHECK: and <4 x i1> %{{.*}}, %{{.*}} return _mm256_mask_cmp_pd_mask(m, __A, __B, 0); } __mmask8 test_mm_cmp_pd_mask(__m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_cmp_pd_mask - // CHECK: call <2 x i1> @llvm.x86.avx512.mask.cmp.pd.128 + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} return (__mmask8)_mm_cmp_pd_mask(__A, __B, 0); } +__mmask8 test_mm_cmp_pd_mask_true_uq(__m128d __A, __m128d __B) { + // CHECK-LABEL: @test_mm_cmp_pd_mask_true_uq + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_TRUE_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_true_us(__m128d __A, __m128d __B) { + // CHECK-LABEL: @test_mm_cmp_pd_mask_true_us + // CHECK-NOT: call + // CHECK: ret i8 -1 + return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_TRUE_US); +} + +__mmask8 test_mm_cmp_pd_mask_false_oq(__m128d __A, __m128d __B) { + // CHECK-LABEL: @test_mm_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_false_os(__m128d __A, __m128d __B) { + // CHECK-LABEL: @test_mm_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_FALSE_OS); +} + __mmask8 test_mm_mask_cmp_pd_mask(__mmask8 m, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_mask_cmp_pd_mask - // CHECK: [[CMP:%.*]] = call <2 x i1> @llvm.x86.avx512.mask.cmp.pd.128 - // CHECK: and <2 x i1> [[CMP]], {{.*}} + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} + // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> + // CHECK: and <2 x i1> %{{.*}}, %{{.*}} return _mm_mask_cmp_pd_mask(m, __A, __B, 0); } -- GitLab From 0b8a6fded3d3ff541e9553a623666553bbb095de Mon Sep 17 00:00:00 2001 From: Kostya Kortchinsky Date: Fri, 22 Jun 2018 14:31:30 +0000 Subject: [PATCH 0232/1023] [Driver] Make scudo compatible with -fsanitize-minimal-runtime Summary: This is the clang side of the change, there is a compiler-rt counterpart. Scudo works with UBSan using `-fsanitize=scudo,integer` for example, and to do so it embeds UBSan runtime. This makes it not compatible with the UBSan minimal runtime, but this is something we want for production purposes. The idea is to have a Scudo minimal runtime on the compiler-rt side that will not embed UBSan. This is basically the runtime that is currently in use for Fuchsia, without coverage, stacktraces or symbolization. With this, Scudo becomes compatible with `-fsanitize-minimal-runtime`. If this approach is suitable, I'll add the tests as well, otherwise I am open to other options. Reviewers: eugenis Reviewed By: eugenis Subscribers: llvm-commits, cfe-commits Differential Revision: https://reviews.llvm.org/D48373 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335352 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/SanitizerArgs.cpp | 5 +++-- lib/Driver/ToolChains/CommonArgs.cpp | 25 +++++++++++++++++-------- test/Driver/fsanitize.c | 8 ++++++++ test/Driver/sanitizer-ld.c | 9 +++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 4eee52c779..743e042a79 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -45,7 +45,7 @@ enum : SanitizerMask { Nullability | LocalBounds | CFI, TrappingDefault = CFI, CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast, - CompatibleWithMinimalRuntime = TrappingSupported, + CompatibleWithMinimalRuntime = TrappingSupported | Scudo, }; enum CoverageFeature { @@ -179,7 +179,8 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D, bool SanitizerArgs::needsUbsanRt() const { // All of these include ubsan. if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() || - needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || needsScudoRt()) + needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() || + (needsScudoRt() && !requiresMinimalRuntime())) return false; return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 4f3d46e246..5bd012a6d8 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -593,14 +593,17 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, HelperStaticRuntimes.push_back("asan-preinit"); } if (SanArgs.needsUbsanRt()) { - if (SanArgs.requiresMinimalRuntime()) { + if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("ubsan_minimal"); - } else { + else SharedRuntimes.push_back("ubsan_standalone"); - } } - if (SanArgs.needsScudoRt()) - SharedRuntimes.push_back("scudo"); + if (SanArgs.needsScudoRt()) { + if (SanArgs.requiresMinimalRuntime()) + SharedRuntimes.push_back("scudo_minimal"); + else + SharedRuntimes.push_back("scudo"); + } if (SanArgs.needsHwasanRt()) SharedRuntimes.push_back("hwasan"); } @@ -666,9 +669,15 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (SanArgs.needsEsanRt()) StaticRuntimes.push_back("esan"); if (SanArgs.needsScudoRt()) { - StaticRuntimes.push_back("scudo"); - if (SanArgs.linkCXXRuntimes()) - StaticRuntimes.push_back("scudo_cxx"); + if (SanArgs.requiresMinimalRuntime()) { + StaticRuntimes.push_back("scudo_minimal"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("scudo_cxx_minimal"); + } else { + StaticRuntimes.push_back("scudo"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("scudo_cxx"); + } } } diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 5f66e24075..3e3b13e8c2 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -674,6 +674,14 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN // CHECK-SCUDO-UBSAN: "-fsanitize={{.*}}scudo" +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-MINIMAL +// CHECK-SCUDO-MINIMAL: "-fsanitize=scudo" +// CHECK-SCUDO-MINIMAL: "-fsanitize-minimal-runtime" + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined,scudo -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN-MINIMAL +// CHECK-SCUDO-UBSAN-MINIMAL: "-fsanitize={{.*}}scudo" +// CHECK-SCUDO-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" + // RUN: %clang -target powerpc-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SCUDO // CHECK-NO-SCUDO: unsupported option diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index 93df586e30..e85a828b33 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -689,6 +689,15 @@ // CHECK-SCUDO-LINUX: "-lpthread" // CHECK-SCUDO-LINUX: "-ldl" +// RUN: %clang -fsanitize=scudo -fsanitize-minimal-runtime %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-SCUDO-MINIMAL-LINUX %s +// CHECK-SCUDO-MINIMAL-LINUX: "{{.*}}ld{{(.exe)?}}" +// CHECK-SCUDO-MINIMAL-LINUX: "-pie" +// CHECK-SCUDO-MINIMAL-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_minimal-i386.a" "--no-whole-archive" +// CHECK-SCUDO-MINIMAL-LINUX: "-lpthread" + // RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \ // RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -- GitLab From db7edbb5681464a9814a6ef6ecef9e177e86aeda Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Fri, 22 Jun 2018 15:45:08 +0000 Subject: [PATCH 0233/1023] [Sema] Updated note for address spaces to print the type. This allows to reuse the same diagnostic for OpenCL or CUDA. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335358 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- lib/Sema/SemaOverload.cpp | 4 +--- test/SemaCXX/address-space-references.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 454aa53774..b7ede8518e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3683,8 +3683,8 @@ def note_ovl_candidate_bad_lvalue : Note< "%select{%ordinal4 argument|object argument}3">; def note_ovl_candidate_bad_addrspace : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " - "%select{%ordinal7|'this'}6 argument (%3) is in " - "address space %4, but parameter must be in address space %5">; + "address space mismatch in %select{%ordinal6|'this'}5 argument (%3), " + "parameter type must be %4">; def note_ovl_candidate_bad_gc : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 " diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index b1df8f6232..34ac5c1647 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -9591,9 +9591,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << FromQs.getAddressSpaceAttributePrintValue() - << ToQs.getAddressSpaceAttributePrintValue() - << (unsigned)isObjectArgument << I + 1; + << ToTy << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } diff --git a/test/SemaCXX/address-space-references.cpp b/test/SemaCXX/address-space-references.cpp index f5a63d24a9..5c297e76c4 100644 --- a/test/SemaCXX/address-space-references.cpp +++ b/test/SemaCXX/address-space-references.cpp @@ -3,10 +3,10 @@ typedef int __attribute__((address_space(1))) int_1; typedef int __attribute__((address_space(2))) int_2; -void f0(int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \ -// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}} -void f0(const int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \ -// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}} +void f0(int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}} \ +// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}} +void f0(const int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}} \ +// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}} void test_f0() { int i; -- GitLab From 1d5bce39c124fc62d71651423e292d4c88bad59b Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Fri, 22 Jun 2018 16:20:21 +0000 Subject: [PATCH 0234/1023] [OpenCL] Fixed parsing of address spaces for C++. Added address space tokens to C++ parsing code to be able to parse declarations that start from an address space keyword. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335362 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseTentative.cpp | 5 +++++ test/SemaOpenCL/address-spaces.cl | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index dbc8d550ad..79860545c2 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1357,6 +1357,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // cv-qualifier case tok::kw_const: case tok::kw_volatile: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___generic: // GNU case tok::kw_restrict: diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl index c5c58a6a30..3ac2569bc2 100644 --- a/test/SemaOpenCL/address-spaces.cl +++ b/test/SemaOpenCL/address-spaces.cl @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only // RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only +// RUN: %clang_cc1 %s -cl-std=c++ -verify -pedantic -fsyntax-only __constant int ci = 1; @@ -8,6 +9,8 @@ __kernel void foo(__global int *gip) { __local int lj = 2; // expected-error {{'__local' variable cannot have an initializer}} int *ip; +// FIXME: Temporarily disable part of the test that doesn't work for C++ yet. +#if !__OPENCL_CPP_VERSION__ #if __OPENCL_C_VERSION__ < 200 ip = gip; // expected-error {{assigning '__global int *' to 'int *' changes address space of pointer}} ip = &li; // expected-error {{assigning '__local int *' to 'int *' changes address space of pointer}} @@ -64,4 +67,5 @@ void func_multiple_addr(void) { __local private_int_t *var4; // expected-error {{multiple address spaces specified for type}} __private private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}} __private private_int_t *var6;// expected-warning {{multiple identical address spaces specified for type}} +#endif // !__OPENCL_CXX_VERSION__ } -- GitLab From 6834f366207620247dd99f5c1fabcc1f4f78ca2d Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Fri, 22 Jun 2018 16:51:17 +0000 Subject: [PATCH 0235/1023] Add const qualifier on FieldChainInfoComparator::operator() libcxx has user defined warning to check for non const call operator. Silence the warning by adding the const on operator(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335366 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index a517e81122..d9168d037e 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -85,7 +85,7 @@ private: }; struct FieldChainInfoComparator { - bool operator()(const FieldChainInfo &lhs, const FieldChainInfo &rhs) { + bool operator()(const FieldChainInfo &lhs, const FieldChainInfo &rhs) const { assert(!lhs.Chain.isEmpty() && !rhs.Chain.isEmpty() && "Attempted to store an empty fieldchain!"); return *lhs.Chain.begin() < *rhs.Chain.begin(); -- GitLab From 349642f32014f2566e5840782903ff5c1bd31fc4 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 22 Jun 2018 17:34:44 +0000 Subject: [PATCH 0236/1023] [NFC] Fix AttributeList allocated_size for ParsedType. This if/elseif structure seems to be missing this case. Previously, this would report a size of 1 pointer too small. This didn't really change anything besides failing to reclaim a very small amount of memory. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335372 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/AttributeList.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index bdb91c7e39..4cd32b361d 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -40,6 +40,8 @@ size_t AttributeList::allocated_size() const { return AttributeFactory::TypeTagForDatatypeAllocSize; else if (IsProperty) return AttributeFactory::PropertyAllocSize; + else if (HasParsedType) + return sizeof(AttributeList) + sizeof(void *); return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); } -- GitLab From 14549a3c6a77d7dad9b8079a433008f6a94a3f14 Mon Sep 17 00:00:00 2001 From: Emmett Neyman Date: Fri, 22 Jun 2018 18:05:00 +0000 Subject: [PATCH 0237/1023] Implemented proto to LLVM conversion and LLVM fuzz target Differential Revision: https://reviews.llvm.org/D48106 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335374 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/CMakeLists.txt | 22 ++- .../ExampleClangLLVMProtoFuzzer.cpp | 28 ++++ tools/clang-fuzzer/cxx_loop_proto.proto | 26 +-- .../fuzzer-initialize/fuzzer_initialize.cpp | 7 + tools/clang-fuzzer/handle-cxx/handle_cxx.cpp | 6 - tools/clang-fuzzer/handle-llvm/CMakeLists.txt | 5 + .../clang-fuzzer/handle-llvm/handle_llvm.cpp | 111 +++++++++++++ tools/clang-fuzzer/handle-llvm/handle_llvm.h | 25 +++ .../proto-to-cxx/loop_proto_to_cxx.cpp | 11 -- .../proto-to-cxx/loop_proto_to_cxx_main.cpp | 1 - .../clang-fuzzer/proto-to-llvm/CMakeLists.txt | 14 ++ .../proto-to-llvm/loop_proto_to_llvm.cpp | 156 ++++++++++++++++++ .../proto-to-llvm/loop_proto_to_llvm.h | 23 +++ .../proto-to-llvm/loop_proto_to_llvm_main.cpp | 31 ++++ 14 files changed, 430 insertions(+), 36 deletions(-) create mode 100644 tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp create mode 100644 tools/clang-fuzzer/handle-llvm/CMakeLists.txt create mode 100644 tools/clang-fuzzer/handle-llvm/handle_llvm.cpp create mode 100644 tools/clang-fuzzer/handle-llvm/handle_llvm.h create mode 100644 tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt create mode 100644 tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp create mode 100644 tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h create mode 100644 tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp diff --git a/tools/clang-fuzzer/CMakeLists.txt b/tools/clang-fuzzer/CMakeLists.txt index 039449aca6..5f07e66fe6 100644 --- a/tools/clang-fuzzer/CMakeLists.txt +++ b/tools/clang-fuzzer/CMakeLists.txt @@ -15,6 +15,7 @@ set(LLVM_OPTIONAL_SOURCES DummyClangFuzzer.cpp ExampleClangProtoFuzzer.cpp ExampleClangLoopProtoFuzzer.cpp + ExampleClangLLVMProtoFuzzer.cpp ) if(CLANG_ENABLE_PROTO_FUZZER) @@ -49,6 +50,9 @@ if(CLANG_ENABLE_PROTO_FUZZER) # Build the protobuf->C++ translation library and driver. add_clang_subdirectory(proto-to-cxx) + + # Build the protobuf->LLVM IR translation library and driver. + add_clang_subdirectory(proto-to-llvm) # Build the fuzzer initialization library. add_clang_subdirectory(fuzzer-initialize) @@ -65,29 +69,45 @@ if(CLANG_ENABLE_PROTO_FUZZER) ExampleClangLoopProtoFuzzer.cpp ) + # Build the llvm protobuf fuzzer + add_clang_executable(clang-llvm-proto-fuzzer + ${DUMMY_MAIN} + ExampleClangLLVMProtoFuzzer.cpp + ) + set(COMMON_PROTO_FUZZ_LIBRARIES ${ProtobufMutator_LIBRARIES} ${PROTOBUF_LIBRARIES} ${LLVM_LIB_FUZZING_ENGINE} clangFuzzerInitialize - clangHandleCXX ) target_link_libraries(clang-proto-fuzzer PRIVATE ${COMMON_PROTO_FUZZ_LIBRARIES} + clangHandleCXX clangCXXProto clangProtoToCXX ) target_link_libraries(clang-loop-proto-fuzzer PRIVATE ${COMMON_PROTO_FUZZ_LIBRARIES} + clangHandleCXX clangCXXLoopProto clangLoopProtoToCXX ) + target_link_libraries(clang-llvm-proto-fuzzer + PRIVATE + ${COMMON_PROTO_FUZZ_LIBRARIES} + clangHandleLLVM + clangCXXLoopProto + clangLoopProtoToLLVM + ) + endif() add_clang_subdirectory(handle-cxx) +add_clang_subdirectory(handle-llvm) add_clang_executable(clang-fuzzer EXCLUDE_FROM_ALL diff --git a/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp b/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp new file mode 100644 index 0000000000..347ba1c320 --- /dev/null +++ b/tools/clang-fuzzer/ExampleClangLLVMProtoFuzzer.cpp @@ -0,0 +1,28 @@ +//===-- ExampleClangLLVMProtoFuzzer.cpp - Fuzz Clang ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a function that compiles a single LLVM IR string as +/// input and uses libprotobuf-mutator to find new inputs. This function is +/// then linked into the Fuzzer library. +/// +//===----------------------------------------------------------------------===// + +#include "cxx_loop_proto.pb.h" +#include "fuzzer-initialize/fuzzer_initialize.h" +#include "handle-llvm/handle_llvm.h" +#include "proto-to-llvm/loop_proto_to_llvm.h" +#include "src/libfuzzer/libfuzzer_macro.h" + +using namespace clang_fuzzer; + +DEFINE_BINARY_PROTO_FUZZER(const LoopFunction &input) { + auto S = LoopFunctionToLLVMString(input); + HandleLLVM(S, GetCLArgs()); +} diff --git a/tools/clang-fuzzer/cxx_loop_proto.proto b/tools/clang-fuzzer/cxx_loop_proto.proto index 7538fc636a..f2b47ed43d 100644 --- a/tools/clang-fuzzer/cxx_loop_proto.proto +++ b/tools/clang-fuzzer/cxx_loop_proto.proto @@ -37,17 +37,15 @@ message BinaryOp { PLUS = 0; MINUS = 1; MUL = 2; - DIV = 3; - MOD = 4; - XOR = 5; - AND = 6; - OR = 7; - EQ = 8; - NE = 9; - LE = 10; - GE = 11; - LT = 12; - GT = 13; + XOR = 3; + AND = 4; + OR = 5; + EQ = 6; + NE = 7; + LE = 8; + GE = 9; + LT = 10; + GT = 11; }; required Op op = 1; required Rvalue left = 2; @@ -67,12 +65,6 @@ message AssignmentStatement { required Rvalue rvalue = 2; } -message IfElse { - required Rvalue cond = 1; - required StatementSeq if_body = 2; - required StatementSeq else_body = 3; -} - message Statement { required AssignmentStatement assignment = 1; } diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp index 08bc242b88..e0131ed892 100644 --- a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp +++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp @@ -15,6 +15,8 @@ //===----------------------------------------------------------------------===// #include "fuzzer_initialize.h" + +#include "llvm/Support/TargetSelect.h" #include using namespace clang_fuzzer; @@ -31,6 +33,11 @@ const std::vector& GetCLArgs() { } extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); + CLArgs.push_back("-O2"); for (int I = 1; I < *argc; I++) { if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) { diff --git a/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp b/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp index 312ab91e5f..4985fedbe1 100644 --- a/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp +++ b/tools/clang-fuzzer/handle-cxx/handle_cxx.cpp @@ -18,17 +18,11 @@ #include "clang/Lex/PreprocessorOptions.h" #include "clang/Tooling/Tooling.h" #include "llvm/Option/Option.h" -#include "llvm/Support/TargetSelect.h" using namespace clang; void clang_fuzzer::HandleCXX(const std::string &S, const std::vector &ExtraArgs) { - llvm::InitializeAllTargets(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmPrinters(); - llvm::InitializeAllAsmParsers(); - llvm::opt::ArgStringList CC1Args; CC1Args.push_back("-cc1"); for (auto &A : ExtraArgs) diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt new file mode 100644 index 0000000000..87314b00f4 --- /dev/null +++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support) + +add_clang_library(clangHandleLLVM + handle_llvm.cpp + ) diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp new file mode 100644 index 0000000000..9dc895295f --- /dev/null +++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp @@ -0,0 +1,111 @@ +//==-- handle_llvm.cpp - Helper function for Clang fuzzers -----------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements HandleLLVM for use by the Clang fuzzers. Mimics the llc tool to +// compile an LLVM IR file to X86_64 assembly. +// +//===----------------------------------------------------------------------===// + +#include "handle_llvm.h" + +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/CodeGen/CommandFlags.inc" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/PassRegistry.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" + +#include + +using namespace llvm; + +static void getOptLevel(const std::vector &ExtraArgs, + CodeGenOpt::Level &OLvl) { + // Find the optimization level from the command line args + OLvl = CodeGenOpt::Default; + for (auto &A : ExtraArgs) { + if (A[0] == '-' && A[1] == 'O') { + switch(A[2]) { + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + default: + errs() << "error: opt level must be between 0 and 3.\n"; + std::exit(1); + } + } + } +} + +void clang_fuzzer::HandleLLVM(const std::string &S, + const std::vector &ExtraArgs) { + // Parse ExtraArgs to set the optimization level + CodeGenOpt::Level OLvl; + getOptLevel(ExtraArgs, OLvl); + + // Set the Module to include the the IR code to be compiled + SMDiagnostic Err; + + LLVMContext Context; + std::unique_ptr M = parseIR(MemoryBufferRef(S, "IR"), Err, Context); + if (!M) { + errs() << "error: could not parse IR!\n"; + std::exit(1); + } + + // Create a new Target + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget( + sys::getDefaultTargetTriple(), Error); + if (!TheTarget) { + errs() << Error; + std::exit(1); + } + + TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + + // Create a new Machine + std::string CPUStr = getCPUStr(); + std::string FeaturesStr = getFeaturesStr(); + std::unique_ptr Target(TheTarget->createTargetMachine( + sys::getDefaultTargetTriple(), CPUStr, FeaturesStr, Options, + getRelocModel(), getCodeModel(), OLvl)); + + // Create a new PassManager + legacy::PassManager PM; + TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple())); + PM.add(new TargetLibraryInfoWrapperPass(TLII)); + M->setDataLayout(Target->createDataLayout()); + + // Make sure the Module has no errors + if (verifyModule(*M, &errs())) { + errs() << "error: input module is broken!\n"; + std::exit(1); + } + + setFunctionAttributes(CPUStr, FeaturesStr, *M); + + raw_null_ostream OS; + Target->addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_ObjectFile, + false); + PM.run(*M); + + return; +} + diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.h b/tools/clang-fuzzer/handle-llvm/handle_llvm.h new file mode 100644 index 0000000000..38aec67994 --- /dev/null +++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.h @@ -0,0 +1,25 @@ +//==-- handle_llvm.h - Helper function for Clang fuzzers -------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines HandleLLVM for use by the Clang fuzzers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H +#define LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H + +#include +#include + +namespace clang_fuzzer { +void HandleLLVM(const std::string &S, + const std::vector &ExtraArgs); +} // namespace clang_fuzzer + +#endif diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp index adebe920f7..7d8f6650aa 100644 --- a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp @@ -67,12 +67,6 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { case BinaryOp::MUL: os << "*"; break; - case BinaryOp::DIV: - os << "/"; - break; - case BinaryOp::MOD: - os << "%"; - break; case BinaryOp::XOR: os << "^"; break; @@ -106,11 +100,6 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { return os << x.varref() << "=" << x.rvalue() << ";\n"; } -std::ostream &operator<<(std::ostream &os, const IfElse &x) { - return os << "if (" << x.cond() << "){\n" - << x.if_body() << "} else { \n" - << x.else_body() << "}\n"; -} std::ostream &operator<<(std::ostream &os, const Statement &x) { return os << x.assignment(); } diff --git a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp index e4b1414c63..a4b8e58c12 100644 --- a/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp +++ b/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -// This is a copy and will be updated later to introduce changes #include #include diff --git a/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt b/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt new file mode 100644 index 0000000000..ae58523f22 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) +set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ}) + +# Needed by LLVM's CMake checks because this file defines multiple targets. +set(LLVM_OPTIONAL_SOURCES loop_proto_to_llvm.cpp loop_proto_to_llvm_main.cpp) + +add_clang_library(clangLoopProtoToLLVM loop_proto_to_llvm.cpp + DEPENDS clangCXXLoopProto + LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES} + ) + +add_clang_executable(clang-loop-proto-to-llvm loop_proto_to_llvm_main.cpp) + +target_link_libraries(clang-loop-proto-to-llvm PRIVATE clangLoopProtoToLLVM) diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp new file mode 100644 index 0000000000..16dbcb7b49 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp @@ -0,0 +1,156 @@ +//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion +//---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements functions for converting between protobufs and LLVM IR. +// +// +//===----------------------------------------------------------------------===// + +#include "loop_proto_to_llvm.h" +#include "cxx_loop_proto.pb.h" + +// The following is needed to convert protos in human-readable form +#include + +#include +#include + +namespace clang_fuzzer { + +// Forward decls +std::string BinopToString(std::ostream &os, const BinaryOp &x); +std::string StateSeqToString(std::ostream &os, const StatementSeq &x); + +// Counter variable to generate new LLVM IR variable names and wrapper function +std::string get_var() { + static int ctr = 0; + return "%var" + std::to_string(ctr++); +} + +// Proto to LLVM. + +std::string ConstToString(const Const &x) { + return std::to_string(x.val()); +} +std::string VarRefToString(std::ostream &os, const VarRef &x) { + std::string arr; + switch(x.arr()) { + case VarRef::ARR_A: + arr = "%a"; + break; + case VarRef::ARR_B: + arr = "%b"; + break; + case VarRef::ARR_C: + arr = "%c"; + break; + } + std::string ptr_var = get_var(); + os << ptr_var << " = getelementptr i32, i32* " << arr << ", i64 %ct\n"; + return ptr_var; +} +std::string RvalueToString(std::ostream &os, const Rvalue &x) { + if(x.has_cons()) + return ConstToString(x.cons()); + if(x.has_binop()) + return BinopToString(os, x.binop()); + if(x.has_varref()) { + std::string var_ref = VarRefToString(os, x.varref()); + std::string val_var = get_var(); + os << val_var << " = load i32, i32* " << var_ref << "\n"; + return val_var; + } + return "1"; + +} +std::string BinopToString(std::ostream &os, const BinaryOp &x) { + std::string left = RvalueToString(os, x.left()); + std::string right = RvalueToString(os, x.right()); + std::string op; + switch (x.op()) { + case BinaryOp::PLUS: + op = "add"; + break; + case BinaryOp::MINUS: + op = "sub"; + break; + case BinaryOp::MUL: + op = "mul"; + break; + case BinaryOp::XOR: + op = "xor"; + break; + case BinaryOp::AND: + op = "and"; + break; + case BinaryOp::OR: + op = "or"; + break; + // Support for Boolean operators will be added later + case BinaryOp::EQ: + case BinaryOp::NE: + case BinaryOp::LE: + case BinaryOp::GE: + case BinaryOp::LT: + case BinaryOp::GT: + op = "add"; + break; + } + std::string val_var = get_var(); + os << val_var << " = " << op << " i32 " << left << ", " << right << "\n"; + return val_var; +} +std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { + std::string rvalue = RvalueToString(os, x.rvalue()); + std::string var_ref = VarRefToString(os, x.varref()); + return os << "store i32 " << rvalue << ", i32* " << var_ref << "\n"; +} +std::ostream &operator<<(std::ostream &os, const Statement &x) { + return os << x.assignment(); +} +std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { + for (auto &st : x.statements()) { + os << st; + } + return os; +} +std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { + return os << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n" + << "%i = alloca i64\n" + << "store i64 0, i64* %i\n" + << "br label %loop\n\n" + << "loop:\n" + << "%ct = load i64, i64* %i\n" + << "%comp = icmp eq i64 %ct, %s\n" + << "br i1 %comp, label %endloop, label %body\n\n" + << "body:\n" + << x.statements() + << "%z = add i64 1, %ct\n" + << "store i64 %z, i64* %i\n" + << "br label %loop\n\n" + << "endloop:\n" + << "ret void\n}\n"; +} + +// --------------------------------- + +std::string LoopFunctionToLLVMString(const LoopFunction &input) { + std::ostringstream os; + os << input; + return os.str(); +} +std::string LoopProtoToLLVM(const uint8_t *data, size_t size) { + LoopFunction message; + if (!message.ParsePartialFromArray(data, size)) + return "#error invalid proto\n"; + return LoopFunctionToLLVMString(message); +} + +} // namespace clang_fuzzer diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h new file mode 100644 index 0000000000..51660fcb71 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h @@ -0,0 +1,23 @@ +//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines functions for converting between protobufs and LLVM IR. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +namespace clang_fuzzer { +class LoopFunction; + +std::string LoopFunctionToLLVMString(const LoopFunction &input); +std::string LoopProtoToLLVM(const uint8_t *data, size_t size); +} diff --git a/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp new file mode 100644 index 0000000000..17ca15ec27 --- /dev/null +++ b/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp @@ -0,0 +1,31 @@ +//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion----==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements a simple driver to print a LLVM program from a protobuf with loops +// +//===----------------------------------------------------------------------===// + + +#include +#include +#include +#include + +#include "loop_proto_to_llvm.h" + +int main(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + std::fstream in(argv[i]); + std::string str((std::istreambuf_iterator(in)), + std::istreambuf_iterator()); + std::cout << ";; " << argv[i] << std::endl; + std::cout << clang_fuzzer::LoopProtoToLLVM( + reinterpret_cast(str.data()), str.size()); + } +} -- GitLab From 91b3d0660705711eb7ab95139d25b1f8fa9cb7be Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 22 Jun 2018 18:05:17 +0000 Subject: [PATCH 0238/1023] Re-apply: Warning for framework headers using double quote includes Introduce -Wquoted-include-in-framework-header, which should fire a warning whenever a quote include appears in a framework header and suggest a fix-it. For instance, for header A.h added in the tests, this is how the warning looks like: ./A.framework/Headers/A.h:2:10: warning: double-quoted include "A0.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "A0.h" ^~~~~~ ./A.framework/Headers/A.h:3:10: warning: double-quoted include "B.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "B.h" ^~~~~ This helps users to prevent frameworks from using local headers when in fact they should be targetting system level ones. The warning is off by default. Differential Revision: https://reviews.llvm.org/D47157 rdar://problem/37077034 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335375 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticLexKinds.td | 5 ++ lib/Lex/HeaderSearch.cpp | 65 ++++++++++++++++++- .../double-quotes/A.framework/Headers/A.h | 6 ++ .../double-quotes/A.framework/Headers/A0.h | 1 + .../A.framework/Modules/module.modulemap | 5 ++ test/Modules/Inputs/double-quotes/B.h | 1 + .../double-quotes/X.framework/Headers/X.h | 1 + .../X.framework/Modules/module.modulemap | 4 ++ test/Modules/Inputs/double-quotes/a.hmap.json | 6 ++ .../Inputs/double-quotes/flat-header-path/Z.h | 1 + .../flat-header-path/Z.modulemap | 4 ++ test/Modules/Inputs/double-quotes/x.hmap.json | 7 ++ test/Modules/Inputs/double-quotes/z.yaml | 28 ++++++++ test/Modules/double-quotes.m | 39 +++++++++++ 15 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/B.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Headers/X.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/a.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.h create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap create mode 100644 test/Modules/Inputs/double-quotes/x.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/z.yaml create mode 100644 test/Modules/double-quotes.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 643c178743..7cc9967738 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; +def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 9b7f7e6777..de6bffcdca 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -714,6 +714,11 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; +def warn_quoted_include_in_framework_header : Warning< + "double-quoted include \"%0\" in framework header, " + "expected angle-bracketed instead" + >, InGroup, DefaultIgnore; + def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup, DefaultIgnore; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 1f2c339ea3..757cd097e4 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,6 +621,59 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } +static bool isFrameworkStylePath(StringRef Path, + SmallVectorImpl &FrameworkName) { + using namespace llvm::sys; + path::const_iterator I = path::begin(Path); + path::const_iterator E = path::end(Path); + + // Detect different types of framework style paths: + // + // ...Foo.framework/{Headers,PrivateHeaders} + // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} + // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} + // ... + // + // and some other variations among these lines. + int FoundComp = 0; + while (I != E) { + if (I->endswith(".framework")) { + FrameworkName.append(I->begin(), I->end()); + ++FoundComp; + } + if (*I == "Headers" || *I == "PrivateHeaders") + ++FoundComp; + ++I; + } + + return FoundComp >= 2; +} + +static void +diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, + StringRef Includer, StringRef IncludeFilename, + const FileEntry *IncludeFE, bool isAngled = false, + bool FoundByHeaderMap = false) { + SmallString<128> FromFramework, ToFramework; + if (!isFrameworkStylePath(Includer, FromFramework)) + return; + bool IsIncludeeInFramework = + isFrameworkStylePath(IncludeFE->getName(), ToFramework); + + if (!isAngled && !FoundByHeaderMap) { + SmallString<128> NewInclude("<"); + if (IsIncludeeInFramework) { + NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework + NewInclude += "/"; + } + NewInclude += IncludeFilename; + NewInclude += ">"; + Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) + << IncludeFilename + << FixItHint::CreateReplacement(IncludeLoc, NewInclude); + } +} + /// LookupFile - Given a "foo" or \ reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -722,8 +775,12 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) + if (First) { + diagnoseFrameworkInclude(Diags, IncludeLoc, + IncluderAndDir.second->getName(), Filename, + FE); return FE; + } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -834,6 +891,12 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } + bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; + if (!Includers.empty()) + diagnoseFrameworkInclude(Diags, IncludeLoc, + Includers.front().second->getName(), Filename, + FE, isAngled, FoundByHeaderMap); + // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h new file mode 100644 index 0000000000..17ceb83bb9 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h @@ -0,0 +1,6 @@ +#include "A0.h" +#include "B.h" + +#include "X.h" + +int foo(); diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h new file mode 100644 index 0000000000..79c6b8893b --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h @@ -0,0 +1 @@ +// double-quotes/A.framework/Headers/A0.h diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..09a887a8f4 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +// double-quotes/A.framework/Modules/module.modulemap +framework module A { + header "A.h" + header "A0.h" +} diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h new file mode 100644 index 0000000000..724faaef80 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/B.h @@ -0,0 +1 @@ +// double-quotes/B.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h new file mode 100644 index 0000000000..0185751299 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h @@ -0,0 +1 @@ +// double-quotes/X.framework/Headers/X.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap new file mode 100644 index 0000000000..95524704c6 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +// double-quotes/X.framework/Modules/module.modulemap +framework module X { + header "X.h" +} diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json new file mode 100644 index 0000000000..bdd383ce41 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/a.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "A.h" : "A/A.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h new file mode 100644 index 0000000000..db96b64962 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h @@ -0,0 +1 @@ +#import "B.h" // Included from Z.h & A.h diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap new file mode 100644 index 0000000000..34441b0701 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap @@ -0,0 +1,4 @@ +// double-quotes/flat-header-path/Z.modulemap +framework module Z { + header "Z.h" +} diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json new file mode 100644 index 0000000000..2b6a059564 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/x.hmap.json @@ -0,0 +1,7 @@ + +{ + "mappings" : + { + "X.h" : "X/X.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml new file mode 100644 index 0000000000..242f821346 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/z.yaml @@ -0,0 +1,28 @@ +{ + 'version': 0, + 'case-sensitive': 'false', + 'roots': [ + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Headers", + 'contents': [ + { + 'type': 'file', + 'name': "Z.h", + 'external-contents': "TEST_DIR/flat-header-path/Z.h" + } + ] + }, + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Modules", + 'contents': [ + { + 'type': 'file', + 'name': "module.modulemap", + 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" + } + ] + } + ] +} diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m new file mode 100644 index 0000000000..a21f12fa5e --- /dev/null +++ b/test/Modules/double-quotes.m @@ -0,0 +1,39 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: %hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap +// RUN: %hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap + +// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \ +// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml + +// The output with and without modules should be the same + +// RUN: %clang_cc1 \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \ +// RUN: 2>%t/stderr + +// The same warnings show up when modules is on but -verify doesn't get it +// because they only show up under the module A building context. +// RUN: FileCheck --input-file=%t/stderr %s +// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead + +#import "A.h" +#import + +int bar() { return foo(); } + +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} -- GitLab From ccd9acb5efb6e89c50caddc0b6f6ce4302ef5aa2 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 22 Jun 2018 19:10:38 +0000 Subject: [PATCH 0239/1023] [OPENMP, NVPTX] Fix reduction of the big data types/structures. If the shuffle is required for the reduced structures/big data type, current code may cause compiler crash because of the loading of the aggregate values. Patch fixes this problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335377 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 136 +++++++++++++++--- ...vptx_target_parallel_reduction_codegen.cpp | 48 +++---- test/OpenMP/nvptx_teams_reduction_codegen.cpp | 64 ++++----- 3 files changed, 171 insertions(+), 77 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index e3cec13f7d..5b7f0c3e43 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -2086,6 +2086,80 @@ static llvm::Value *createRuntimeShuffleFunction(CodeGenFunction &CGF, return castValueToType(CGF, ShuffledVal, CastTy, ElemType, Loc); } +static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, + Address DestAddr, QualType ElemType, + llvm::Value *Offset, SourceLocation Loc) { + CGBuilderTy &Bld = CGF.Builder; + + CharUnits Size = CGF.getContext().getTypeSizeInChars(ElemType); + // Create the loop over the big sized data. + // ptr = (void*)Elem; + // ptrEnd = (void*) Elem + 1; + // Step = 8; + // while (ptr + Step < ptrEnd) + // shuffle((int64_t)*ptr); + // Step = 4; + // while (ptr + Step < ptrEnd) + // shuffle((int32_t)*ptr); + // ... + Address ElemPtr = DestAddr; + Address Ptr = SrcAddr; + Address PtrEnd = Bld.CreatePointerBitCastOrAddrSpaceCast( + Bld.CreateConstGEP(SrcAddr, 1, Size), CGF.VoidPtrTy); + for (int IntSize = 8; IntSize >= 1; IntSize /= 2) { + if (Size < CharUnits::fromQuantity(IntSize)) + continue; + QualType IntType = CGF.getContext().getIntTypeForBitwidth( + CGF.getContext().toBits(CharUnits::fromQuantity(IntSize)), + /*Signed=*/1); + llvm::Type *IntTy = CGF.ConvertTypeForMem(IntType); + Ptr = Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr, IntTy->getPointerTo()); + ElemPtr = + Bld.CreatePointerBitCastOrAddrSpaceCast(ElemPtr, IntTy->getPointerTo()); + if (Size.getQuantity() / IntSize > 1) { + llvm::BasicBlock *PreCondBB = CGF.createBasicBlock(".shuffle.pre_cond"); + llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".shuffle.then"); + llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".shuffle.exit"); + llvm::BasicBlock *CurrentBB = Bld.GetInsertBlock(); + CGF.EmitBlock(PreCondBB); + llvm::PHINode *PhiSrc = + Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); + PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); + llvm::PHINode *PhiDest = + Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); + PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); + Ptr = Address(PhiSrc, Ptr.getAlignment()); + ElemPtr = Address(PhiDest, ElemPtr.getAlignment()); + llvm::Value *PtrDiff = Bld.CreatePtrDiff( + PtrEnd.getPointer(), Bld.CreatePointerBitCastOrAddrSpaceCast( + Ptr.getPointer(), CGF.VoidPtrTy)); + Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), + ThenBB, ExitBB); + CGF.EmitBlock(ThenBB); + llvm::Value *Res = createRuntimeShuffleFunction( + CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc), + IntType, Offset, Loc); + CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType); + Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize)); + ElemPtr = + Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize)); + PhiSrc->addIncoming(Ptr.getPointer(), ThenBB); + PhiDest->addIncoming(ElemPtr.getPointer(), ThenBB); + CGF.EmitBranch(PreCondBB); + CGF.EmitBlock(ExitBB); + } else { + llvm::Value *Res = createRuntimeShuffleFunction( + CGF, CGF.EmitLoadOfScalar(Ptr, /*Volatile=*/false, IntType, Loc), + IntType, Offset, Loc); + CGF.EmitStoreOfScalar(Res, ElemPtr, /*Volatile=*/false, IntType); + Ptr = Bld.CreateConstGEP(Ptr, 1, CharUnits::fromQuantity(IntSize)); + ElemPtr = + Bld.CreateConstGEP(ElemPtr, 1, CharUnits::fromQuantity(IntSize)); + } + Size = Size % IntSize; + } +} + namespace { enum CopyAction : unsigned { // RemoteLaneToThread: Copy over a Reduce list from a remote lane in @@ -2227,25 +2301,30 @@ static void emitReductionListCopy( // element as this is required in all directions SrcElementAddr = Bld.CreateElementBitCast( SrcElementAddr, CGF.ConvertTypeForMem(Private->getType())); - llvm::Value *Elem = - CGF.EmitLoadOfScalar(SrcElementAddr, /*Volatile=*/false, - Private->getType(), Private->getExprLoc()); + DestElementAddr = Bld.CreateElementBitCast(DestElementAddr, + SrcElementAddr.getElementType()); // Now that all active lanes have read the element in the // Reduce list, shuffle over the value from the remote lane. if (ShuffleInElement) { - Elem = - createRuntimeShuffleFunction(CGF, Elem, Private->getType(), - RemoteLaneOffset, Private->getExprLoc()); + shuffleAndStore(CGF, SrcElementAddr, DestElementAddr, Private->getType(), + RemoteLaneOffset, Private->getExprLoc()); + } else { + if (Private->getType()->isScalarType()) { + llvm::Value *Elem = + CGF.EmitLoadOfScalar(SrcElementAddr, /*Volatile=*/false, + Private->getType(), Private->getExprLoc()); + // Store the source element value to the dest element address. + CGF.EmitStoreOfScalar(Elem, DestElementAddr, /*Volatile=*/false, + Private->getType()); + } else { + CGF.EmitAggregateCopy( + CGF.MakeAddrLValue(DestElementAddr, Private->getType()), + CGF.MakeAddrLValue(SrcElementAddr, Private->getType()), + Private->getType(), AggValueSlot::DoesNotOverlap); + } } - DestElementAddr = Bld.CreateElementBitCast(DestElementAddr, - SrcElementAddr.getElementType()); - - // Store the source element value to the dest element address. - CGF.EmitStoreOfScalar(Elem, DestElementAddr, /*Volatile=*/false, - Private->getType()); - // Step 3.1: Modify reference in dest Reduce list as needed. // Modifying the reference in Reduce list to point to the newly // created element. The element is live in the current function @@ -2616,9 +2695,6 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, Address(ElemPtrPtr, C.getTypeAlignInChars(Private->getType())); ElemPtr = Bld.CreateElementBitCast( ElemPtr, CGF.ConvertTypeForMem(Private->getType())); - // elem = *elemptr - llvm::Value *Elem = CGF.EmitLoadOfScalar( - ElemPtr, /*Volatile=*/false, Private->getType(), SourceLocation()); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -2630,8 +2706,19 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, MediumPtr = Bld.CreateElementBitCast( MediumPtr, CGF.ConvertTypeForMem(Private->getType())); + // elem = *elemptr //*MediumPtr = elem - Bld.CreateStore(Elem, MediumPtr); + if (Private->getType()->isScalarType()) { + llvm::Value *Elem = CGF.EmitLoadOfScalar(ElemPtr, /*Volatile=*/false, + Private->getType(), Loc); + // Store the source element value to the dest element address. + CGF.EmitStoreOfScalar(Elem, MediumPtr, /*Volatile=*/false, + Private->getType()); + } else { + CGF.EmitAggregateCopy(CGF.MakeAddrLValue(ElemPtr, Private->getType()), + CGF.MakeAddrLValue(MediumPtr, Private->getType()), + Private->getType(), AggValueSlot::DoesNotOverlap); + } Bld.CreateBr(MergeBB); @@ -2671,8 +2758,6 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // SrcMediumVal = *SrcMediumPtr; SrcMediumPtr = Bld.CreateElementBitCast( SrcMediumPtr, CGF.ConvertTypeForMem(Private->getType())); - llvm::Value *SrcMediumValue = CGF.EmitLoadOfScalar( - SrcMediumPtr, /*Volatile=*/false, Private->getType(), SourceLocation()); // TargetElemPtr = (type[i]*)(SrcDataAddr[i]) Address TargetElemPtrPtr = @@ -2685,8 +2770,17 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtr, CGF.ConvertTypeForMem(Private->getType())); // *TargetElemPtr = SrcMediumVal; - CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false, - Private->getType()); + if (Private->getType()->isScalarType()) { + llvm::Value *SrcMediumValue = CGF.EmitLoadOfScalar( + SrcMediumPtr, /*Volatile=*/false, Private->getType(), Loc); + CGF.EmitStoreOfScalar(SrcMediumValue, TargetElemPtr, /*Volatile=*/false, + Private->getType()); + } else { + CGF.EmitAggregateCopy( + CGF.MakeAddrLValue(SrcMediumPtr, Private->getType()), + CGF.MakeAddrLValue(TargetElemPtr, Private->getType()), + Private->getType(), AggValueSlot::DoesNotOverlap); + } Bld.CreateBr(W0MergeBB); CGF.EmitBlock(W0ElseBB); diff --git a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp index 569a876307..f13e113db0 100644 --- a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp +++ b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp @@ -117,15 +117,15 @@ int bar(int n){ // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* - // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // - // CHECK: [[ELT_CAST:%.+]] = bitcast double [[ELT_VAL]] to i64 + // CHECK: [[ELT_CAST:%.+]] = bitcast double* [[ELT]] to i64* + // CHECK: [[REMOTE_ELT_CAST:%.+]] = bitcast double* [[REMOTE_ELT]] to i64* + // CHECK: [[ELT_VAL:%.+]] = load i64, i64* [[ELT_CAST]], align // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16 - // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]]) - // CHECK: [[REMOTE_ELT_VAL:%.+]] = bitcast i64 [[REMOTE_ELT_VAL64]] to double + // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]]) // - // CHECK: store double [[REMOTE_ELT_VAL]], double* [[REMOTE_ELT]], align + // CHECK: store i64 [[REMOTE_ELT_VAL64]], i64* [[REMOTE_ELT_CAST]], align // CHECK: [[REMOTE_ELT_VOID:%.+]] = bitcast double* [[REMOTE_ELT]] to i8* // CHECK: store i8* [[REMOTE_ELT_VOID]], i8** [[REMOTE_ELT_REF]], align // @@ -169,8 +169,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -193,10 +193,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* - // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -216,10 +216,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -347,15 +347,15 @@ int bar(int n){ // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* - // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // - // CHECK: [[ELT_CAST:%.+]] = bitcast float [[ELT_VAL]] to i32 + // CHECK: [[ELT_CAST:%.+]] = bitcast float* [[ELT]] to i32* + // CHECK: [[REMOTE_ELT2_CAST:%.+]] = bitcast float* [[REMOTE_ELT2]] to i32* + // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT_CAST]], align // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16 - // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]]) - // CHECK: [[REMOTE_ELT2_VAL:%.+]] = bitcast i32 [[REMOTE_ELT2_VAL32]] to float + // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]]) // - // CHECK: store float [[REMOTE_ELT2_VAL]], float* [[REMOTE_ELT2]], align + // CHECK: store i32 [[REMOTE_ELT2_VAL32]], i32* [[REMOTE_ELT2_CAST]], align // CHECK: [[REMOTE_ELT2C:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8* // CHECK: store i8* [[REMOTE_ELT2C]], i8** [[REMOTE_ELT_REF]], align // @@ -406,8 +406,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -429,10 +429,10 @@ int bar(int n){ // [[DO_COPY]] // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], - // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align // CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -452,9 +452,9 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -470,10 +470,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* - // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -493,10 +493,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -715,8 +715,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align // // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 @@ -724,8 +724,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -748,10 +748,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* - // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -771,10 +771,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -790,10 +790,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* - // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -813,10 +813,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i{{32|64}} 0, i{{32|64}} 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // diff --git a/test/OpenMP/nvptx_teams_reduction_codegen.cpp b/test/OpenMP/nvptx_teams_reduction_codegen.cpp index b462542108..6925b17163 100644 --- a/test/OpenMP/nvptx_teams_reduction_codegen.cpp +++ b/test/OpenMP/nvptx_teams_reduction_codegen.cpp @@ -117,15 +117,15 @@ int bar(int n){ // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* - // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // - // CHECK: [[ELT_CAST:%.+]] = bitcast double [[ELT_VAL]] to i64 + // CHECK: [[ELT_CAST:%.+]] = bitcast double* [[ELT]] to i64* + // CHECK: [[REMOTE_ELT_CAST:%.+]] = bitcast double* [[REMOTE_ELT]] to i64* + // CHECK: [[ELT_VAL:%.+]] = load i64, i64* [[ELT_CAST]], align // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16 - // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]]) - // CHECK: [[REMOTE_ELT_VAL:%.+]] = bitcast i64 [[REMOTE_ELT_VAL64]] to double + // CHECK: [[REMOTE_ELT_VAL64:%.+]] = call i64 @__kmpc_shuffle_int64(i64 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]]) // - // CHECK: store double [[REMOTE_ELT_VAL]], double* [[REMOTE_ELT]], align + // CHECK: store i64 [[REMOTE_ELT_VAL64]], i64* [[REMOTE_ELT_CAST]], align // CHECK: [[REMOTE_ELT_VOID:%.+]] = bitcast double* [[REMOTE_ELT]] to i8* // CHECK: store i8* [[REMOTE_ELT_VOID]], i8** [[REMOTE_ELT_REF]], align // @@ -169,8 +169,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -193,10 +193,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* - // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // CHECK: store double [[ELT_VAL]], double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -216,10 +216,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to double addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load double, double addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store double [[MEDIUM_ELT_VAL]], double* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -250,8 +250,8 @@ int bar(int n){ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]] // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8* // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* - // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to double* + // CHECK: [[ELT_VAL:%.+]] = load double, double* [[ELT]], align // CHECK: store double [[ELT_VAL]], double* [[SCRATCHPAD_ELT_PTR]], align // // CHECK: ret @@ -299,8 +299,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to double* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to double* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load double, double* [[REMOTE_ELT]], align // CHECK: store double [[REMOTE_ELT_VAL]], double* [[ELT]], align // CHECK: br label {{%?}}[[REDUCE_CONT]] // @@ -412,15 +412,15 @@ int bar(int n){ // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* - // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // - // CHECK: [[ELT_CAST:%.+]] = bitcast float [[ELT_VAL]] to i32 + // CHECK: [[ELT_CAST:%.+]] = bitcast float* [[ELT]] to i32* + // CHECK: [[REMOTE_ELT2_CAST:%.+]] = bitcast float* [[REMOTE_ELT2]] to i32* + // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT_CAST]], align // CHECK: [[WS32:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() // CHECK: [[WS:%.+]] = trunc i32 [[WS32]] to i16 - // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_CAST]], i16 [[LANEOFFSET]], i16 [[WS]]) - // CHECK: [[REMOTE_ELT2_VAL:%.+]] = bitcast i32 [[REMOTE_ELT2_VAL32]] to float + // CHECK: [[REMOTE_ELT2_VAL32:%.+]] = call i32 @__kmpc_shuffle_int32(i32 [[ELT_VAL]], i16 [[LANEOFFSET]], i16 [[WS]]) // - // CHECK: store float [[REMOTE_ELT2_VAL]], float* [[REMOTE_ELT2]], align + // CHECK: store i32 [[REMOTE_ELT2_VAL32]], i32* [[REMOTE_ELT2_CAST]], align // CHECK: [[REMOTE_ELT2C:%.+]] = bitcast float* [[REMOTE_ELT2]] to i8* // CHECK: store i8* [[REMOTE_ELT2C]], i8** [[REMOTE_ELT_REF]], align // @@ -471,8 +471,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -494,10 +494,10 @@ int bar(int n){ // [[DO_COPY]] // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], - // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i8, i8* [[ELT_VOID]], align // CHECK: store i8 [[ELT_VAL]], i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -517,9 +517,9 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i8 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i8, i8 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i8 [[MEDIUM_ELT_VAL]], i8* [[ELT_VOID]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -535,10 +535,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* - // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // CHECK: store float [[ELT_VAL]], float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -558,10 +558,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to float addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load float, float addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store float [[MEDIUM_ELT_VAL]], float* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -608,8 +608,8 @@ int bar(int n){ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]] // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8* // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* - // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to float* + // CHECK: [[ELT_VAL:%.+]] = load float, float* [[ELT]], align // CHECK: store float [[ELT_VAL]], float* [[SCRATCHPAD_ELT_PTR]], align // // CHECK: ret @@ -681,8 +681,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to float* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to float* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load float, float* [[REMOTE_ELT]], align // CHECK: store float [[REMOTE_ELT_VAL]], float* [[ELT]], align // CHECK: br label {{%?}}[[REDUCE_CONT]] // @@ -885,8 +885,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align // // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 @@ -894,8 +894,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -918,10 +918,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* - // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // CHECK: store i32 [[ELT_VAL]], i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -941,10 +941,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i32 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i32, i32 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i32 [[MEDIUM_ELT_VAL]], i32* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -960,10 +960,10 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* - // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[WARPID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])* + // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // CHECK: store i16 [[ELT_VAL]], i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: br label {{%?}}[[COPY_CONT:.+]] // @@ -983,10 +983,10 @@ int bar(int n){ // CHECK: [[DO_READ]] // CHECK: [[MEDIUM_ELT64:%.+]] = getelementptr inbounds [32 x i64], [32 x i64] addrspace([[SHARED_ADDRSPACE]])* [[TRANSFER_STORAGE]], i64 0, i32 [[TID]] // CHECK: [[MEDIUM_ELT:%.+]] = bitcast i64 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT64]] to i16 addrspace([[SHARED_ADDRSPACE]])* - // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* + // CHECK: [[MEDIUM_ELT_VAL:%.+]] = load i16, i16 addrspace([[SHARED_ADDRSPACE]])* [[MEDIUM_ELT]], align // CHECK: store i16 [[MEDIUM_ELT_VAL]], i16* [[ELT]], align // CHECK: br label {{%?}}[[READ_CONT:.+]] // @@ -1017,8 +1017,8 @@ int bar(int n){ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD]], [[P]] // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8* // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* - // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i32* + // CHECK: [[ELT_VAL:%.+]] = load i32, i32* [[ELT]], align // CHECK: store i32 [[ELT_VAL]], i32* [[SCRATCHPAD_ELT_PTR]], align // // CHECK: [[OF:%.+]] = mul nuw i[[SZ]] [[NUM_TEAMS]], 4 @@ -1035,8 +1035,8 @@ int bar(int n){ // CHECK: [[SCRATCHPAD_ELT_PTR64:%.+]] = add nuw i[[SZ]] [[SCRATCHPAD_NEXT]], [[P]] // CHECK: [[SCRATCHPAD_ELT_PTR_VOID:%.+]] = inttoptr i[[SZ]] [[SCRATCHPAD_ELT_PTR64]] to i8* // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* - // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // CHECK: [[SCRATCHPAD_ELT_PTR:%.+]] = bitcast i8* [[SCRATCHPAD_ELT_PTR_VOID]] to i16* + // CHECK: [[ELT_VAL:%.+]] = load i16, i16* [[ELT]], align // CHECK: store i16 [[ELT_VAL]], i16* [[SCRATCHPAD_ELT_PTR]], align // // CHECK: ret @@ -1103,8 +1103,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 0 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i32* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i32* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i32, i32* [[REMOTE_ELT]], align // CHECK: store i32 [[REMOTE_ELT_VAL]], i32* [[ELT]], align // // CHECK: [[REMOTE_ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[REMOTE_RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1 @@ -1112,8 +1112,8 @@ int bar(int n){ // CHECK: [[ELT_REF:%.+]] = getelementptr inbounds [[RLT]], [[RLT]]* [[RED_LIST:%.+]], i[[SZ]] 0, i[[SZ]] 1 // CHECK: [[ELT_VOID:%.+]] = load i8*, i8** [[ELT_REF]], // CHECK: [[REMOTE_ELT:%.+]] = bitcast i8* [[REMOTE_ELT_VOID]] to i16* - // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: [[ELT:%.+]] = bitcast i8* [[ELT_VOID]] to i16* + // CHECK: [[REMOTE_ELT_VAL:%.+]] = load i16, i16* [[REMOTE_ELT]], align // CHECK: store i16 [[REMOTE_ELT_VAL]], i16* [[ELT]], align // CHECK: br label {{%?}}[[REDUCE_CONT]] // -- GitLab From b7643123e19d18a5e0166d7ba25b27a1f1a8cbd0 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 22 Jun 2018 19:44:48 +0000 Subject: [PATCH 0240/1023] Fix BUILD_SHARED_LIBS=1 build of libclangHandleLLVM Differential Revision: https://reviews.llvm.org/D48503 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335380 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/handle-llvm/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt index 87314b00f4..905d814f1a 100644 --- a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt +++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt @@ -1,4 +1,10 @@ -set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support) +set(LLVM_LINK_COMPONENTS + Core + IRReader + MC + Support + Analysis +) add_clang_library(clangHandleLLVM handle_llvm.cpp -- GitLab From 257046ff24322a46dd7b74649f16d559fadf4a29 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 22 Jun 2018 19:50:19 +0000 Subject: [PATCH 0241/1023] Restore pre-r335182 behavior for naming inherited constructors as members of dependent contexts. This permits cases where the names before and after the '::' in a dependent inherited constructor using-declaration do not match, but where we can nonetheless tell when parsing the template that a constructor is being named. Under (open) core language DR 2070, such cases will probably be ill-formed, but r335182 does not quite give that result and didn't intend to change this, so restore the old behavior for now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335381 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++- lib/Parse/ParseExprCXX.cpp | 6 ++++-- lib/Sema/SemaExprCXX.cpp | 11 ++++++++++- .../basic.lookup.qual/class.qual/p2.cpp | 15 +++++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5d2f4f0811..5780cc01d7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4985,7 +4985,8 @@ public: IdentifierInfo &Name); ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS); + Scope *S, CXXScopeSpec &SS, + bool EnteringContext); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec &SS, diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 26b8a0f779..12aee8cff3 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2505,7 +2505,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. - ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS); + ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS, + EnteringContext); if (!Ty) return true; Result.setConstructorName(Ty, IdLoc, IdLoc); @@ -2555,7 +2556,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, << FixItHint::CreateRemoval( SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); ParsedType Ty = Actions.getConstructorName( - *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS); + *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS, + EnteringContext); if (!Ty) return true; Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d977ea3453..59066ee34f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -82,11 +82,20 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, ParsedType Sema::getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS) { + Scope *S, CXXScopeSpec &SS, + bool EnteringContext) { CXXRecordDecl *CurClass = getCurrentClass(S, &SS); assert(CurClass && &II == CurClass->getIdentifier() && "not a constructor name"); + // When naming a constructor as a member of a dependent context (eg, in a + // friend declaration or an inherited constructor declaration), form an + // unresolved "typename" type. + if (CurClass->isDependentContext() && !EnteringContext) { + QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II); + return ParsedType::make(T); + } + if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass)) return ParsedType(); diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp index cf58a85d84..73e0369e60 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -199,5 +199,20 @@ namespace InhCtor { using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} }; UsingIntTemplate uit; // expected-note {{here}} + + // This case is odd: we don't name the constructor of a dependent base as + // Base::Base, but we still happen to have enough information to identify + // when parsing the template that we're inheriting constructors. + // + // FIXME: Once CWG 2070 is resolved, check whether this case should be + // accepted or not. + namespace DependentCtorName { + template struct B { B(int); }; + template struct A : B { + using X = B; + using X::B; + }; + A ab = 0; + } #endif } -- GitLab From e1ac5637a3d5f62f7ac569665a5b758ebca0ab99 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 22 Jun 2018 20:03:32 +0000 Subject: [PATCH 0242/1023] Reinstate quotes around the path to python that I accidentaly removed in r335330 This broke users with spaces in the path, like C:\Program Files\Python git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335382 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/lit.cfg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 5b11691f44..ad30988c17 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -70,7 +70,7 @@ if config.clang_examples: llvm_config.add_tool_substitutions(tools, tool_dirs) config.substitutions.append( - ('%hmaptool', '%s %s' % (config.python_executable, + ('%hmaptool', "'%s' %s" % (config.python_executable, os.path.join(config.llvm_tools_dir, 'hmaptool')))) # Plugins (loadable modules) -- GitLab From 8246e4314763066223547505fe18a288f639a475 Mon Sep 17 00:00:00 2001 From: Tobias Edler von Koch Date: Fri, 22 Jun 2018 20:23:21 +0000 Subject: [PATCH 0243/1023] Re-land "[LTO] Enable module summary emission by default for regular LTO" Since we are now producing a summary also for regular LTO builds, we need to run the NameAnonGlobals pass in those cases as well (the summary cannot handle anonymous globals). See https://reviews.llvm.org/D34156 for details on the original change. This reverts commit 6c9ee4a4a438a8059aacc809b2dd57128fccd6b3. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335385 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/CodeGenOptions.def | 2 +- lib/CodeGen/BackendUtil.cpp | 43 ++++++++++++++++------- lib/CodeGen/CGDebugInfo.cpp | 2 +- lib/Frontend/CompilerInvocation.cpp | 4 +-- test/CodeGen/emit-summary-index.c | 17 +++++++++ test/CodeGen/lto-newpm-pipeline.c | 1 + test/Misc/thinlto.c | 4 --- 7 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 test/CodeGen/emit-summary-index.c delete mode 100644 test/Misc/thinlto.c diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 019425d194..99567e04ba 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -110,7 +110,7 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. -CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the +CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 4125d507a1..2a02b838d2 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -524,7 +524,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.Inliner = createFunctionInliningPass( CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize, (!CodeGenOpts.SampleProfileFile.empty() && - CodeGenOpts.EmitSummaryIndex)); + CodeGenOpts.PrepareForThinLTO)); } PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel; @@ -534,7 +534,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; - PMBuilder.PrepareForThinLTO = CodeGenOpts.EmitSummaryIndex; + PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO; PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; @@ -776,7 +776,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -784,10 +784,20 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, } PerModulePasses.add(createWriteThinLTOBitcodePass( *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); - } - else + } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + PerModulePasses.add( - createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists)); + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, + EmitLTOSummary)); + } break; case Backend_EmitLL: @@ -935,7 +945,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( ModulePassManager MPM(CodeGenOpts.DebugPassManager); if (!CodeGenOpts.DisableLLVMPasses) { - bool IsThinLTO = CodeGenOpts.EmitSummaryIndex; + bool IsThinLTO = CodeGenOpts.PrepareForThinLTO; bool IsLTO = CodeGenOpts.PrepareForLTO; if (CodeGenOpts.OptimizationLevel == 0) { @@ -950,8 +960,8 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass())); - // Lastly, add a semantically necessary pass for ThinLTO. - if (IsThinLTO) + // Lastly, add a semantically necessary pass for LTO. + if (IsLTO || IsThinLTO) MPM.addPass(NameAnonGlobalPass()); } else { // Map our optimization levels into one of the distinct levels used to @@ -977,6 +987,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( } else if (IsLTO) { MPM = PB.buildLTOPreLinkDefaultPipeline(Level, CodeGenOpts.DebugPassManager); + MPM.addPass(NameAnonGlobalPass()); } else { MPM = PB.buildPerModuleDefaultPipeline(Level, CodeGenOpts.DebugPassManager); @@ -996,7 +1007,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( break; case Backend_EmitBC: - if (CodeGenOpts.EmitSummaryIndex) { + if (CodeGenOpts.PrepareForThinLTO) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile); if (!ThinLinkOS) @@ -1005,9 +1016,17 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); } else { + // Emit a module summary by default for Regular LTO except for ld64 + // targets + bool EmitLTOSummary = + (CodeGenOpts.PrepareForLTO && + llvm::Triple(TheModule->getTargetTriple()).getVendor() != + llvm::Triple::Apple); + if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO")) + TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, - CodeGenOpts.EmitSummaryIndex, - CodeGenOpts.EmitSummaryIndex)); + EmitLTOSummary)); } break; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3ca6459a6a..a0d5fd6236 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -578,7 +578,7 @@ void CGDebugInfo::CreateCompileUnit() { CSInfo, getSource(SM, SM.getMainFileID())), CGOpts.EmitVersionIdentMetadata ? Producer : "", - LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex, + LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind, 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1f9d6b0d7f..60ed5fdf70 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -749,11 +749,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - Opts.EmitSummaryIndex = false; + Opts.PrepareForThinLTO = false; if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { StringRef S = A->getValue(); if (S == "thin") - Opts.EmitSummaryIndex = true; + Opts.PrepareForThinLTO = true; else if (S != "full") Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; } diff --git a/test/CodeGen/emit-summary-index.c b/test/CodeGen/emit-summary-index.c new file mode 100644 index 0000000000..6126410206 --- /dev/null +++ b/test/CodeGen/emit-summary-index.c @@ -0,0 +1,17 @@ +// ; Check that the -flto=thin option emits a ThinLTO summary +// RUN: %clang_cc1 -flto=thin -emit-llvm-bc < %s | llvm-bcanalyzer -dump | FileCheck %s +// CHECK: Date: Fri, 22 Jun 2018 21:54:40 +0000 Subject: [PATCH 0244/1023] [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %zu/%zi on Darwin Summary: Pick D42933 back up, and make NSInteger/NSUInteger with %zu/%zi specifiers on Darwin warn only in pedantic mode. The default -Wformat recently started warning for the following code because of the added support for analysis for the '%zi' specifier. NSInteger i = NSIntegerMax; NSLog(@"max NSInteger = %zi", i); The problem is that on armv7 %zi is 'long', and NSInteger is typedefed to 'int' in Foundation. We should avoid this warning as it's inconvenient to our users: it's target specific (happens only on armv7 and not arm64), and breaks their existing code. We should also silence the warning for the '%zu' specifier to ensure consistency. This is acceptable because Darwin guarantees that, despite the unfortunate choice of typedef, sizeof(size_t) == sizeof(NS[U]Integer), the warning is therefore noisy for pedantic reasons. Once this is in I'll update public documentation. Related discussion on cfe-dev: http://lists.llvm.org/pipermail/cfe-dev/2018-May/058050.html Reviewers: ahatanak, vsapsai, alexshap, aaron.ballman, javed.absar, jfb, rjmccall Subscribers: kristof.beyls, aheejin, cfe-commits Differential Revision: https://reviews.llvm.org/D47290 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335393 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Analysis/Analyses/FormatString.h | 22 +++++-- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++ lib/Analysis/PrintfFormatString.cpp | 4 +- lib/Sema/SemaChecking.cpp | 66 ++++++++++--------- test/FixIt/fixit-format-ios-nopedantic.m | 21 ++++++ test/FixIt/fixit-format-ios.m | 2 +- test/SemaObjC/format-size-spec-nsinteger.m | 30 +++++++++ 7 files changed, 109 insertions(+), 40 deletions(-) create mode 100644 test/FixIt/fixit-format-ios-nopedantic.m create mode 100644 test/SemaObjC/format-size-spec-nsinteger.m diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index a23aaae766..6d76718048 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -256,18 +256,19 @@ public: private: const Kind K; QualType T; - const char *Name; - bool Ptr; + const char *Name = nullptr; + bool Ptr = false, IsSizeT = false; + public: - ArgType(Kind k = UnknownTy, const char *n = nullptr) - : K(k), Name(n), Ptr(false) {} - ArgType(QualType t, const char *n = nullptr) - : K(SpecificTy), T(t), Name(n), Ptr(false) {} - ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {} + ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} + ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {} + ArgType(CanQualType T) : K(SpecificTy), T(T) {} static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } + bool isSizeT() const { return IsSizeT; } + /// Create an ArgType which corresponds to the type pointer to A. static ArgType PtrTo(const ArgType& A) { assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); @@ -276,6 +277,13 @@ public: return Res; } + /// Create an ArgType which corresponds to the size_t/ssize_t type. + static ArgType makeSizeT(const ArgType &A) { + ArgType Res = A; + Res.IsSizeT = true; + return Res; + } + MatchKind matchesType(ASTContext &C, QualType argTy) const; QualType getRepresentativeType(ASTContext &C) const; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b7ede8518e..f08cd00c62 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7719,6 +7719,10 @@ def warn_format_argument_needs_cast : Warning< "%select{values of type|enum values with underlying type}2 '%0' should not " "be used as format arguments; add an explicit cast to %1 instead">, InGroup; +def warn_format_argument_needs_cast_pedantic : Warning< + "%select{values of type|enum values with underlying type}2 '%0' should not " + "be used as format arguments; add an explicit cast to %1 instead">, + InGroup, DefaultIgnore; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, InGroup; diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 3b64508b5a..93d64f03ea 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -466,7 +466,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType(Ctx.getIntMaxType(), "intmax_t"); case LengthModifier::AsSizeT: - return ArgType(Ctx.getSignedSizeType(), "ssize_t"); + return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() ? ArgType(Ctx.LongLongTy, "__int64") @@ -499,7 +499,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, case LengthModifier::AsIntMax: return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); case LengthModifier::AsSizeT: - return ArgType(Ctx.getSizeType(), "size_t"); + return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 53be0f6d9f..12a599b4f1 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6805,11 +6805,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ExprTy = TET->getUnderlyingExpr()->getType(); } - analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy); - - if (match == analyze_printf::ArgType::Match) { + const analyze_printf::ArgType::MatchKind Match = + AT.matchesType(S.Context, ExprTy); + bool Pedantic = Match == analyze_printf::ArgType::NoMatchPedantic; + if (Match == analyze_printf::ArgType::Match) return true; - } // Look through argument promotions for our error message's reported type. // This includes the integral and floating promotions, but excludes array @@ -6885,6 +6885,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, QualType CastTy; std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { + // %zi/%zu are OK to use for NSInteger/NSUInteger of type int + // (long in ASTContext). Only complain to pedants. + if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && + AT.isSizeT() && AT.matchesType(S.Context, CastTy)) + Pedantic = true; IntendedTy = CastTy; ShouldNotPrintDirectly = true; } @@ -6892,10 +6897,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // We may be able to offer a FixItHint if it is a supported type. PrintfSpecifier fixedFS = FS; - bool success = + bool Success = fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext()); - if (success) { + if (Success) { // Get the fix string from the fixed format specifier SmallString<16> buf; llvm::raw_svector_ostream os(buf); @@ -6904,13 +6909,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen); if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) { - unsigned diag = diag::warn_format_conversion_argument_type_mismatch; - if (match == analyze_format_string::ArgType::NoMatchPedantic) { - diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; - } + unsigned Diag = + Pedantic + ? diag::warn_format_conversion_argument_type_mismatch_pedantic + : diag::warn_format_conversion_argument_type_mismatch; // In this case, the specifier is wrong and should be changed to match // the argument. - EmitFormatDiagnostic(S.PDiag(diag) + EmitFormatDiagnostic(S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum << E->getSourceRange(), E->getLocStart(), @@ -6963,9 +6968,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, Name = TypedefTy->getDecl()->getName(); else Name = CastTyName; - EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast) - << Name << IntendedTy << IsEnum - << E->getSourceRange(), + unsigned Diag = Pedantic + ? diag::warn_format_argument_needs_cast_pedantic + : diag::warn_format_argument_needs_cast; + EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum + << E->getSourceRange(), E->getLocStart(), /*IsStringLocation=*/false, SpecRange, Hints); } else { @@ -6989,13 +6996,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, switch (S.isValidVarArgType(ExprTy)) { case Sema::VAK_Valid: case Sema::VAK_ValidInCXX11: { - unsigned diag = diag::warn_format_conversion_argument_type_mismatch; - if (match == analyze_printf::ArgType::NoMatchPedantic) { - diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; - } + unsigned Diag = + Pedantic + ? diag::warn_format_conversion_argument_type_mismatch_pedantic + : diag::warn_format_conversion_argument_type_mismatch; EmitFormatDiagnostic( - S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy + S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum << CSR << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/ false, CSR); break; @@ -7178,29 +7185,28 @@ bool CheckScanfHandler::HandleScanfSpecifier( return true; } - analyze_format_string::ArgType::MatchKind match = + analyze_format_string::ArgType::MatchKind Match = AT.matchesType(S.Context, Ex->getType()); - if (match == analyze_format_string::ArgType::Match) { + bool Pedantic = Match == analyze_format_string::ArgType::NoMatchPedantic; + if (Match == analyze_format_string::ArgType::Match) return true; - } ScanfSpecifier fixedFS = FS; - bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(), + bool Success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(), S.getLangOpts(), S.Context); - unsigned diag = diag::warn_format_conversion_argument_type_mismatch; - if (match == analyze_format_string::ArgType::NoMatchPedantic) { - diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; - } + unsigned Diag = + Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic + : diag::warn_format_conversion_argument_type_mismatch; - if (success) { + if (Success) { // Get the fix string from the fixed format specifier. SmallString<128> buf; llvm::raw_svector_ostream os(buf); fixedFS.toString(os); EmitFormatDiagnostic( - S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) + S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), /*IsStringLocation*/ false, @@ -7208,7 +7214,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( FixItHint::CreateReplacement( getSpecifierRange(startSpecifier, specifierLen), os.str())); } else { - EmitFormatDiagnostic(S.PDiag(diag) + EmitFormatDiagnostic(S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), diff --git a/test/FixIt/fixit-format-ios-nopedantic.m b/test/FixIt/fixit-format-ios-nopedantic.m new file mode 100644 index 0000000000..0b332376c0 --- /dev/null +++ b/test/FixIt/fixit-format-ios-nopedantic.m @@ -0,0 +1,21 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat -Werror -fixit %t + +int printf(const char *restrict, ...); +typedef unsigned int NSUInteger; +typedef int NSInteger; +NSUInteger getNSUInteger(); +NSInteger getNSInteger(); + +void test() { + // For thumbv7-apple-ios8.0.0 the underlying type of ssize_t is long + // and the underlying type of size_t is unsigned long. + + printf("test 1: %zu", getNSUInteger()); + + printf("test 2: %zu %zu", getNSUInteger(), getNSUInteger()); + + printf("test 3: %zd", getNSInteger()); + + printf("test 4: %zd %zd", getNSInteger(), getNSInteger()); +} diff --git a/test/FixIt/fixit-format-ios.m b/test/FixIt/fixit-format-ios.m index ef66430778..9c3670d0c8 100644 --- a/test/FixIt/fixit-format-ios.m +++ b/test/FixIt/fixit-format-ios.m @@ -1,5 +1,5 @@ // RUN: cp %s %t -// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat -fixit %t +// RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -fsyntax-only -Wformat-pedantic -fixit %t // RUN: grep -v CHECK %t | FileCheck %s int printf(const char * restrict, ...); diff --git a/test/SemaObjC/format-size-spec-nsinteger.m b/test/SemaObjC/format-size-spec-nsinteger.m new file mode 100644 index 0000000000..9eb954ec51 --- /dev/null +++ b/test/SemaObjC/format-size-spec-nsinteger.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat %s +// RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat-pedantic -DPEDANTIC %s + +#if !defined(PEDANTIC) +// expected-no-diagnostics +#endif + +#if __LP64__ +typedef unsigned long NSUInteger; +typedef long NSInteger; +#else +typedef unsigned int NSUInteger; +typedef int NSInteger; +#endif + +@class NSString; + +extern void NSLog(NSString *format, ...); + +void testSizeSpecifier() { + NSInteger i = 0; + NSUInteger j = 0; + NSLog(@"max NSInteger = %zi", i); + NSLog(@"max NSUinteger = %zu", j); + +#if defined(PEDANTIC) + // expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} + // expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} +#endif +} -- GitLab From c455528947fce048a46f05abf3be9093d8edd22d Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Sat, 23 Jun 2018 03:15:07 +0000 Subject: [PATCH 0245/1023] [Fuchsia] Enable static libc++, libc++abi, libunwind This is needed for building Fuchsia drivers. Differential Revision: https://reviews.llvm.org/D48208 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335410 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 3 --- lib/Driver/ToolChains/Fuchsia.cpp | 9 ++++++++- test/Driver/fuchsia.cpp | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 0a5ea37cfd..39af3ecb0c 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -77,12 +77,9 @@ foreach(target x86_64;aarch64) set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ${FUCHSIA_RUNTIMES_ENABLE_ASSERTIONS} CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBUNWIND_ENABLE_STATIC OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXXABI_ENABLE_STATIC OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia-asan_LLVM_USE_SANITIZER Address CACHE STRING "") diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index c54cf60ef8..bea59b1ac3 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -115,8 +115,15 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Bdynamic"); if (D.CCCIsCXX()) { - if (ToolChain.ShouldLinkCXXStdlib(Args)) + if (ToolChain.ShouldLinkCXXStdlib(Args)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + } CmdArgs.push_back("-lm"); } diff --git a/test/Driver/fuchsia.cpp b/test/Driver/fuchsia.cpp index 8989071cec..5b33532d75 100644 --- a/test/Driver/fuchsia.cpp +++ b/test/Driver/fuchsia.cpp @@ -27,8 +27,8 @@ // RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-STATIC -// CHECK-STATIC-NOT: "-Bstatic" +// CHECK-STATIC: "-Bstatic" // CHECK-STATIC: "-lc++" -// CHECK-STATIC-NOT: "-Bdynamic" +// CHECK-STATIC: "-Bdynamic" // CHECK-STATIC: "-lm" // CHECK-STATIC: "-lc" -- GitLab From fb922a1cfabbd444e12532d7aa738abbf3b45d9d Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Sat, 23 Jun 2018 17:32:51 +0000 Subject: [PATCH 0246/1023] Attempt to fix latent tablegen dependency issue git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335419 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/handle-llvm/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt index 905d814f1a..27640a0bf5 100644 --- a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt +++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt @@ -4,8 +4,17 @@ set(LLVM_LINK_COMPONENTS MC Support Analysis -) + ) + +# Depend on LLVM IR intrinsic generation. +set(handle_llvm_deps intrinsics_gen) +if (CLANG_BUILT_STANDALONE) + set(handle_llvm_deps) +endif() add_clang_library(clangHandleLLVM handle_llvm.cpp + + DEPENDS + ${handle_llvm_deps} ) -- GitLab From 86ed6a42485ff5406cc0f3442baa8674f495ca89 Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Sat, 23 Jun 2018 18:01:02 +0000 Subject: [PATCH 0247/1023] [Sema] isValidCoroutineContext FIXME and citations Summary: Add citations to the Coroutines TS to the `isValidCoroutineContext` function, as well as a FIXME and test for [expr.await]p2, which states a co_await expression cannot be used in a default argument. Test Plan: check-clang Reviewers: GorNishanov, EricWF Reviewed By: GorNishanov Subscribers: rsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D48519 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335420 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCoroutine.cpp | 34 ++++++++++++++++++++++++++++++++-- test/SemaCXX/coroutines.cpp | 8 ++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index c58172cabf..658bdcbafc 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -9,6 +9,9 @@ // // This file implements semantic analysis for C++ Coroutines. // +// This file contains references to sections of the Coroutines TS, which +// can be found at http://wg21.link/coroutines. +// //===----------------------------------------------------------------------===// #include "CoroutineStmtBuilder.h" @@ -196,13 +199,25 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) { - // 'co_await' and 'co_yield' are not permitted in unevaluated operands. + // 'co_await' and 'co_yield' are not permitted in unevaluated operands, + // such as subexpressions of \c sizeof. + // + // [expr.await]p2, emphasis added: "An await-expression shall appear only in + // a *potentially evaluated* expression within the compound-statement of a + // function-body outside of a handler [...] A context within a function where + // an await-expression can appear is called a suspension context of the + // function." And per [expr.yield]p1: "A yield-expression shall appear only + // within a suspension context of a function." if (S.isUnevaluatedContext()) { S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword; return false; } - // Any other usage must be within a function. + // Per [expr.await]p2, any other usage must be within a function. + // FIXME: This also covers [expr.await]p2: "An await-expression shall not + // appear in a default argument." But the diagnostic QoI here could be + // improved to inform the user that default arguments specifically are not + // allowed. auto *FD = dyn_cast(S.CurContext); if (!FD) { S.Diag(Loc, isa(S.CurContext) @@ -233,22 +248,37 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, // Diagnose when a constructor, destructor, copy/move assignment operator, // or the function 'main' are declared as a coroutine. auto *MD = dyn_cast(FD); + // [class.ctor]p6: "A constructor shall not be a coroutine." if (MD && isa(MD)) return DiagInvalid(DiagCtor); + // [class.dtor]p17: "A destructor shall not be a coroutine." else if (MD && isa(MD)) return DiagInvalid(DiagDtor); + // N4499 [special]p6: "A special member function shall not be a coroutine." + // Per C++ [special]p1, special member functions are the "default constructor, + // copy constructor and copy assignment operator, move constructor and move + // assignment operator, and destructor." else if (MD && MD->isCopyAssignmentOperator()) return DiagInvalid(DiagCopyAssign); else if (MD && MD->isMoveAssignmentOperator()) return DiagInvalid(DiagMoveAssign); + // [basic.start.main]p3: "The function main shall not be a coroutine." else if (FD->isMain()) return DiagInvalid(DiagMain); // Emit a diagnostics for each of the following conditions which is not met. + // [expr.const]p2: "An expression e is a core constant expression unless the + // evaluation of e [...] would evaluate one of the following expressions: + // [...] an await-expression [...] a yield-expression." if (FD->isConstexpr()) DiagInvalid(DiagConstexpr); + // [dcl.spec.auto]p15: "A function declared with a return type that uses a + // placeholder type shall not be a coroutine." if (FD->getReturnType()->isUndeducedType()) DiagInvalid(DiagAutoRet); + // [dcl.fct.def.coroutine]p1: "The parameter-declaration-clause of the + // coroutine shall not terminate with an ellipsis that is not part of a + // parameter-declaration." if (FD->isVariadic()) DiagInvalid(DiagVarargs); diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index b5f67045fa..d58cedf414 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -1,3 +1,6 @@ +// This file contains references to sections of the Coroutines TS, which can be +// found at http://wg21.link/coroutines. + // RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result void no_coroutine_traits_bad_arg_await() { @@ -320,6 +323,11 @@ void unevaluated() { typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}} } +// [expr.await]p2: "An await-expression shall not appear in a default argument." +// FIXME: A better diagnostic would explicitly state that default arguments are +// not allowed. A user may not understand that this is "outside a function." +void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}} + constexpr auto constexpr_deduced_return_coroutine() { co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}} // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}} -- GitLab From d80dd82cc4a40b1855f4847800688dc59680db0d Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Sat, 23 Jun 2018 18:57:26 +0000 Subject: [PATCH 0248/1023] [Coroutines] Less IR for noexcept await_resume Summary: In his review of https://reviews.llvm.org/D45860, @GorNishanov suggested avoiding generating additional exception-handling IR in the case that the resume function was marked as 'noexcept', and exceptions could not occur. This implements that suggestion. Test Plan: `check-clang` Reviewers: GorNishanov, EricWF Reviewed By: GorNishanov Subscribers: cfe-commits, GorNishanov Differential Revision: https://reviews.llvm.org/D47673 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335422 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCoroutine.cpp | 39 +++++++++++++++---- .../coro-await-resume-eh.cpp | 39 ++++++++++++++++--- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp index bd1689688f..4f525c8aac 100644 --- a/lib/CodeGen/CGCoroutine.cpp +++ b/lib/CodeGen/CGCoroutine.cpp @@ -130,6 +130,16 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { return Prefix; } +static bool memberCallExpressionCanThrow(const Expr *E) { + if (const auto *CE = dyn_cast(E)) + if (const auto *Proto = + CE->getMethodDecl()->getType()->getAs()) + if (isNoexceptExceptionSpec(Proto->getExceptionSpecType()) && + Proto->canThrow() == CT_Cannot) + return false; + return true; +} + // Emit suspend expression which roughly looks like: // // auto && x = CommonExpr(); @@ -217,8 +227,12 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co // Emit await_resume expression. CGF.EmitBlock(ReadyBlock); + + // Exception handling requires additional IR. If the 'await_resume' function + // is marked as 'noexcept', we avoid generating this additional IR. CXXTryStmt *TryStmt = nullptr; - if (Coro.ExceptionHandler && Kind == AwaitKind::Init) { + if (Coro.ExceptionHandler && Kind == AwaitKind::Init && + memberCallExpressionCanThrow(S.getResumeExpr())) { Coro.ResumeEHVar = CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); Builder.CreateFlagStore(true, Coro.ResumeEHVar); @@ -625,12 +639,20 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; if (CurCoro.Data->ExceptionHandler) { - BasicBlock *BodyBB = createBasicBlock("coro.resumed.body"); - BasicBlock *ContBB = createBasicBlock("coro.resumed.cont"); - Value *SkipBody = - Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar, "coro.resumed.eh"); - Builder.CreateCondBr(SkipBody, ContBB, BodyBB); - EmitBlock(BodyBB); + // If we generated IR to record whether an exception was thrown from + // 'await_resume', then use that IR to determine whether the coroutine + // body should be skipped. + // If we didn't generate the IR (perhaps because 'await_resume' was marked + // as 'noexcept'), then we skip this check. + BasicBlock *ContBB = nullptr; + if (CurCoro.Data->ResumeEHVar) { + BasicBlock *BodyBB = createBasicBlock("coro.resumed.body"); + ContBB = createBasicBlock("coro.resumed.cont"); + Value *SkipBody = Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar, + "coro.resumed.eh"); + Builder.CreateCondBr(SkipBody, ContBB, BodyBB); + EmitBlock(BodyBB); + } auto Loc = S.getLocStart(); CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, @@ -642,7 +664,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock()); ExitCXXTryStmt(*TryStmt); - EmitBlock(ContBB); + if (ContBB) + EmitBlock(ContBB); } else { emitBodyAndFallthrough(*this, S, S.getBody()); diff --git a/test/CodeGenCoroutines/coro-await-resume-eh.cpp b/test/CodeGenCoroutines/coro-await-resume-eh.cpp index 96a3a74a2d..f0f8855fbd 100644 --- a/test/CodeGenCoroutines/coro-await-resume-eh.cpp +++ b/test/CodeGenCoroutines/coro-await-resume-eh.cpp @@ -18,9 +18,9 @@ struct throwing_awaitable { void await_resume() { throw 42; } }; -struct task { +struct throwing_task { struct promise_type { - task get_return_object() { return task{}; } + auto get_return_object() { return throwing_task{}; } auto initial_suspend() { return throwing_awaitable{}; } auto final_suspend() { return coro::suspend_never{}; } void return_void() {} @@ -29,7 +29,7 @@ struct task { }; // CHECK-LABEL: define void @_Z1fv() -task f() { +throwing_task f() { // A variable RESUMETHREW is used to keep track of whether the body // of 'await_resume' threw an exception. Exceptions thrown in // 'await_resume' are unwound to RESUMELPAD. @@ -50,7 +50,7 @@ task f() { // CHECK: [[RESUMELPAD]]: // CHECK: br label %[[RESUMECATCH:.+]] // CHECK: [[RESUMECATCH]]: - // CHECK: invoke void @_ZN4task12promise_type19unhandled_exceptionEv + // CHECK: invoke void @_ZN13throwing_task12promise_type19unhandled_exceptionEv // CHECK-NEXT: to label %[[RESUMEENDCATCH:.+]] unwind label // CHECK: [[RESUMEENDCATCH]]: // CHECK-NEXT: invoke void @__cxa_end_catch() @@ -67,7 +67,7 @@ task f() { // CHECK-NEXT: br i1 %[[RESUMETHREWLOAD]], label %[[RESUMEDCONT:.+]], label %[[RESUMEDBODY:.+]] // CHECK: [[RESUMEDBODY]]: - // CHECK: invoke void @_ZN4task12promise_type11return_voidEv + // CHECK: invoke void @_ZN13throwing_task12promise_type11return_voidEv // CHECK-NEXT: to label %[[REDUMEDBODYCONT:.+]] unwind label // CHECK: [[REDUMEDBODYCONT]]: // CHECK-NEXT: br label %[[COROFINAL:.+]] @@ -76,6 +76,33 @@ task f() { // CHECK-NEXT: br label %[[COROFINAL]] // CHECK: [[COROFINAL]]: - // CHECK-NEXT: invoke void @_ZN4task12promise_type13final_suspendEv + // CHECK-NEXT: invoke void @_ZN13throwing_task12promise_type13final_suspendEv + co_return; +} + +struct noexcept_awaitable { + bool await_ready() { return true; } + void await_suspend(coro::coroutine_handle<>) {} + void await_resume() noexcept {} +}; + +struct noexcept_task { + struct promise_type { + auto get_return_object() { return noexcept_task{}; } + auto initial_suspend() { return noexcept_awaitable{}; } + auto final_suspend() { return coro::suspend_never{}; } + void return_void() {} + void unhandled_exception() {} + }; +}; + +// CHECK-LABEL: define void @_Z1gv() +noexcept_task g() { + // If the await_resume function is marked as noexcept, none of the additional + // conditions that are present in f() above are added to the IR. + // This means that no i1 are stored before or after calling await_resume: + // CHECK: init.ready: + // CHECK-NEXT: call void @_ZN18noexcept_awaitable12await_resumeEv + // CHECK-NOT: store i1 false, i1* co_return; } -- GitLab From 6463d2234a096423550702ad98d95caa02869ef8 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Mon, 25 Jun 2018 05:48:04 +0000 Subject: [PATCH 0249/1023] [CodeGen] Provide source locations for UBSan type checks when emitting constructor calls. Differential Revision: https://reviews.llvm.org/D48531 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335445 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGClass.cpp | 15 ++++++++------- lib/CodeGen/CodeGenFunction.h | 3 ++- test/CodeGenCXX/ubsan-ctor-srcloc.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 test/CodeGenCXX/ubsan-ctor-srcloc.cpp diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index db947d6514..11a327d2d2 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -2031,7 +2031,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, /*ParamsToSkip*/ 0, Order); EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args, - Overlap); + Overlap, E->getExprLoc()); } static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, @@ -2064,14 +2064,14 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, bool Delegating, Address This, CallArgList &Args, - AggValueSlot::Overlap_t Overlap) { + AggValueSlot::Overlap_t Overlap, + SourceLocation Loc) { const CXXRecordDecl *ClassDecl = D->getParent(); // C++11 [class.mfct.non-static]p2: // If a non-static member function of a class X is called for an object that // is not of type X, or of a type derived from X, the behavior is undefined. - // FIXME: Provide a source location here. - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), getContext().getRecordType(ClassDecl)); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2180,7 +2180,8 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( } EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false, - This, Args, AggValueSlot::MayOverlap); + This, Args, AggValueSlot::MayOverlap, + E->getLocation()); } void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall( @@ -2277,7 +2278,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, /*ParamsToSkip*/ 1); EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args, - AggValueSlot::MayOverlap); + AggValueSlot::MayOverlap, E->getExprLoc()); } void @@ -2313,7 +2314,7 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false, /*Delegating=*/true, This, DelegateArgs, - AggValueSlot::MayOverlap); + AggValueSlot::MayOverlap, Loc); } namespace { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d713cb4c6f..afe199c4eb 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2362,7 +2362,8 @@ public: void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, Address This, CallArgList &Args, - AggValueSlot::Overlap_t Overlap); + AggValueSlot::Overlap_t Overlap, + SourceLocation Loc); /// Emit assumption load for all bases. Requires to be be called only on /// most-derived class and not under construction of the object. diff --git a/test/CodeGenCXX/ubsan-ctor-srcloc.cpp b/test/CodeGenCXX/ubsan-ctor-srcloc.cpp new file mode 100644 index 0000000000..da27a668cf --- /dev/null +++ b/test/CodeGenCXX/ubsan-ctor-srcloc.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=alignment -fblocks %s -o %t.ll +// RUN: FileCheck -check-prefix=ZEROINIT < %t.ll %s +// RUN: FileCheck -check-prefix=SRCLOC < %t.ll %s +// ZEROINIT-NOT: @{{.+}} = private unnamed_addr global {{.+}} zeroinitializer + +struct A { + A(int); + int k; +}; + +struct B : A { + B(); + B(const B &); +// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 12 } + using A::A; + void f() const; +}; + +// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 10 } +B::B() : A(1) {} + +void foo() { + B b(2); +// SRCLOC-DAG: @{{.+}} = private unnamed_addr global {{.+}} @.src, i32 [[@LINE+1]], i32 5 } + ^{b.f();}(); +} -- GitLab From 4b2e36517a5228732749a6814bcc99226413303f Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 25 Jun 2018 11:08:24 +0000 Subject: [PATCH 0250/1023] [clang-format] Fix end-of-file comments text proto formatting Summary: The case of end-of-file comments was formatted badly: ``` key: value # end-of-file comment ``` This patch fixes that formatting: ``` key: value # end-of-file comment ``` Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48539 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335449 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/UnwrappedLineParser.cpp | 12 ++++++++++++ unittests/Format/FormatTestTextProto.cpp | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index e1fa72e84b..e5afa1264a 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -303,6 +303,18 @@ void UnwrappedLineParser::parseFile() { else parseLevel(/*HasOpeningBrace=*/false); // Make sure to format the remaining tokens. + // + // LK_TextProto is special since its top-level is parsed as the body of a + // braced list, which does not necessarily have natural line separators such + // as a semicolon. Comments after the last entry that have been determined to + // not belong to that line, as in: + // key: value + // // endfile comment + // do not have a chance to be put on a line of their own until this point. + // Here we add this newline before end-of-file comments. + if (Style.Language == FormatStyle::LK_TextProto && + !CommentsBeforeNextToken.empty()) + addUnwrappedLine(); flushComments(true); addUnwrappedLine(); } diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index 8ef4bf9a40..9c4e1a8520 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -700,5 +700,22 @@ TEST_F(FormatTestTextProto, PreventBreaksBetweenKeyAndSubmessages) { "}"); } +TEST_F(FormatTestTextProto, FormatsCommentsAtEndOfFile) { + verifyFormat("key: value\n" + "# endfile comment"); + verifyFormat("key: value\n" + "// endfile comment"); + verifyFormat("key: value\n" + "// endfile comment 1\n" + "// endfile comment 2"); + verifyFormat("submessage { key: value }\n" + "# endfile comment"); + verifyFormat("submessage <\n" + " key: value\n" + " item {}\n" + ">\n" + "# endfile comment"); +} + } // end namespace tooling } // end namespace clang -- GitLab From 8d628b252961cdf29d758a1c4da43bbe3957cff2 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 25 Jun 2018 11:38:43 +0000 Subject: [PATCH 0251/1023] [ASTImporter] Add new tests about templated-described swing Summary: Add a new test about importing a partial specialization (of a class). Also, this patch adds new tests about the templated-described swing, some of these fail ATM, but subsequent patches will fix them. Reviewers: a.sidorin, r.stahl, xazax.hun Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47534 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335455 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index c81b4b338b..1cdae8066f 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -1095,6 +1095,20 @@ TEST(ImportDecl, ImportTemplatedDeclForTemplate) { unless(has(cxxRecordDecl(hasName("declToImport")))))))); } +TEST(ImportDecl, ImportClassTemplatePartialSpecialization) { + MatchVerifier Verifier; + auto Code = + R"s( + struct declToImport { + template struct X; + template struct X {}; + }; + )s"; + testImport(Code, Lang_CXX, "", Lang_CXX, Verifier, + recordDecl(has(classTemplateDecl()), + has(classTemplateSpecializationDecl()))); +} + TEST(ImportExpr, CXXOperatorCallExpr) { MatchVerifier Verifier; testImport("class declToImport {" @@ -1128,6 +1142,52 @@ TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { EXPECT_EQ(ToTemplated1, ToTemplated); } +TEST_P(ASTImporterTestBase, + DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) { + Decl *FromTU = getTuDecl("template void f(){}", Lang_CXX); + auto From = FirstDeclMatcher().match( + FromTU, functionTemplateDecl()); + ASSERT_TRUE(From); + auto To = cast(Import(From, Lang_CXX)); + ASSERT_TRUE(To); + Decl *ToTemplated = To->getTemplatedDecl(); + Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX); + EXPECT_TRUE(ToTemplated1); + EXPECT_EQ(ToTemplated1, ToTemplated); +} + +TEST_P(ASTImporterTestBase, + ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) { + Decl *FromTU = getTuDecl("template struct S{};", Lang_CXX); + auto FromFT = + FirstDeclMatcher().match(FromTU, classTemplateDecl()); + ASSERT_TRUE(FromFT); + + auto ToTemplated = + cast(Import(FromFT->getTemplatedDecl(), Lang_CXX)); + EXPECT_TRUE(ToTemplated); + auto ToTU = ToTemplated->getTranslationUnitDecl(); + auto ToFT = + FirstDeclMatcher().match(ToTU, classTemplateDecl()); + EXPECT_TRUE(ToFT); +} + +TEST_P(ASTImporterTestBase, + DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) { + Decl *FromTU = getTuDecl("template void f(){}", Lang_CXX); + auto FromFT = FirstDeclMatcher().match( + FromTU, functionTemplateDecl()); + ASSERT_TRUE(FromFT); + + auto ToTemplated = + cast(Import(FromFT->getTemplatedDecl(), Lang_CXX)); + EXPECT_TRUE(ToTemplated); + auto ToTU = ToTemplated->getTranslationUnitDecl(); + auto ToFT = FirstDeclMatcher().match( + ToTU, functionTemplateDecl()); + EXPECT_TRUE(ToFT); +} + TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) { auto Code = R"( -- GitLab From 69593b34c37d3bb5ecc02790118e543522a92b00 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 25 Jun 2018 12:43:12 +0000 Subject: [PATCH 0252/1023] [clang-format] Keep @message together in text protos Summary: In C++ code snippets of the form `@field` are common. This makes clang-format keep them together in text protos, whereas before it would break them. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48543 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335459 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 3 ++- lib/Format/TokenAnnotator.cpp | 21 +++++++++++++++++++-- unittests/Format/FormatTestTextProto.cpp | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 294c58d621..1a5a6deb04 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -379,7 +379,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { if (Current.is(TT_ObjCMethodExpr) && !Previous.is(TT_SelectorName) && State.Line->startsWith(TT_ObjCMethodSpecifier)) return true; - if (Current.is(TT_SelectorName) && State.Stack.back().ObjCSelectorNameFound && + if (Current.is(TT_SelectorName) && !Previous.is(tok::at) && + State.Stack.back().ObjCSelectorNameFound && State.Stack.back().BreakBeforeParameter) return true; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 3280f25fef..68ea02296b 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -2949,15 +2949,32 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // // Be careful to exclude the case [proto.ext] { ... } since the `]` is // the TT_SelectorName there, but we don't want to break inside the brackets. + // + // Another edge case is @submessage { key: value }, which is a common + // substitution placeholder. In this case we want to keep `@` and `submessage` + // together. + // // We ensure elsewhere that extensions are always on their own line. if ((Style.Language == FormatStyle::LK_Proto || Style.Language == FormatStyle::LK_TextProto) && Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) { + // Keep `@submessage` together in: + // @submessage { key: value } + if (Right.Previous && Right.Previous->is(tok::at)) + return false; // Look for the scope opener after selector in cases like: // selector { ... // selector: { ... - FormatToken *LBrace = - Right.Next->is(tok::colon) ? Right.Next->Next : Right.Next; + // selector: @base { ... + FormatToken *LBrace = Right.Next; + if (LBrace && LBrace->is(tok::colon)) { + LBrace = LBrace->Next; + if (LBrace && LBrace->is(tok::at)) { + LBrace = LBrace->Next; + if (LBrace) + LBrace = LBrace->Next; + } + } if (LBrace && // The scope opener is one of {, [, <: // selector { ... } diff --git a/unittests/Format/FormatTestTextProto.cpp b/unittests/Format/FormatTestTextProto.cpp index 9c4e1a8520..0875bd8925 100644 --- a/unittests/Format/FormatTestTextProto.cpp +++ b/unittests/Format/FormatTestTextProto.cpp @@ -717,5 +717,23 @@ TEST_F(FormatTestTextProto, FormatsCommentsAtEndOfFile) { "# endfile comment"); } +TEST_F(FormatTestTextProto, KeepsAmpersandsNextToKeys) { + verifyFormat("@tmpl { field: 1 }"); + verifyFormat("@placeholder: 1"); + verifyFormat("@name <>"); + verifyFormat("submessage: @base { key: value }"); + verifyFormat("submessage: @base {\n" + " key: value\n" + " item: {}\n" + "}"); + verifyFormat("submessage: {\n" + " msg: @base {\n" + " yolo: {}\n" + " key: value\n" + " }\n" + " key: value\n" + "}"); +} + } // end namespace tooling } // end namespace clang -- GitLab From 9bbcb03216cb2f853c4603bf367284992c47a1aa Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 25 Jun 2018 13:04:37 +0000 Subject: [PATCH 0253/1023] [ASTImporter] Add ms compatibility to tests which use the TestBase Summary: In order to avoid build failures on MS, we use -fms-compatibility too in the tests which use the TestBase. Moved the family of `testImport` functions under a test fixture class, so we can use parameterized tests. Refactored `testImport` and `testImportSequence`, because `for` loops over the different compiler options is no longer needed, that is handeld by the test framework via parameters from now on. Reviewers: a.sidorin, r.stahl, xazax.hun Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47367 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335464 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 559 +++++++++++++++--------------- unittests/AST/Language.cpp | 14 - unittests/AST/Language.h | 6 - 3 files changed, 283 insertions(+), 296 deletions(-) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 1cdae8066f..77dbd43a7d 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -50,114 +50,233 @@ static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName, llvm::MemoryBuffer::getMemBuffer(Code)); } -template -NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer, - NodeType Node) { - ASTContext &ToCtx = To->getASTContext(); +const StringRef DeclToImportID = "declToImport"; +const StringRef DeclToVerifyID = "declToVerify"; - // Add 'From' file to virtual file system so importer can 'find' it - // while importing SourceLocations. It is safe to add same file multiple - // times - it just isn't replaced. - StringRef FromFileName = From->getMainFileName(); - createVirtualFileIfNeeded(To, FromFileName, - From->getBufferForFile(FromFileName)); +// Common base for the different families of ASTImporter tests that are +// parameterized on the compiler options which may result a different AST. E.g. +// -fms-compatibility or -fdelayed-template-parsing. +struct ParameterizedTestsFixture : ::testing::TestWithParam { - auto Imported = Importer.Import(Node); + // Returns the argument vector used for a specific language option, this set + // can be tweaked by the test parameters. + ArgVector getArgVectorForLanguage(Language Lang) const { + ArgVector Args = getBasicRunOptionsForLanguage(Lang); + ArgVector ExtraArgs = GetParam(); + for (const auto &Arg : ExtraArgs) { + Args.push_back(Arg); + } + return Args; + } - // This should dump source locations and assert if some source locations - // were not imported. - SmallString<1024> ImportChecker; - llvm::raw_svector_ostream ToNothing(ImportChecker); - ToCtx.getTranslationUnitDecl()->print(ToNothing); +}; - // This traverses the AST to catch certain bugs like poorly or not - // implemented subtrees. - Imported->dump(ToNothing); +// Base class for those tests which use the family of `testImport` functions. +class TestImportBase : public ParameterizedTestsFixture { - return Imported; -} + template + NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer, + NodeType Node) { + ASTContext &ToCtx = To->getASTContext(); -const StringRef DeclToImportID = "declToImport"; -const StringRef DeclToVerifyID = "declToVerify"; + // Add 'From' file to virtual file system so importer can 'find' it + // while importing SourceLocations. It is safe to add same file multiple + // times - it just isn't replaced. + StringRef FromFileName = From->getMainFileName(); + createVirtualFileIfNeeded(To, FromFileName, + From->getBufferForFile(FromFileName)); -template -testing::AssertionResult -testImport(const std::string &FromCode, const ArgVector &FromArgs, - const std::string &ToCode, const ArgVector &ToArgs, - MatchVerifier &Verifier, - const BindableMatcher &SearchMatcher, - const BindableMatcher &VerificationMatcher) { - const char *const InputFileName = "input.cc"; - const char *const OutputFileName = "output.cc"; + auto Imported = Importer.Import(Node); - std::unique_ptr - FromAST = tooling::buildASTFromCodeWithArgs( - FromCode, FromArgs, InputFileName), - ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); - - ASTContext &FromCtx = FromAST->getASTContext(), - &ToCtx = ToAST->getASTContext(); - - FromAST->enableSourceFileDiagnostics(); - ToAST->enableSourceFileDiagnostics(); - - ASTImporter Importer(ToCtx, ToAST->getFileManager(), - FromCtx, FromAST->getFileManager(), false); - - auto FoundNodes = match(SearchMatcher, FromCtx); - if (FoundNodes.size() != 1) - return testing::AssertionFailure() - << "Multiple potential nodes were found!"; - - auto ToImport = selectFirst(DeclToImportID, FoundNodes); - if (!ToImport) - return testing::AssertionFailure() << "Node type mismatch!"; - - // Sanity check: the node being imported should match in the same way as - // the result node. - BindableMatcher WrapperMatcher(VerificationMatcher); - EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher)); - - auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); - if (!Imported) - return testing::AssertionFailure() << "Import failed, nullptr returned!"; - - return Verifier.match(Imported, WrapperMatcher); -} - -template -testing::AssertionResult -testImport(const std::string &FromCode, const ArgVector &FromArgs, - const std::string &ToCode, const ArgVector &ToArgs, - MatchVerifier &Verifier, - const BindableMatcher &VerificationMatcher) { - return testImport( - FromCode, FromArgs, ToCode, ToArgs, Verifier, - translationUnitDecl( - has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))), - VerificationMatcher); -} - -/// Test how AST node named "declToImport" located in the translation unit -/// of "FromCode" virtual file is imported to "ToCode" virtual file. -/// The verification is done by running AMatcher over the imported node. -template -void testImport(const std::string &FromCode, Language FromLang, - const std::string &ToCode, Language ToLang, - MatchVerifier &Verifier, - const MatcherType &AMatcher) { - auto RunOptsFrom = getRunOptionsForLanguage(FromLang); - auto RunOptsTo = getRunOptionsForLanguage(ToLang); - for (const auto &FromArgs : RunOptsFrom) - for (const auto &ToArgs : RunOptsTo) - EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs, - Verifier, AMatcher)); -} + // This should dump source locations and assert if some source locations + // were not imported. + SmallString<1024> ImportChecker; + llvm::raw_svector_ostream ToNothing(ImportChecker); + ToCtx.getTranslationUnitDecl()->print(ToNothing); + + // This traverses the AST to catch certain bugs like poorly or not + // implemented subtrees. + Imported->dump(ToNothing); + + return Imported; + } + + template + testing::AssertionResult + testImport(const std::string &FromCode, const ArgVector &FromArgs, + const std::string &ToCode, const ArgVector &ToArgs, + MatchVerifier &Verifier, + const BindableMatcher &SearchMatcher, + const BindableMatcher &VerificationMatcher) { + const char *const InputFileName = "input.cc"; + const char *const OutputFileName = "output.cc"; + + std::unique_ptr FromAST = tooling::buildASTFromCodeWithArgs( + FromCode, FromArgs, InputFileName), + ToAST = tooling::buildASTFromCodeWithArgs( + ToCode, ToArgs, OutputFileName); + + ASTContext &FromCtx = FromAST->getASTContext(), + &ToCtx = ToAST->getASTContext(); + + ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, + FromAST->getFileManager(), false); + + auto FoundNodes = match(SearchMatcher, FromCtx); + if (FoundNodes.size() != 1) + return testing::AssertionFailure() + << "Multiple potential nodes were found!"; + + auto ToImport = selectFirst(DeclToImportID, FoundNodes); + if (!ToImport) + return testing::AssertionFailure() << "Node type mismatch!"; + + // Sanity check: the node being imported should match in the same way as + // the result node. + BindableMatcher WrapperMatcher(VerificationMatcher); + EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher)); + + auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); + if (!Imported) + return testing::AssertionFailure() << "Import failed, nullptr returned!"; + + return Verifier.match(Imported, WrapperMatcher); + } + + template + testing::AssertionResult + testImport(const std::string &FromCode, const ArgVector &FromArgs, + const std::string &ToCode, const ArgVector &ToArgs, + MatchVerifier &Verifier, + const BindableMatcher &VerificationMatcher) { + return testImport( + FromCode, FromArgs, ToCode, ToArgs, Verifier, + translationUnitDecl( + has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))), + VerificationMatcher); + } + +public: + + /// Test how AST node named "declToImport" located in the translation unit + /// of "FromCode" virtual file is imported to "ToCode" virtual file. + /// The verification is done by running AMatcher over the imported node. + template + void testImport(const std::string &FromCode, Language FromLang, + const std::string &ToCode, Language ToLang, + MatchVerifier &Verifier, + const MatcherType &AMatcher) { + ArgVector FromArgs = getArgVectorForLanguage(FromLang), + ToArgs = getArgVectorForLanguage(ToLang); + EXPECT_TRUE( + testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher)); + } + + struct ImportAction { + StringRef FromFilename; + StringRef ToFilename; + // FIXME: Generalize this to support other node kinds. + BindableMatcher ImportPredicate; + + ImportAction(StringRef FromFilename, StringRef ToFilename, + DeclarationMatcher ImportPredicate) + : FromFilename(FromFilename), ToFilename(ToFilename), + ImportPredicate(ImportPredicate) {} + + ImportAction(StringRef FromFilename, StringRef ToFilename, + const std::string &DeclName) + : FromFilename(FromFilename), ToFilename(ToFilename), + ImportPredicate(namedDecl(hasName(DeclName))) {} + }; + + using SingleASTUnit = std::unique_ptr; + using AllASTUnits = StringMap; + + struct CodeEntry { + std::string CodeSample; + Language Lang; + }; + + using CodeFiles = StringMap; + + /// Builds an ASTUnit for one potential compile options set. + SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const { + ArgVector Args = getArgVectorForLanguage(CE.Lang); + auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName); + EXPECT_TRUE(AST.get()); + return AST; + } + + /// Test an arbitrary sequence of imports for a set of given in-memory files. + /// The verification is done by running VerificationMatcher against a + /// specified AST node inside of one of given files. + /// \param CodeSamples Map whose key is the file name and the value is the + /// file content. + /// \param ImportActions Sequence of imports. Each import in sequence + /// specifies "from file" and "to file" and a matcher that is used for + /// searching a declaration for import in "from file". + /// \param FileForFinalCheck Name of virtual file for which the final check is + /// applied. + /// \param FinalSelectPredicate Matcher that specifies the AST node in the + /// FileForFinalCheck for which the verification will be done. + /// \param VerificationMatcher Matcher that will be used for verification + /// after all imports in sequence are done. + void testImportSequence(const CodeFiles &CodeSamples, + const std::vector &ImportActions, + StringRef FileForFinalCheck, + BindableMatcher FinalSelectPredicate, + BindableMatcher VerificationMatcher) { + AllASTUnits AllASTs; + using ImporterKey = std::pair; + llvm::DenseMap> Importers; + + auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) { + if (!AllASTs.count(Filename)) { + auto Found = CodeSamples.find(Filename); + assert(Found != CodeSamples.end() && "Wrong file for import!"); + AllASTs[Filename] = createASTUnit(Filename, Found->getValue()); + } + }; + + for (const ImportAction &Action : ImportActions) { + StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename; + GenASTsIfNeeded(FromFile); + GenASTsIfNeeded(ToFile); + + ASTUnit *From = AllASTs[FromFile].get(); + ASTUnit *To = AllASTs[ToFile].get(); + + // Create a new importer if needed. + std::unique_ptr &ImporterRef = Importers[{From, To}]; + if (!ImporterRef) + ImporterRef.reset(new ASTImporter( + To->getASTContext(), To->getFileManager(), From->getASTContext(), + From->getFileManager(), false)); + + // Find the declaration and import it. + auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID), + From->getASTContext()); + EXPECT_TRUE(FoundDecl.size() == 1); + const Decl *ToImport = selectFirst(DeclToImportID, FoundDecl); + auto Imported = importNode(From, To, *ImporterRef, ToImport); + EXPECT_TRUE(Imported); + } + + // Find the declaration and import it. + auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID), + AllASTs[FileForFinalCheck]->getASTContext()); + EXPECT_TRUE(FoundDecl.size() == 1); + const Decl *ToVerify = selectFirst(DeclToVerifyID, FoundDecl); + MatchVerifier Verifier; + EXPECT_TRUE( + Verifier.match(ToVerify, BindableMatcher(VerificationMatcher))); + } +}; // This class provides generic methods to write tests which can check internal // attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also, // this fixture makes it possible to import from several "From" contexts. -class ASTImporterTestBase : public ::testing::TestWithParam { +class ASTImporterTestBase : public ParameterizedTestsFixture { const char *const InputFileName = "input.cc"; const char *const OutputFileName = "output.cc"; @@ -193,17 +312,6 @@ public: // We may have several From context but only one To context. std::unique_ptr ToAST; - // Returns the argument vector used for a specific language, this set - // can be tweaked by the test parameters. - ArgVector getArgVectorForLanguage(Language Lang) { - ArgVector Args = getBasicRunOptionsForLanguage(Lang); - ArgVector ExtraArgs = GetParam(); - for (const auto& Arg : ExtraArgs) { - Args.push_back(Arg); - } - return Args; - } - // Creates an AST both for the From and To source code and imports the Decl // of the identifier into the To context. // Must not be called more than once within the same test. @@ -316,124 +424,11 @@ public: } }; +struct ImportExpr : TestImportBase {}; +struct ImportType : TestImportBase {}; +struct ImportDecl : TestImportBase {}; -struct ImportAction { - StringRef FromFilename; - StringRef ToFilename; - // FIXME: Generalize this to support other node kinds. - BindableMatcher ImportPredicate; - - ImportAction(StringRef FromFilename, StringRef ToFilename, - DeclarationMatcher ImportPredicate) - : FromFilename(FromFilename), ToFilename(ToFilename), - ImportPredicate(ImportPredicate) {} - - ImportAction(StringRef FromFilename, StringRef ToFilename, - const std::string &DeclName) - : FromFilename(FromFilename), ToFilename(ToFilename), - ImportPredicate(namedDecl(hasName(DeclName))) {} -}; - -using SingleASTUnitForAllOpts = std::vector>; -using AllASTUnitsForAllOpts = StringMap; - -struct CodeEntry { - std::string CodeSample; - Language Lang; - - /// Builds N copies of ASTUnits for each potential compile options set - /// for further import actions. N is equal to size of this option set. - SingleASTUnitForAllOpts createASTUnits(StringRef FileName) const { - auto RunOpts = getRunOptionsForLanguage(Lang); - size_t NumOpts = RunOpts.size(); - SingleASTUnitForAllOpts ResultASTs(NumOpts); - for (size_t CompileOpt = 0; CompileOpt < NumOpts; ++CompileOpt) { - auto AST = tooling::buildASTFromCodeWithArgs( - CodeSample, RunOpts[CompileOpt], FileName); - EXPECT_TRUE(AST.get()); - ResultASTs[CompileOpt] = std::move(AST); - } - return ResultASTs; - } -}; - -using CodeFiles = StringMap; - -/// Test an arbitrary sequence of imports for a set of given in-memory files. -/// The verification is done by running VerificationMatcher against a specified -/// AST node inside of one of given files. -/// \param CodeSamples Map whose key is the file name and the value is the file -/// content. -/// \param ImportActions Sequence of imports. Each import in sequence -/// specifies "from file" and "to file" and a matcher that is used for -/// searching a declaration for import in "from file". -/// \param FileForFinalCheck Name of virtual file for which the final check is -/// applied. -/// \param FinalSelectPredicate Matcher that specifies the AST node in the -/// FileForFinalCheck for which the verification will be done. -/// \param VerificationMatcher Matcher that will be used for verification after -/// all imports in sequence are done. -void testImportSequence(const CodeFiles &CodeSamples, - const std::vector &ImportActions, - StringRef FileForFinalCheck, - BindableMatcher FinalSelectPredicate, - BindableMatcher VerificationMatcher) { - AllASTUnitsForAllOpts AllASTUnits; - using ImporterKey = std::pair; - llvm::DenseMap> Importers; - - auto GenASTsIfNeeded = [&AllASTUnits, &CodeSamples](StringRef Filename) { - if (!AllASTUnits.count(Filename)) { - auto Found = CodeSamples.find(Filename); - assert(Found != CodeSamples.end() && "Wrong file for import!"); - AllASTUnits[Filename] = Found->getValue().createASTUnits(Filename); - } - }; - - size_t NumCompileOpts = 0; - for (const ImportAction &Action : ImportActions) { - StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename; - GenASTsIfNeeded(FromFile); - GenASTsIfNeeded(ToFile); - NumCompileOpts = AllASTUnits[FromFile].size(); - - for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) { - ASTUnit *From = AllASTUnits[FromFile][CompileOpt].get(); - ASTUnit *To = AllASTUnits[ToFile][CompileOpt].get(); - - // Create a new importer if needed. - std::unique_ptr &ImporterRef = Importers[{From, To}]; - if (!ImporterRef) - ImporterRef.reset(new ASTImporter( - To->getASTContext(), To->getFileManager(), From->getASTContext(), - From->getFileManager(), false)); - - // Find the declaration and import it. - auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID), - From->getASTContext()); - EXPECT_TRUE(FoundDecl.size() == 1); - const Decl *ToImport = selectFirst(DeclToImportID, FoundDecl); - auto Imported = importNode(From, To, *ImporterRef, ToImport); - EXPECT_TRUE(Imported); - } - } - - // NOTE: We don't do cross-option import check here due to fast growth of - // potential option sets. - for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) { - // Find the declaration and import it. - auto FoundDecl = - match(FinalSelectPredicate.bind(DeclToVerifyID), - AllASTUnits[FileForFinalCheck][CompileOpt]->getASTContext()); - EXPECT_TRUE(FoundDecl.size() == 1); - const Decl *ToVerify = selectFirst(DeclToVerifyID, FoundDecl); - MatchVerifier Verifier; - EXPECT_TRUE(Verifier.match(ToVerify, - BindableMatcher(VerificationMatcher))); - } -} - -TEST(ImportExpr, ImportStringLiteral) { +TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier Verifier; testImport("void declToImport() { \"foo\"; }", Lang_CXX, "", Lang_CXX, Verifier, @@ -464,7 +459,7 @@ TEST(ImportExpr, ImportStringLiteral) { asString("const char [7]")))))))); } -TEST(ImportExpr, ImportGNUNullExpr) { +TEST_P(ImportExpr, ImportGNUNullExpr) { MatchVerifier Verifier; testImport("void declToImport() { __null; }", Lang_CXX, "", Lang_CXX, Verifier, @@ -476,7 +471,7 @@ TEST(ImportExpr, ImportGNUNullExpr) { hasType(isInteger()))))))); } -TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) { +TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) { MatchVerifier Verifier; testImport("void declToImport() { nullptr; }", Lang_CXX11, "", Lang_CXX11, Verifier, @@ -488,7 +483,7 @@ TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) { } -TEST(ImportExpr, ImportFloatinglLiteralExpr) { +TEST_P(ImportExpr, ImportFloatinglLiteralExpr) { MatchVerifier Verifier; testImport("void declToImport() { 1.0; }", Lang_C, "", Lang_C, Verifier, @@ -510,7 +505,7 @@ TEST(ImportExpr, ImportFloatinglLiteralExpr) { hasType(asString("float")))))))); } -TEST(ImportExpr, ImportCompoundLiteralExpr) { +TEST_P(ImportExpr, ImportCompoundLiteralExpr) { MatchVerifier Verifier; testImport("void declToImport() {" " struct s { int x; long y; unsigned z; }; " @@ -534,7 +529,7 @@ TEST(ImportExpr, ImportCompoundLiteralExpr) { )))))))); } -TEST(ImportExpr, ImportCXXThisExpr) { +TEST_P(ImportExpr, ImportCXXThisExpr) { MatchVerifier Verifier; testImport("class declToImport { void f() { this; } };", Lang_CXX, "", Lang_CXX, Verifier, @@ -548,7 +543,7 @@ TEST(ImportExpr, ImportCXXThisExpr) { asString("class declToImport *"))))))))); } -TEST(ImportExpr, ImportAtomicExpr) { +TEST_P(ImportExpr, ImportAtomicExpr) { MatchVerifier Verifier; testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_C, "", Lang_C, Verifier, @@ -559,7 +554,7 @@ TEST(ImportExpr, ImportAtomicExpr) { has(integerLiteral(equals(1), hasType(asString("int")))))))))); } -TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { +TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { MatchVerifier Verifier; testImport( "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C, @@ -575,7 +570,7 @@ AST_MATCHER_P(TemplateDecl, hasTemplateDecl, return Template && InnerMatcher.matches(*Template, Finder, Builder); } -TEST(ImportExpr, ImportParenListExpr) { +TEST_P(ImportExpr, ImportParenListExpr) { MatchVerifier Verifier; testImport( "template class dummy { void f() { dummy X(*this); } };" @@ -592,7 +587,7 @@ TEST(ImportExpr, ImportParenListExpr) { hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))); } -TEST(ImportExpr, ImportSwitch) { +TEST_P(ImportExpr, ImportSwitch) { MatchVerifier Verifier; testImport("void declToImport() { int b; switch (b) { case 1: break; } }", Lang_C, "", Lang_C, Verifier, @@ -600,7 +595,7 @@ TEST(ImportExpr, ImportSwitch) { has(switchStmt(has(compoundStmt(has(caseStmt()))))))))); } -TEST(ImportExpr, ImportStmtExpr) { +TEST_P(ImportExpr, ImportStmtExpr) { MatchVerifier Verifier; // NOTE: has() ignores implicit casts, using hasDescendant() to match it testImport( @@ -630,7 +625,7 @@ TEST(ImportExpr, ImportStmtExpr) { ))))))))))); } -TEST(ImportExpr, ImportConditionalOperator) { +TEST_P(ImportExpr, ImportConditionalOperator) { MatchVerifier Verifier; testImport( "void declToImport() { true ? 1 : -5; }", @@ -647,7 +642,7 @@ TEST(ImportExpr, ImportConditionalOperator) { ))))))); } -TEST(ImportExpr, ImportBinaryConditionalOperator) { +TEST_P(ImportExpr, ImportBinaryConditionalOperator) { MatchVerifier Verifier; testImport( "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier, @@ -671,7 +666,7 @@ TEST(ImportExpr, ImportBinaryConditionalOperator) { )))))); } -TEST(ImportExpr, ImportDesignatedInitExpr) { +TEST_P(ImportExpr, ImportDesignatedInitExpr) { MatchVerifier Verifier; testImport("void declToImport() {" " struct point { double x; double y; };" @@ -714,7 +709,7 @@ TEST(ImportExpr, ImportDesignatedInitExpr) { } -TEST(ImportExpr, ImportPredefinedExpr) { +TEST_P(ImportExpr, ImportPredefinedExpr) { MatchVerifier Verifier; // __func__ expands as StringLiteral("declToImport") testImport("void declToImport() { __func__; }", @@ -732,7 +727,7 @@ TEST(ImportExpr, ImportPredefinedExpr) { asString("const char [13]")))))))))); } -TEST(ImportExpr, ImportInitListExpr) { +TEST_P(ImportExpr, ImportInitListExpr) { MatchVerifier Verifier; testImport( "void declToImport() {" @@ -769,7 +764,7 @@ TEST(ImportExpr, ImportInitListExpr) { const internal::VariadicDynCastAllOfMatcher vaArgExpr; -TEST(ImportExpr, ImportVAArgExpr) { +TEST_P(ImportExpr, ImportVAArgExpr) { MatchVerifier Verifier; testImport("void declToImport(__builtin_va_list list, ...) {" " (void)__builtin_va_arg(list, int); }", @@ -783,7 +778,7 @@ TEST(ImportExpr, ImportVAArgExpr) { vaArgExpr()))))))); } -TEST(ImportExpr, CXXTemporaryObjectExpr) { +TEST_P(ImportExpr, CXXTemporaryObjectExpr) { MatchVerifier Verifier; testImport("struct C {};" "void declToImport() { C c = C(); }", @@ -794,7 +789,7 @@ TEST(ImportExpr, CXXTemporaryObjectExpr) { has(cxxTemporaryObjectExpr()))))))))))))))))); } -TEST(ImportType, ImportAtomicType) { +TEST_P(ImportType, ImportAtomicType) { MatchVerifier Verifier; testImport("void declToImport() { typedef _Atomic(int) a_int; }", Lang_CXX11, "", Lang_CXX11, Verifier, @@ -808,7 +803,7 @@ TEST(ImportType, ImportAtomicType) { has(atomicType()))))))))); } -TEST(ImportDecl, ImportFunctionTemplateDecl) { +TEST_P(ImportDecl, ImportFunctionTemplateDecl) { MatchVerifier Verifier; testImport("template void declToImport() { };", Lang_CXX, "", Lang_CXX, Verifier, functionTemplateDecl()); @@ -817,7 +812,7 @@ TEST(ImportDecl, ImportFunctionTemplateDecl) { const internal::VariadicDynCastAllOfMatcher cxxDependentScopeMemberExpr; -TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) { +TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) { MatchVerifier Verifier; testImport("template struct C { T t; };" "template void declToImport() {" @@ -839,7 +834,7 @@ TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) { has(compoundStmt(has(cxxDependentScopeMemberExpr()))))))); } -TEST(ImportType, ImportTypeAliasTemplate) { +TEST_P(ImportType, ImportTypeAliasTemplate) { MatchVerifier Verifier; testImport( "template " @@ -856,7 +851,7 @@ TEST(ImportType, ImportTypeAliasTemplate) { const internal::VariadicDynCastAllOfMatcher varTemplateSpecializationDecl; -TEST(ImportDecl, ImportVarTemplate) { +TEST_P(ImportDecl, ImportVarTemplate) { MatchVerifier Verifier; testImport( "template " @@ -869,7 +864,7 @@ TEST(ImportDecl, ImportVarTemplate) { hasName("pi"), unless(varTemplateSpecializationDecl())))))))); } -TEST(ImportType, ImportPackExpansion) { +TEST_P(ImportType, ImportPackExpansion) { MatchVerifier Verifier; testImport("template " "struct dummy {" @@ -893,7 +888,7 @@ const internal::VariadicDynCastAllOfMatcher dependentTemplateSpecializationType; -TEST(ImportType, ImportDependentTemplateSpecialization) { +TEST_P(ImportType, ImportDependentTemplateSpecialization) { MatchVerifier Verifier; testImport("template" "struct A;" @@ -909,7 +904,7 @@ TEST(ImportType, ImportDependentTemplateSpecialization) { const internal::VariadicDynCastAllOfMatcher sizeOfPackExpr; -TEST(ImportExpr, ImportSizeOfPackExpr) { +TEST_P(ImportExpr, ImportSizeOfPackExpr) { MatchVerifier Verifier; testImport("template " "void declToImport() {" @@ -942,7 +937,7 @@ TEST(ImportExpr, ImportSizeOfPackExpr) { // will generate TypeTraitExpr <...> 'int' const internal::VariadicDynCastAllOfMatcher typeTraitExpr; -TEST(ImportExpr, ImportTypeTraitExpr) { +TEST_P(ImportExpr, ImportTypeTraitExpr) { MatchVerifier Verifier; testImport("void declToImport() { " " __builtin_types_compatible_p(int, int);" @@ -957,7 +952,7 @@ TEST(ImportExpr, ImportTypeTraitExpr) { const internal::VariadicDynCastAllOfMatcher cxxTypeidExpr; -TEST(ImportExpr, ImportCXXTypeidExpr) { +TEST_P(ImportExpr, ImportCXXTypeidExpr) { MatchVerifier Verifier; testImport( "namespace std { class type_info {}; }" @@ -973,7 +968,7 @@ TEST(ImportExpr, ImportCXXTypeidExpr) { hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr())))))); } -TEST(ImportExpr, ImportTypeTraitExprValDep) { +TEST_P(ImportExpr, ImportTypeTraitExprValDep) { MatchVerifier Verifier; testImport("template struct declToImport {" " void m() { __is_pod(T); }" @@ -996,7 +991,7 @@ TEST(ImportExpr, ImportTypeTraitExprValDep) { const internal::VariadicDynCastAllOfMatcher cxxPseudoDestructorExpr; -TEST(ImportExpr, ImportCXXPseudoDestructorExpr) { +TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) { MatchVerifier Verifier; testImport("typedef int T;" "void declToImport(int *p) {" @@ -1008,7 +1003,7 @@ TEST(ImportExpr, ImportCXXPseudoDestructorExpr) { callExpr(has(cxxPseudoDestructorExpr()))))))); } -TEST(ImportDecl, ImportUsingDecl) { +TEST_P(ImportDecl, ImportUsingDecl) { MatchVerifier Verifier; testImport("namespace foo { int bar; }" "void declToImport() { using foo::bar; }", @@ -1035,7 +1030,7 @@ TEST(ImportDecl, ImportUsingDecl) { const internal::VariadicDynCastAllOfMatcher usingShadowDecl; -TEST(ImportDecl, ImportUsingShadowDecl) { +TEST_P(ImportDecl, ImportUsingShadowDecl) { MatchVerifier Verifier; testImport("namespace foo { int bar; }" "namespace declToImport { using foo::bar; }", @@ -1043,7 +1038,7 @@ TEST(ImportDecl, ImportUsingShadowDecl) { namespaceDecl(has(usingShadowDecl()))); } -TEST(ImportExpr, ImportUnresolvedLookupExpr) { +TEST_P(ImportExpr, ImportUnresolvedLookupExpr) { MatchVerifier Verifier; testImport("template int foo();" "template void declToImport() {" @@ -1056,7 +1051,7 @@ TEST(ImportExpr, ImportUnresolvedLookupExpr) { has(compoundStmt(has(unresolvedLookupExpr()))))))); } -TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) { +TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) { MatchVerifier Verifier; testImport("template struct C { T t; };" "template void declToImport() {" @@ -1081,7 +1076,7 @@ TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) { /// Check that function "declToImport()" (which is the templated function /// for corresponding FunctionTemplateDecl) is not added into DeclContext. /// Same for class template declarations. -TEST(ImportDecl, ImportTemplatedDeclForTemplate) { +TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) { MatchVerifier Verifier; testImport("template void declToImport() { T a = 1; }" "void instantiate() { declToImport(); }", @@ -1095,7 +1090,7 @@ TEST(ImportDecl, ImportTemplatedDeclForTemplate) { unless(has(cxxRecordDecl(hasName("declToImport")))))))); } -TEST(ImportDecl, ImportClassTemplatePartialSpecialization) { +TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) { MatchVerifier Verifier; auto Code = R"s( @@ -1109,7 +1104,7 @@ TEST(ImportDecl, ImportClassTemplatePartialSpecialization) { has(classTemplateSpecializationDecl()))); } -TEST(ImportExpr, CXXOperatorCallExpr) { +TEST_P(ImportExpr, CXXOperatorCallExpr) { MatchVerifier Verifier; testImport("class declToImport {" " void f() { *this = declToImport(); }" @@ -1119,7 +1114,7 @@ TEST(ImportExpr, CXXOperatorCallExpr) { has(exprWithCleanups(has(cxxOperatorCallExpr()))))))))); } -TEST(ImportExpr, DependentSizedArrayType) { +TEST_P(ImportExpr, DependentSizedArrayType) { MatchVerifier Verifier; testImport("template class declToImport {" " T data[Size];" @@ -1675,10 +1670,6 @@ TEST_P( .match(ToTU, classTemplateSpecializationDecl())); } -INSTANTIATE_TEST_CASE_P( - ParameterizedTests, ASTImporterTestBase, - ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),); - struct ImportFunctions : ASTImporterTestBase {}; TEST_P(ImportFunctions, @@ -1903,10 +1894,6 @@ TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { EXPECT_TRUE(To->isVirtual()); } -INSTANTIATE_TEST_CASE_P( - ParameterizedTests, ImportFunctions, - ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),); - AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher, InnerMatcher) { if (auto *Typedef = Node.getTypedefNameForAnonDecl()) @@ -1914,7 +1901,7 @@ AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher, return false; } -TEST(ImportDecl, ImportEnumSequential) { +TEST_P(ImportDecl, ImportEnumSequential) { CodeFiles Samples{{"main.c", {"void foo();" "void moo();" @@ -1956,7 +1943,7 @@ TEST(ImportDecl, ImportEnumSequential) { const internal::VariadicDynCastAllOfMatcher dependentScopeDeclRefExpr; -TEST(ImportExpr, DependentScopeDeclRefExpr) { +TEST_P(ImportExpr, DependentScopeDeclRefExpr) { MatchVerifier Verifier; testImport("template struct S { static T foo; };" "template void declToImport() {" @@ -1982,7 +1969,7 @@ TEST(ImportExpr, DependentScopeDeclRefExpr) { const internal::VariadicDynCastAllOfMatcher dependentNameType; -TEST(ImportExpr, DependentNameType) { +TEST_P(ImportExpr, DependentNameType) { MatchVerifier Verifier; testImport("template struct declToImport {" " typedef typename T::type dependent_name;" @@ -1995,7 +1982,7 @@ TEST(ImportExpr, DependentNameType) { const internal::VariadicDynCastAllOfMatcher unresolvedMemberExpr; -TEST(ImportExpr, UnresolvedMemberExpr) { +TEST_P(ImportExpr, UnresolvedMemberExpr) { MatchVerifier Verifier; testImport("struct S { template void mem(); };" "template void declToImport() {" @@ -2037,9 +2024,29 @@ TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { EXPECT_FALSE(NS->containsDecl(Spec)); } -INSTANTIATE_TEST_CASE_P( - ParameterizedTests, DeclContextTest, - ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, + ::testing::Values(ArgVector()), ); + +auto DefaultTestValuesForRunOptions = ::testing::Values( + ArgVector(), + ArgVector{"-fdelayed-template-parsing"}, + ArgVector{"-fms-compatibility"}, + ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"}); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, + DefaultTestValuesForRunOptions, ); } // end namespace ast_matchers } // end namespace clang diff --git a/unittests/AST/Language.cpp b/unittests/AST/Language.cpp index 972c2a5495..5d1664019c 100644 --- a/unittests/AST/Language.cpp +++ b/unittests/AST/Language.cpp @@ -42,19 +42,5 @@ ArgVector getBasicRunOptionsForLanguage(Language Lang) { return BasicArgs; } -RunOptions getRunOptionsForLanguage(Language Lang) { - ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang); - - // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC - // default behaviour. - if (isCXX(Lang)) { - ArgVector ArgsForDelayedTemplateParse = BasicArgs; - ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing"); - return {BasicArgs, ArgsForDelayedTemplateParse}; - } - - return {BasicArgs}; -} - } // end namespace ast_matchers } // end namespace clang diff --git a/unittests/AST/Language.h b/unittests/AST/Language.h index b4f5404797..0eb2fb2417 100644 --- a/unittests/AST/Language.h +++ b/unittests/AST/Language.h @@ -22,7 +22,6 @@ namespace clang { namespace ast_matchers { typedef std::vector ArgVector; -typedef std::vector RunOptions; enum Language { Lang_C, @@ -34,12 +33,7 @@ enum Language { Lang_OBJCXX }; -inline bool isCXX(Language Lang) { - return Lang == Lang_CXX || Lang == Lang_CXX11 || Lang == Lang_CXX14; -} - ArgVector getBasicRunOptionsForLanguage(Language Lang); -RunOptions getRunOptionsForLanguage(Language Lang); } // end namespace ast_matchers } // end namespace clang -- GitLab From 7f055b7e1a07716517c5ef7564aa95b7749fc2f7 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 25 Jun 2018 13:23:49 +0000 Subject: [PATCH 0254/1023] [clang-cl] Don't emit dllexport inline functions etc. from pch files (PR37801) With MSVC, PCH files are created along with an object file that needs to be linked into the final library or executable. That object file contains the code generated when building the headers. In particular, it will include definitions of inline dllexport functions, and because they are emitted in this object file, other files using the PCH do not need to emit them. See the bug for an example. This patch makes clang-cl match MSVC's behaviour in this regard, causing significant compile-time savings when building dlls using precompiled headers. For example, in a 64-bit optimized shared library build of Chromium with PCH, it reduces the binary size and compile time of stroke_opacity_custom.obj from 9315564 bytes to 3659629 bytes and 14.6 to 6.63 s. The wall-clock time of building blink_core.dll goes from 38m41s to 22m33s. ("user" time goes from 1979m to 1142m). Differential Revision: https://reviews.llvm.org/D48426 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335466 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExternalASTSource.h | 4 + include/clang/Basic/LangOptions.def | 1 + include/clang/Driver/CC1Options.td | 4 +- .../clang/Sema/MultiplexExternalSemaSource.h | 2 + include/clang/Serialization/ASTBitCodes.h | 2 +- include/clang/Serialization/ASTReader.h | 2 + include/clang/Serialization/Module.h | 3 + lib/AST/ASTContext.cpp | 27 +++++- lib/Driver/Driver.cpp | 2 + lib/Driver/ToolChains/Clang.cpp | 4 + lib/Frontend/CompilerInvocation.cpp | 1 + lib/Frontend/FrontendActions.cpp | 8 +- lib/Sema/MultiplexExternalSemaSource.cpp | 7 ++ lib/Serialization/ASTReader.cpp | 9 +- lib/Serialization/ASTWriter.cpp | 15 +++- test/CodeGen/pch-dllexport.cpp | 84 +++++++++++++++++++ test/Driver/cl-pch.cpp | 6 ++ 17 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 test/CodeGen/pch-dllexport.cpp diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 52de0fcbe2..1e05a309af 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -163,6 +163,10 @@ public: /// Retrieve the module that corresponds to the given module ID. virtual Module *getModule(unsigned ID) { return nullptr; } + /// Determine whether D comes from a PCH which was built with a corresponding + /// object file. + virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; } + /// Abstracts clang modules and precompiled header files and holds /// everything needed to generate debug info for an imported module /// or PCH. diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index d7d66be32d..55f057a0d6 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -154,6 +154,7 @@ COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS") BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None, "compiling a module interface") BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") +BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references") COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 18d0483a79..d500cab92b 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -609,7 +609,9 @@ def find_pch_source_EQ : Joined<["-"], "find-pch-source=">, "to this flag.">; def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, HelpText<"Disable inclusion of timestamp in precompiled headers">; - +def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">, + HelpText<"This compilation is part of building a PCH with corresponding object file.">; + def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">, HelpText<"Aligned allocation/deallocation functions are unavailable">; diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 8514fff333..4c242c89f3 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -152,6 +152,8 @@ public: /// Retrieve the module that corresponds to the given module ID. Module *getModule(unsigned ID) override; + bool DeclIsFromPCHWithObjectFile(const Decl *D) override; + /// Perform layout on the given record. /// /// This routine allows the external AST source to provide an specific diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index e98a6236a4..82bb1f5fa1 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -42,7 +42,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. - const unsigned VERSION_MAJOR = 6; + const unsigned VERSION_MAJOR = 7; /// AST file minor version number supported by this version of /// Clang. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 7de511ad61..d09a9f4023 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -2071,6 +2071,8 @@ public: /// Note: overrides method in ExternalASTSource Module *getModule(unsigned ID) override; + bool DeclIsFromPCHWithObjectFile(const Decl *D) override; + /// Retrieve the module file with a given local ID within the specified /// ModuleFile. ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID); diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 5f41f3927a..653981b142 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -157,6 +157,9 @@ public: /// Whether timestamps are included in this module file. bool HasTimestamps = false; + /// Whether the PCH has a corresponding object file. + bool PCHHasObjectFile = false; + /// The file entry for the module file. const FileEntry *File = nullptr; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 96b7b56c1c..43577e8640 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -9553,6 +9553,29 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { else return false; + if (D->isFromASTFile() && !LangOpts.BuildingPCHWithObjectFile) { + assert(getExternalSource() && "It's from an AST file; must have a source."); + // On Windows, PCH files are built together with an object file. If this + // declaration comes from such a PCH and DeclMustBeEmitted would return + // true, it would have returned true and the decl would have been emitted + // into that object file, so it doesn't need to be emitted here. + // Note that decls are still emitted if they're referenced, as usual; + // DeclMustBeEmitted is used to decide whether a decl must be emitted even + // if it's not referenced. + // + // Explicit template instantiation definitions are tricky. If there was an + // explicit template instantiation decl in the PCH before, it will look like + // the definition comes from there, even if that was just the declaration. + // (Explicit instantiation defs of variable templates always get emitted.) + bool IsExpInstDef = + isa(D) && + cast(D)->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition; + + if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef) + return false; + } + // If this is a member of a class template, we do not need to emit it. if (D->getDeclContext()->isDependentContext()) return false; @@ -9573,7 +9596,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Constructors and destructors are required. if (FD->hasAttr() || FD->hasAttr()) return true; - + // The key function for a class is required. This rule only comes // into play when inline functions can be key functions, though. if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { @@ -9594,7 +9617,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Implicit template instantiations can also be deferred in C++. return !isDiscardableGVALinkage(Linkage); } - + const auto *VD = cast(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 14d94c029d..7b890d80f0 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -3088,6 +3088,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // The driver currently exits after the first failed command. This // relies on that behavior, to make sure if the pch generation fails, // the main compilation won't run. + // FIXME: If the main compilation fails, the PCH generation should + // probably not be considered successful either. } } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index bce2083051..88e2f83f6d 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1084,6 +1084,10 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") + Inputs[0].second->getValue())); } + if (YcIndex != -1 && JA.getKind() >= Action::PrecompileJobClass && + JA.getKind() <= Action::AssembleJobClass) { + CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj")); + } bool RenderedImplicitInclude = false; int AI = -1; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 60ed5fdf70..26414f1a52 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2776,6 +2776,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers); + Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj); } static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 602fee1fdc..06db814f4b 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -112,14 +112,14 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (!CI.getFrontendOpts().RelocatablePCH) Sysroot.clear(); + const auto &FrontendOpts = CI.getFrontendOpts(); auto Buffer = std::make_shared(); std::vector> Consumers; Consumers.push_back(llvm::make_unique( CI.getPreprocessor(), OutputFile, Sysroot, - Buffer, CI.getFrontendOpts().ModuleFileExtensions, - /*AllowASTWithErrors*/CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - /*IncludeTimestamps*/ - +CI.getFrontendOpts().IncludeTimestamps)); + Buffer, FrontendOpts.ModuleFileExtensions, + CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, + FrontendOpts.IncludeTimestamps)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp index 9370cf27ef..7e61ccbb10 100644 --- a/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -171,6 +171,13 @@ Module *MultiplexExternalSemaSource::getModule(unsigned ID) { return nullptr; } +bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) { + for (auto *S : Sources) + if (S->DeclIsFromPCHWithObjectFile(D)) + return true; + return false; +} + bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 3dd233e449..982c4cbee8 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2482,7 +2482,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, return VersionMismatch; } - bool hasErrors = Record[6]; + bool hasErrors = Record[7]; if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) { Diag(diag::err_pch_with_compiler_errors); return HadErrors; @@ -2500,6 +2500,8 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.HasTimestamps = Record[5]; + F.PCHHasObjectFile = Record[6]; + const std::string &CurBranch = getClangFullRepositoryVersion(); StringRef ASTBranch = Blob; if (StringRef(CurBranch) != ASTBranch && !DisableValidation) { @@ -8448,6 +8450,11 @@ Module *ASTReader::getModule(unsigned ID) { return getSubmodule(ID); } +bool ASTReader::DeclIsFromPCHWithObjectFile(const Decl *D) { + ModuleFile *MF = getOwningModuleFile(D); + return MF && MF->PCHHasObjectFile; +} + ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) { if (ID & 1) { // It's a module, look it up by submodule ID. diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 1e3a098b09..7d5b521d4d 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1458,16 +1458,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev)); assert((!WritingModule || isysroot.empty()) && "writing module as a relocatable PCH?"); { - RecordData::value_type Record[] = {METADATA, VERSION_MAJOR, VERSION_MINOR, - CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR, - !isysroot.empty(), IncludeTimestamps, - ASTHasCompilerErrors}; + RecordData::value_type Record[] = { + METADATA, + VERSION_MAJOR, + VERSION_MINOR, + CLANG_VERSION_MAJOR, + CLANG_VERSION_MINOR, + !isysroot.empty(), + IncludeTimestamps, + Context.getLangOpts().BuildingPCHWithObjectFile, + ASTHasCompilerErrors}; Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); } diff --git a/test/CodeGen/pch-dllexport.cpp b/test/CodeGen/pch-dllexport.cpp new file mode 100644 index 0000000000..9c6623be43 --- /dev/null +++ b/test/CodeGen/pch-dllexport.cpp @@ -0,0 +1,84 @@ +// Build PCH without object file, then use it. +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-pch -o %t %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCH %s + +// Build PCH with object file, then use it. +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-pch -building-pch-with-obj -o %t %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -building-pch-with-obj -o - %s | FileCheck -check-prefix=OBJ %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCHWITHOBJ %s + +// Check for vars separately to avoid having to reorder the check statements. +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-obj -emit-llvm -include-pch %t -o - %s | FileCheck -check-prefix=PCHWITHOBJVARS %s + +#ifndef IN_HEADER +#define IN_HEADER + +inline void __declspec(dllexport) foo() {} +// OBJ: define weak_odr dso_local dllexport void @"?foo@@YAXXZ" +// PCH: define weak_odr dso_local dllexport void @"?foo@@YAXXZ" +// PCHWITHOBJ-NOT: define {{.*}}foo + + +// This function is referenced, so gets emitted as usual. +inline void __declspec(dllexport) baz() {} +// OBJ: define weak_odr dso_local dllexport void @"?baz@@YAXXZ" +// PCH: define weak_odr dso_local dllexport void @"?baz@@YAXXZ" +// PCHWITHOBJ: define weak_odr dso_local dllexport void @"?baz@@YAXXZ" + + +struct __declspec(dllexport) S { + void bar() {} +// OBJ: define weak_odr dso_local dllexport x86_thiscallcc void @"?bar@S@@QAEXXZ" +// PCH: define weak_odr dso_local dllexport x86_thiscallcc void @"?bar@S@@QAEXXZ" +// PCHWITHOBJ-NOT: define {{.*}}bar +}; + +// This isn't dllexported, attribute((used)) or referenced, so not emitted. +inline void quux() {} +// OBJ-NOT: define {{.*}}quux +// PCH-NOT: define {{.*}}quux +// PCHWITHOBJ-NOT: define {{.*}}quux + +// Referenced non-dllexport function. +inline void referencedNonExported() {} +// OBJ: define {{.*}}referencedNonExported +// PCH: define {{.*}}referencedNonExported +// PCHWITHOBJ: define {{.*}}referencedNonExported + +template void __declspec(dllexport) implicitInstantiation(T) {} + +template inline void __declspec(dllexport) explicitSpecialization(T) {} + +template void __declspec(dllexport) explicitInstantiationDef(T) {} + +template void __declspec(dllexport) explicitInstantiationDefAfterDecl(T) {} +extern template void explicitInstantiationDefAfterDecl(int); + +template T __declspec(dllexport) variableTemplate; +extern template int variableTemplate; + +#else + +void use() { + baz(); + referencedNonExported(); +} + +// Templates can be tricky. None of the definitions below come from the PCH. + +void useTemplate() { implicitInstantiation(42); } +// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$implicitInstantiation@H@@YAXH@Z" + +template<> inline void __declspec(dllexport) explicitSpecialization(int) {} +// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitSpecialization@H@@YAXH@Z" + +template void __declspec(dllexport) explicitInstantiationDef(int); +// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitInstantiationDef@H@@YAXH@Z" + +template void __declspec(dllexport) explicitInstantiationDefAfterDecl(int); +// PCHWITHOBJ: define weak_odr dso_local dllexport void @"??$explicitInstantiationDefAfterDecl@H@@YAXH@Z"(i32) + +template int __declspec(dllexport) variableTemplate; +// PCHWITHOBJVARS: @"??$variableTemplate@H@@3HA" = weak_odr dso_local dllexport global + +#endif diff --git a/test/Driver/cl-pch.cpp b/test/Driver/cl-pch.cpp index 2503c97373..bef5ce6bd0 100644 --- a/test/Driver/cl-pch.cpp +++ b/test/Driver/cl-pch.cpp @@ -7,6 +7,7 @@ // 1. Build .pch file. // CHECK-YC: cc1 // CHECK-YC: -emit-pch +// CHECK-YC: -building-pch-with-obj // CHECK-YC: -o // CHECK-YC: pchfile.pch // CHECK-YC: -x @@ -14,6 +15,7 @@ // 2. Use .pch file. // CHECK-YC: cc1 // CHECK-YC: -emit-obj +// CHECK-YC: -building-pch-with-obj // CHECK-YC: -include-pch // CHECK-YC: pchfile.pch @@ -24,11 +26,13 @@ // 1. Build .pch file. // CHECK-YCO: cc1 // CHECK-YCO: -emit-pch +// CHECK-YCO: -building-pch-with-obj // CHECK-YCO: -o // CHECK-YCO: pchfile.pch // 2. Use .pch file. // CHECK-YCO: cc1 // CHECK-YCO: -emit-obj +// CHECK-YCO: -building-pch-with-obj // CHECK-YCO: -include-pch // CHECK-YCO: pchfile.pch // CHECK-YCO: -o @@ -46,6 +50,7 @@ // RUN: | FileCheck -check-prefix=CHECK-YU %s // Use .pch file, but don't build it. // CHECK-YU-NOT: -emit-pch +// CHECK-YU-NOT: -building-pch-with-obj // CHECK-YU: cc1 // CHECK-YU: -emit-obj // CHECK-YU: -include-pch @@ -63,6 +68,7 @@ // 1. Build .pch file. // CHECK-YC-YU: cc1 // CHECK-YC-YU: -emit-pch +// CHECK-YC-YU: -building-pch-with-obj // CHECK-YC-YU: -o // CHECK-YC-YU: pchfile.pch // 2. Use .pch file. -- GitLab From 029be8c2f349782b0075c78687ab09e87f0bdf4a Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 25 Jun 2018 14:41:58 +0000 Subject: [PATCH 0255/1023] [ASTImporter] Import the whole redecl chain of functions Summary: With this patch when any `FunctionDecl` of a redeclaration chain is imported then we bring in the whole declaration chain. This involves functions and function template specializations. Also friend functions are affected. The chain is imported as it is in the "from" tu, the order of the redeclarations are kept. I also changed the lookup logic in order to find friends, but first making them visible in their declaration context. We may have long redeclaration chains if all TU contains the same prototype, but our measurements shows no degradation in time of CTU analysis (Tmux, Xerces, Bitcoin, Protobuf). Also, as further work we could squash redundant prototypes, but first ensure that functionality is working properly; then should we optimize. This may seem like a huge patch, sorry about that. But, most of the changes are new tests, changes in the production code is not that much. I also tried to create a smaller patch which does not affect specializations, but that patch failed to pass some of the `clang-import-test`s because there we import function specializations. Also very importantly, we can't just change the import of `FunctionDecl`s without changing the import of function template specializations because they are handled as `FunctionDecl`s. Reviewers: a.sidorin, r.stahl, xazax.hun, balazske Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47532 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335480 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTImporter.h | 9 + lib/AST/ASTImporter.cpp | 165 +++++-- lib/AST/DeclBase.cpp | 2 + test/ASTMerge/class/test.cpp | 8 +- unittests/AST/ASTImporterTest.cpp | 714 +++++++++++++++++++++++++++--- 5 files changed, 787 insertions(+), 111 deletions(-) diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 42f99f3f3f..de3bfbdf04 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -43,6 +43,15 @@ class TagDecl; class TypeSourceInfo; class Attr; + // \brief Returns with a list of declarations started from the canonical decl + // then followed by subsequent decls in the translation unit. + // This gives a canonical list for each entry in the redecl chain. + // `Decl::redecls()` gives a list of decls which always start from the + // previous decl and the next item is actually the previous item in the order + // of source locations. Thus, `Decl::redecls()` gives different lists for + // the different entries in a given redecl chain. + llvm::SmallVector getCanonicalForwardRedeclChain(Decl* D); + /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index f812244ed3..7dfcdeb8c4 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -71,6 +71,25 @@ namespace clang { + template + SmallVector + getCanonicalForwardRedeclChain(Redeclarable* D) { + SmallVector Redecls; + for (auto *R : D->getFirstDecl()->redecls()) { + if (R != D->getFirstDecl()) + Redecls.push_back(R); + } + Redecls.push_back(D->getFirstDecl()); + std::reverse(Redecls.begin(), Redecls.end()); + return Redecls; + } + + SmallVector getCanonicalForwardRedeclChain(Decl* D) { + // Currently only FunctionDecl is supported + auto FD = cast(D); + return getCanonicalForwardRedeclChain(FD); + } + class ASTNodeImporter : public TypeVisitor, public DeclVisitor, public StmtVisitor { @@ -195,6 +214,12 @@ namespace clang { const InContainerTy &Container, TemplateArgumentListInfo &Result); + using TemplateArgsTy = SmallVector; + using OptionalTemplateArgsTy = Optional; + std::tuple + ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD); + bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -408,6 +433,8 @@ namespace clang { // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); + + FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); }; template @@ -437,6 +464,25 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo< From.arguments(), Result); } +std::tuple +ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD) { + assert(FromFD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization); + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null( + Importer.Import(FTSInfo->getTemplate())); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + TemplateArgsTy ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) // Error during import. + return std::make_tuple(Template, OptionalTemplateArgsTy()); + + return std::make_tuple(Template, ToTemplArgs); +} + } // namespace clang //---------------------------------------------------------------------------- @@ -2252,23 +2298,17 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, } case FunctionDecl::TK_FunctionTemplateSpecialization: { - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); - auto *Template = cast_or_null( - Importer.Import(FTSInfo->getTemplate())); - if (!Template) - return true; - TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); - - // Import template arguments. - auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - SmallVector ToTemplArgs; - if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - ToTemplArgs)) + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) return true; TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( - Importer.getToContext(), ToTemplArgs); + Importer.getToContext(), *ToTemplArgs); + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) @@ -2277,6 +2317,7 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); ToFD->setFunctionTemplateSpecialization( Template, ToTAList, /* InsertPos= */ nullptr, TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); @@ -2312,7 +2353,31 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, llvm_unreachable("All cases should be covered!"); } +FunctionDecl * +ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) + return nullptr; + + void *InsertPos = nullptr; + auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); + return FoundSpec; +} + Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { + + SmallVector Redecls = getCanonicalForwardRedeclChain(D); + auto RedeclIt = Redecls.begin(); + // Import the first part of the decl chain. I.e. import all previous + // declarations starting from the canonical decl. + for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) + if (!Importer.Import(*RedeclIt)) + return nullptr; + assert(*RedeclIt == D); + // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2323,13 +2388,27 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; - const FunctionDecl *FoundWithoutBody = nullptr; - + const FunctionDecl *FoundByLookup = nullptr; + + // If this is a function template specialization, then try to find the same + // existing specialization in the "to" context. The localUncachedLookup + // below will not find any specialization, but would find the primary + // template; thus, we have to skip normal lookup in case of specializations. + // FIXME handle member function templates (TK_MemberSpecialization) similarly? + if (D->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody()) + return Importer.Imported(D, FoundFunction); + FoundByLookup = FoundFunction; + } + } // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. - if (!LexicalDC->isFunctionOrMethod()) { + else if (!LexicalDC->isFunctionOrMethod()) { SmallVector ConflictingDecls; - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; SmallVector FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { @@ -2341,15 +2420,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { - // FIXME: Actually try to merge the body and other attributes. - const FunctionDecl *FromBodyDecl = nullptr; - D->hasBody(FromBodyDecl); - if (D == FromBodyDecl && !FoundFunction->hasBody()) { - // This function is needed to merge completely. - FoundWithoutBody = FoundFunction; + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody()) + return Importer.Imported(D, FoundFunction); + FoundByLookup = FoundFunction; break; - } - return Importer.Imported(D, FoundFunction); } // FIXME: Check for overloading more carefully, e.g., by boosting @@ -2499,9 +2574,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setParams(Parameters); - if (FoundWithoutBody) { + if (FoundByLookup) { auto *Recent = const_cast( - FoundWithoutBody->getMostRecentDecl()); + FoundByLookup->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); } @@ -2523,10 +2598,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(T); } - // Import the body, if any. - if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); + if (D->doesThisDeclarationHaveABody()) { + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); + } } } @@ -2536,14 +2612,29 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ImportTemplateInformation(D, ToFunction)) return nullptr; - // Add this function to the lexical context. - // NOTE: If the function is templated declaration, it should be not added into - // LexicalDC. But described template is imported during import of - // FunctionTemplateDecl (it happens later). So, we use source declaration - // to determine if we should add the result function. - if (!D->getDescribedFunctionTemplate()) + bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); + + // TODO Can we generalize this approach to other AST nodes as well? + if (D->getDeclContext()->containsDecl(D)) + DC->addDeclInternal(ToFunction); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDecl(D)) LexicalDC->addDeclInternal(ToFunction); + // Friend declaration's lexical context is the befriending class, but the + // semantic context is the enclosing scope of the befriending class. + // We want the friend functions to be found in the semantic context by lookup. + // FIXME should we handle this generically in VisitFriendDecl? + // In Other cases when LexicalDC != DC we don't want it to be added, + // e.g out-of-class definitions like void B::f() {} . + if (LexicalDC != DC && IsFriend) { + DC->makeDeclVisibleInContext(ToFunction); + } + + // Import the rest of the chain. I.e. import all subsequent declarations. + for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) + if (!Importer.Import(*RedeclIt)) + return nullptr; + if (auto *FromCXXMethod = dyn_cast(D)) ImportOverrides(cast(ToFunction), FromCXXMethod); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 7b7febdc41..64fac22bac 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1343,6 +1343,8 @@ bool DeclContext::decls_empty() const { } bool DeclContext::containsDecl(Decl *D) const { + if (hasExternalLexicalStorage()) + LoadLexicalDeclsFromExternalStorage(); return (D->getLexicalDeclContext() == this && (D->NextInContextAndBits.getPointer() || D == LastDecl)); } diff --git a/test/ASTMerge/class/test.cpp b/test/ASTMerge/class/test.cpp index 99926b649b..ba553af407 100644 --- a/test/ASTMerge/class/test.cpp +++ b/test/ASTMerge/class/test.cpp @@ -13,12 +13,12 @@ // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here -// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units -// CHECK: class1.cpp:39:3: note: friend declared here -// CHECK: class2.cpp:30:8: note: no corresponding friend here - // CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units // CHECK: class1.cpp:46:3: note: friend declared here // CHECK: class2.cpp:36:8: note: no corresponding friend here +// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units +// CHECK: class1.cpp:39:3: note: friend declared here +// CHECK: class2.cpp:30:8: note: no corresponding friend here + // CHECK: 4 warnings generated. diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 77dbd43a7d..69611a4624 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -20,7 +20,7 @@ #include "DeclMatcher.h" #include "Language.h" -#include "gtest/gtest.h" +#include "gmock/gmock.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -428,6 +428,48 @@ struct ImportExpr : TestImportBase {}; struct ImportType : TestImportBase {}; struct ImportDecl : TestImportBase {}; +struct CanonicalRedeclChain : ASTImporterTestBase {}; + +TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { + Decl *FromTU = getTuDecl("void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + + auto Redecls = getCanonicalForwardRedeclChain(D0); + ASSERT_EQ(Redecls.size(), 1u); + EXPECT_EQ(D0, Redecls[0]); +} + +TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { + Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + auto *D2 = LastDeclMatcher().match(FromTU, Pattern); + FunctionDecl *D1 = D2->getPreviousDecl(); + + auto Redecls = getCanonicalForwardRedeclChain(D0); + ASSERT_EQ(Redecls.size(), 3u); + EXPECT_EQ(D0, Redecls[0]); + EXPECT_EQ(D1, Redecls[1]); + EXPECT_EQ(D2, Redecls[2]); +} + +TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { + Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + auto *D2 = LastDeclMatcher().match(FromTU, Pattern); + FunctionDecl *D1 = D2->getPreviousDecl(); + + auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); + auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); + auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); + + EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); + EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); +} + + TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier Verifier; testImport("void declToImport() { \"foo\"; }", @@ -1672,34 +1714,6 @@ TEST_P( struct ImportFunctions : ASTImporterTestBase {}; -TEST_P(ImportFunctions, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); -} - -TEST_P(ImportFunctions, - PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) { - Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = // Prototype - FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); -} - TEST_P(ImportFunctions, DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); @@ -1710,7 +1724,7 @@ TEST_P(ImportFunctions, Decl *ImportedD = Import(FromD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } @@ -1727,30 +1741,40 @@ TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } -TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) { +TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - FunctionDecl *PrototypeFD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *From = + FirstDeclMatcher().match(FromTU, Pattern); // Proto - Decl *ImportedD = Import(PrototypeFD, Lang_CXX); + Decl *ImportedD = Import(From, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - FunctionDecl *DefinitionFD = - LastDeclMatcher().match(FromTU, Pattern); + auto *From = + LastDeclMatcher().match(FromTU, Pattern); // Def - Decl *ImportedD = Import(DefinitionFD, Lang_CXX); + Decl *ImportedD = Import(From, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportPrototypes) { @@ -1759,23 +1783,48 @@ TEST_P(ImportFunctions, ImportPrototypes) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } - Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - ImportedD1 = Import(FromD, Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctions, ImportDefinitions) { + auto Pattern = functionDecl(hasName("f")); + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_EQ(ImportedD, ImportedD1); - EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { @@ -1784,23 +1833,24 @@ TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } - Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - ImportedD1 = Import(FromD, Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_EQ(ImportedD, ImportedD1); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { @@ -1823,38 +1873,40 @@ TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } -TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) { +TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { auto Pattern = functionDecl(hasName("f")); { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); Import(FromD, Lang_CXX); } { Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 3u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); + FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); + + EXPECT_TRUE(DefinitionD->getPreviousDecl()); + EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); + EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); } TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { @@ -1894,6 +1946,202 @@ TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { EXPECT_TRUE(To->isVirtual()); } +TEST_P(ImportFunctions, + ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { + Decl *ToTU = getToTuDecl( + R"( + void f() {} + void f(); + )", + Lang_CXX); + ASSERT_EQ(1u, + DeclCounterWithPredicate([](const FunctionDecl *FD) { + return FD->doesThisDeclarationHaveABody(); + }).match(ToTU, functionDecl())); + + Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, functionDecl()); + + Import(FromD, Lang_CXX); + + EXPECT_EQ(1u, + DeclCounterWithPredicate([](const FunctionDecl *FD) { + return FD->doesThisDeclarationHaveABody(); + }).match(ToTU, functionDecl())); +} + +struct ImportFriendFunctions : ImportFunctions {}; + +TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(); };" + "void f();", + Lang_CXX, + "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, + ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("void f();" + "struct X { friend void f(); };", + Lang_CXX, "input0.cc"); + auto FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(){} };" + "void f();", + Lang_CXX, + "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, + ImportFriendFunctionRedeclChainDef_OutOfClassDef) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(); };" + "void f(){}", + Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +// This test is disabled, because ATM we create a redundant FunctionDecl. We +// start the import with the definition of `f` then we continue with the import +// of the type of `f` which involves `X`. During the import of `X` we start +// again the import of the definition of `f` and then finally we create the +// node. But then in the first frame of `VisitFunctionDecl` we create a node +// again since we do not check if such a node exists yet or not. This is being +// fixed in a separate patch: https://reviews.llvm.org/D47632 +// FIXME enable this test once the above patch is approved. +TEST_P(ImportFriendFunctions, + DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl( + R"( + class X; + void f(X *x){} + class X{ + friend void f(X *x); + }; + )", + Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + auto *InClassFD = cast(FirstDeclMatcher() + .match(ToTU, friendDecl()) + ->getFriendDecl()); + EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); + // The parameters must refer the same type + EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), + (*ImportedD->param_begin())->getOriginalType()); +} + +// This test is disabled, because ATM we create a redundant FunctionDecl. We +// start the import with the definition of `f` then we continue with the import +// of the type of `f` which involves `X`. During the import of `X` we start +// again the import of the definition of `f` and then finally we create the +// node. But then in the first frame of `VisitFunctionDecl` we create a node +// again since we do not check if such a node exists yet or not. This is being +// fixed in a separate patch: https://reviews.llvm.org/D47632 +// FIXME enable this test once the above patch is approved. +TEST_P(ImportFriendFunctions, + DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl( + R"( + class X; + void f(X *x){} + class X{ + friend void f(X *x); + }; + )", + Lang_CXX, "input0.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *OutOfClassFD = FirstDeclMatcher().match( + ToTU, functionDecl(unless(hasParent(friendDecl())))); + + EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); + // The parameters must refer the same type + EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), + (*ImportedD->param_begin())->getOriginalType()); +} + +TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { + auto Pattern = functionDecl(hasName("f")); + + FunctionDecl *ImportedD; + { + Decl *FromTU = + getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = cast(Import(FromD, Lang_CXX)); + } + FunctionDecl *ImportedD1; + { + Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD1 = cast(Import(FromD, Lang_CXX)); + } + + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); +} + AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher, InnerMatcher) { if (auto *Typedef = Node.getTypedefNameForAnonDecl()) @@ -2024,9 +2272,328 @@ TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { EXPECT_FALSE(NS->containsDecl(Spec)); } +struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {}; + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldNotContainFunctionTemplateImplicitInstantiation) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + void foo() { f(); } + )", + Lang_CXX, "input0.cc"); + + // Check that the function template instantiation is NOT the child of the TU. + auto Pattern = translationUnitDecl( + unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + auto *Foo = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + ASSERT_TRUE(Import(Foo, Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldNotContainFunctionTemplateExplicitInstantiation) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template int f(); + )", + Lang_CXX, "input0.cc"); + + // Check that the function template instantiation is NOT the child of the TU. + auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); + auto Pattern = translationUnitDecl(unless(has(Instantiation))); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + ASSERT_TRUE( + Import(FirstDeclMatcher().match(FromTU, Instantiation), Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldContainFunctionTemplateSpecialization) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template <> int f() { return 4; } + )", + Lang_CXX, "input0.cc"); + + // Check that the function template specialization is the child of the TU. + auto Specialization = + functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Pattern = translationUnitDecl(has(Specialization)); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + ASSERT_TRUE( + Import(FirstDeclMatcher().match(FromTU, Specialization), Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + FunctionTemplateSpecializationRedeclChain) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template <> int f() { return 4; } + )", + Lang_CXX, "input0.cc"); + + auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), + hasParent(translationUnitDecl())); + auto *FromSpecD = FirstDeclMatcher().match(FromTU, Spec); + { + auto *TU = FromTU; + auto *SpecD = FromSpecD; + auto *TemplateD = FirstDeclMatcher().match( + TU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + ASSERT_EQ(SpecD, FirstSpecD); + ASSERT_TRUE(SpecD->getPreviousDecl()); + ASSERT_FALSE(cast(SpecD->getPreviousDecl()) + ->doesThisDeclarationHaveABody()); + } + + ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); + + { + auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); + auto *SpecD = FirstDeclMatcher().match(TU, Spec); + auto *TemplateD = FirstDeclMatcher().match( + TU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + EXPECT_EQ(SpecD, FirstSpecD); + ASSERT_TRUE(SpecD->getPreviousDecl()); + EXPECT_FALSE(cast(SpecD->getPreviousDecl()) + ->doesThisDeclarationHaveABody()); + } +} + +TEST_P(ImportFunctionTemplateSpecializations, + MatchNumberOfFunctionTemplateSpecializations) { + + Decl *FromTU = getTuDecl( + R"( + template constexpr int f() { return 0; } + template <> constexpr int f() { return 4; } + void foo() { + static_assert(f() == 0, ""); + static_assert(f() == 4, ""); + } + )", + Lang_CXX11, "input0.cc"); + auto *FromD = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + Import(FromD, Lang_CXX11); + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_EQ( + DeclCounter().match(FromTU, functionDecl(hasName("f"))), + DeclCounter().match(ToTU, functionDecl(hasName("f")))); +} + +TEST_P(ImportFunctionTemplateSpecializations, + ImportPrototypes) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Proto of the specialization. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + // Check that they are part of the same redecl chain. + EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); +} + +TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization and definition. + template <> + void f() {} + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + + auto *TemplateD = FirstDeclMatcher().match( + ToTU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); +} + +TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization proto. + template <> + void f(); + // Specialization proto. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization proto. + template <> + void f(); + // Specialization definition. + template <> + void f() {} + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization definition. + template <> + void f() {} + // Specialization proto. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, ::testing::Values(ArgVector()), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, CanonicalRedeclChain, + ::testing::Values(ArgVector()),); + auto DefaultTestValuesForRunOptions = ::testing::Values( ArgVector(), ArgVector{"-fdelayed-template-parsing"}, @@ -2048,5 +2615,12 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, + ImportFunctionTemplateSpecializations, + DefaultTestValuesForRunOptions, ); + } // end namespace ast_matchers } // end namespace clang -- GitLab From f65e8af1d209d15e3c9b2d1874c77bdb8b4c2140 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 25 Jun 2018 15:32:05 +0000 Subject: [PATCH 0256/1023] [OPENMP] Do not consider address constant vars as possibly threadprivate. Do not delay emission of the address constant variables in OpenMP mode as they cannot be defined as threadprivate. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335483 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 3 ++- test/OpenMP/constexpr_codegen.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/OpenMP/constexpr_codegen.cpp diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6595694ebd..5a2f2a01d3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1914,7 +1914,8 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // If OpenMP is enabled and threadprivates must be generated like TLS, delay // codegen for global variables, because they may be marked as threadprivate. if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && - getContext().getTargetInfo().isTLSSupported() && isa(Global)) + getContext().getTargetInfo().isTLSSupported() && isa(Global) && + !isTypeConstant(Global->getType(), false)) return false; return true; diff --git a/test/OpenMP/constexpr_codegen.cpp b/test/OpenMP/constexpr_codegen.cpp new file mode 100644 index 0000000000..f1fa4ac2a9 --- /dev/null +++ b/test/OpenMP/constexpr_codegen.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -triple x86_64-unknown-unknown -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// SIMD-ONLY1-NOT: {{__kmpc|__tgt}} + +// expected-no-diagnostics +// +#ifndef HEADER +#define HEADER + +// CHECK: @{{.*}}Foo{{.*}}bar{{.*}} = constant i32 1, + +// Section A - Define a class with a static constexpr data member. +struct Foo { + static constexpr int bar = 1; +}; + +// Section B - ODR-use the data member. +void F(const int &); +void Test() { F(Foo::bar); } + +// Section C - Define the data member. +constexpr int Foo::bar; +#endif + -- GitLab From a605c7e73552ba349e2ceb5baa8daba92d9faf98 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 25 Jun 2018 16:25:30 +0000 Subject: [PATCH 0257/1023] Revert "[ASTImporter] Import the whole redecl chain of functions" This reverts commit r335480. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335491 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTImporter.h | 9 - lib/AST/ASTImporter.cpp | 165 ++----- lib/AST/DeclBase.cpp | 2 - test/ASTMerge/class/test.cpp | 8 +- unittests/AST/ASTImporterTest.cpp | 714 +++--------------------------- 5 files changed, 111 insertions(+), 787 deletions(-) diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index de3bfbdf04..42f99f3f3f 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -43,15 +43,6 @@ class TagDecl; class TypeSourceInfo; class Attr; - // \brief Returns with a list of declarations started from the canonical decl - // then followed by subsequent decls in the translation unit. - // This gives a canonical list for each entry in the redecl chain. - // `Decl::redecls()` gives a list of decls which always start from the - // previous decl and the next item is actually the previous item in the order - // of source locations. Thus, `Decl::redecls()` gives different lists for - // the different entries in a given redecl chain. - llvm::SmallVector getCanonicalForwardRedeclChain(Decl* D); - /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 7dfcdeb8c4..f812244ed3 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -71,25 +71,6 @@ namespace clang { - template - SmallVector - getCanonicalForwardRedeclChain(Redeclarable* D) { - SmallVector Redecls; - for (auto *R : D->getFirstDecl()->redecls()) { - if (R != D->getFirstDecl()) - Redecls.push_back(R); - } - Redecls.push_back(D->getFirstDecl()); - std::reverse(Redecls.begin(), Redecls.end()); - return Redecls; - } - - SmallVector getCanonicalForwardRedeclChain(Decl* D) { - // Currently only FunctionDecl is supported - auto FD = cast(D); - return getCanonicalForwardRedeclChain(FD); - } - class ASTNodeImporter : public TypeVisitor, public DeclVisitor, public StmtVisitor { @@ -214,12 +195,6 @@ namespace clang { const InContainerTy &Container, TemplateArgumentListInfo &Result); - using TemplateArgsTy = SmallVector; - using OptionalTemplateArgsTy = Optional; - std::tuple - ImportFunctionTemplateWithTemplateArgsFromSpecialization( - FunctionDecl *FromFD); - bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -433,8 +408,6 @@ namespace clang { // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); - - FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); }; template @@ -464,25 +437,6 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo< From.arguments(), Result); } -std::tuple -ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( - FunctionDecl *FromFD) { - assert(FromFD->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization); - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); - auto *Template = cast_or_null( - Importer.Import(FTSInfo->getTemplate())); - - // Import template arguments. - auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - TemplateArgsTy ToTemplArgs; - if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - ToTemplArgs)) // Error during import. - return std::make_tuple(Template, OptionalTemplateArgsTy()); - - return std::make_tuple(Template, ToTemplArgs); -} - } // namespace clang //---------------------------------------------------------------------------- @@ -2298,17 +2252,23 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, } case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = - ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null( + Importer.Import(FTSInfo->getTemplate())); + if (!Template) + return true; + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + SmallVector ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) return true; TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( - Importer.getToContext(), *ToTemplArgs); + Importer.getToContext(), ToTemplArgs); - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) @@ -2317,7 +2277,6 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); - TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); ToFD->setFunctionTemplateSpecialization( Template, ToTAList, /* InsertPos= */ nullptr, TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); @@ -2353,31 +2312,7 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, llvm_unreachable("All cases should be covered!"); } -FunctionDecl * -ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = - ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) - return nullptr; - - void *InsertPos = nullptr; - auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); - return FoundSpec; -} - Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { - - SmallVector Redecls = getCanonicalForwardRedeclChain(D); - auto RedeclIt = Redecls.begin(); - // Import the first part of the decl chain. I.e. import all previous - // declarations starting from the canonical decl. - for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; - assert(*RedeclIt == D); - // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2388,27 +2323,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; - const FunctionDecl *FoundByLookup = nullptr; - - // If this is a function template specialization, then try to find the same - // existing specialization in the "to" context. The localUncachedLookup - // below will not find any specialization, but would find the primary - // template; thus, we have to skip normal lookup in case of specializations. - // FIXME handle member function templates (TK_MemberSpecialization) similarly? - if (D->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization) { - if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); - FoundByLookup = FoundFunction; - } - } + const FunctionDecl *FoundWithoutBody = nullptr; + // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. - else if (!LexicalDC->isFunctionOrMethod()) { + if (!LexicalDC->isFunctionOrMethod()) { SmallVector ConflictingDecls; - unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; + unsigned IDNS = Decl::IDNS_Ordinary; SmallVector FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { @@ -2420,11 +2341,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); - FoundByLookup = FoundFunction; + // FIXME: Actually try to merge the body and other attributes. + const FunctionDecl *FromBodyDecl = nullptr; + D->hasBody(FromBodyDecl); + if (D == FromBodyDecl && !FoundFunction->hasBody()) { + // This function is needed to merge completely. + FoundWithoutBody = FoundFunction; break; + } + return Importer.Imported(D, FoundFunction); } // FIXME: Check for overloading more carefully, e.g., by boosting @@ -2574,9 +2499,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setParams(Parameters); - if (FoundByLookup) { + if (FoundWithoutBody) { auto *Recent = const_cast( - FoundByLookup->getMostRecentDecl()); + FoundWithoutBody->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); } @@ -2598,11 +2523,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(T); } - if (D->doesThisDeclarationHaveABody()) { - if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); - } + // Import the body, if any. + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); } } @@ -2612,29 +2536,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ImportTemplateInformation(D, ToFunction)) return nullptr; - bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); - - // TODO Can we generalize this approach to other AST nodes as well? - if (D->getDeclContext()->containsDecl(D)) - DC->addDeclInternal(ToFunction); - if (DC != LexicalDC && D->getLexicalDeclContext()->containsDecl(D)) + // Add this function to the lexical context. + // NOTE: If the function is templated declaration, it should be not added into + // LexicalDC. But described template is imported during import of + // FunctionTemplateDecl (it happens later). So, we use source declaration + // to determine if we should add the result function. + if (!D->getDescribedFunctionTemplate()) LexicalDC->addDeclInternal(ToFunction); - // Friend declaration's lexical context is the befriending class, but the - // semantic context is the enclosing scope of the befriending class. - // We want the friend functions to be found in the semantic context by lookup. - // FIXME should we handle this generically in VisitFriendDecl? - // In Other cases when LexicalDC != DC we don't want it to be added, - // e.g out-of-class definitions like void B::f() {} . - if (LexicalDC != DC && IsFriend) { - DC->makeDeclVisibleInContext(ToFunction); - } - - // Import the rest of the chain. I.e. import all subsequent declarations. - for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; - if (auto *FromCXXMethod = dyn_cast(D)) ImportOverrides(cast(ToFunction), FromCXXMethod); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 64fac22bac..7b7febdc41 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1343,8 +1343,6 @@ bool DeclContext::decls_empty() const { } bool DeclContext::containsDecl(Decl *D) const { - if (hasExternalLexicalStorage()) - LoadLexicalDeclsFromExternalStorage(); return (D->getLexicalDeclContext() == this && (D->NextInContextAndBits.getPointer() || D == LastDecl)); } diff --git a/test/ASTMerge/class/test.cpp b/test/ASTMerge/class/test.cpp index ba553af407..99926b649b 100644 --- a/test/ASTMerge/class/test.cpp +++ b/test/ASTMerge/class/test.cpp @@ -13,12 +13,12 @@ // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here -// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units -// CHECK: class1.cpp:46:3: note: friend declared here -// CHECK: class2.cpp:36:8: note: no corresponding friend here - // CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units // CHECK: class1.cpp:39:3: note: friend declared here // CHECK: class2.cpp:30:8: note: no corresponding friend here +// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units +// CHECK: class1.cpp:46:3: note: friend declared here +// CHECK: class2.cpp:36:8: note: no corresponding friend here + // CHECK: 4 warnings generated. diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 69611a4624..77dbd43a7d 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -20,7 +20,7 @@ #include "DeclMatcher.h" #include "Language.h" -#include "gmock/gmock.h" +#include "gtest/gtest.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -428,48 +428,6 @@ struct ImportExpr : TestImportBase {}; struct ImportType : TestImportBase {}; struct ImportDecl : TestImportBase {}; -struct CanonicalRedeclChain : ASTImporterTestBase {}; - -TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { - Decl *FromTU = getTuDecl("void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); - - auto Redecls = getCanonicalForwardRedeclChain(D0); - ASSERT_EQ(Redecls.size(), 1u); - EXPECT_EQ(D0, Redecls[0]); -} - -TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { - Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); - auto *D2 = LastDeclMatcher().match(FromTU, Pattern); - FunctionDecl *D1 = D2->getPreviousDecl(); - - auto Redecls = getCanonicalForwardRedeclChain(D0); - ASSERT_EQ(Redecls.size(), 3u); - EXPECT_EQ(D0, Redecls[0]); - EXPECT_EQ(D1, Redecls[1]); - EXPECT_EQ(D2, Redecls[2]); -} - -TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { - Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); - auto *D2 = LastDeclMatcher().match(FromTU, Pattern); - FunctionDecl *D1 = D2->getPreviousDecl(); - - auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); - auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); - auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); - - EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); - EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); -} - - TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier Verifier; testImport("void declToImport() { \"foo\"; }", @@ -1714,6 +1672,34 @@ TEST_P( struct ImportFunctions : ASTImporterTestBase {}; +TEST_P(ImportFunctions, + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { + Decl *FromTU = getTuDecl("void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); +} + +TEST_P(ImportFunctions, + PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) { + Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + FunctionDecl *FromD = // Prototype + FirstDeclMatcher().match(FromTU, Pattern); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); +} + TEST_P(ImportFunctions, DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); @@ -1724,7 +1710,7 @@ TEST_P(ImportFunctions, Decl *ImportedD = Import(FromD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } @@ -1741,40 +1727,30 @@ TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } -TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { +TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - auto *From = - FirstDeclMatcher().match(FromTU, Pattern); // Proto + FunctionDecl *PrototypeFD = + FirstDeclMatcher().match(FromTU, Pattern); - Decl *ImportedD = Import(From, Lang_CXX); + Decl *ImportedD = Import(PrototypeFD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - auto *From = - LastDeclMatcher().match(FromTU, Pattern); // Def + FunctionDecl *DefinitionFD = + LastDeclMatcher().match(FromTU, Pattern); - Decl *ImportedD = Import(From, Lang_CXX); + Decl *ImportedD = Import(DefinitionFD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportPrototypes) { @@ -1783,48 +1759,23 @@ TEST_P(ImportFunctions, ImportPrototypes) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } + Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctions, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f")); - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); + ImportedD1 = Import(FromD, Lang_CXX); } - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD, ImportedD1); + EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { @@ -1833,24 +1784,23 @@ TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); } + Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); + ImportedD1 = Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_EQ(ImportedD, ImportedD1); + EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { @@ -1873,40 +1823,38 @@ TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); + EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } -TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { +TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) { auto Pattern = functionDecl(hasName("f")); { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } { Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher().match(FromTU, Pattern); Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 3u); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - + EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - - EXPECT_TRUE(DefinitionD->getPreviousDecl()); - EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); + EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { @@ -1946,202 +1894,6 @@ TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { EXPECT_TRUE(To->isVirtual()); } -TEST_P(ImportFunctions, - ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { - Decl *ToTU = getToTuDecl( - R"( - void f() {} - void f(); - )", - Lang_CXX); - ASSERT_EQ(1u, - DeclCounterWithPredicate([](const FunctionDecl *FD) { - return FD->doesThisDeclarationHaveABody(); - }).match(ToTU, functionDecl())); - - Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, functionDecl()); - - Import(FromD, Lang_CXX); - - EXPECT_EQ(1u, - DeclCounterWithPredicate([](const FunctionDecl *FD) { - return FD->doesThisDeclarationHaveABody(); - }).match(ToTU, functionDecl())); -} - -struct ImportFriendFunctions : ImportFunctions {}; - -TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(); };" - "void f();", - Lang_CXX, - "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, - ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("void f();" - "struct X { friend void f(); };", - Lang_CXX, "input0.cc"); - auto FromD = FirstDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(){} };" - "void f();", - Lang_CXX, - "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, - ImportFriendFunctionRedeclChainDef_OutOfClassDef) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(); };" - "void f(){}", - Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. -TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl( - R"( - class X; - void f(X *x){} - class X{ - friend void f(X *x); - }; - )", - Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - auto *InClassFD = cast(FirstDeclMatcher() - .match(ToTU, friendDecl()) - ->getFriendDecl()); - EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); - // The parameters must refer the same type - EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), - (*ImportedD->param_begin())->getOriginalType()); -} - -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. -TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl( - R"( - class X; - void f(X *x){} - class X{ - friend void f(X *x); - }; - )", - Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher().match(FromTU, Pattern); - - auto *ImportedD = cast(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *OutOfClassFD = FirstDeclMatcher().match( - ToTU, functionDecl(unless(hasParent(friendDecl())))); - - EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); - // The parameters must refer the same type - EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), - (*ImportedD->param_begin())->getOriginalType()); -} - -TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { - auto Pattern = functionDecl(hasName("f")); - - FunctionDecl *ImportedD; - { - Decl *FromTU = - getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = cast(Import(FromD, Lang_CXX)); - } - FunctionDecl *ImportedD1; - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD1 = cast(Import(FromD, Lang_CXX)); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); - EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); -} - AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher, InnerMatcher) { if (auto *Typedef = Node.getTypedefNameForAnonDecl()) @@ -2272,328 +2024,9 @@ TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { EXPECT_FALSE(NS->containsDecl(Spec)); } -struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {}; - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldNotContainFunctionTemplateImplicitInstantiation) { - - Decl *FromTU = getTuDecl( - R"( - template - int f() { return 0; } - void foo() { f(); } - )", - Lang_CXX, "input0.cc"); - - // Check that the function template instantiation is NOT the child of the TU. - auto Pattern = translationUnitDecl( - unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); - ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); - - auto *Foo = FirstDeclMatcher().match( - FromTU, functionDecl(hasName("foo"))); - ASSERT_TRUE(Import(Foo, Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldNotContainFunctionTemplateExplicitInstantiation) { - - Decl *FromTU = getTuDecl( - R"( - template - int f() { return 0; } - template int f(); - )", - Lang_CXX, "input0.cc"); - - // Check that the function template instantiation is NOT the child of the TU. - auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); - auto Pattern = translationUnitDecl(unless(has(Instantiation))); - ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); - - ASSERT_TRUE( - Import(FirstDeclMatcher().match(FromTU, Instantiation), Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldContainFunctionTemplateSpecialization) { - - Decl *FromTU = getTuDecl( - R"( - template - int f() { return 0; } - template <> int f() { return 4; } - )", - Lang_CXX, "input0.cc"); - - // Check that the function template specialization is the child of the TU. - auto Specialization = - functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Pattern = translationUnitDecl(has(Specialization)); - ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); - - ASSERT_TRUE( - Import(FirstDeclMatcher().match(FromTU, Specialization), Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - FunctionTemplateSpecializationRedeclChain) { - - Decl *FromTU = getTuDecl( - R"( - template - int f() { return 0; } - template <> int f() { return 4; } - )", - Lang_CXX, "input0.cc"); - - auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), - hasParent(translationUnitDecl())); - auto *FromSpecD = FirstDeclMatcher().match(FromTU, Spec); - { - auto *TU = FromTU; - auto *SpecD = FromSpecD; - auto *TemplateD = FirstDeclMatcher().match( - TU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - ASSERT_EQ(SpecD, FirstSpecD); - ASSERT_TRUE(SpecD->getPreviousDecl()); - ASSERT_FALSE(cast(SpecD->getPreviousDecl()) - ->doesThisDeclarationHaveABody()); - } - - ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); - - { - auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); - auto *SpecD = FirstDeclMatcher().match(TU, Spec); - auto *TemplateD = FirstDeclMatcher().match( - TU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - EXPECT_EQ(SpecD, FirstSpecD); - ASSERT_TRUE(SpecD->getPreviousDecl()); - EXPECT_FALSE(cast(SpecD->getPreviousDecl()) - ->doesThisDeclarationHaveABody()); - } -} - -TEST_P(ImportFunctionTemplateSpecializations, - MatchNumberOfFunctionTemplateSpecializations) { - - Decl *FromTU = getTuDecl( - R"( - template constexpr int f() { return 0; } - template <> constexpr int f() { return 4; } - void foo() { - static_assert(f() == 0, ""); - static_assert(f() == 4, ""); - } - )", - Lang_CXX11, "input0.cc"); - auto *FromD = FirstDeclMatcher().match( - FromTU, functionDecl(hasName("foo"))); - - Import(FromD, Lang_CXX11); - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_EQ( - DeclCounter().match(FromTU, functionDecl(hasName("f"))), - DeclCounter().match(ToTU, functionDecl(hasName("f")))); -} - -TEST_P(ImportFunctionTemplateSpecializations, - ImportPrototypes) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Proto of the specialization. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = LastDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - // Check that they are part of the same redecl chain. - EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization and definition. - template <> - void f() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - - auto *TemplateD = FirstDeclMatcher().match( - ToTU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization proto. - template <> - void f(); - // Specialization proto. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization proto. - template <> - void f(); - // Specialization definition. - template <> - void f() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template - void f(); - // Specialization definition. - template <> - void f() {} - // Specialization proto. - template <> - void f(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, ::testing::Values(ArgVector()), ); -INSTANTIATE_TEST_CASE_P( - ParameterizedTests, CanonicalRedeclChain, - ::testing::Values(ArgVector()),); - auto DefaultTestValuesForRunOptions = ::testing::Values( ArgVector(), ArgVector{"-fdelayed-template-parsing"}, @@ -2615,12 +2048,5 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, DefaultTestValuesForRunOptions, ); -INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, - DefaultTestValuesForRunOptions, ); - -INSTANTIATE_TEST_CASE_P(ParameterizedTests, - ImportFunctionTemplateSpecializations, - DefaultTestValuesForRunOptions, ); - } // end namespace ast_matchers } // end namespace clang -- GitLab From e0e097a759cc3c58306d8201dcc4e2f5fcc84e63 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Mon, 25 Jun 2018 16:29:19 +0000 Subject: [PATCH 0258/1023] [clang-format] Add a default format style that can be used by users of `getStyle` Summary: Tools that reformat code often call `getStyle` to decide the format style to use on a certain source file. In practice, "file" style is widely used. As a result, many tools hardcode "file" when calling `getStyle`, which makes it hard to control the default style in tools across a codebase when needed. This change introduces a `DefaultFormatStyle` constant (default to "file" in upstream), which can be modified downstream if wanted, so that all users/tools built from the same source tree can have a consistent default format style. This also adds an DefaultFallbackStyle that is recommended to be used by tools and can be modified downstream. Reviewers: sammccall, djasper Reviewed By: sammccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48492 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335492 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 9 +++++++++ lib/Format/Format.cpp | 4 ++++ tools/clang-format/ClangFormat.cpp | 21 +++++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 1d135fe1bd..36616e556a 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -1963,6 +1963,15 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle()); /// of ``getStyle()``. extern const char *StyleOptionHelpDescription; +/// The suggested format style to use by default. This allows tools using +/// `getStyle` to have a consistent default style. +/// Different builds can modify the value to the preferred styles. +extern const char *DefaultFormatStyle; + +/// The suggested predefined style to use as the fallback style in `getStyle`. +/// Different builds can modify the value to the preferred styles. +extern const char *DefaultFallbackStyle; + /// Construct a FormatStyle based on ``StyleName``. /// /// ``StyleName`` can take several forms: diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 76dfc81950..374c25064a 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -2144,6 +2144,10 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { return GuessedLanguage; } +const char *DefaultFormatStyle = "file"; + +const char *DefaultFallbackStyle = "LLVM"; + llvm::Expected getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, StringRef Code, vfs::FileSystem *FS) { diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index fdd0c41d08..de2f9d7fe7 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -60,17 +60,18 @@ LineRanges("lines", cl::desc(": - format a range of\n" "Can only be used with one input file."), cl::cat(ClangFormatCategory)); static cl::opt - Style("style", - cl::desc(clang::format::StyleOptionHelpDescription), - cl::init("file"), cl::cat(ClangFormatCategory)); + Style("style", cl::desc(clang::format::StyleOptionHelpDescription), + cl::init(clang::format::DefaultFormatStyle), + cl::cat(ClangFormatCategory)); static cl::opt -FallbackStyle("fallback-style", - cl::desc("The name of the predefined style used as a\n" - "fallback in case clang-format is invoked with\n" - "-style=file, but can not find the .clang-format\n" - "file to use.\n" - "Use -fallback-style=none to skip formatting."), - cl::init("LLVM"), cl::cat(ClangFormatCategory)); + FallbackStyle("fallback-style", + cl::desc("The name of the predefined style used as a\n" + "fallback in case clang-format is invoked with\n" + "-style=file, but can not find the .clang-format\n" + "file to use.\n" + "Use -fallback-style=none to skip formatting."), + cl::init(clang::format::DefaultFallbackStyle), + cl::cat(ClangFormatCategory)); static cl::opt AssumeFileName("assume-filename", -- GitLab From 983e34e0d748161c2f8bb21dfedc62ae1ddefda7 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Mon, 25 Jun 2018 16:49:52 +0000 Subject: [PATCH 0259/1023] Use Triple::isMIPS() instead of enumerating all Triples. NFC Reviewed By: atanasyan Differential Revision: https://reviews.llvm.org/D48549 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335495 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/Mips.cpp | 12 +++--------- lib/Basic/Targets/Mips.h | 5 +---- lib/Driver/ToolChains/Arch/Mips.cpp | 11 +---------- lib/Driver/ToolChains/Arch/Mips.h | 2 -- lib/Driver/ToolChains/CommonArgs.cpp | 5 +---- lib/Driver/ToolChains/FreeBSD.cpp | 19 ++++++------------- lib/Driver/ToolChains/Gnu.cpp | 21 ++++++--------------- lib/Driver/ToolChains/Linux.cpp | 17 +++++++---------- lib/Driver/ToolChains/NetBSD.cpp | 7 +++---- lib/Driver/ToolChains/OpenBSD.cpp | 6 +++--- 10 files changed, 31 insertions(+), 74 deletions(-) diff --git a/lib/Basic/Targets/Mips.cpp b/lib/Basic/Targets/Mips.cpp index 77fba482b6..cbd5a01c3d 100644 --- a/lib/Basic/Targets/Mips.cpp +++ b/lib/Basic/Targets/Mips.cpp @@ -200,9 +200,7 @@ ArrayRef MipsTargetInfo::getTargetBuiltins() const { bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { // microMIPS64R6 backend was removed. - if ((getTriple().getArch() == llvm::Triple::mips64 || - getTriple().getArch() == llvm::Triple::mips64el) && - IsMicromips && (ABI == "n32" || ABI == "n64")) { + if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU; return false; } @@ -222,9 +220,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend // can't handle this yet. It's better to fail here than on the // backend assertion. - if ((getTriple().getArch() == llvm::Triple::mips64 || - getTriple().getArch() == llvm::Triple::mips64el) && - ABI == "o32") { + if (getTriple().isMIPS64() && ABI == "o32") { Diags.Report(diag::err_target_unsupported_abi_for_triple) << ABI << getTriple().str(); return false; @@ -233,9 +229,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend // can't handle this yet. It's better to fail here than on the // backend assertion. - if ((getTriple().getArch() == llvm::Triple::mips || - getTriple().getArch() == llvm::Triple::mipsel) && - (ABI == "n32" || ABI == "n64")) { + if (getTriple().isMIPS32() && (ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_target_unsupported_abi_for_triple) << ABI << getTriple().str(); return false; diff --git a/lib/Basic/Targets/Mips.h b/lib/Basic/Targets/Mips.h index ff9e790fca..11e9ac9144 100644 --- a/lib/Basic/Targets/Mips.h +++ b/lib/Basic/Targets/Mips.h @@ -69,10 +69,7 @@ public: UseIndirectJumpHazard(false), HasFP64(false) { TheCXXABI.set(TargetCXXABI::GenericMIPS); - setABI((getTriple().getArch() == llvm::Triple::mips || - getTriple().getArch() == llvm::Triple::mipsel) - ? "o32" - : "n64"); + setABI(getTriple().isMIPS32() ? "o32" : "n64"); CPU = ABI == "o32" ? "mips32r2" : "mips64r2"; diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index a8bed7d752..85aef3295b 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -20,11 +20,6 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; -bool tools::isMipsArch(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || - Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; -} - // Get CPU and ABI names. They are not independent // so we have to calculate them together. void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, @@ -106,11 +101,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, if (ABIName.empty()) { // Deduce ABI name from the target triple. - if (Triple.getArch() == llvm::Triple::mips || - Triple.getArch() == llvm::Triple::mipsel) - ABIName = "o32"; - else - ABIName = "n64"; + ABIName = Triple.isMIPS32() ? "o32" : "n64"; } if (CPUName.empty()) { diff --git a/lib/Driver/ToolChains/Arch/Mips.h b/lib/Driver/ToolChains/Arch/Mips.h index 7e90488363..a232ddbc8f 100644 --- a/lib/Driver/ToolChains/Arch/Mips.h +++ b/lib/Driver/ToolChains/Arch/Mips.h @@ -21,8 +21,6 @@ namespace clang { namespace driver { namespace tools { -bool isMipsArch(llvm::Triple::ArchType Arch); - namespace mips { typedef enum { Legacy = 1, Std2008 = 2 } IEEE754Standard; diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 5bd012a6d8..43f7d7f3b7 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -1030,10 +1030,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { if ((ROPI || RWPI) && (PIC || PIE)) ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic); - if (Triple.getArch() == llvm::Triple::mips || - Triple.getArch() == llvm::Triple::mipsel || - Triple.getArch() == llvm::Triple::mips64 || - Triple.getArch() == llvm::Triple::mips64el) { + if (Triple.isMIPS()) { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index ef1b6471b4..b6c4e8fdd9 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -57,11 +57,10 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); - if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mips64) - CmdArgs.push_back("-EB"); - else + if (getToolChain().getTriple().isLittleEndian()) CmdArgs.push_back("-EL"); + else + CmdArgs.push_back("-EB"); if (Arg *A = Args.getLastArg(options::OPT_G)) { StringRef v = A->getValue(); @@ -179,10 +178,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (Arg *A = Args.getLastArg(options::OPT_G)) { - if (ToolChain.getArch() == llvm::Triple::mips || - ToolChain.getArch() == llvm::Triple::mipsel || - ToolChain.getArch() == llvm::Triple::mips64 || - ToolChain.getArch() == llvm::Triple::mips64el) { + if (ToolChain.getTriple().isMIPS()) { StringRef v = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-G" + v)); A->claim(); @@ -322,9 +318,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall // back to '/usr/lib' if it doesn't exist. - if ((Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::mips || - Triple.getArch() == llvm::Triple::mipsel || + if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() || Triple.getArch() == llvm::Triple::ppc) && D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o")) getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32"); @@ -389,8 +383,7 @@ bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } SanitizerMask FreeBSD::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; - const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 || - getTriple().getArch() == llvm::Triple::mips64el; + const bool IsMIPS64 = getTriple().isMIPS32(); SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; Res |= SanitizerKind::Vptr; diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index cc925c7027..deaf51dc77 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -707,11 +707,10 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, if (ABIName != "64" && !Args.hasArg(options::OPT_mno_abicalls)) CmdArgs.push_back("-call_nonpic"); - if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mips64) - CmdArgs.push_back("-EB"); - else + if (getToolChain().getTriple().isLittleEndian()) CmdArgs.push_back("-EL"); + else + CmdArgs.push_back("-EB"); if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { if (StringRef(A->getValue()) == "2008") @@ -835,14 +834,6 @@ static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb; } -static bool isMips32(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel; -} - -static bool isMips64(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; -} - static bool isMipsEL(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el; } @@ -1305,8 +1296,8 @@ bool clang::driver::findMIPSMultilibs(const Driver &D, llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); Multilib::flags_list Flags; - addMultilibFlag(isMips32(TargetArch), "m32", Flags); - addMultilibFlag(isMips64(TargetArch), "m64", Flags); + addMultilibFlag(TargetTriple.isMIPS32(), "m32", Flags); + addMultilibFlag(TargetTriple.isMIPS64(), "m64", Flags); addMultilibFlag(isMips16(Args), "mips16", Flags); addMultilibFlag(CPUName == "mips32", "march=mips32", Flags); addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" || @@ -2151,7 +2142,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs( if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) { // It should also work without multilibs in a simplified toolchain. findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected); - } else if (tools::isMipsArch(TargetArch)) { + } else if (TargetTriple.isMIPS()) { if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected)) return false; } else if (isRISCV(TargetArch)) { diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 9ef63b47d4..675d7b2029 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -156,7 +156,7 @@ static std::string getMultiarchTriple(const Driver &D, } static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { - if (tools::isMipsArch(Triple.getArch())) { + if (Triple.isMIPS()) { if (Triple.isAndroid()) { StringRef CPUName; StringRef ABIName; @@ -242,7 +242,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("-X"); const bool IsAndroid = Triple.isAndroid(); - const bool IsMips = tools::isMipsArch(Arch); + const bool IsMips = Triple.isMIPS(); const bool IsHexagon = Arch == llvm::Triple::hexagon; const bool IsRISCV = Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64; @@ -438,7 +438,7 @@ std::string Linux::computeSysRoot() const { return AndroidSysRootPath; } - if (!GCCInstallation.isValid() || !tools::isMipsArch(getTriple().getArch())) + if (!GCCInstallation.isValid() || !getTriple().isMIPS()) return std::string(); // Standalone MIPS toolchains use different names for sysroot folder @@ -530,8 +530,6 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: { - bool LE = (Triple.getArch() == llvm::Triple::mipsel) || - (Triple.getArch() == llvm::Triple::mips64el); bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple); LibDir = "lib" + tools::mips::getMipsABILibSuffix(Args, Triple); @@ -540,7 +538,8 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const { Loader = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0"; else if (!Triple.hasEnvironment() && Triple.getVendor() == llvm::Triple::VendorType::MipsTechnologies) - Loader = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1"; + Loader = + Triple.isLittleEndian() ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1"; else Loader = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1"; @@ -894,10 +893,8 @@ bool Linux::isPIEDefault() const { SanitizerMask Linux::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; - const bool IsMIPS = getTriple().getArch() == llvm::Triple::mips || - getTriple().getArch() == llvm::Triple::mipsel; - const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 || - getTriple().getArch() == llvm::Triple::mips64el; + const bool IsMIPS = getTriple().isMIPS32(); + const bool IsMIPS64 = getTriple().isMIPS64(); const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 || getTriple().getArch() == llvm::Triple::ppc64le; const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 || diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp index 2c5639496e..cbf5908d10 100644 --- a/lib/Driver/ToolChains/NetBSD.cpp +++ b/lib/Driver/ToolChains/NetBSD.cpp @@ -64,11 +64,10 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); - if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mips64) - CmdArgs.push_back("-EB"); - else + if (getToolChain().getTriple().isLittleEndian()) CmdArgs.push_back("-EL"); + else + CmdArgs.push_back("-EB"); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index a12d83d3b3..3a2a004306 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -68,10 +68,10 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); - if (getToolChain().getArch() == llvm::Triple::mips64) - CmdArgs.push_back("-EB"); - else + if (getToolChain().getTriple().isLittleEndian()) CmdArgs.push_back("-EL"); + else + CmdArgs.push_back("-EB"); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; -- GitLab From 9dee2b4694b92fbf366b5d322c48ad62c81d7b07 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Mon, 25 Jun 2018 17:27:51 +0000 Subject: [PATCH 0260/1023] [MachineOutliner] Make last of -moutline/-mno-outline win The expected behaviour of command-line flags to clang is to have the last of -m(whatever) and -mno-(whatever) win. The outliner didn't do that. This fixes that and updates the test. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335503 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 10 ++++++---- test/Driver/aarch64-outliner.c | 8 ++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 88e2f83f6d..248c460aa0 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1477,10 +1477,12 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-aarch64-enable-global-merge=true"); } - if (!Args.hasArg(options::OPT_mno_outline) && - Args.getLastArg(options::OPT_moutline)) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); + if (Arg *A = Args.getLastArg(options::OPT_moutline, + options::OPT_mno_outline)) { + if (A->getOption().matches(options::OPT_moutline)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner"); + } } } diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c index 94034566b3..311ee59901 100644 --- a/test/Driver/aarch64-outliner.c +++ b/test/Driver/aarch64-outliner.c @@ -1,9 +1,5 @@ // REQUIRES: aarch64-registered-target - // RUN: %clang -target aarch64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=ON // ON: "-mllvm" "-enable-machine-outliner" - -// RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF1 -// RUN: %clang -target aarch64 -mno-outline -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF2 -// OFF1-NOT: "-mllvm" "-enable-machine-outliner" -// OFF2-NOT: "-mllvm" "-enable-machine-outliner" +// RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF +// OFF-NOT: "-mllvm" "-enable-machine-outliner" -- GitLab From 7f4f83642fbc23380edd820247831effe53a8cb9 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Mon, 25 Jun 2018 17:36:05 +0000 Subject: [PATCH 0261/1023] [MachineOutliner] Outline from linkonceodrs by default in LTO when -moutline is passed Pass -enable-linkonceodr-outlining by default when LTO is enabled. The outliner shouldn't compete with any sort of linker deduplication on linkonceodr functions when LTO is enabled. Therefore, this behaviour should be the default. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335504 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 8 ++++++++ test/Driver/aarch64-outliner.c | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 248c460aa0..5cb3796723 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1482,6 +1482,14 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, if (A->getOption().matches(options::OPT_moutline)) { CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-enable-machine-outliner"); + + // The outliner shouldn't compete with linkers that dedupe linkonceodr + // functions in LTO. Enable that behaviour by default when compiling with + // LTO. + if (getToolChain().getDriver().isUsingLTO()) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-linkonceodr-outlining"); + } } } } diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c index 311ee59901..dd2ae2a66c 100644 --- a/test/Driver/aarch64-outliner.c +++ b/test/Driver/aarch64-outliner.c @@ -3,3 +3,7 @@ // ON: "-mllvm" "-enable-machine-outliner" // RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF // OFF-NOT: "-mllvm" "-enable-machine-outliner" +// RUN: %clang -target aarch64 -moutline -flto=thin -S %s -### 2>&1 | FileCheck %s -check-prefix=FLTO +// FLTO: "-mllvm" "-enable-linkonceodr-outlining" +// RUN: %clang -target aarch64 -moutline -flto=full -S %s -### 2>&1 | FileCheck %s -check-prefix=TLTO +// TLTO: "-mllvm" "-enable-linkonceodr-outlining" -- GitLab From f3b7928366f63b51ffc97e74f8afcff497c57e8d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 25 Jun 2018 18:47:32 +0000 Subject: [PATCH 0262/1023] [WebAssembly] Add no-prototype attribute to prototype-less C functions The WebAssembly backend in particular benefits from being able to distinguish between varargs functions (...) and prototype-less C functions. Differential Revision: https://reviews.llvm.org/D48443 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335510 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/TargetInfo.cpp | 9 +++++++++ test/CodeGen/no-prototype.c | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/CodeGen/no-prototype.c diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index b29bcce237..3fcafbbfd3 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -747,6 +747,15 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { public: explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) : TargetCodeGenInfo(new WebAssemblyABIInfo(CGT)) {} + + void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &CGM) const override { + if (auto *FD = dyn_cast_or_null(D)) { + llvm::Function *Fn = cast(GV); + if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype()) + Fn->addFnAttr("no-prototype"); + } + } }; /// Classify argument of given type \p Ty. diff --git a/test/CodeGen/no-prototype.c b/test/CodeGen/no-prototype.c new file mode 100644 index 0000000000..6030357b70 --- /dev/null +++ b/test/CodeGen/no-prototype.c @@ -0,0 +1,20 @@ +// REQUIRES: webassembly-registered-target +// RUN: %clang_cc1 -triple wasm32 -emit-llvm %s -o - | FileCheck %s + +int foo(); + +int bar(int a) { + return foo(); +} + +int baz() { + return foo(); +} + +// CHECK: define i32 @bar(i32 %a) [[BAR_ATTR:#[0-9]+]] { +// CHECK: declare i32 @foo(...) [[FOO_ATTR:#[0-9]+]] +// CHECK: define i32 @baz() [[BAZ_ATTR:#[0-9]+]] { + +// CHECK: attributes [[FOO_ATTR]] = { {{.*}}"no-prototype"{{.*}} } +// CHECK-NOT: attributes [[BAR_ATTR]] = { {{.*}}"no-prototype"{{.*}} } +// CHECK-NOT: attributes [[BAZ_ATTR]] = { {{.*}}"no-prototype"{{.*}} } -- GitLab From f479c70eb4f9546892e1bfc84b34fa54c8f6070e Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 25 Jun 2018 20:06:13 +0000 Subject: [PATCH 0263/1023] Revert "Append new attributes to the end of an AttributeList." This reverts commit r335084 as requested by David Jones and Eric Christopher because of differences of emitted warnings. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335516 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/AttributeList.h | 7 +-- lib/AST/ItaniumMangle.cpp | 6 +- lib/Parse/ParseDecl.cpp | 4 +- lib/Sema/SemaOverload.cpp | 47 ++++++++++----- lib/Serialization/ASTReaderDecl.cpp | 33 +++++++---- .../annotate-comments-availability-attrs.cpp | 2 +- test/Index/complete-with-annotations.cpp | 2 +- test/Misc/ast-print-pragmas.cpp | 17 +++--- test/PCH/pragma-loop.cpp | 21 ++++--- test/Parser/pragma-loop-safety.cpp | 8 +-- test/Parser/pragma-loop.cpp | 57 ++++++++++--------- test/Parser/pragma-unroll.cpp | 32 +++++------ test/Sema/attr-availability-tvos.c | 6 +- test/Sema/attr-availability.c | 4 +- test/Sema/attr-coldhot.c | 4 +- test/Sema/attr-disable-tail-calls.c | 4 +- test/Sema/attr-long-call.c | 4 +- test/Sema/attr-micromips.c | 4 +- test/Sema/attr-notail.c | 4 +- test/Sema/attr-ownership.c | 6 +- test/Sema/attr-ownership.cpp | 4 +- test/Sema/attr-print.c | 6 +- test/Sema/attr-swiftcall.c | 2 +- test/Sema/attr-target-mv.c | 2 +- test/Sema/attr-visibility.c | 4 +- test/Sema/internal_linkage.c | 4 +- test/Sema/mips-interrupt-attr.c | 8 +-- test/Sema/ms_abi-sysv_abi.c | 4 +- test/Sema/nullability.c | 4 +- test/Sema/stdcall-fastcall.c | 2 +- test/SemaCXX/attr-print.cpp | 2 +- test/SemaCXX/attr-swiftcall.cpp | 2 +- test/SemaCXX/decl-microsoft-call-conv.cpp | 2 +- test/SemaCXX/ms-uuid.cpp | 8 +-- test/SemaOpenCL/address-spaces.cl | 4 +- test/SemaTemplate/attributes.cpp | 4 +- 36 files changed, 188 insertions(+), 146 deletions(-) diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index dcbd116aa1..dd15b7a2f5 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -764,11 +764,8 @@ public: void add(AttributeList *newAttr) { assert(newAttr); assert(newAttr->getNext() == nullptr); - - // FIXME: AttributeList is a singly linked list, i.e. appending to the end - // requires walking to the last element. For adding n attributes, this - // requires O(n^2) time. However, AttributeLists should be very short. - addAllAtEnd(newAttr); + newAttr->setNext(list); + list = newAttr; } void addAll(AttributeList *newList) { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 86b9fb5d6a..d8c435991e 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -707,8 +707,10 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; - for (AttrVec::const_iterator I = FD->getAttrs().begin(), - E = FD->getAttrs().end(); + // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use + // it here. + for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(), + E = FD->getAttrs().rend(); I != E; ++I) { EnableIfAttr *EIA = dyn_cast(*I); if (!EIA) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e369156548..d1f87c9df0 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1649,7 +1649,9 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, } // Find end of type attributes Attrs and add NewTypeAttributes in the same - // order they were in originally. + // order they were in originally. (Remember, in AttributeList things earlier + // in source order are later in the list, since new attributes are added to + // the front of the list.) Attrs.addAllAtEnd(TypeAttrHead); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 34ac5c1647..d730bb27a1 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6189,6 +6189,24 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, return nullptr; } +// specific_attr_iterator iterates over enable_if attributes in reverse, and +// enable_if is order-sensitive. As a result, we need to reverse things +// sometimes. Size of 4 elements is arbitrary. +static SmallVector +getOrderedEnableIfAttrs(const FunctionDecl *Function) { + SmallVector Result; + if (!Function->hasAttrs()) + return Result; + + const auto &FuncAttrs = Function->getAttrs(); + for (Attr *Attr : FuncAttrs) + if (auto *EnableIf = dyn_cast(Attr)) + Result.push_back(EnableIf); + + std::reverse(Result.begin(), Result.end()); + return Result; +} + static bool convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, ArrayRef Args, Sema::SFINAETrap &Trap, @@ -6262,9 +6280,9 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef Args, bool MissingImplicitThis) { - auto EnableIfAttrs = Function->specific_attrs(); - - if (EnableIfAttrs.begin() == EnableIfAttrs.end()) + SmallVector EnableIfAttrs = + getOrderedEnableIfAttrs(Function); + if (EnableIfAttrs.empty()) return nullptr; SFINAETrap Trap(*this); @@ -6274,7 +6292,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef Args, if (!convertArgsForAvailabilityChecks( *this, Function, /*ThisArg=*/nullptr, Args, Trap, /*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs)) - return *EnableIfAttrs.begin(); + return EnableIfAttrs[0]; for (auto *EIA : EnableIfAttrs) { APValue Result; @@ -8923,21 +8941,24 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1Attr ? Comparison::Better : Comparison::Worse; } - auto Cand1Attrs = Cand1->specific_attrs(); - auto Cand2Attrs = Cand2->specific_attrs(); + // FIXME: The next several lines are just + // specific_attr_iterator but going in declaration order, + // instead of reverse order which is how they're stored in the AST. + auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1); + auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2); + + // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 + // has fewer enable_if attributes than Cand2. + if (Cand1Attrs.size() < Cand2Attrs.size()) + return Comparison::Worse; auto Cand1I = Cand1Attrs.begin(); llvm::FoldingSetNodeID Cand1ID, Cand2ID; - for (auto Cand2A : Cand2Attrs) { + for (auto &Cand2A : Cand2Attrs) { Cand1ID.clear(); Cand2ID.clear(); - // It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1 - // has fewer enable_if attributes than Cand2. - if (Cand1I == Cand1Attrs.end()) - return Comparison::Worse; - auto Cand1A = Cand1I++; - + auto &Cand1A = *Cand1I++; Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true); Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true); if (Cand1ID != Cand2ID) diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 0daf1b3bdb..a1ce26d27c 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2804,25 +2804,36 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A, // Note that pass_object_size attributes are represented in the function's // ExtParameterInfo, so we don't need to check them here. - // Return false if any of the enable_if expressions of A and B are different. + SmallVector AEnableIfs; + // Since this is an equality check, we can ignore that enable_if attrs show up + // in reverse order. + for (const auto *EIA : A->specific_attrs()) + AEnableIfs.push_back(EIA); + + SmallVector BEnableIfs; + for (const auto *EIA : B->specific_attrs()) + BEnableIfs.push_back(EIA); + + // Two very common cases: either we have 0 enable_if attrs, or we have an + // unequal number of enable_if attrs. + if (AEnableIfs.empty() && BEnableIfs.empty()) + return true; + + if (AEnableIfs.size() != BEnableIfs.size()) + return false; + llvm::FoldingSetNodeID Cand1ID, Cand2ID; - auto AEnableIfAttrs = A->specific_attrs(); - auto BEnableIfAttrs = B->specific_attrs(); - auto AEnableIf = AEnableIfAttrs.begin(); - auto BEnableIf = BEnableIfAttrs.begin(); - for (; AEnableIf != AEnableIfAttrs.end() && BEnableIf != BEnableIfAttrs.end(); - ++BEnableIf, ++AEnableIf) { + for (unsigned I = 0, E = AEnableIfs.size(); I != E; ++I) { Cand1ID.clear(); Cand2ID.clear(); - AEnableIf->getCond()->Profile(Cand1ID, A->getASTContext(), true); - BEnableIf->getCond()->Profile(Cand2ID, B->getASTContext(), true); + AEnableIfs[I]->getCond()->Profile(Cand1ID, A->getASTContext(), true); + BEnableIfs[I]->getCond()->Profile(Cand2ID, B->getASTContext(), true); if (Cand1ID != Cand2ID) return false; } - // Return false if the number of enable_if attributes was different. - return AEnableIf == AEnableIfAttrs.end() && BEnableIf == BEnableIfAttrs.end(); + return true; } /// Determine whether the two declarations refer to the same entity. diff --git a/test/Index/annotate-comments-availability-attrs.cpp b/test/Index/annotate-comments-availability-attrs.cpp index 2722c06fc8..f31c4e16cc 100644 --- a/test/Index/annotate-comments-availability-attrs.cpp +++ b/test/Index/annotate-comments-availability-attrs.cpp @@ -13,7 +13,7 @@ void attr_availability_1() __attribute__((availability(macosx,obsoleted=10.0,introduced=8.0,deprecated=9.0, message="use availability_test in "))) __attribute__((availability(ios,unavailable, message="not for iOS"))); -// CHECK: FullCommentAsXML=[attr_availability_1c:@F@attr_availability_1#void attr_availability_1() Aaa.8.09.010.0use availability_test in <foo.h>not for iOS] +// CHECK: FullCommentAsXML=[attr_availability_1c:@F@attr_availability_1#void attr_availability_1() Aaa.not for iOS8.09.010.0use availability_test in <foo.h>] /// Aaa. void attr_availability_2() __attribute__((availability(macosx,obsoleted=10.0.1,introduced=8.0.1,deprecated=9.0.1))); diff --git a/test/Index/complete-with-annotations.cpp b/test/Index/complete-with-annotations.cpp index 459bd9f573..7bad8f1b7c 100644 --- a/test/Index/complete-with-annotations.cpp +++ b/test/Index/complete-with-annotations.cpp @@ -14,7 +14,7 @@ void X::doSomething() { } // CHECK: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) -// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("one", "two", "three") +// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("three", "two", "one") // CHECK: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) ("some annotation") // CHECK: FieldDecl:{ResultType int}{TypedText member2} (35) ("another annotation", "some annotation") // CHECK: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (79) diff --git a/test/Misc/ast-print-pragmas.cpp b/test/Misc/ast-print-pragmas.cpp index a87be2a340..f1a7b2479b 100644 --- a/test/Misc/ast-print-pragmas.cpp +++ b/test/Misc/ast-print-pragmas.cpp @@ -1,8 +1,11 @@ // RUN: %clang_cc1 -ast-print %s -o - | FileCheck %s // RUN: %clang_cc1 -DMS_EXT -fsyntax-only -fms-extensions %s -triple x86_64-pc-win32 -ast-print | FileCheck %s --check-prefix=MS-EXT -// CHECK: #pragma clang loop vectorize_width(4) -// CHECK-NEXT: #pragma clang loop interleave_count(8){{$}} +// FIXME: A bug in ParsedAttributes causes the order of the attributes to be +// reversed. The checks are consequently in the reverse order below. + +// CHECK: #pragma clang loop interleave_count(8){{$}} +// CHECK-NEXT: #pragma clang loop vectorize_width(4) void test(int *List, int Length) { int i = 0; @@ -14,9 +17,9 @@ void test(int *List, int Length) { i++; } -// CHECK: #pragma clang loop distribute(disable) +// CHECK: #pragma clang loop interleave(disable) // CHECK-NEXT: #pragma clang loop vectorize(enable) -// CHECK-NEXT: #pragma clang loop interleave(disable) +// CHECK-NEXT: #pragma clang loop distribute(disable) #pragma clang loop distribute(disable) #pragma clang loop vectorize(enable) @@ -27,9 +30,9 @@ void test(int *List, int Length) { i++; } -// CHECK: #pragma clang loop distribute(enable) +// CHECK: #pragma clang loop interleave(enable) // CHECK-NEXT: #pragma clang loop vectorize(disable) -// CHECK-NEXT: #pragma clang loop interleave(enable) +// CHECK-NEXT: #pragma clang loop distribute(enable) #pragma clang loop distribute(enable) #pragma clang loop vectorize(disable) @@ -49,8 +52,8 @@ void test_nontype_template_param(int *List, int Length) { } } -// CHECK: #pragma clang loop vectorize_width(V) // CHECK: #pragma clang loop interleave_count(I) +// CHECK: #pragma clang loop vectorize_width(V) void test_templates(int *List, int Length) { test_nontype_template_param<2, 4>(List, Length); diff --git a/test/PCH/pragma-loop.cpp b/test/PCH/pragma-loop.cpp index b8079ff608..7f443ddb03 100644 --- a/test/PCH/pragma-loop.cpp +++ b/test/PCH/pragma-loop.cpp @@ -1,23 +1,26 @@ // RUN: %clang_cc1 -emit-pch -o %t.a %s // RUN: %clang_cc1 -include-pch %t.a %s -ast-print -o - | FileCheck %s -// CHECK: #pragma clang loop vectorize_width(4) -// CHECK: #pragma clang loop interleave_count(8) +// FIXME: A bug in ParsedAttributes causes the order of the attributes to be +// reversed. The checks are consequently in the reverse order below. + // CHECK: #pragma clang loop unroll_count(16){{$}} -// CHECK: #pragma clang loop vectorize(enable) -// CHECK: #pragma clang loop interleave(disable) -// CHECK: #pragma clang loop unroll(disable) +// CHECK: #pragma clang loop interleave_count(8) +// CHECK: #pragma clang loop vectorize_width(4) // CHECK: #pragma clang loop distribute(enable) -// CHECK: #pragma clang loop vectorize(disable) -// CHECK: #pragma clang loop interleave(enable) -// CHECK: #pragma clang loop unroll(full) +// CHECK: #pragma clang loop unroll(disable) +// CHECK: #pragma clang loop interleave(disable) +// CHECK: #pragma clang loop vectorize(enable) // CHECK: #pragma clang loop distribute(disable) +// CHECK: #pragma clang loop unroll(full) +// CHECK: #pragma clang loop interleave(enable) +// CHECK: #pragma clang loop vectorize(disable) // FIXME: "#pragma unroll (enable)" is invalid and is not the input source. // CHECK: #pragma unroll (enable){{$}} // CHECK: #pragma unroll (32){{$}} // CHECK: #pragma nounroll{{$}} -// CHECK: #pragma clang loop vectorize_width(V) // CHECK: #pragma clang loop interleave_count(I) +// CHECK: #pragma clang loop vectorize_width(V) #ifndef HEADER #define HEADER diff --git a/test/Parser/pragma-loop-safety.cpp b/test/Parser/pragma-loop-safety.cpp index 1393cf7474..ab87dcdcb6 100644 --- a/test/Parser/pragma-loop-safety.cpp +++ b/test/Parser/pragma-loop-safety.cpp @@ -25,10 +25,10 @@ void test(int *List, int Length) { List[i] = i; } -#pragma clang loop vectorize(enable) -/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(assume_safety)'}} */ #pragma clang loop vectorize(assume_safety) -#pragma clang loop interleave(enable) -/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(assume_safety)'}} */ #pragma clang loop interleave(assume_safety) +/* expected-error {{duplicate directives 'vectorize(assume_safety)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable) +#pragma clang loop vectorize(assume_safety) +/* expected-error {{duplicate directives 'interleave(assume_safety)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable) +#pragma clang loop interleave(assume_safety) while (i-9 < Length) { List[i] = i; } diff --git a/test/Parser/pragma-loop.cpp b/test/Parser/pragma-loop.cpp index 3db0fc4596..f42d196ce8 100644 --- a/test/Parser/pragma-loop.cpp +++ b/test/Parser/pragma-loop.cpp @@ -231,50 +231,51 @@ const int VV = 4; // of the next three tests rather than the last, and the order of the kinds // is also reversed. -#pragma clang loop vectorize_width(4) -/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable) -#pragma clang loop interleave_count(4) -/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable) -#pragma clang loop unroll_count(4) -/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable) +/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) +#pragma clang loop vectorize(disable) +/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) +#pragma clang loop interleave(disable) +/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) +#pragma clang loop unroll(disable) while (i-8 < Length) { List[i] = i; } -#pragma clang loop vectorize(enable) -/* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable) -#pragma clang loop interleave(enable) -/* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable) -#pragma clang loop unroll(full) -/* expected-error {{duplicate directives 'unroll(full)' and 'unroll(disable)'}} */ #pragma clang loop unroll(disable) -#pragma clang loop distribute(enable) -/* expected-error {{duplicate directives 'distribute(enable)' and 'distribute(disable)'}} */ #pragma clang loop distribute(disable) +/* expected-error {{duplicate directives 'vectorize(disable)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable) +#pragma clang loop vectorize(disable) +/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable) +#pragma clang loop interleave(disable) +/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(full)'}} */ #pragma clang loop unroll(full) +#pragma clang loop unroll(disable) +/* expected-error {{duplicate directives 'distribute(disable)' and 'distribute(enable)'}} */ #pragma clang loop distribute(enable) +#pragma clang loop distribute(disable) while (i-9 < Length) { List[i] = i; } -#pragma clang loop vectorize(disable) -/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) -#pragma clang loop interleave(disable) -/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) -#pragma clang loop unroll(disable) -/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) +/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable) +#pragma clang loop vectorize_width(4) +/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable) +#pragma clang loop interleave_count(4) +/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable) +#pragma clang loop unroll_count(4) while (i-10 < Length) { List[i] = i; } -#pragma clang loop vectorize_width(8) -/* expected-error {{duplicate directives 'vectorize_width(8)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4) -#pragma clang loop interleave_count(8) -/* expected-error {{duplicate directives 'interleave_count(8)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4) -#pragma clang loop unroll_count(8) -/* expected-error {{duplicate directives 'unroll_count(8)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) +/* expected-error {{duplicate directives 'vectorize_width(4)' and 'vectorize_width(8)'}} */ #pragma clang loop vectorize_width(8) +#pragma clang loop vectorize_width(4) +/* expected-error {{duplicate directives 'interleave_count(4)' and 'interleave_count(8)'}} */ #pragma clang loop interleave_count(8) +#pragma clang loop interleave_count(4) +/* expected-error {{duplicate directives 'unroll_count(4)' and 'unroll_count(8)'}} */ #pragma clang loop unroll_count(8) +#pragma clang loop unroll_count(4) while (i-11 < Length) { List[i] = i; } -#pragma clang loop unroll(full) -/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) + +/* expected-error {{incompatible directives 'unroll(full)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(full) +#pragma clang loop unroll_count(4) while (i-11 < Length) { List[i] = i; } diff --git a/test/Parser/pragma-unroll.cpp b/test/Parser/pragma-unroll.cpp index fb71381287..b1d7798798 100644 --- a/test/Parser/pragma-unroll.cpp +++ b/test/Parser/pragma-unroll.cpp @@ -55,56 +55,56 @@ void test(int *List, int Length) { #pragma nounroll /* expected-error {{expected a for, while, or do-while loop to follow '#pragma nounroll'}} */ int l = Length; -#pragma unroll 4 -/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(disable) +/* expected-error {{incompatible directives 'unroll(disable)' and '#pragma unroll(4)'}} */ #pragma unroll 4 +#pragma clang loop unroll(disable) while (i-10 < Length) { List[i] = i; } -#pragma unroll(4) -/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(full) +/* expected-error {{incompatible directives 'unroll(full)' and '#pragma unroll(4)'}} */ #pragma unroll(4) +#pragma clang loop unroll(full) while (i-11 < Length) { List[i] = i; } -#pragma unroll(4) -/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma clang loop unroll(enable) +/* expected-error {{incompatible directives 'unroll(enable)' and '#pragma unroll(4)'}} */ #pragma unroll(4) +#pragma clang loop unroll(enable) while (i-11 < Length) { List[i] = i; } -#pragma unroll(4) -/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll +/* expected-error {{incompatible directives '#pragma unroll' and '#pragma unroll(4)'}} */ #pragma unroll(4) +#pragma unroll while (i-11 < Length) { List[i] = i; } -#pragma clang loop unroll_count(4) -/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma nounroll +/* expected-error {{incompatible directives '#pragma nounroll' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4) +#pragma nounroll while (i-12 < Length) { List[i] = i; } -#pragma nounroll /* expected-error {{duplicate directives '#pragma nounroll' and '#pragma nounroll'}} */ #pragma nounroll +#pragma nounroll while (i-13 < Length) { List[i] = i; } -#pragma unroll /* expected-error {{duplicate directives '#pragma unroll' and '#pragma unroll'}} */ #pragma unroll +#pragma unroll while (i-14 < Length) { List[i] = i; } -#pragma unroll -/* expected-error {{duplicate directives '#pragma unroll' and 'unroll(full)'}} */ #pragma clang loop unroll(full) +/* expected-error {{duplicate directives 'unroll(full)' and '#pragma unroll'}} */ #pragma unroll +#pragma clang loop unroll(full) while (i-15 < Length) { List[i] = i; } -#pragma unroll 4 -/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll(4) +/* expected-error {{duplicate directives '#pragma unroll(4)' and '#pragma unroll(4)'}} */ #pragma unroll 4 +#pragma unroll(4) while (i-16 < Length) { List[i] = i; } diff --git a/test/Sema/attr-availability-tvos.c b/test/Sema/attr-availability-tvos.c index 4f8c4588ec..68337e49ce 100644 --- a/test/Sema/attr-availability-tvos.c +++ b/test/Sema/attr-availability-tvos.c @@ -27,8 +27,10 @@ void test_transcribed_availability() { f9(0); } -__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-warning 2{{availability does not match previous declaration}} -__attribute__((availability(ios,introduced=7_0))) // expected-note 2{{previous attribute is here}} +__attribute__((availability(ios,introduced=9_0,deprecated=9_0,message="" ))) // expected-note{{previous attribute is here}} \ + // expected-note{{previous attribute is here}} +__attribute__((availability(ios,introduced=7_0))) // expected-warning{{availability does not match previous declaration}} \ + // expected-warning{{availability does not match previous declaration}} void f10(int); // Test tvOS specific attributes. diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c index 4a26638252..1b8cbd256c 100644 --- a/test/Sema/attr-availability.c +++ b/test/Sema/attr-availability.c @@ -64,8 +64,8 @@ enum { void f4(int) __attribute__((availability(ios,deprecated=3.0))); void f4(int) __attribute__((availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} -void f5(int) __attribute__((availability(ios,deprecated=3.0), // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} - availability(ios,introduced=4.0))); +void f5(int) __attribute__((availability(ios,deprecated=3.0), + availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}} void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{previous attribute is here}} void f6(int) __attribute__((availability(ios,deprecated=4.0))); // expected-warning {{availability does not match previous declaration}} diff --git a/test/Sema/attr-coldhot.c b/test/Sema/attr-coldhot.c index a4b1582206..972f5a5266 100644 --- a/test/Sema/attr-coldhot.c +++ b/test/Sema/attr-coldhot.c @@ -6,7 +6,7 @@ int bar() __attribute__((__cold__)); int var1 __attribute__((__cold__)); // expected-warning{{'__cold__' attribute only applies to functions}} int var2 __attribute__((__hot__)); // expected-warning{{'__hot__' attribute only applies to functions}} -int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \ +int qux() __attribute__((__hot__)) __attribute__((__cold__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__hot__' and 'cold' attributes are not compatible}} \ +int baz() __attribute__((__cold__)) __attribute__((__hot__)); // expected-error{{'__cold__' and 'hot' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} diff --git a/test/Sema/attr-disable-tail-calls.c b/test/Sema/attr-disable-tail-calls.c index 0545e951e6..e8f5bcc73e 100644 --- a/test/Sema/attr-disable-tail-calls.c +++ b/test/Sema/attr-disable-tail-calls.c @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}} +void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}} __asm__(""); } -void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} expected-note {{conflicting attribute is here}} +void __attribute__((naked,disable_tail_calls)) foo2(int a) { // expected-error {{'naked' and 'disable_tail_calls' attributes are not compatible}} expected-note {{conflicting attribute is here}} __asm__(""); } diff --git a/test/Sema/attr-long-call.c b/test/Sema/attr-long-call.c index e80f8fdd52..cd3de1bf9e 100644 --- a/test/Sema/attr-long-call.c +++ b/test/Sema/attr-long-call.c @@ -19,8 +19,8 @@ __attribute((near)) void foo6(); __attribute((long_call, far)) void foo7(); __attribute((short_call, near)) void foo11(); -__attribute((far, near)) void foo8(); // expected-error {{'near' and 'far' attributes are not compatible}} \ +__attribute((far, near)) void foo8(); // expected-error {{'far' and 'near' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute((short_call, long_call)) void foo12(); // expected-error {{'long_call' and 'short_call' attributes are not compatible}} \ +__attribute((short_call, long_call)) void foo12(); // expected-error {{'short_call' and 'long_call' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} diff --git a/test/Sema/attr-micromips.c b/test/Sema/attr-micromips.c index 27c9d3b54f..fe587fa3db 100644 --- a/test/Sema/attr-micromips.c +++ b/test/Sema/attr-micromips.c @@ -6,9 +6,9 @@ __attribute__((micromips(1))) void foo2(); // expected-error {{'micromips' at __attribute((nomicromips)) int a; // expected-error {{attribute only applies to functions}} __attribute((micromips)) int b; // expected-error {{attribute only applies to functions}} -__attribute__((micromips,mips16)) void foo5(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \ +__attribute__((micromips,mips16)) void foo5(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16,micromips)) void foo6(); // expected-error {{'micromips' and 'mips16' attributes are not compatible}} \ +__attribute__((mips16,micromips)) void foo6(); // expected-error {{'mips16' and 'micromips' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} __attribute((micromips)) void foo7(); diff --git a/test/Sema/attr-notail.c b/test/Sema/attr-notail.c index f65af47518..4d05fcf6f2 100644 --- a/test/Sema/attr-notail.c +++ b/test/Sema/attr-notail.c @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \ +int callee0() __attribute__((not_tail_called,always_inline)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'not_tail_called' and 'always_inline' attributes are not compatible}} \ +int callee1() __attribute__((always_inline,not_tail_called)); // expected-error{{'always_inline' and 'not_tail_called' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} int foo(int a) { diff --git a/test/Sema/attr-ownership.c b/test/Sema/attr-ownership.c index 5ce758d9f4..ff6c7197df 100644 --- a/test/Sema/attr-ownership.c +++ b/test/Sema/attr-ownership.c @@ -16,11 +16,11 @@ void *f11(float i) __attribute__((ownership_returns(foo, 1))); // expected-erro void *f12(float i, int k, int f, int *j) __attribute__((ownership_returns(foo, 4))); // expected-error {{'ownership_returns' attribute only applies to integer arguments}} void f13(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_takes(foo, 2))); -void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_takes' and 'ownership_holds' attributes are not compatible}} +void f14(int i, int j, int *k) __attribute__((ownership_holds(foo, 3))) __attribute__((ownership_takes(foo, 3))); // expected-error {{'ownership_holds' and 'ownership_takes' attributes are not compatible}} void f15(int, int) - __attribute__((ownership_returns(foo, 1))) // expected-error {{'ownership_returns' attribute index does not match; here it is 1}} - __attribute__((ownership_returns(foo, 2))); // expected-note {{declared with index 2 here}} + __attribute__((ownership_returns(foo, 1))) // expected-note {{declared with index 1 here}} + __attribute__((ownership_returns(foo, 2))); // expected-error {{'ownership_returns' attribute index does not match; here it is 2}} void f16(int *i, int *j) __attribute__((ownership_holds(foo, 1))) __attribute__((ownership_holds(foo, 1))); // OK, same index void f17(void*) __attribute__((ownership_takes(__, 1))); void f18() __attribute__((ownership_takes(foo, 1))); // expected-warning {{'ownership_takes' attribute only applies to non-K&R-style functions}} diff --git a/test/Sema/attr-ownership.cpp b/test/Sema/attr-ownership.cpp index 7381285e2d..cde195ff0a 100644 --- a/test/Sema/attr-ownership.cpp +++ b/test/Sema/attr-ownership.cpp @@ -2,6 +2,6 @@ class C { void f(int, int) - __attribute__((ownership_returns(foo, 2))) // expected-error {{'ownership_returns' attribute index does not match; here it is 2}} - __attribute__((ownership_returns(foo, 3))); // expected-note {{declared with index 3 here}} + __attribute__((ownership_returns(foo, 2))) // expected-note {{declared with index 2 here}} + __attribute__((ownership_returns(foo, 3))); // expected-error {{'ownership_returns' attribute index does not match; here it is 3}} }; diff --git a/test/Sema/attr-print.c b/test/Sema/attr-print.c index 645b8bc3e7..16b440d5d7 100644 --- a/test/Sema/attr-print.c +++ b/test/Sema/attr-print.c @@ -24,13 +24,13 @@ int * __ptr64 p64; // TODO: the Type Printer has no way to specify the order to print attributes // in, and so it currently always prints them in reverse order. Fix this. -// CHECK: int * __uptr __ptr32 p32_2; +// CHECK: int * __ptr32 __uptr p32_2; int * __uptr __ptr32 p32_2; -// CHECK: int * __sptr __ptr64 p64_2; +// CHECK: int * __ptr64 __sptr p64_2; int * __sptr __ptr64 p64_2; -// CHECK: int * __uptr __ptr32 p32_3; +// CHECK: int * __ptr32 __uptr p32_3; int * __uptr __ptr32 p32_3; // CHECK: int * __sptr * __ptr32 ppsp32; diff --git a/test/Sema/attr-swiftcall.c b/test/Sema/attr-swiftcall.c index 77cf1b314d..0323f059ba 100644 --- a/test/Sema/attr-swiftcall.c +++ b/test/Sema/attr-swiftcall.c @@ -9,7 +9,7 @@ int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} void unprototyped() SWIFTCALL; // expected-error {{function with no prototype cannot use the swiftcall calling convention}} -void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{swiftcall and vectorcall attributes are not compatible}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} diff --git a/test/Sema/attr-target-mv.c b/test/Sema/attr-target-mv.c index e65f6486fb..671adff5b0 100644 --- a/test/Sema/attr-target-mv.c +++ b/test/Sema/attr-target-mv.c @@ -95,7 +95,7 @@ void __attribute__((target("arch=sandybridge"))) addtl_attrs4(void); void __attribute__((used,target("arch=ivybridge"))) addtl_attrs4(void); int __attribute__((target("sse4.2"))) diff_cc(void); -// expected-error@+1 {{attribute 'target' multiversioning cannot be combined with other attributes}} +// expected-error@+1 {{multiversioned function declaration has a different calling convention}} __vectorcall int __attribute__((target("arch=sandybridge"))) diff_cc(void); int __attribute__((target("sse4.2"))) diff_ret(void); diff --git a/test/Sema/attr-visibility.c b/test/Sema/attr-visibility.c index 798d6dcd78..ed52ec2743 100644 --- a/test/Sema/attr-visibility.c +++ b/test/Sema/attr-visibility.c @@ -15,8 +15,8 @@ struct test5; struct __attribute__((visibility("hidden"))) test5; // expected-note {{previous attribute is here}} struct __attribute__((visibility("default"))) test5; // expected-error {{visibility does not match previous declaration}} -void test6() __attribute__((visibility("default"), // expected-error {{visibility does not match previous declaration}} - visibility("hidden"))); // expected-note {{previous attribute is here}} +void test6() __attribute__((visibility("hidden"), // expected-note {{previous attribute is here}} + visibility("default"))); // expected-error {{visibility does not match previous declaration}} extern int test7 __attribute__((visibility("default"))); // expected-note {{previous attribute is here}} extern int test7 __attribute__((visibility("hidden"))); // expected-error {{visibility does not match previous declaration}} diff --git a/test/Sema/internal_linkage.c b/test/Sema/internal_linkage.c index cc8039acd2..57315d826e 100644 --- a/test/Sema/internal_linkage.c +++ b/test/Sema/internal_linkage.c @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fdouble-square-bracket-attributes %s int var __attribute__((internal_linkage)); -int var2 __attribute__((internal_linkage,common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ +int var2 __attribute__((internal_linkage,common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} -int var3 __attribute__((common,internal_linkage)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \ +int var3 __attribute__((common,internal_linkage)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ // expected-note{{conflicting attribute is here}} int var4 __attribute__((common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ diff --git a/test/Sema/mips-interrupt-attr.c b/test/Sema/mips-interrupt-attr.c index 7c5c9ddab5..17344b6edc 100644 --- a/test/Sema/mips-interrupt-attr.c +++ b/test/Sema/mips-interrupt-attr.c @@ -19,11 +19,11 @@ __attribute__((interrupt(""))) void food() {} __attribute__((interrupt)) int foob() {return 0;} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have a 'void' return type}} __attribute__((interrupt())) void fooc(int a) {} // expected-warning {{MIPS 'interrupt' attribute only applies to functions that have no parameters}} -__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ +__attribute__((interrupt,mips16)) void fooe() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ +__attribute__((mips16,interrupt)) void foof() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ +__attribute__((interrupt)) __attribute__ ((mips16)) void foo10() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} -__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'interrupt' and 'mips16' attributes are not compatible}} \ +__attribute__((mips16)) __attribute ((interrupt)) void foo11() {} // expected-error {{'mips16' and 'interrupt' attributes are not compatible}} \ // expected-note {{conflicting attribute is here}} diff --git a/test/Sema/ms_abi-sysv_abi.c b/test/Sema/ms_abi-sysv_abi.c index e97914d7dd..35a5fad9ce 100644 --- a/test/Sema/ms_abi-sysv_abi.c +++ b/test/Sema/ms_abi-sysv_abi.c @@ -6,9 +6,9 @@ int __attribute__((sysv_abi)) var2; // expected-warning{{'sysv_abi' only applies // Different CC qualifiers are not compatible // FIXME: Should say 'sysv_abi' instead of 'cdecl' -void __attribute__((ms_abi, sysv_abi)) foo3(void); // expected-error{{ms_abi and cdecl attributes are not compatible}} +void __attribute__((ms_abi, sysv_abi)) foo3(void); // expected-error{{cdecl and ms_abi attributes are not compatible}} void __attribute__((ms_abi)) foo4(); // expected-note{{previous declaration is here}} void __attribute__((sysv_abi)) foo4(void); // expected-error{{function declared 'cdecl' here was previously declared 'ms_abi'}} -void bar(int i, int j) __attribute__((ms_abi, cdecl)); // expected-error{{ms_abi and cdecl attributes are not compatible}} +void bar(int i, int j) __attribute__((ms_abi, cdecl)); // expected-error{{cdecl and ms_abi attributes are not compatible}} void bar2(int i, int j) __attribute__((sysv_abi, cdecl)); // no-error diff --git a/test/Sema/nullability.c b/test/Sema/nullability.c index cc251257e4..a0247e5af8 100644 --- a/test/Sema/nullability.c +++ b/test/Sema/nullability.c @@ -20,8 +20,8 @@ typedef int * _Null_unspecified null_unspecified_int_ptr; typedef int * _Nonnull _Nonnull redundant_1; // expected-warning{{duplicate nullability specifier '_Nonnull'}} // Conflicting nullability type specifiers. -typedef int *_Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}} -typedef int *_Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Null_unspecified'}} +typedef int * _Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Nullable'}} +typedef int * _Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Null_unspecified' conflicts with existing specifier '_Nonnull'}} // Redundant nullability specifiers via a typedef are okay. typedef nonnull_int_ptr _Nonnull redundant_okay_1; diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c index e011b45518..256f5588e6 100644 --- a/test/Sema/stdcall-fastcall.c +++ b/test/Sema/stdcall-fastcall.c @@ -5,7 +5,7 @@ int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies t int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}} // Different CC qualifiers are not compatible -void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}} +void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{fastcall and stdcall attributes are not compatible}} void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}} expected-warning{{function with no prototype cannot use the stdcall calling convention}} void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}} diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index b741574b12..960050bc71 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -14,7 +14,7 @@ void foo() __attribute__((const)); void bar() __attribute__((__const)); // FIXME: Print this with correct format and order. -// CHECK: void foo1() __attribute__((noinline)) __attribute__((pure)); +// CHECK: void foo1() __attribute__((pure)) __attribute__((noinline)); void foo1() __attribute__((noinline, pure)); // CHECK: typedef int Small1 __attribute__((mode(byte))); diff --git a/test/SemaCXX/attr-swiftcall.cpp b/test/SemaCXX/attr-swiftcall.cpp index be4d4e8f77..eb9538e310 100644 --- a/test/SemaCXX/attr-swiftcall.cpp +++ b/test/SemaCXX/attr-swiftcall.cpp @@ -7,7 +7,7 @@ int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} -void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{swiftcall and vectorcall attributes are not compatible}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} void (*functionPointer)(void) SWIFTCALL; void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index 232549988e..acd9b0720b 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -161,7 +161,7 @@ void multi_attribute(int x) { __builtin_unreachable(); } // expected-error@+3 {{vectorcall and cdecl attributes are not compatible}} // expected-error@+2 {{stdcall and cdecl attributes are not compatible}} // expected-error@+1 {{fastcall and cdecl attributes are not compatible}} -void __vectorcall __fastcall __cdecl __stdcall __cdecl __cdecl multi_cc(int x); +void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x); template void __stdcall StdcallTemplate(T) {} template <> void StdcallTemplate(int) {} diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp index c177570682..624ac0541d 100644 --- a/test/SemaCXX/ms-uuid.cpp +++ b/test/SemaCXX/ms-uuid.cpp @@ -62,14 +62,14 @@ class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2; [uuid("220000A0-0000-0000-C000-000000000049")] class C4 {}; // Both cl and clang-cl error out on this: -// expected-error@+1 {{uuid does not match previous declaration}} -class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) // expected-note@+1 {{previous uuid specified here}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) +// expected-error@+1 {{uuid does not match previous declaration}} __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5; -// expected-error@+1 {{uuid does not match previous declaration}} -[uuid("000000A0-0000-0000-C000-000000000049"), // expected-note@+1 {{previous uuid specified here}} +[uuid("000000A0-0000-0000-C000-000000000049"), +// expected-error@+1 {{uuid does not match previous declaration}} uuid("110000A0-0000-0000-C000-000000000049")] class C6; // cl doesn't diagnose having one uuid each as []-style attributes and as diff --git a/test/SemaOpenCL/address-spaces.cl b/test/SemaOpenCL/address-spaces.cl index 3ac2569bc2..52c891e16b 100644 --- a/test/SemaOpenCL/address-spaces.cl +++ b/test/SemaOpenCL/address-spaces.cl @@ -61,8 +61,8 @@ __generic int func_return_generic(void); //expected-error {{return value cann void func_multiple_addr(void) { typedef __private int private_int_t; - __private __local int var1; // expected-error {{multiple address spaces specified for type}} - __private __local int *var2; // expected-error {{multiple address spaces specified for type}} + __local __private int var1; // expected-error {{multiple address spaces specified for type}} + __local __private int *var2; // expected-error {{multiple address spaces specified for type}} __local private_int_t var3; // expected-error {{multiple address spaces specified for type}} __local private_int_t *var4; // expected-error {{multiple address spaces specified for type}} __private private_int_t var5; // expected-warning {{multiple identical address spaces specified for type}} diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp index 7a04c4705b..7634b937c9 100644 --- a/test/SemaTemplate/attributes.cpp +++ b/test/SemaTemplate/attributes.cpp @@ -55,11 +55,11 @@ namespace PR9049 { } // CHECK: FunctionTemplateDecl {{.*}} HasAnnotations -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" // CHECK: FunctionDecl {{.*}} HasAnnotations // CHECK: TemplateArgument type 'int' -// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" // CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR" +// CHECK: AnnotateAttr {{.*}} "ANNOTATE_FOO" template [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations(); void UseAnnotations() { HasAnnotations(); } -- GitLab From 50ebf26c30b297dbea9c20d993415b13f27b0300 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 25 Jun 2018 22:24:17 +0000 Subject: [PATCH 0264/1023] Warning for framework include violation from Headers to PrivateHeaders Framework vendors usually layout their framework headers in the following way: Foo.framework/Headers -> "public" headers Foo.framework/PrivateHeader -> "private" headers Since both headers in both directories can be found with #import , it's easy to make mistakes and include headers in Foo.framework/PrivateHeader from headers in Foo.framework/Headers, which usually configures a layering violation on Darwin ecosystems. One of the problem this causes is dep cycles when modules are used, since it's very common for "private" modules to include from the "public" ones; adding an edge the other way around will trigger cycles. Add a warning to catch those cases such that: ./A.framework/Headers/A.h:1:10: warning: public framework header includes private framework header 'A/APriv.h' #include ^ rdar://problem/38712182 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335542 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 2 + include/clang/Basic/DiagnosticLexKinds.td | 3 ++ lib/Lex/HeaderSearch.cpp | 25 ++++++++--- .../A.framework/Headers/A.h | 4 ++ .../A.framework/Modules/module.modulemap | 4 ++ .../Modules/module.private.modulemap | 4 ++ .../A.framework/PrivateHeaders/APriv.h | 1 + .../A.framework/PrivateHeaders/APriv2.h | 1 + .../a.hmap.json | 8 ++++ .../flat-header-path/Z.h | 2 + .../flat-header-path/Z.modulemap | 4 ++ .../flat-header-path/Z.private.modulemap | 4 ++ .../flat-header-path/ZPriv.h | 1 + .../z.hmap.json | 7 +++ .../framework-public-includes-private/z.yaml | 45 +++++++++++++++++++ .../framework-public-includes-private.m | 37 +++++++++++++++ 16 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h create mode 100644 test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap create mode 100644 test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h create mode 100644 test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h create mode 100644 test/Modules/Inputs/framework-public-includes-private/a.hmap.json create mode 100644 test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h create mode 100644 test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap create mode 100644 test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap create mode 100644 test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h create mode 100644 test/Modules/Inputs/framework-public-includes-private/z.hmap.json create mode 100644 test/Modules/Inputs/framework-public-includes-private/z.yaml create mode 100644 test/Modules/framework-public-includes-private.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 7cc9967738..56384db124 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -32,6 +32,8 @@ def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; +def FrameworkIncludePrivateFromPublic : + DiagGroup<"framework-include-private-from-public">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index de6bffcdca..5d1e149eab 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -718,6 +718,9 @@ def warn_quoted_include_in_framework_header : Warning< "double-quoted include \"%0\" in framework header, " "expected angle-bracketed instead" >, InGroup, DefaultIgnore; +def warn_framework_include_private_from_public : Warning< + "public framework header includes private framework header '%0'" + >, InGroup; def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 757cd097e4..312bd2d061 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,11 +621,12 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } -static bool isFrameworkStylePath(StringRef Path, +static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, SmallVectorImpl &FrameworkName) { using namespace llvm::sys; path::const_iterator I = path::begin(Path); path::const_iterator E = path::end(Path); + IsPrivateHeader = false; // Detect different types of framework style paths: // @@ -637,12 +638,16 @@ static bool isFrameworkStylePath(StringRef Path, // and some other variations among these lines. int FoundComp = 0; while (I != E) { + if (*I == "Headers") + ++FoundComp; if (I->endswith(".framework")) { FrameworkName.append(I->begin(), I->end()); ++FoundComp; } - if (*I == "Headers" || *I == "PrivateHeaders") + if (*I == "PrivateHeaders") { ++FoundComp; + IsPrivateHeader = true; + } ++I; } @@ -654,11 +659,13 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, StringRef Includer, StringRef IncludeFilename, const FileEntry *IncludeFE, bool isAngled = false, bool FoundByHeaderMap = false) { + bool IsIncluderPrivateHeader = false; SmallString<128> FromFramework, ToFramework; - if (!isFrameworkStylePath(Includer, FromFramework)) + if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework)) return; - bool IsIncludeeInFramework = - isFrameworkStylePath(IncludeFE->getName(), ToFramework); + bool IsIncludeePrivateHeader = false; + bool IsIncludeeInFramework = isFrameworkStylePath( + IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework); if (!isAngled && !FoundByHeaderMap) { SmallString<128> NewInclude("<"); @@ -672,6 +679,14 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, << IncludeFilename << FixItHint::CreateReplacement(IncludeLoc, NewInclude); } + + // Headers in Foo.framework/Headers should not include headers + // from Foo.framework/PrivateHeaders, since this violates public/private + // API boundaries and can cause modular dependency cycles. + if (!IsIncluderPrivateHeader && IsIncludeeInFramework && + IsIncludeePrivateHeader && FromFramework == ToFramework) + Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public) + << IncludeFilename; } /// LookupFile - Given a "foo" or \ reference, look up the indicated file, diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h new file mode 100644 index 0000000000..03bd90b494 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Headers/A.h @@ -0,0 +1,4 @@ +#include +#include "APriv2.h" +#include +int foo(); diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..09639b2b50 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +// framework-public-includes-private/A.framework/Modules/module.modulemap +framework module A { + header "A.h" +} diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000..8ede0b0d6e --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/Modules/module.private.modulemap @@ -0,0 +1,4 @@ +// framework-public-includes-private/A.framework/Modules/module.private.modulemap +framework module A_Private { + header "APriv.h" +} diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h new file mode 100644 index 0000000000..34cc847512 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv.h @@ -0,0 +1 @@ +// framework-public-includes-private/A.framework/PrivateHeaders/APriv.h diff --git a/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h new file mode 100644 index 0000000000..8ffeb41837 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h @@ -0,0 +1 @@ +// framework-public-includes-private/A.framework/PrivateHeaders/APriv2.h diff --git a/test/Modules/Inputs/framework-public-includes-private/a.hmap.json b/test/Modules/Inputs/framework-public-includes-private/a.hmap.json new file mode 100644 index 0000000000..42aed4551c --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/a.hmap.json @@ -0,0 +1,8 @@ + +{ + "mappings" : + { + "A.h" : "A/A.h", + "APriv2.h" : "A/APriv2.h" + } +} diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h new file mode 100644 index 0000000000..157c6daa76 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.h @@ -0,0 +1,2 @@ +// framework-public-includes-private/flat-header-path/Z.h +#import "ZPriv.h" diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap new file mode 100644 index 0000000000..0a1a9710c4 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.modulemap @@ -0,0 +1,4 @@ +// framework-public-includes-private/flat-header-path/Z.modulemap +framework module Z { + header "Z.h" +} diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap new file mode 100644 index 0000000000..f409af8a15 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/Z.private.modulemap @@ -0,0 +1,4 @@ +// framework-public-includes-private/flat-header-path/Z.private.modulemap +framework module Z_Private { + header "ZPriv.h" +} diff --git a/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h new file mode 100644 index 0000000000..08532fedbf --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/flat-header-path/ZPriv.h @@ -0,0 +1 @@ +// framework-public-includes-private/flat-header-path/ZPriv.h diff --git a/test/Modules/Inputs/framework-public-includes-private/z.hmap.json b/test/Modules/Inputs/framework-public-includes-private/z.hmap.json new file mode 100644 index 0000000000..206b25ec73 --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/z.hmap.json @@ -0,0 +1,7 @@ + +{ + "mappings" : + { + "ZPriv.h" : "Z/ZPriv.h" + } +} diff --git a/test/Modules/Inputs/framework-public-includes-private/z.yaml b/test/Modules/Inputs/framework-public-includes-private/z.yaml new file mode 100644 index 0000000000..5793c1ff1f --- /dev/null +++ b/test/Modules/Inputs/framework-public-includes-private/z.yaml @@ -0,0 +1,45 @@ +{ + 'version': 0, + 'case-sensitive': 'false', + 'use-external-names' : 'false', + 'roots': [ + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Headers", + 'contents': [ + { + 'type': 'file', + 'name': "Z.h", + 'external-contents': "TEST_DIR/flat-header-path/Z.h" + } + ] + }, + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/PrivateHeaders", + 'contents': [ + { + 'type': 'file', + 'name': "ZPriv.h", + 'external-contents': "TEST_DIR/flat-header-path/ZPriv.h" + } + ] + }, + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Modules", + 'contents': [ + { + 'type': 'file', + 'name': "module.modulemap", + 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" + }, + { + 'type': 'file', + 'name': "module.private.modulemap", + 'external-contents': "TEST_DIR/flat-header-path/Z.private.modulemap" + } + ] + } + ] +} diff --git a/test/Modules/framework-public-includes-private.m b/test/Modules/framework-public-includes-private.m new file mode 100644 index 0000000000..e58492091e --- /dev/null +++ b/test/Modules/framework-public-includes-private.m @@ -0,0 +1,37 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: hmaptool write %S/Inputs/framework-public-includes-private/a.hmap.json %t/a.hmap +// RUN: hmaptool write %S/Inputs/framework-public-includes-private/z.hmap.json %t/z.hmap + +// RUN: sed -e "s:TEST_DIR:%S/Inputs/framework-public-includes-private:g" \ +// RUN: %S/Inputs/framework-public-includes-private/z.yaml > %t/z.yaml + +// The output with and without modules should be the same, without modules first. +// RUN: %clang_cc1 \ +// RUN: -iquote %t/z.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/framework-public-includes-private \ +// RUN: -fsyntax-only %s -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ +// RUN: -iquote %t/z.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/framework-public-includes-private \ +// RUN: -fsyntax-only %s \ +// RUN: 2>%t/stderr + +// The same warnings show up when modules is on but -verify doesn't get it +// because they only show up under the module A building context. +// RUN: FileCheck --input-file=%t/stderr %s +// CHECK: public framework header includes private framework header 'A/APriv.h' +// CHECK: public framework header includes private framework header 'A/APriv2.h' +// CHECK: public framework header includes private framework header 'Z/ZPriv.h' + +#import "A.h" + +int bar() { return foo(); } + +// expected-warning@Inputs/framework-public-includes-private/A.framework/Headers/A.h:1{{public framework header includes private framework header 'A/APriv.h'}} +// expected-warning@Inputs/framework-public-includes-private/A.framework/Headers/A.h:2{{public framework header includes private framework header 'A/APriv2.h'}} +// expected-warning@Inputs/framework-public-includes-private/flat-header-path/Z.h:2{{public framework header includes private framework header 'Z/ZPriv.h'}} -- GitLab From c0fec042d11f57c9ab12b33a86e02856f6f276f0 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 25 Jun 2018 22:25:48 +0000 Subject: [PATCH 0265/1023] Fix tests from r335542 to use %hmaptool git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335543 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Modules/framework-public-includes-private.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Modules/framework-public-includes-private.m b/test/Modules/framework-public-includes-private.m index e58492091e..eb4d2877a1 100644 --- a/test/Modules/framework-public-includes-private.m +++ b/test/Modules/framework-public-includes-private.m @@ -3,8 +3,8 @@ // RUN: rm -rf %t // RUN: mkdir %t -// RUN: hmaptool write %S/Inputs/framework-public-includes-private/a.hmap.json %t/a.hmap -// RUN: hmaptool write %S/Inputs/framework-public-includes-private/z.hmap.json %t/z.hmap +// RUN: %hmaptool write %S/Inputs/framework-public-includes-private/a.hmap.json %t/a.hmap +// RUN: %hmaptool write %S/Inputs/framework-public-includes-private/z.hmap.json %t/z.hmap // RUN: sed -e "s:TEST_DIR:%S/Inputs/framework-public-includes-private:g" \ // RUN: %S/Inputs/framework-public-includes-private/z.yaml > %t/z.yaml -- GitLab From 3707aa46066aa2da2490fe79c65c6c45c6957ece Mon Sep 17 00:00:00 2001 From: Yunlian Jiang Date: Mon, 25 Jun 2018 23:05:27 +0000 Subject: [PATCH 0266/1023] Add an option to support debug fission on implicit ThinLTO. Summary: This adds an option -gsplit-dwarf=. LLVM can create .dwo files in the given directory during the implicit ThinLTO link stage. Reviewers: tejohnson, dblaikie, pcc Reviewed By: pcc Subscribers: steven_wu, aprantl, JDevlieghere, yunlian, probinson, mehdi_amini, inglorion, cfe-commits Differential Revision: https://reviews.llvm.org/D44788 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335546 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/CommonArgs.cpp | 6 ++++++ test/Driver/lto-dwo.c | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 test/Driver/lto-dwo.c diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 43f7d7f3b7..98a36bcd83 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -416,6 +416,12 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt)); } + if (Args.hasArg(options::OPT_gsplit_dwarf)) { + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=dwo_dir=") + + Output.getFilename() + "_dwo")); + } + if (IsThinLTO) CmdArgs.push_back("-plugin-opt=thinlto"); diff --git a/test/Driver/lto-dwo.c b/test/Driver/lto-dwo.c new file mode 100644 index 0000000000..486ace43f0 --- /dev/null +++ b/test/Driver/lto-dwo.c @@ -0,0 +1,6 @@ +// Confirm that -gsplit-dwarf=DIR is passed to linker + +// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -gsplit-dwarf -o a.out 2> %t +// RUN: FileCheck -check-prefix=CHECK-LINK-DWO-DIR-DEFAULT < %t %s +// +// CHECK-LINK-DWO-DIR-DEFAULT: "-plugin-opt=dwo_dir=a.out_dwo" -- GitLab From c877647f1b60d295bfea9d984c1c9844aadc4e61 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Mon, 25 Jun 2018 23:20:18 +0000 Subject: [PATCH 0267/1023] [MachineOutliner] NFC - simplify -moutline/-mno-outline logic It's a bit cleaner to use `hasFlag` instead of nested ifs. This just refactors the -moutline/-mno-outline logic to use that. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335549 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 5cb3796723..327fa6b57b 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1477,19 +1477,16 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-aarch64-enable-global-merge=true"); } - if (Arg *A = Args.getLastArg(options::OPT_moutline, - options::OPT_mno_outline)) { - if (A->getOption().matches(options::OPT_moutline)) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); + if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner"); - // The outliner shouldn't compete with linkers that dedupe linkonceodr - // functions in LTO. Enable that behaviour by default when compiling with - // LTO. - if (getToolChain().getDriver().isUsingLTO()) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-linkonceodr-outlining"); - } + // The outliner shouldn't compete with linkers that dedupe linkonceodr + // functions in LTO. Enable that behaviour by default when compiling with + // LTO. + if (getToolChain().getDriver().isUsingLTO()) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-linkonceodr-outlining"); } } } -- GitLab From 3176c137ab9ddbe71836d05d482f102a9c3fdee1 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 25 Jun 2018 23:43:45 +0000 Subject: [PATCH 0268/1023] [analyzer] Fix invalidation on C++ const methods with arrow syntax. Conservative evaluation of a C++ method call would invalidate the object, as long as the method is not const or the object has mutable fields. When checking for mutable fields, we need to scan the type of the object on which the method is called, which may be more specific than the type of the object on which the method is defined, hence we look up the type from the this-argument expression. If arrow syntax or implicit-this syntax is used, this-argument expression has pointer type, not record type, and lookup accidentally failed for that reason. Obtain object type correctly. Differential Revision: https://reviews.llvm.org/D48460 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335555 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/CallEvent.cpp | 9 +++++++-- test/Analysis/const-method-call.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index a7d0f3894b..2b2de16dbd 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -534,9 +534,14 @@ void CXXInstanceCall::getExtraInvalidatedValues( // Get the record decl for the class of 'This'. D->getParent() may return a // base class decl, rather than the class of the instance which needs to be // checked for mutable fields. + // TODO: We might as well look at the dynamic type of the object. const Expr *Ex = getCXXThisExpr()->ignoreParenBaseCasts(); - const CXXRecordDecl *ParentRecord = Ex->getType()->getAsCXXRecordDecl(); - if (!ParentRecord || ParentRecord->hasMutableFields()) + QualType T = Ex->getType(); + if (T->isPointerType()) // Arrow or implicit-this syntax? + T = T->getPointeeType(); + const CXXRecordDecl *ParentRecord = T->getAsCXXRecordDecl(); + assert(ParentRecord); + if (ParentRecord->hasMutableFields()) return; // Preserve CXXThis. const MemRegion *ThisRegion = ThisVal.getAsRegion(); diff --git a/test/Analysis/const-method-call.cpp b/test/Analysis/const-method-call.cpp index 17df2a016b..a5a38929c2 100644 --- a/test/Analysis/const-method-call.cpp +++ b/test/Analysis/const-method-call.cpp @@ -6,6 +6,14 @@ struct A { int x; void foo() const; void bar(); + + void testImplicitThisSyntax() { + x = 3; + foo(); + clang_analyzer_eval(x == 3); // expected-warning{{TRUE}} + bar(); + clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}} + } }; struct B { @@ -108,6 +116,22 @@ void checkThatContainedConstMethodDoesNotInvalidateObjects() { clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}} } +void checkPointerTypedThisExpression(A *a) { + a->x = 3; + a->foo(); + clang_analyzer_eval(a->x == 3); // expected-warning{{TRUE}} + a->bar(); + clang_analyzer_eval(a->x == 3); // expected-warning{{UNKNOWN}} +} + +void checkReferenceTypedThisExpression(A &a) { + a.x = 3; + a.foo(); + clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}} + a.bar(); + clang_analyzer_eval(a.x == 3); // expected-warning{{UNKNOWN}} +} + // --- Versions of the above tests where the const method is inherited --- // struct B1 { -- GitLab From 707983ea1f326ae9c8499ca585785c7679e3f7e1 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 25 Jun 2018 23:55:07 +0000 Subject: [PATCH 0269/1023] [analyzer] Track null and undef values through expressions with cleanups. ExprWithCleanups wraps full-expressions that require temporary destructors and highlights the moment of time in which these destructors need to be called (i.e., "at the end of the full-expression..."). Such expressions don't necessarily return an object; they may return anything, including a null or undefined value. When the analyzer tries to understand where the null or undefined value came from in order to present better diagnostics to the user, it will now skip any ExprWithCleanups it encounters and look into the expression itself. Differential Revision: https://reviews.llvm.org/D48204 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335559 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 ++ .../inlining/inline-defensive-checks.cpp | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 4765db0741..fc31d3c1fb 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -141,6 +141,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { E = AE->getBase(); } else if (const auto *PE = dyn_cast(E)) { E = PE->getSubExpr(); + } else if (const auto *EWC = dyn_cast(E)) { + E = EWC->getSubExpr(); } else { // Other arbitrary stuff. break; diff --git a/test/Analysis/inlining/inline-defensive-checks.cpp b/test/Analysis/inlining/inline-defensive-checks.cpp index eaae8d2ae2..6fb0e1cd70 100644 --- a/test/Analysis/inlining/inline-defensive-checks.cpp +++ b/test/Analysis/inlining/inline-defensive-checks.cpp @@ -84,3 +84,20 @@ void testRefToField(Bar *b) { int &x = b->x; // no-warning x = 5; } + +namespace get_deref_expr_with_cleanups { +struct S { +~S(); +}; +S *conjure(); +// The argument won't be used, but it'll cause cleanups +// to appear around the call site. +S *get_conjured(S _) { + S *s = conjure(); + if (s) {} + return s; +} +void test_conjured() { + S &s = *get_conjured(S()); // no-warning +} +} // namespace get_deref_expr_with_cleanups -- GitLab From 265fa9857ba66631d565c5292458b8bcbcedc401 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Jun 2018 00:44:02 +0000 Subject: [PATCH 0270/1023] [X86] Redefine avx512 packed fpclass intrinsics to return a vXi1 mask and implement the mask input argument using an 'and' IR instruction. Additional IR is emitted to convert between scalar and vXi1 type to match the expected software inferface for the builtin that clang exposes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335564 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index de96127987..09edfa7568 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10120,6 +10120,43 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return Builder.CreateExtractValue(Call, 1); } + case X86::BI__builtin_ia32_fpclassps128_mask: + case X86::BI__builtin_ia32_fpclassps256_mask: + case X86::BI__builtin_ia32_fpclassps512_mask: + case X86::BI__builtin_ia32_fpclasspd128_mask: + case X86::BI__builtin_ia32_fpclasspd256_mask: + case X86::BI__builtin_ia32_fpclasspd512_mask: { + unsigned NumElts = Ops[0]->getType()->getVectorNumElements(); + Value *MaskIn = Ops[2]; + Ops.erase(&Ops[2]); + + Intrinsic::ID ID; + switch (BuiltinID) { + default: llvm_unreachable("Unsupported intrinsic!"); + case X86::BI__builtin_ia32_fpclassps128_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_ps_128; + break; + case X86::BI__builtin_ia32_fpclassps256_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_ps_256; + break; + case X86::BI__builtin_ia32_fpclassps512_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_ps_512; + break; + case X86::BI__builtin_ia32_fpclasspd128_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_pd_128; + break; + case X86::BI__builtin_ia32_fpclasspd256_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_pd_256; + break; + case X86::BI__builtin_ia32_fpclasspd512_mask: + ID = Intrinsic::x86_avx512_mask_fpclass_pd_512; + break; + } + + Value *Fpclass = Builder.CreateCall(CGM.getIntrinsic(ID), Ops); + return EmitX86MaskedCompareResult(*this, Fpclass, NumElts, MaskIn); + } + // packed comparison intrinsics case X86::BI__builtin_ia32_cmpeqps: case X86::BI__builtin_ia32_cmpeqpd: -- GitLab From 736ed08304d9589cdebf8eb54ef117931a217428 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 26 Jun 2018 02:15:47 +0000 Subject: [PATCH 0271/1023] Implement CFI for indirect calls via a member function pointer. Similarly to CFI on virtual and indirect calls, this implementation tries to use program type information to make the checks as precise as possible. The basic way that it works is as follows, where `C` is the name of the class being defined or the target of a call and the function type is assumed to be `void()`. For virtual calls: - Attach type metadata to the addresses of function pointers in vtables (not the functions themselves) of type `void (B::*)()` for each `B` that is a recursive dynamic base class of `C`, including `C` itself. This type metadata has an annotation that the type is for virtual calls (to distinguish it from the non-virtual case). - At the call site, check that the computed address of the function pointer in the vtable has type `void (C::*)()`. For non-virtual calls: - Attach type metadata to each non-virtual member function whose address can be taken with a member function pointer. The type of a function in class `C` of type `void()` is each of the types `void (B::*)()` where `B` is a most-base class of `C`. A most-base class of `C` is defined as a recursive base class of `C`, including `C` itself, that does not have any bases. - At the call site, check that the function pointer has one of the types `void (B::*)()` where `B` is a most-base class of `C`. Differential Revision: https://reviews.llvm.org/D47567 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335569 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ControlFlowIntegrity.rst | 30 ++++++++ docs/LTOVisibility.rst | 6 +- include/clang/Basic/Sanitizers.def | 5 +- lib/CodeGen/CGClass.cpp | 4 +- lib/CodeGen/CGVTables.cpp | 43 +++++++---- lib/CodeGen/CodeGenFunction.h | 2 + lib/CodeGen/CodeGenModule.cpp | 89 ++++++++++++++++------- lib/CodeGen/CodeGenModule.h | 19 ++++- lib/CodeGen/ItaniumCXXABI.cpp | 87 ++++++++++++++++++++-- lib/Driver/SanitizerArgs.cpp | 29 +++++++- lib/Driver/ToolChains/MSVC.cpp | 1 + test/CodeGenCXX/cfi-mfcall-incomplete.cpp | 12 +++ test/CodeGenCXX/cfi-mfcall.cpp | 30 ++++++++ test/CodeGenCXX/type-metadata-memfun.cpp | 31 ++++++++ test/CodeGenCXX/type-metadata.cpp | 43 +++++++++++ test/Driver/fsanitize.c | 16 ++-- 16 files changed, 387 insertions(+), 60 deletions(-) create mode 100644 test/CodeGenCXX/cfi-mfcall-incomplete.cpp create mode 100644 test/CodeGenCXX/cfi-mfcall.cpp create mode 100644 test/CodeGenCXX/type-metadata-memfun.cpp diff --git a/docs/ControlFlowIntegrity.rst b/docs/ControlFlowIntegrity.rst index 6b397befdd..fcc6409888 100644 --- a/docs/ControlFlowIntegrity.rst +++ b/docs/ControlFlowIntegrity.rst @@ -66,6 +66,8 @@ Available schemes are: wrong dynamic type. - ``-fsanitize=cfi-icall``: Indirect call of a function with wrong dynamic type. + - ``-fsanitize=cfi-mfcall``: Indirect call via a member function pointer with + wrong dynamic type. You can use ``-fsanitize=cfi`` to enable all the schemes and use ``-fno-sanitize`` flag to narrow down the set of schemes as desired. @@ -255,6 +257,34 @@ the identity of function pointers is maintained, and calls across shared library boundaries are no different from calls within a single program or shared library. +Member Function Pointer Call Checking +===================================== + +This scheme checks that indirect calls via a member function pointer +take place using an object of the correct dynamic type. Specifically, we +check that the dynamic type of the member function referenced by the member +function pointer matches the "function pointer" part of the member function +pointer, and that the member function's class type is related to the base +type of the member function. This CFI scheme can be enabled on its own using +``-fsanitize=cfi-mfcall``. + +The compiler will only emit a full CFI check if the member function pointer's +base type is complete. This is because the complete definition of the base +type contains information that is necessary to correctly compile the CFI +check. To ensure that the compiler always emits a full CFI check, it is +recommended to also pass the flag ``-fcomplete-member-pointers``, which +enables a non-conforming language extension that requires member pointer +base types to be complete if they may be used for a call. + +For this scheme to work, all translation units containing the definition +of a virtual member function (whether inline or not), other than members +of :ref:`blacklisted ` types or types with public :doc:`LTO +visibility `, must be compiled with ``-flto`` or ``-flto=thin`` +enabled and be statically linked into the program. + +This scheme is currently not compatible with cross-DSO CFI or the +Microsoft ABI. + .. _cfi-blacklist: Blacklist diff --git a/docs/LTOVisibility.rst b/docs/LTOVisibility.rst index e1372d667a..ed15d8d786 100644 --- a/docs/LTOVisibility.rst +++ b/docs/LTOVisibility.rst @@ -11,9 +11,9 @@ linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit. The LTO visibility of a class is used by the compiler to determine which classes the whole-program devirtualization (``-fwhole-program-vtables``) and -control flow integrity (``-fsanitize=cfi-vcall``) features apply to. These -features use whole-program information, so they require the entire class -hierarchy to be visible in order to work correctly. +control flow integrity (``-fsanitize=cfi-vcall`` and ``-fsanitize=cfi-mfcall``) +features apply to. These features use whole-program information, so they +require the entire class hierarchy to be visible in order to work correctly. If any translation unit in the program uses either of the whole-program devirtualization or control flow integrity features, it is effectively an ODR diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index b81b7e9f0a..5a36822a63 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -104,12 +104,13 @@ SANITIZER("dataflow", DataFlow) SANITIZER("cfi-cast-strict", CFICastStrict) SANITIZER("cfi-derived-cast", CFIDerivedCast) SANITIZER("cfi-icall", CFIICall) +SANITIZER("cfi-mfcall", CFIMFCall) SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast) SANITIZER("cfi-nvcall", CFINVCall) SANITIZER("cfi-vcall", CFIVCall) SANITIZER_GROUP("cfi", CFI, - CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall | - CFIVCall) + CFIDerivedCast | CFIICall | CFIMFCall | CFIUnrelatedCast | + CFINVCall | CFIVCall) // Safe Stack SANITIZER("safe-stack", SafeStack) diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 11a327d2d2..0b9311f777 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -2688,7 +2688,9 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, SSK = llvm::SanStat_CFI_UnrelatedCast; break; case CFITCK_ICall: - llvm_unreachable("not expecting CFITCK_ICall"); + case CFITCK_NVMFCall: + case CFITCK_VMFCall: + llvm_unreachable("unexpected sanitizer kind"); } std::string TypeName = RD->getQualifiedNameAsString(); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 86bceb6ee9..5a2ec65f77 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -1012,30 +1012,29 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits PointerWidth = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - typedef std::pair TypeMetadata; - std::vector TypeMetadatas; - // Create type metadata for each address point. + typedef std::pair AddressPoint; + std::vector AddressPoints; for (auto &&AP : VTLayout.getAddressPoints()) - TypeMetadatas.push_back(std::make_pair( + AddressPoints.push_back(std::make_pair( AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + AP.second.AddressPointIndex)); - // Sort the type metadata for determinism. - llvm::sort(TypeMetadatas.begin(), TypeMetadatas.end(), - [this](const TypeMetadata &M1, const TypeMetadata &M2) { - if (&M1 == &M2) + // Sort the address points for determinism. + llvm::sort(AddressPoints.begin(), AddressPoints.end(), + [this](const AddressPoint &AP1, const AddressPoint &AP2) { + if (&AP1 == &AP2) return false; std::string S1; llvm::raw_string_ostream O1(S1); getCXXABI().getMangleContext().mangleTypeName( - QualType(M1.first->getTypeForDecl(), 0), O1); + QualType(AP1.first->getTypeForDecl(), 0), O1); O1.flush(); std::string S2; llvm::raw_string_ostream O2(S2); getCXXABI().getMangleContext().mangleTypeName( - QualType(M2.first->getTypeForDecl(), 0), O2); + QualType(AP2.first->getTypeForDecl(), 0), O2); O2.flush(); if (S1 < S2) @@ -1043,10 +1042,26 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, if (S1 != S2) return false; - return M1.second < M2.second; + return AP1.second < AP2.second; }); - for (auto TypeMetadata : TypeMetadatas) - AddVTableTypeMetadata(VTable, PointerWidth * TypeMetadata.second, - TypeMetadata.first); + ArrayRef Comps = VTLayout.vtable_components(); + for (auto AP : AddressPoints) { + // Create type metadata for the address point. + AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first); + + // The class associated with each address point could also potentially be + // used for indirect calls via a member function pointer, so we need to + // annotate the address of each function pointer with the appropriate member + // function pointer type. + for (unsigned I = 0; I != Comps.size(); ++I) { + if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) + continue; + llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( + Context.getMemberPointerType( + Comps[I].getFunctionDecl()->getType(), + Context.getRecordType(AP.first).getTypePtr())); + VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD); + } + } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index afe199c4eb..548a4178ef 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1765,6 +1765,8 @@ public: CFITCK_DerivedCast, CFITCK_UnrelatedCast, CFITCK_ICall, + CFITCK_NVMFCall, + CFITCK_VMFCall, }; /// Derived is the presumed address of an object of type T after a diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5a2f2a01d3..35e9dea37a 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1132,6 +1132,34 @@ static bool hasUnwindExceptions(const LangOptions &LangOpts) { return true; } +static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM, + const CXXMethodDecl *MD) { + // Check that the type metadata can ever actually be used by a call. + if (!CGM.getCodeGenOpts().LTOUnit || + !CGM.HasHiddenLTOVisibility(MD->getParent())) + return false; + + // Only functions whose address can be taken with a member function pointer + // need this sort of type metadata. + return !MD->isStatic() && !MD->isVirtual() && !isa(MD) && + !isa(MD); +} + +std::vector +CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) { + llvm::SetVector MostBases; + + std::function CollectMostBases; + CollectMostBases = [&](const CXXRecordDecl *RD) { + if (RD->getNumBases() == 0) + MostBases.insert(RD); + for (const CXXBaseSpecifier &B : RD->bases()) + CollectMostBases(B.getType()->getAsCXXRecordDecl()); + }; + CollectMostBases(RD); + return MostBases.takeVector(); +} + void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { llvm::AttrBuilder B; @@ -1257,7 +1285,20 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, // In the cross-dso CFI mode, we want !type attributes on definitions only. if (CodeGenOpts.SanitizeCfiCrossDso) if (auto *FD = dyn_cast(D)) - CreateFunctionTypeMetadata(FD, F); + CreateFunctionTypeMetadataForIcall(FD, F); + + // Emit type metadata on member functions for member function pointer checks. + // These are only ever necessary on definitions; we're guaranteed that the + // definition will be present in the LTO unit as a result of LTO visibility. + auto *MD = dyn_cast(D); + if (MD && requiresMemberFunctionPointerTypeMetadata(*this, MD)) { + for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { + llvm::Metadata *Id = + CreateMetadataIdentifierForType(Context.getMemberPointerType( + MD->getType(), Context.getRecordType(Base).getTypePtr())); + F->addTypeMetadata(0, Id); + } + } } void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) { @@ -1378,13 +1419,14 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) { GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } -void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD, - llvm::Function *F) { +void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, + llvm::Function *F) { // Only if we are checking indirect calls. if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall)) return; - // Non-static class methods are handled via vtable pointer checks elsewhere. + // Non-static class methods are handled via vtable or member function pointer + // checks elsewhere. if (isa(FD) && !cast(FD)->isStatic()) return; @@ -1476,7 +1518,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, // Don't emit entries for function declarations in the cross-DSO mode. This // is handled with better precision by the receiving DSO. if (!CodeGenOpts.SanitizeCfiCrossDso) - CreateFunctionTypeMetadata(FD, F); + CreateFunctionTypeMetadataForIcall(FD, F); if (getLangOpts().OpenMP && FD->hasAttr()) getOpenMPRuntime().emitDeclareSimdFunction(FD, F); @@ -4925,8 +4967,10 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { } } -llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { - llvm::Metadata *&InternalId = MetadataIdMap[T.getCanonicalType()]; +llvm::Metadata * +CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, + StringRef Suffix) { + llvm::Metadata *&InternalId = Map[T.getCanonicalType()]; if (InternalId) return InternalId; @@ -4934,6 +4978,7 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { std::string OutName; llvm::raw_string_ostream Out(OutName); getCXXABI().getMangleContext().mangleTypeName(T, Out); + Out << Suffix; InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); } else { @@ -4944,6 +4989,15 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { return InternalId; } +llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { + return CreateMetadataIdentifierImpl(T, MetadataIdMap, ""); +} + +llvm::Metadata * +CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) { + return CreateMetadataIdentifierImpl(T, VirtualMetadataIdMap, ".virtual"); +} + // Generalize pointer types to a void pointer with the qualifiers of the // originally pointed-to type, e.g. 'const char *' and 'char * const *' // generalize to 'const void *' while 'char *' and 'const char **' generalize to @@ -4977,25 +5031,8 @@ static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) { } llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) { - T = GeneralizeFunctionType(getContext(), T); - - llvm::Metadata *&InternalId = GeneralizedMetadataIdMap[T.getCanonicalType()]; - if (InternalId) - return InternalId; - - if (isExternallyVisible(T->getLinkage())) { - std::string OutName; - llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName(T, Out); - Out << ".generalized"; - - InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); - } else { - InternalId = llvm::MDNode::getDistinct(getLLVMContext(), - llvm::ArrayRef()); - } - - return InternalId; + return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T), + GeneralizedMetadataIdMap, ".generalized"); } /// Returns whether this module needs the "all-vtables" type identifier. diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index bf22ad246c..d2c7b327f9 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -503,6 +503,7 @@ private: /// MDNodes. typedef llvm::DenseMap MetadataTypeMap; MetadataTypeMap MetadataIdMap; + MetadataTypeMap VirtualMetadataIdMap; MetadataTypeMap GeneralizedMetadataIdMap; public: @@ -1232,13 +1233,18 @@ public: /// internal identifiers). llvm::Metadata *CreateMetadataIdentifierForType(QualType T); + /// Create a metadata identifier that is intended to be used to check virtual + /// calls via a member function pointer. + llvm::Metadata *CreateMetadataIdentifierForVirtualMemPtrType(QualType T); + /// Create a metadata identifier for the generalization of the given type. /// This may either be an MDString (for external identifiers) or a distinct /// unnamed MDNode (for internal identifiers). llvm::Metadata *CreateMetadataIdentifierGeneralized(QualType T); /// Create and attach type metadata to the given function. - void CreateFunctionTypeMetadata(const FunctionDecl *FD, llvm::Function *F); + void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, + llvm::Function *F); /// Returns whether this module needs the "all-vtables" type identifier. bool NeedAllVtablesTypeId() const; @@ -1247,6 +1253,14 @@ public: void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD); + /// Return a vector of most-base classes for RD. This is used to implement + /// control flow integrity checks for member function pointers. + /// + /// A most-base class of a class C is defined as a recursive base class of C, + /// including C itself, that does not have any bases. + std::vector + getMostBaseClasses(const CXXRecordDecl *RD); + /// Get the declaration of std::terminate for the platform. llvm::Constant *getTerminateFn(); @@ -1408,6 +1422,9 @@ private: void ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, bool AttrOnCallSite, llvm::AttrBuilder &FuncAttrs); + + llvm::Metadata *CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, + StringRef Suffix); }; } // end namespace CodeGen diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index d855afab22..8dd94e4955 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -622,13 +622,53 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty); VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy); } - VTable = Builder.CreateGEP(VTable, VTableOffset); + // Compute the address of the virtual function pointer. + llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); + + // Check the address of the function pointer if CFI on member function + // pointers is enabled. + llvm::Constant *CheckSourceLocation; + llvm::Constant *CheckTypeDesc; + bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) && + CGM.HasHiddenLTOVisibility(RD); + if (ShouldEmitCFICheck) { + CodeGenFunction::SanitizerScope SanScope(&CGF); + + CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getLocStart()); + CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0)); + llvm::Constant *StaticData[] = { + llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall), + CheckSourceLocation, + CheckTypeDesc, + }; + + llvm::Metadata *MD = + CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0)); + llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); + + llvm::Value *TypeTest = Builder.CreateCall( + CGM.getIntrinsic(llvm::Intrinsic::type_test), {VFPAddr, TypeId}); + + if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) { + CGF.EmitTrapCheck(TypeTest); + } else { + llvm::Value *AllVtables = llvm::MetadataAsValue::get( + CGM.getLLVMContext(), + llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); + llvm::Value *ValidVtable = Builder.CreateCall( + CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables}); + CGF.EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIMFCall), + SanitizerHandler::CFICheckFail, StaticData, + {VTable, ValidVtable}); + } + + FnVirtual = Builder.GetInsertBlock(); + } // Load the virtual function to call. - VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); - llvm::Value *VirtualFn = - Builder.CreateAlignedLoad(VTable, CGF.getPointerAlign(), - "memptr.virtualfn"); + VFPAddr = Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo()); + llvm::Value *VirtualFn = Builder.CreateAlignedLoad( + VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn"); CGF.EmitBranch(FnEnd); // In the non-virtual path, the function pointer is actually a @@ -637,6 +677,43 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *NonVirtualFn = Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); + // Check the function pointer if CFI on member function pointers is enabled. + if (ShouldEmitCFICheck) { + CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + if (RD->hasDefinition()) { + CodeGenFunction::SanitizerScope SanScope(&CGF); + + llvm::Constant *StaticData[] = { + llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall), + CheckSourceLocation, + CheckTypeDesc, + }; + + llvm::Value *Bit = Builder.getFalse(); + llvm::Value *CastedNonVirtualFn = + Builder.CreateBitCast(NonVirtualFn, CGF.Int8PtrTy); + for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) { + llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType( + getContext().getMemberPointerType( + MPT->getPointeeType(), + getContext().getRecordType(Base).getTypePtr())); + llvm::Value *TypeId = + llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); + + llvm::Value *TypeTest = + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), + {CastedNonVirtualFn, TypeId}); + Bit = Builder.CreateOr(Bit, TypeTest); + } + + CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall), + SanitizerHandler::CFICheckFail, StaticData, + {CastedNonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)}); + + FnNonVirtual = Builder.GetInsertBlock(); + } + } + // We're done. CGF.EmitBlock(FnEnd); llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2); diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 743e042a79..bdc17d11c9 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -44,7 +44,8 @@ enum : SanitizerMask { TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow | Nullability | LocalBounds | CFI, TrappingDefault = CFI, - CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast, + CFIClasses = + CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast, CompatibleWithMinimalRuntime = TrappingSupported | Scudo, }; @@ -219,6 +220,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, // Used to deduplicate diagnostics. SanitizerMask Kinds = 0; const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers()); + + CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, + options::OPT_fno_sanitize_cfi_cross_dso, false); + ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); const Driver &D = TC.getDriver(); @@ -278,6 +283,24 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, Add &= ~NotAllowedWithMinimalRuntime; } + // FIXME: Make CFI on member function calls compatible with cross-DSO CFI. + // There are currently two problems: + // - Virtual function call checks need to pass a pointer to the function + // address to llvm.type.test and a pointer to the address point to the + // diagnostic function. Currently we pass the same pointer to both + // places. + // - Non-virtual function call checks may need to check multiple type + // identifiers. + // Fixing both of those may require changes to the cross-DSO CFI + // interface. + if (CfiCrossDso && (Add & CFIMFCall & ~DiagnosedKinds)) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fsanitize=cfi-mfcall" + << "-fsanitize-cfi-cross-dso"; + Add &= ~CFIMFCall; + DiagnosedKinds |= CFIMFCall; + } + if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) { std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); D.Diag(diag::err_drv_unsupported_opt_for_target) @@ -316,6 +339,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, if (MinimalRuntime) { Add &= ~NotAllowedWithMinimalRuntime; } + if (CfiCrossDso) + Add &= ~CFIMFCall; Add &= Supported; if (Add & Fuzzer) @@ -554,8 +579,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } if (AllAddedKinds & CFI) { - CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, - options::OPT_fno_sanitize_cfi_cross_dso, false); // Without PIE, external function address may resolve to a PLT record, which // can not be verified by the target module. NeedPIE |= CfiCrossDso; diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index 22257092bb..3ce1bfa0aa 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -1297,6 +1297,7 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, SanitizerMask MSVCToolChain::getSupportedSanitizers() const { SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res &= ~SanitizerKind::CFIMFCall; return Res; } diff --git a/test/CodeGenCXX/cfi-mfcall-incomplete.cpp b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp new file mode 100644 index 0000000000..345be124e9 --- /dev/null +++ b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s + +struct S; + +void f(S *s, void (S::*p)()) { + // CHECK-NOT: llvm.type.test + // CHECK: llvm.type.test{{.*}}!"_ZTSM1SFvvE.virtual" + // CHECK-NOT: llvm.type.test + (s->*p)(); +} + +// CHECK: declare i1 @llvm.type.test diff --git a/test/CodeGenCXX/cfi-mfcall.cpp b/test/CodeGenCXX/cfi-mfcall.cpp new file mode 100644 index 0000000000..c16b20b8dc --- /dev/null +++ b/test/CodeGenCXX/cfi-mfcall.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility default -emit-llvm -o - %s | FileCheck --check-prefix=DEFAULT %s + +struct B1 {}; +struct B2 {}; +struct B3 : B2 {}; +struct S : B1, B3 {}; + +// DEFAULT-NOT: llvm.type.test + +void f(S *s, void (S::*p)()) { + // CHECK: [[OFFSET:%.*]] = sub i64 {{.*}}, 1 + // CHECK: [[VFPTR:%.*]] = getelementptr i8, i8* %{{.*}}, i64 [[OFFSET]] + // CHECK: [[TT:%.*]] = call i1 @llvm.type.test(i8* [[VFPTR]], metadata !"_ZTSM1SFvvE.virtual") + // CHECK: br i1 [[TT]], label {{.*}}, label %[[TRAP1:[^,]*]] + + // CHECK: [[TRAP1]]: + // CHECK-NEXT: llvm.trap + + // CHECK: [[NVFPTR:%.*]] = bitcast void (%struct.S*)* {{.*}} to i8* + // CHECK: [[TT1:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B1FvvE") + // CHECK: [[OR1:%.*]] = or i1 false, [[TT1]] + // CHECK: [[TT2:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B2FvvE") + // CHECK: [[OR2:%.*]] = or i1 [[OR1]], [[TT2]] + // CHECK: br i1 [[OR2]], label {{.*}}, label %[[TRAP2:[^,]*]] + + // CHECK: [[TRAP2]]: + // CHECK-NEXT: llvm.trap + (s->*p)(); +} diff --git a/test/CodeGenCXX/type-metadata-memfun.cpp b/test/CodeGenCXX/type-metadata-memfun.cpp new file mode 100644 index 0000000000..2ff574e7da --- /dev/null +++ b/test/CodeGenCXX/type-metadata-memfun.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm -o - %s | FileCheck %s + +struct S1 { + S1(); + ~S1(); + virtual void vf(); + void f(); + void fdecl(); +}; + +struct [[clang::lto_visibility_public]] S2 { + void f(); +}; + +// CHECK-NOT: declare{{.*}}!type +// CHECK-NOT: define{{.*}}!type + +S1::S1() {} +S1::~S1() {} +void S1::vf() {} +// CHECK: define hidden void @_ZN2S11fEv{{.*}} !type [[S2F:![0-9]+]] +void S1::f() { + fdecl(); +} + +void S2::f() {} + +// CHECK-NOT: declare{{.*}}!type +// CHECK-NOT: define{{.*}}!type + +// CHECK: [[S2F]] = !{i64 0, !"_ZTSM2S1FvvE"} diff --git a/test/CodeGenCXX/type-metadata.cpp b/test/CodeGenCXX/type-metadata.cpp index be415c3839..8e3e4bd182 100644 --- a/test/CodeGenCXX/type-metadata.cpp +++ b/test/CodeGenCXX/type-metadata.cpp @@ -14,16 +14,25 @@ // ITANIUM: @_ZTV1A = {{[^!]*}}, !type [[A16:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL16:![0-9]+]] +// ITANIUM-SAME: !type [[AF16:![0-9]+]] // ITANIUM: @_ZTV1B = {{[^!]*}}, !type [[A32:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL32:![0-9]+]] +// ITANIUM-SAME: !type [[AF32:![0-9]+]] +// ITANIUM-SAME: !type [[AF40:![0-9]+]] +// ITANIUM-SAME: !type [[AF48:![0-9]+]] // ITANIUM-SAME: !type [[B32:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[BF32:![0-9]+]] +// ITANIUM-SAME: !type [[BF40:![0-9]+]] +// ITANIUM-SAME: !type [[BF48:![0-9]+]] // ITANIUM: @_ZTV1C = {{[^!]*}}, !type [[A32]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[AF32]] // ITANIUM-SAME: !type [[C32:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[CF32:![0-9]+]] // DIAG: @[[SRC:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}type-metadata.cpp\00", align 1 // DIAG: @[[TYPE:.*]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } @@ -31,12 +40,24 @@ // ITANIUM: @_ZTVN12_GLOBAL__N_11DE = {{[^!]*}}, !type [[A32]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[AF32]] +// ITANIUM-SAME: !type [[AF40]] +// ITANIUM-SAME: !type [[AF48]] // ITANIUM-SAME: !type [[B32]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[BF32]] +// ITANIUM-SAME: !type [[BF40]] +// ITANIUM-SAME: !type [[BF48]] // ITANIUM-SAME: !type [[C88:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL88:![0-9]+]] +// ITANIUM-SAME: !type [[CF32]] +// ITANIUM-SAME: !type [[CF40:![0-9]+]] +// ITANIUM-SAME: !type [[CF48:![0-9]+]] // ITANIUM-SAME: !type [[D32:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[DF32:![0-9]+]] +// ITANIUM-SAME: !type [[DF40:![0-9]+]] +// ITANIUM-SAME: !type [[DF48:![0-9]+]] // ITANIUM: @_ZTCN12_GLOBAL__N_11DE0_1B = {{[^!]*}}, !type [[A32]] // ITANIUM-DIAG-SAME: !type [[ALL32]] @@ -45,13 +66,17 @@ // ITANIUM: @_ZTCN12_GLOBAL__N_11DE8_1C = {{[^!]*}}, !type [[A64:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL64:![0-9]+]] +// ITANIUM-SAME: !type [[AF64:![0-9]+]] // ITANIUM-SAME: !type [[C32]] // ITANIUM-DIAG-SAME: !type [[ALL32]] +// ITANIUM-SAME: !type [[CF64:![0-9]+]] // ITANIUM: @_ZTVZ3foovE2FA = {{[^!]*}}, !type [[A16]] // ITANIUM-DIAG-SAME: !type [[ALL16]] +// ITANIUM-SAME: !type [[AF16]] // ITANIUM-SAME: !type [[FA16:![0-9]+]] // ITANIUM-DIAG-SAME: !type [[ALL16]] +// ITANIUM-SAME: !type [[FAF16:![0-9]+]] // MS: comdat($"??_7A@@6B@"), !type [[A8:![0-9]+]] // MS: comdat($"??_7B@@6B0@@"), !type [[B8:![0-9]+]] @@ -227,18 +252,36 @@ void f(D *d) { // ITANIUM: [[A16]] = !{i64 16, !"_ZTS1A"} // ITANIUM-DIAG: [[ALL16]] = !{i64 16, !"all-vtables"} +// ITANIUM: [[AF16]] = !{i64 16, !"_ZTSM1AFvvE.virtual"} // ITANIUM: [[A32]] = !{i64 32, !"_ZTS1A"} // ITANIUM-DIAG: [[ALL32]] = !{i64 32, !"all-vtables"} +// ITANIUM: [[AF32]] = !{i64 32, !"_ZTSM1AFvvE.virtual"} +// ITANIUM: [[AF40]] = !{i64 40, !"_ZTSM1AFvvE.virtual"} +// ITANIUM: [[AF48]] = !{i64 48, !"_ZTSM1AFvvE.virtual"} // ITANIUM: [[B32]] = !{i64 32, !"_ZTS1B"} +// ITANIUM: [[BF32]] = !{i64 32, !"_ZTSM1BFvvE.virtual"} +// ITANIUM: [[BF40]] = !{i64 40, !"_ZTSM1BFvvE.virtual"} +// ITANIUM: [[BF48]] = !{i64 48, !"_ZTSM1BFvvE.virtual"} // ITANIUM: [[C32]] = !{i64 32, !"_ZTS1C"} +// ITANIUM: [[CF32]] = !{i64 32, !"_ZTSM1CFvvE.virtual"} // ITANIUM: [[C88]] = !{i64 88, !"_ZTS1C"} // ITANIUM-DIAG: [[ALL88]] = !{i64 88, !"all-vtables"} +// ITANIUM: [[CF40]] = !{i64 40, !"_ZTSM1CFvvE.virtual"} +// ITANIUM: [[CF48]] = !{i64 48, !"_ZTSM1CFvvE.virtual"} // ITANIUM: [[D32]] = !{i64 32, [[D_ID:![0-9]+]]} // ITANIUM: [[D_ID]] = distinct !{} +// ITANIUM: [[DF32]] = !{i64 32, [[DF_ID:![0-9]+]]} +// ITANIUM: [[DF_ID]] = distinct !{} +// ITANIUM: [[DF40]] = !{i64 40, [[DF_ID]]} +// ITANIUM: [[DF48]] = !{i64 48, [[DF_ID]]} // ITANIUM: [[A64]] = !{i64 64, !"_ZTS1A"} // ITANIUM-DIAG: [[ALL64]] = !{i64 64, !"all-vtables"} +// ITANIUM: [[AF64]] = !{i64 64, !"_ZTSM1AFvvE.virtual"} +// ITANIUM: [[CF64]] = !{i64 64, !"_ZTSM1CFvvE.virtual"} // ITANIUM: [[FA16]] = !{i64 16, [[FA_ID:![0-9]+]]} // ITANIUM: [[FA_ID]] = distinct !{} +// ITANIUM: [[FAF16]] = !{i64 16, [[FAF_ID:![0-9]+]]} +// ITANIUM: [[FAF_ID]] = distinct !{} // MS: [[A8]] = !{i64 8, !"?AUA@@"} // MS: [[B8]] = !{i64 8, !"?AUB@@"} diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 3e3b13e8c2..98fd1636b7 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -476,6 +476,8 @@ // RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // RUN: %clang -target x86_64-apple-darwin10 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI +// RUN: %clang -target x86_64-pc-win32 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOMFCALL +// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOMFCALL // RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-derived-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-DCAST // RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-unrelated-cast -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-UCAST // RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -fsanitize=cfi-nvcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NVCALL @@ -484,7 +486,8 @@ // RUN: %clang -target aarch64-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // RUN: %clang -target arm-linux-android -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // RUN: %clang -target aarch64-linux-android -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI -// CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall +// CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall +// CHECK-CFI-NOMFCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall // CHECK-CFI-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast // CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast // CHECK-CFI-NVCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-nvcall @@ -526,6 +529,9 @@ // CHECK-CFI-NO-CROSS-DSO: -emit-llvm-bc // CHECK-CFI-NO-CROSS-DSO-NOT: -fsanitize-cfi-cross-dso +// RUN: %clang -target x86_64-linux-gnu -fvisibility=hidden -fsanitize=cfi-mfcall -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-MFCALL-CROSS-DSO +// CHECK-CFI-MFCALL-CROSS-DSO: '-fsanitize=cfi-mfcall' not allowed with '-fsanitize-cfi-cross-dso' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-icall -fsanitize-cfi-icall-generalize-pointers -fvisibility=hidden -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-GENERALIZE-POINTERS // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-icall -fvisibility=hidden -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-CFI-GENERALIZE-POINTERS // CHECK-CFI-GENERALIZE-POINTERS: -fsanitize-cfi-icall-generalize-pointers @@ -644,16 +650,16 @@ // CHECK-HWASAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=hwaddress' // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-MINIMAL -// CHECK-CFI-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" -// CHECK-CFI-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" +// CHECK-CFI-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" +// CHECK-CFI-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" // CHECK-CFI-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -fno-sanitize-trap=cfi-icall -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOTRAP-MINIMAL // CHECK-CFI-NOTRAP-MINIMAL: error: invalid argument 'fsanitize-minimal-runtime' only allowed with 'fsanitize-trap=cfi' // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -fno-sanitize-trap=cfi-icall -fno-sanitize=cfi-icall -flto -fvisibility=hidden -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-NOICALL-MINIMAL -// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" -// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" +// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" +// CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO -- GitLab From 0e974309d197fcc1ee6829c0b2a7d7b267c20152 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 26 Jun 2018 02:50:01 +0000 Subject: [PATCH 0272/1023] Modernize a function, NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335571 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaLambda.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index fec0d575e5..b6ea484cea 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -692,9 +692,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } // Third case: only one return statement. Don't bother doing extra work! - SmallVectorImpl::iterator I = CSI.Returns.begin(), - E = CSI.Returns.end(); - if (I+1 == E) + if (CSI.Returns.size() == 1) return; // General case: many return statements. @@ -703,8 +701,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { // We require the return types to strictly match here. // Note that we've already done the required promotions as part of // processing the return statement. - for (; I != E; ++I) { - const ReturnStmt *RS = *I; + for (const ReturnStmt *RS : CSI.Returns) { const Expr *RetE = RS->getRetValue(); QualType ReturnType = -- GitLab From f759bf6afbe728cf398cda332ad74b9a424f9a4f Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 26 Jun 2018 02:50:04 +0000 Subject: [PATCH 0273/1023] [ubsan] Relax nullability-return for blocks with deduced types When the return type of an ObjC-style block literals is deduced, pick the candidate type with the strictest nullability annotation applicable to every other candidate. This suppresses a UBSan false-positive in situations where a too-strict nullability would be deduced, despite the fact that the returned value would be implicitly cast to _Nullable. rdar://41317163 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335572 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Specifiers.h | 6 +++++ lib/Sema/SemaLambda.cpp | 9 ++++++- test/CodeGenObjC/ubsan-nullability.m | 37 ++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 6fb96f67bb..c5edb5ea96 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -294,6 +294,12 @@ namespace clang { Unspecified }; + /// Return true if \p L has a weaker nullability annotation than \p R. The + /// ordering is: Unspecified < Nullable < NonNull. + inline bool operator<(NullabilityKind L, NullabilityKind R) { + return uint8_t(L) > uint8_t(R); + } + /// Retrieve the spelling of the given nullability kind. llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive = false); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index b6ea484cea..98b428b089 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -707,8 +707,15 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); if (Context.getCanonicalFunctionResultType(ReturnType) == - Context.getCanonicalFunctionResultType(CSI.ReturnType)) + Context.getCanonicalFunctionResultType(CSI.ReturnType)) { + // Use the return type with the strictest possible nullability annotation. + auto RetTyNullability = ReturnType->getNullability(Ctx); + auto BlockNullability = CSI.ReturnType->getNullability(Ctx); + if (BlockNullability && + (!RetTyNullability || *RetTyNullability < *BlockNullability)) + CSI.ReturnType = ReturnType; continue; + } // FIXME: This is a poor diagnostic for ReturnStmts without expressions. // TODO: It's possible that the *first* return is the divergent one. diff --git a/test/CodeGenObjC/ubsan-nullability.m b/test/CodeGenObjC/ubsan-nullability.m index eeb24b03c8..8e7a9cba7c 100644 --- a/test/CodeGenObjC/ubsan-nullability.m +++ b/test/CodeGenObjC/ubsan-nullability.m @@ -1,6 +1,6 @@ // REQUIRES: asserts -// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s -// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s +// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6 // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 @@ -177,6 +177,37 @@ void call_A(A *a, int *p) { void dont_crash(int *_Nonnull p, ...) {} +@protocol NSObject +- (id)init; +@end +@interface NSObject {} +@end + +#pragma clang assume_nonnull begin + +/// Create a "NSObject * _Nonnull" instance. +NSObject *get_nonnull_error() { + // Use nil for convenience. The actual object doesn't matter. + return (NSObject *)NULL; +} + +NSObject *_Nullable no_null_return_value_diagnostic(int flag) { +// CHECK-LABEL: define internal {{.*}}no_null_return_value_diagnostic{{i?}}_block_invoke +// CHECK-NOT: @__ubsan_handle_nullability_return + NSObject *_Nullable (^foo)() = ^() { + if (flag) { + // Clang should not infer a nonnull return value for this block when this + // call is present. + return get_nonnull_error(); + } else { + return (NSObject *)NULL; + } + }; + return foo(); +} + +#pragma clang assume_nonnull end + int main() { nonnull_retval1(INULL); nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0); @@ -188,5 +219,7 @@ int main() { nonnull_init2(INULL); call_A((A *)NULL, INULL); dont_crash(INNULL, NULL); + no_null_return_value_diagnostic(0); + no_null_return_value_diagnostic(1); return 0; } -- GitLab From d4b57547051f0bd30420c8e53dc46566c70de30f Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 26 Jun 2018 03:53:06 +0000 Subject: [PATCH 0274/1023] Fix an ambiguous overload issue pointed out by MSVC Log: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11390 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335577 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Specifiers.h | 2 +- lib/Sema/SemaLambda.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index c5edb5ea96..303b77e448 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -296,7 +296,7 @@ namespace clang { /// Return true if \p L has a weaker nullability annotation than \p R. The /// ordering is: Unspecified < Nullable < NonNull. - inline bool operator<(NullabilityKind L, NullabilityKind R) { + inline bool hasWeakerNullability(NullabilityKind L, NullabilityKind R) { return uint8_t(L) > uint8_t(R); } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 98b428b089..fcacc2a17c 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -712,7 +712,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { auto RetTyNullability = ReturnType->getNullability(Ctx); auto BlockNullability = CSI.ReturnType->getNullability(Ctx); if (BlockNullability && - (!RetTyNullability || *RetTyNullability < *BlockNullability)) + (!RetTyNullability || + hasWeakerNullability(*RetTyNullability, *BlockNullability))) CSI.ReturnType = ReturnType; continue; } -- GitLab From a8fca7b41c7c42dcbceb46f1a0fb70cd9dbd016f Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 26 Jun 2018 12:00:14 +0000 Subject: [PATCH 0275/1023] [clang-format] Enable text proto formatting in common functions Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48363 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335595 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 374c25064a..741584d138 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -774,7 +774,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { "PROTO", }, /*EnclosingFunctionNames=*/ - {}, + { + "PARSE_TEXT_PROTO", + "EqualsProto", + }, /*CanonicalDelimiter=*/"", /*BasedOnStyle=*/"google", }, -- GitLab From 109df809f086d717e89b81cad4458f7055e8f10b Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Tue, 26 Jun 2018 13:44:24 +0000 Subject: [PATCH 0276/1023] [ASTImporter] Use InjectedClassNameType at import of templated record. Summary: At import of a record describing a template set its type to InjectedClassNameType (instead of RecordType). Reviewers: a.sidorin, martong, r.stahl Reviewed By: a.sidorin, martong, r.stahl Subscribers: a_sidorin, rnkovacs, martong, cfe-commits Differential Revision: https://reviews.llvm.org/D47450 Patch by Balazs Keri! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335600 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 23 +++++++++++++++++++ .../Inputs/inject1.cpp | 2 ++ .../Inputs/inject2.cpp | 2 ++ .../injected-class-name-decl/test.cpp | 3 +++ 4 files changed, 30 insertions(+) create mode 100644 test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp create mode 100644 test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp create mode 100644 test/ASTMerge/injected-class-name-decl/test.cpp diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index f812244ed3..6f14ab02ea 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2135,6 +2135,29 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (!ToDescribed) return nullptr; D2CXX->setDescribedClassTemplate(ToDescribed); + if (!DCXX->isInjectedClassName()) { + // In a record describing a template the type should be an + // InjectedClassNameType (see Sema::CheckClassTemplate). Update the + // previously set type to the correct value here (ToDescribed is not + // available at record create). + // FIXME: The previous type is cleared but not removed from + // ASTContext's internal storage. + CXXRecordDecl *Injected = nullptr; + for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { + auto *Record = dyn_cast(Found); + if (Record && Record->isInjectedClassName()) { + Injected = Record; + break; + } + } + D2CXX->setTypeForDecl(nullptr); + Importer.getToContext().getInjectedClassNameType(D2CXX, + ToDescribed->getInjectedClassNameSpecialization()); + if (Injected) { + Injected->setTypeForDecl(nullptr); + Importer.getToContext().getTypeDeclType(Injected, D2CXX); + } + } } else if (MemberSpecializationInfo *MemberInfo = DCXX->getMemberSpecializationInfo()) { TemplateSpecializationKind SK = diff --git a/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp b/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp new file mode 100644 index 0000000000..f6f769746d --- /dev/null +++ b/test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp @@ -0,0 +1,2 @@ +template +class C { static X x; }; diff --git a/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp b/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp new file mode 100644 index 0000000000..7cf5fc2232 --- /dev/null +++ b/test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp @@ -0,0 +1,2 @@ +template +X C::x; diff --git a/test/ASTMerge/injected-class-name-decl/test.cpp b/test/ASTMerge/injected-class-name-decl/test.cpp new file mode 100644 index 0000000000..9f31674108 --- /dev/null +++ b/test/ASTMerge/injected-class-name-decl/test.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.ast %S/Inputs/inject1.cpp +// RUN: %clang_cc1 -std=c++1z -emit-obj -o /dev/null -ast-merge %t.ast %S/Inputs/inject2.cpp +// expected-no-diagnostics -- GitLab From df4e40a91cabc39da987aa5fe5f9b7c3049554b6 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 26 Jun 2018 15:20:20 +0000 Subject: [PATCH 0277/1023] Avoid spurious 'comma operator within array index expression' MSVC warning. NFCI. Split the braces list initialization from the [] map operator to keep MSVC happy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335614 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ItaniumCXXABI.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index 2403e048da..a75ae14f90 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -135,9 +135,10 @@ public: /// Variable decls are numbered by identifier. unsigned getManglingNumber(const VarDecl *VD, unsigned) override { - if (auto *DD = dyn_cast(VD)) - return ++DecompsitionDeclManglingNumbers[ - DecompositionDeclName{DD->bindings()}]; + if (auto *DD = dyn_cast(VD)) { + DecompositionDeclName Name{DD->bindings()}; + return ++DecompsitionDeclManglingNumbers[Name]; + } const IdentifierInfo *Identifier = VD->getIdentifier(); if (!Identifier) { -- GitLab From 3e914648ae0f8adb2ae0cd147b5967251f57fd19 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Tue, 26 Jun 2018 15:50:34 +0000 Subject: [PATCH 0278/1023] [ThinLTO] Add testing of summary index parsing to a couple CFI tests Summary: Changes to some clang side tests to go with the summary parsing patch. Depends on D47905. Reviewers: pcc, dexonsmith, mehdi_amini Subscribers: inglorion, eraman, cfe-commits, steven_wu Differential Revision: https://reviews.llvm.org/D47906 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335618 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/thinlto-distributed-cfi-devirt.ll | 2 ++ test/CodeGen/thinlto-distributed-cfi.ll | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/CodeGen/thinlto-distributed-cfi-devirt.ll b/test/CodeGen/thinlto-distributed-cfi-devirt.ll index c4a3164497..ab33a59b69 100644 --- a/test/CodeGen/thinlto-distributed-cfi-devirt.ll +++ b/test/CodeGen/thinlto-distributed-cfi-devirt.ll @@ -30,6 +30,8 @@ ; CHECK-LABEL: Date: Tue, 26 Jun 2018 16:14:35 +0000 Subject: [PATCH 0279/1023] [Driver] Do not add -lpthread & -lrt with -static-libsan on Android Summary: I am not sure anyone has tried to compile an application with sanitizers on Android with `-static-libsan`, and a recent NDK, but it fails with: ``` .../i686-linux-android/bin/ld.gold: error: cannot find -lpthread .../i686-linux-android/bin/ld.gold: error: cannot find -lrt ``` My understanding is that both are included in Bionic and as such are not needed, and actually error out. So remove the addition of those two in `linkSanitizerRuntimeDeps` when dealing with Android, and update the tests. I am unfamiliar with the evolution of the NDK and I am not sure if this has always been the case or if this is somewhat of a recent evolution. I'll let Android people chime in. Reviewers: eugenis, pirama, srhines Reviewed By: eugenis, srhines Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48570 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335620 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/CommonArgs.cpp | 5 +++-- test/Driver/sanitizer-ld.c | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 98a36bcd83..1e093b25b9 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -564,8 +564,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, // Force linking against the system libraries sanitizers depends on // (see PR15823 why this is necessary). CmdArgs.push_back("--no-as-needed"); - // There's no libpthread or librt on RTEMS. - if (TC.getTriple().getOS() != llvm::Triple::RTEMS) { + // There's no libpthread or librt on RTEMS & Android. + if (TC.getTriple().getOS() != llvm::Triple::RTEMS && + !TC.getTriple().isAndroid()) { CmdArgs.push_back("-lpthread"); if (TC.getTriple().getOS() != llvm::Triple::OpenBSD) CmdArgs.push_back("-lrt"); diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index e85a828b33..483c87a624 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -153,7 +153,8 @@ // // CHECK-ASAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-ASAN-ANDROID-STATICLIBASAN: libclang_rt.asan-arm-android.a" -// CHECK-ASAN-ANDROID-STATICLIBASAN: "-lpthread" +// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lpthread" +// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lrt" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=undefined \ @@ -175,7 +176,8 @@ // // CHECK-UBSAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-UBSAN-ANDROID-STATICLIBASAN: libclang_rt.ubsan_standalone-arm-android.a" -// CHECK-UBSAN-ANDROID-STATICLIBASAN: "-lpthread" +// CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lpthread" +// CHECK-UBSAN-ANDROID-STATICLIBASAN-NOT: "-lrt" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ @@ -735,7 +737,8 @@ // CHECK-SCUDO-ANDROID-STATIC: "-pie" // CHECK-SCUDO-ANDROID-STATIC: "--whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "--no-whole-archive" // CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++" -// CHECK-SCUDO-ANDROID-STATIC: "-lpthread" +// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lpthread" +// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lrt" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=hwaddress \ -- GitLab From c812eefd7b0649481ed4df031e851211354e565e Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih Date: Tue, 26 Jun 2018 17:05:01 +0000 Subject: [PATCH 0280/1023] Revert "[CMake][Darwin] Match cxx-headers -> cxx_headers libcxx target rename." This reverts commit r334550. Try to fix the stage2 build failing on Green Dragon for a while. http://green.lab.llvm.org/green/job/clang-stage2-Rthinlto/11124/console git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335628 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Apple-stage2.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake index 3b80b5f407..c7f3f04b42 100644 --- a/cmake/caches/Apple-stage2.cmake +++ b/cmake/caches/Apple-stage2.cmake @@ -61,7 +61,7 @@ set(LLVM_DISTRIBUTION_COMPONENTS LTO clang-format clang-headers - cxx_headers + cxx-headers ${LLVM_TOOLCHAIN_TOOLS} CACHE STRING "") -- GitLab From 52b5428f4ed70327143838764094db3fdc699a2e Mon Sep 17 00:00:00 2001 From: Aaron Enye Shi Date: Tue, 26 Jun 2018 17:12:29 +0000 Subject: [PATCH 0281/1023] [Test] Initial test commit access git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335630 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/HIP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 8514aa6481..0f6fb2d309 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -254,7 +254,7 @@ HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, for (Arg *A : Args) { if (A->getOption().matches(options::OPT_Xarch__)) { - // Skip this argument unless the architecture matches BoundArch + // Skip this argument unless the architecture matches BoundArch. if (BoundArch.empty() || A->getValue(0) != BoundArch) continue; -- GitLab From ad2ab0a634a255ca5207eb64f2791aa1a07553bd Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 26 Jun 2018 17:24:03 +0000 Subject: [PATCH 0282/1023] [OPENMP, NVPTX] Reduce the number of the globalized variables. Patch tries to make better analysis of the variables that should be globalized. From now, instead of all parallel directives it will check only distribute parallel .. directives and check only for firstprivte/lastprivate variables if they must be globalized. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335632 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 52 +++++++++++++++---- ...stribute_parallel_generic_mode_codegen.cpp | 51 ++++++++++++++++++ 2 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 5b7f0c3e43..8cf5bb2f44 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -187,7 +187,7 @@ class CheckVarsEscapingDeclContext final RecordDecl *GlobalizedRD = nullptr; llvm::SmallDenseMap MappedDeclsFields; bool AllEscaped = false; - bool IsForParallelRegion = false; + bool IsForCombinedParallelRegion = false; static llvm::Optional isDeclareTargetDeclaration(const ValueDecl *VD) { @@ -210,7 +210,7 @@ class CheckVarsEscapingDeclContext final if (const FieldDecl *FD = CSI->lookup(cast(VD))) { // Check if need to capture the variable that was already captured by // value in the outer region. - if (!IsForParallelRegion) { + if (!IsForCombinedParallelRegion) { if (!FD->hasAttrs()) return; const auto *Attr = FD->getAttr(); @@ -225,13 +225,13 @@ class CheckVarsEscapingDeclContext final assert(!VD->getType()->isVariablyModifiedType() && "Parameter captured by value with variably modified type"); EscapedParameters.insert(VD); - } else if (!IsForParallelRegion) { + } else if (!IsForCombinedParallelRegion) { return; } } } if ((!CGF.CapturedStmtInfo || - (IsForParallelRegion && CGF.CapturedStmtInfo)) && + (IsForCombinedParallelRegion && CGF.CapturedStmtInfo)) && VD->getType()->isReferenceType()) // Do not globalize variables with reference type. return; @@ -253,18 +253,49 @@ class CheckVarsEscapingDeclContext final } } } - void VisitOpenMPCapturedStmt(const CapturedStmt *S, bool IsParallelRegion) { + void VisitOpenMPCapturedStmt(const CapturedStmt *S, + ArrayRef Clauses, + bool IsCombinedParallelRegion) { if (!S) return; for (const CapturedStmt::Capture &C : S->captures()) { if (C.capturesVariable() && !C.capturesVariableByCopy()) { const ValueDecl *VD = C.getCapturedVar(); - bool SavedIsParallelRegion = IsForParallelRegion; - IsForParallelRegion = IsParallelRegion; + bool SavedIsForCombinedParallelRegion = IsForCombinedParallelRegion; + if (IsCombinedParallelRegion) { + // Check if the variable is privatized in the combined construct and + // those private copies must be shared in the inner parallel + // directive. + IsForCombinedParallelRegion = false; + for (const OMPClause *C : Clauses) { + if (!isOpenMPPrivate(C->getClauseKind()) || + C->getClauseKind() == OMPC_reduction || + C->getClauseKind() == OMPC_linear || + C->getClauseKind() == OMPC_private) + continue; + ArrayRef Vars; + if (const auto *PC = dyn_cast(C)) + Vars = PC->getVarRefs(); + else if (const auto *PC = dyn_cast(C)) + Vars = PC->getVarRefs(); + else + llvm_unreachable("Unexpected clause."); + for (const auto *E : Vars) { + const Decl *D = + cast(E)->getDecl()->getCanonicalDecl(); + if (D == VD->getCanonicalDecl()) { + IsForCombinedParallelRegion = true; + break; + } + } + if (IsForCombinedParallelRegion) + break; + } + } markAsEscaped(VD); if (isa(VD)) VisitValueDecl(VD); - IsForParallelRegion = SavedIsParallelRegion; + IsForCombinedParallelRegion = SavedIsForCombinedParallelRegion; } } } @@ -341,7 +372,10 @@ public: VisitStmt(S->getCapturedStmt()); return; } - VisitOpenMPCapturedStmt(S, CaptureRegions.back() == OMPD_parallel); + VisitOpenMPCapturedStmt( + S, D->clauses(), + CaptureRegions.back() == OMPD_parallel && + isOpenMPDistributeDirective(D->getDirectiveKind())); } } void VisitCapturedStmt(const CapturedStmt *S) { diff --git a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp new file mode 100644 index 0000000000..5dc440e46d --- /dev/null +++ b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp @@ -0,0 +1,51 @@ +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm-bc %s -o %t-x86-host.bc +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -fexceptions -fcxx-exceptions -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +int a; + +int foo(int *a); + +int main(int argc, char **argv) { + int b[10], c[10], d[10]; +#pragma omp target teams map(tofrom:a) +#pragma omp distribute parallel for firstprivate(b) lastprivate(c) if(a) + for (int i= 0; i < argc; ++i) + a = foo(&i) + foo(&a) + foo(&b[i]) + foo(&c[i]) + foo(&d[i]); + return 0; +} + +// CHECK: @__omp_offloading_{{.*}}_main_l17_exec_mode = weak constant i8 1 + +// CHECK-LABEL: define internal void @__omp_offloading_{{.*}}_main_l17_worker( + +// CHECK: define weak void @__omp_offloading_{{.*}}_main_l17([10 x i32]* dereferenceable(40) %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}}, i32* dereferenceable(4) %{{.+}}, i{{64|32}} %{{.+}}, [10 x i32]* dereferenceable(40) %{{.+}}) +// CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 84, i16 0) +// CHECK: [[STACK:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty* +// CHECK: [[ARGC:%.+]] = load i32, i32* %{{.+}}, align +// CHECK: [[ARGC_ADDR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 0 +// CHECK: store i32 [[ARGC]], i32* [[ARGC_ADDR]], +// CHECK: getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 1 +// CHECK: getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[STACK]], i{{32|64}} 0, i{{32|64}} 2 +// CHECK: call void @__kmpc_for_static_init_4( + +// CHECK: call void @__kmpc_serialized_parallel( +// CHECK: call void [[PARALLEL:@.+]]( +// CHECK: call void @__kmpc_end_serialized_parallel( + +// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @ + +// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]]) + +// CHECK: define internal void [[PARALLEL]]( +// CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0) + +// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]]) + +#endif -- GitLab From d0be2a09df65ce879927a55fa21eddb0eccaba7f Mon Sep 17 00:00:00 2001 From: Aaron Enye Shi Date: Tue, 26 Jun 2018 17:40:36 +0000 Subject: [PATCH 0283/1023] [HIP] Remove hip/hc.amdgcn.bc from HIP Toolchains Summary: The hc.amdgcn.bc and hip.amdgcn.bc are removed in VDI build and no longer needed. Reviewers: yaxunl Reviewed By: yaxunl Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48455 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335634 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/HIP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 0f6fb2d309..38dfb0e192 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -75,12 +75,12 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( std::string ISAVerBC = "oclc_isa_version_" + SubArchName.drop_front(3).str() + ".amdgcn.bc"; - BCLibs.append({"hip.amdgcn.bc", "hc.amdgcn.bc", "opencl.amdgcn.bc", + BCLibs.append({"opencl.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc", "ocml.amdgcn.bc", "oclc_finite_only_off.amdgcn.bc", "oclc_daz_opt_off.amdgcn.bc", "oclc_correctly_rounded_sqrt_on.amdgcn.bc", - "oclc_unsafe_math_off.amdgcn.bc", "hc.amdgcn.bc", ISAVerBC}); + "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC}); } for (auto Lib : BCLibs) addBCLib(C, Args, CmdArgs, LibraryPaths, Lib); -- GitLab From 032d43a8fe02938486e7d60c9f738a6e34be0fa6 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 26 Jun 2018 17:45:26 +0000 Subject: [PATCH 0284/1023] Compile CodeGenModule.cpp with /bigobj. Apparently we're now hitting an object file section limit on this file with expensive checks enabled. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 29e54966a0..2a0f4f0e83 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -32,6 +32,10 @@ if (CLANG_BUILT_STANDALONE) set(codegen_deps) endif() +if (MSVC) + set_source_files_properties(CodeGenModule.cpp PROPERTIES COMPILE_FLAGS /bigobj) +endif() + add_clang_library(clangCodeGen BackendUtil.cpp CGAtomic.cpp -- GitLab From 4d1c54646bd2e3bcb05ff96c7373f1069aed9f9a Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Tue, 26 Jun 2018 17:56:48 +0000 Subject: [PATCH 0285/1023] [Sema] Fix infinite typo correction loop. NumTypos guard value ~0U doesn't prevent from creating new delayed typos. When you create new delayed typos during typo correction, value ~0U wraps around to 0. When NumTypos is 0 we can miss some typos and treat an expression as it can be typo-corrected. But if the expression is still invalid after correction, we can get stuck in infinite loop trying to correct it. Fix by not using value ~0U so that NumTypos correctly reflects the number of typos. rdar://problem/38642201 Reviewers: arphaman, majnemer, rsmith Reviewed By: rsmith Subscribers: rsmith, nicholas, cfe-commits Differential Revision: https://reviews.llvm.org/D47341 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335638 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 4 ---- test/Sema/typo-correction.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 59066ee34f..02cb78b9de 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -7727,12 +7727,8 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl, if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos && (E->isTypeDependent() || E->isValueDependent() || E->isInstantiationDependent())) { - auto TyposInContext = ExprEvalContexts.back().NumTypos; - assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr"); - ExprEvalContexts.back().NumTypos = ~0U; auto TyposResolved = DelayedTypos.size(); auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E); - ExprEvalContexts.back().NumTypos = TyposInContext; TyposResolved -= DelayedTypos.size(); if (Result.isInvalid() || Result.get() != E) { ExprEvalContexts.back().NumTypos -= TyposResolved; diff --git a/test/Sema/typo-correction.c b/test/Sema/typo-correction.c index 78007015dc..e7992ac90b 100644 --- a/test/Sema/typo-correction.c +++ b/test/Sema/typo-correction.c @@ -87,3 +87,16 @@ __attribute__((overloadable)) void func_overloadable(float); void overloadable_callexpr(int arg) { func_overloadable(ar); //expected-error{{use of undeclared identifier}} } + +// rdar://problem/38642201 +struct rdar38642201 { + int fieldName; +}; + +void rdar38642201_callee(int x, int y); +void rdar38642201_caller() { + struct rdar38642201 structVar; + rdar38642201_callee( + structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} + structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} +} -- GitLab From 2348c7f06faeab209b8b09824f0ec7e38763a8d5 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 26 Jun 2018 19:48:05 +0000 Subject: [PATCH 0286/1023] [mips] Use more conservative default CPUs for MIPS on FreeBSD. FreeBSD defaults to mips3 for all MIPS ABIs with GCC as that is the minimum MIPS architecture FreeBSD supports. Use mips3 for MIPS64 and mips2 for MIPS32 to match. Reviewed By: atanasyan Differential Revision: https://reviews.llvm.org/D48499 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335653 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Arch/Mips.cpp | 7 +++++++ test/Driver/freebsd-mips-as.c | 24 ++++++++++++------------ test/Driver/freebsd.c | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index 85aef3295b..5aeb9288e7 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -45,6 +45,13 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, if (Triple.getOS() == llvm::Triple::OpenBSD) DefMips64CPU = "mips3"; + // MIPS2 is the default for mips(el)?-unknown-freebsd. + // MIPS3 is the default for mips64(el)?-unknown-freebsd. + if (Triple.getOS() == llvm::Triple::FreeBSD) { + DefMips32CPU = "mips2"; + DefMips64CPU = "mips3"; + } + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, options::OPT_mcpu_EQ)) CPUName = A->getValue(); diff --git a/test/Driver/freebsd-mips-as.c b/test/Driver/freebsd-mips-as.c index af02c38693..a053c2180e 100644 --- a/test/Driver/freebsd-mips-as.c +++ b/test/Driver/freebsd-mips-as.c @@ -3,62 +3,62 @@ // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-AS %s -// MIPS32-EB-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" +// MIPS32-EB-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" // MIPS32-EB-AS-NOT: "-KPIC" // // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -fPIC -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-PIC %s -// MIPS32-EB-PIC: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" +// MIPS32-EB-PIC: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" // MIPS32-EB-PIC: "-KPIC" // // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -fpic -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-PIC-SMALL %s -// MIPS32-EB-PIC-SMALL: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" +// MIPS32-EB-PIC-SMALL: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" // MIPS32-EB-PIC-SMALL: "-KPIC" // // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -fPIE -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-PIE %s -// MIPS32-EB-PIE: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" +// MIPS32-EB-PIE: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" // MIPS32-EB-PIE: "-KPIC" // // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -fpie -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-PIE-SMALL %s -// MIPS32-EB-PIE-SMALL: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" +// MIPS32-EB-PIE-SMALL: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" // MIPS32-EB-PIE-SMALL: "-KPIC" // // RUN: %clang -target mipsel-unknown-freebsd -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-DEF-EL-AS %s -// MIPS32-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EL" +// MIPS32-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EL" // // RUN: %clang -target mips64-unknown-freebsd -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS64-EB-AS %s -// MIPS64-EB-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EB" +// MIPS64-EB-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EB" // // RUN: %clang -target mips64el-unknown-freebsd -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS64-DEF-EL-AS %s -// MIPS64-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EL" +// MIPS64-DEF-EL-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EL" // // RUN: %clang -target mips64-unknown-freebsd -mabi=n32 -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS-N32 %s -// MIPS-N32: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "n32" "-EB" +// MIPS-N32: as{{(.exe)?}}" "-march" "mips3" "-mabi" "n32" "-EB" // // RUN: %clang -target mipsel-unknown-freebsd -mabi=32 -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EL-AS %s -// MIPS32-EL-AS: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EL" +// MIPS32-EL-AS: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EL" // // RUN: %clang -target mips64el-unknown-freebsd -mabi=64 -### \ // RUN: -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS64-EL-AS %s -// MIPS64-EL-AS: as{{(.exe)?}}" "-march" "mips64r2" "-mabi" "64" "-EL" +// MIPS64-EL-AS: as{{(.exe)?}}" "-march" "mips3" "-mabi" "64" "-EL" // // RUN: %clang -target mips-linux-freebsd -march=mips32r2 -### \ // RUN: -no-integrated-as -c %s 2>&1 \ @@ -88,5 +88,5 @@ // RUN: %clang -target mips-unknown-freebsd -### \ // RUN: -no-integrated-as -G0 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS32-EB-AS-G0 %s -// MIPS32-EB-AS-G0: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-EB" "-G0" +// MIPS32-EB-AS-G0: as{{(.exe)?}}" "-march" "mips2" "-mabi" "32" "-EB" "-G0" // MIPS32-EB-AS-G0-NOT: "-KPIC" diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c index ac663ffacc..b6493823bc 100644 --- a/test/Driver/freebsd.c +++ b/test/Driver/freebsd.c @@ -148,3 +148,17 @@ // RUN: %clang -target mips-unknown-freebsd %s -### -G0 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS-G %s // CHECK-MIPS-G: ld{{.*}}" "-G0" + +// Check CPU type for MIPS +// RUN: %clang -target mips-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS-CPU %s +// RUN: %clang -target mipsel-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS-CPU %s +// CHECK-MIPS-CPU: "-target-cpu" "mips2" + +// Check CPU type for MIPS64 +// RUN: %clang -target mips64-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s +// RUN: %clang -target mips64el-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s +// CHECK-MIPS64-CPU: "-target-cpu" "mips3" -- GitLab From 495d25c4469822341840cb74ac457c8bcd19c42c Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Tue, 26 Jun 2018 20:05:18 +0000 Subject: [PATCH 0287/1023] [AST] Fix typo in LazyOffsetPtr::get docs (NFC) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335655 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExternalASTSource.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 1e05a309af..82255bb1c4 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -393,7 +393,7 @@ public: /// Whether this pointer is currently stored as an offset. bool isOffset() const { return Ptr & 0x01; } - /// Retrieve the pointer to the AST node that this lazy pointer + /// Retrieve the pointer to the AST node that this lazy pointer points to. /// /// \param Source the external AST source. /// -- GitLab From d245644c76fc9fdddef557021c2affb3afdeb7ba Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 26 Jun 2018 21:12:08 +0000 Subject: [PATCH 0288/1023] [analyzer] Do not run visitors until the fixpoint, run only once. In the current implementation, we run visitors until the fixed point is reached. That is, if a visitor adds another visitor, the currently processed path is destroyed, all diagnostics is discarded, and it is regenerated again, until it's no longer modified. This pattern has a few negative implications: - This loop does not even guarantee to terminate. E.g. just imagine two visitors bouncing a diagnostics around. - Performance-wise, e.g. for sqlite3 all visitors are being re-run at least 10 times for some bugs. We have already seen a few reports where it leads to timeouts. - If we want to add more computationally intense visitors, this will become worse. - From architectural standpoint, the current layout requires copying visitors, which is conceptually wrong, and can be annoying (e.g. no unique_ptr on visitors allowed). The proposed change is a much simpler architecture: the outer loop processes nodes upwards, and whenever the visitor is added it only processes current nodes and above, thus guaranteeing termination. Differential Revision: https://reviews.llvm.org/D47856 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335666 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/BugReporter.h | 73 ++- .../Core/BugReporter/BugReporterVisitors.h | 69 +- .../Core/BugReporter/PathDiagnostic.h | 9 +- .../DeleteWithNonVirtualDtorChecker.cpp | 2 +- .../Checkers/DynamicTypeChecker.cpp | 3 +- .../Checkers/DynamicTypePropagation.cpp | 2 +- .../Checkers/LocalizationChecker.cpp | 3 +- .../Checkers/MPI-Checker/MPIBugReporter.h | 2 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 3 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 7 +- .../Checkers/MisusedMovedObjectChecker.cpp | 2 +- .../Checkers/NullabilityChecker.cpp | 3 +- .../Checkers/ObjCSuperDeallocChecker.cpp | 4 +- .../Checkers/RetainCountChecker.cpp | 22 +- .../Checkers/TestAfterDivZeroChecker.cpp | 2 +- lib/StaticAnalyzer/Checkers/ValistChecker.cpp | 7 +- .../Checkers/VirtualCallChecker.cpp | 2 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 610 ++++++++++-------- .../Core/BugReporterVisitors.cpp | 16 +- test/Analysis/null-deref-path-notes.c | 4 +- 20 files changed, 418 insertions(+), 427 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 67d2dedc15..9f0a83d255 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -23,6 +23,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" @@ -65,6 +66,11 @@ class SValBuilder; // Interface for individual bug reports. //===----------------------------------------------------------------------===// +/// A mapping from diagnostic consumers to the diagnostics they should +/// consume. +using DiagnosticForConsumerMapTy = + llvm::DenseMap>; + /// This class provides an interface through which checkers can create /// individual bug reports. class BugReport : public llvm::ilist_node { @@ -130,10 +136,6 @@ protected: /// Used for ensuring the visitors are only added once. llvm::FoldingSet CallbacksSet; - /// Used for clients to tell if the report's configuration has changed - /// since the last time they checked. - unsigned ConfigurationChangeToken = 0; - /// When set, this flag disables all callstack pruning from a diagnostic /// path. This is useful for some reports that want maximum fidelty /// when reporting an issue. @@ -229,10 +231,6 @@ public: bool isInteresting(SVal V); bool isInteresting(const LocationContext *LC); - unsigned getConfigurationChangeToken() const { - return ConfigurationChangeToken; - } - /// Returns whether or not this report should be considered valid. /// /// Invalid reports are those that have been classified as likely false @@ -345,6 +343,9 @@ public: /// registerVarDeclsLastStore(). void addVisitor(std::unique_ptr visitor); + /// Remove all visitors attached to this bug report. + void clearVisitors(); + /// Iterators through the custom diagnostic visitors. visitor_iterator visitor_begin() { return Callbacks.begin(); } visitor_iterator visitor_end() { return Callbacks.end(); } @@ -406,6 +407,8 @@ public: /// BugReporter is a utility class for generating PathDiagnostics for analysis. /// It collects the BugReports and BugTypes and knows how to generate /// and flush the corresponding diagnostics. +/// +/// The base class is used for generating path-insensitive class BugReporter { public: enum Kind { BaseBRKind, GRBugReporterKind }; @@ -422,11 +425,11 @@ private: /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); - /// Generate and flush the diagnostics for the given bug report - /// and PathDiagnosticConsumer. - void FlushReport(BugReport *exampleReport, - PathDiagnosticConsumer &PD, - ArrayRef BugReports); + /// Generate the diagnostics for the given bug report. + std::unique_ptr + generateDiagnosticForConsumerMap(BugReport *exampleReport, + ArrayRef consumers, + ArrayRef bugReports); /// The set of bug reports tracked by the BugReporter. llvm::FoldingSet EQClasses; @@ -472,10 +475,10 @@ public: AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); } - virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, - PathDiagnosticConsumer &PC, - ArrayRef &bugReports) { - return true; + virtual std::unique_ptr + generatePathDiagnostics(ArrayRef consumers, + ArrayRef &bugReports) { + return {}; } void Register(BugType *BT); @@ -506,7 +509,7 @@ private: StringRef category); }; -// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. +/// GRBugReporter is used for generating path-sensitive reports. class GRBugReporter : public BugReporter { ExprEngine& Eng; @@ -528,16 +531,14 @@ public: /// engine. ProgramStateManager &getStateManager(); - /// Generates a path corresponding to one of the given bug reports. - /// - /// Which report is used for path generation is not specified. The - /// bug reporter will try to pick the shortest path, but this is not - /// guaranteed. + /// \p bugReports A set of bug reports within a *single* equivalence class /// - /// \return True if the report was valid and a path was generated, - /// false if the reports should be considered invalid. - bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, - ArrayRef &bugReports) override; + /// \return A mapping from consumers to the corresponding diagnostics. + /// Iterates through the bug reports within a single equivalence class, + /// stops at a first non-invalidated report. + std::unique_ptr + generatePathDiagnostics(ArrayRef consumers, + ArrayRef &bugReports) override; /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { @@ -545,13 +546,27 @@ public: } }; + +class NodeMapClosure : public BugReport::NodeResolver { + InterExplodedGraphMap &M; + +public: + NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} + + const ExplodedNode *getOriginalNode(const ExplodedNode *N) override { + return M.lookup(N); + } +}; + class BugReporterContext { GRBugReporter &BR; + NodeMapClosure NMC; virtual void anchor(); public: - BugReporterContext(GRBugReporter& br) : BR(br) {} + BugReporterContext(GRBugReporter &br, InterExplodedGraphMap &Backmap) + : BR(br), NMC(Backmap) {} virtual ~BugReporterContext() = default; @@ -575,7 +590,7 @@ public: return BR.getSourceManager(); } - virtual BugReport::NodeResolver& getNodeResolver() = 0; + NodeMapClosure& getNodeResolver() { return NMC; } }; } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 9662d91fea..031a76c7bd 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -40,12 +40,6 @@ class MemRegion; class PathDiagnosticPiece; /// BugReporterVisitors are used to add custom diagnostics along a path. -/// -/// Custom visitors should subclass the BugReporterVisitorImpl class for a -/// default implementation of the clone() method. -/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the -/// default implementation of clone() will NOT do the right thing, and you -/// will have to provide your own implementation.) class BugReporterVisitor : public llvm::FoldingSetNode { public: BugReporterVisitor() = default; @@ -53,19 +47,13 @@ public: BugReporterVisitor(BugReporterVisitor &&) {} virtual ~BugReporterVisitor(); - /// Returns a copy of this BugReporter. - /// - /// Custom BugReporterVisitors should not override this method directly. - /// Instead, they should inherit from BugReporterVisitorImpl and provide - /// a protected or public copy constructor. - /// - /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the - /// default implementation of clone() will NOT do the right thing, and you - /// will have to provide your own implementation.) - virtual std::unique_ptr clone() const = 0; - /// Return a diagnostic piece which should be associated with the /// given node. + /// Note that this function does *not* get run on the very last node + /// of the report, as the PathDiagnosticPiece associated with the + /// last node should be unique. + /// Use {@code getEndPath} to customize the note associated with the report + /// end instead. /// /// The last parameter can be used to register a new visitor with the given /// BugReport while processing a node. @@ -84,34 +72,18 @@ public: /// /// NOTE that this function can be implemented on at most one used visitor, /// and otherwise it crahes at runtime. - virtual std::unique_ptr + virtual std::shared_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; /// Generates the default final diagnostic piece. - static std::unique_ptr + static std::shared_ptr getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); }; -/// This class provides a convenience implementation for clone() using the -/// Curiously-Recurring Template Pattern. If you are implementing a custom -/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public -/// or protected copy constructor. -/// -/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the -/// default implementation of clone() will NOT do the right thing, and you -/// will have to provide your own implementation.) -template -class BugReporterVisitorImpl : public BugReporterVisitor { - std::unique_ptr clone() const override { - return llvm::make_unique(*static_cast(this)); - } -}; - -class FindLastStoreBRVisitor final - : public BugReporterVisitorImpl { +class FindLastStoreBRVisitor final : public BugReporterVisitor { const MemRegion *R; SVal V; bool Satisfied = false; @@ -138,8 +110,7 @@ public: BugReport &BR) override; }; -class TrackConstraintBRVisitor final - : public BugReporterVisitorImpl { +class TrackConstraintBRVisitor final : public BugReporterVisitor { DefinedSVal Constraint; bool Assumption; bool IsSatisfied = false; @@ -172,8 +143,7 @@ private: /// \class NilReceiverBRVisitor /// Prints path notes when a message is sent to a nil receiver. -class NilReceiverBRVisitor final - : public BugReporterVisitorImpl { +class NilReceiverBRVisitor final : public BugReporterVisitor { public: void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; @@ -191,8 +161,7 @@ public: }; /// Visitor that tries to report interesting diagnostics from conditions. -class ConditionBRVisitor final - : public BugReporterVisitorImpl { +class ConditionBRVisitor final : public BugReporterVisitor { // FIXME: constexpr initialization isn't supported by MSVC2013. static const char *const GenericTrueMessage; static const char *const GenericFalseMessage; @@ -255,7 +224,7 @@ public: /// /// Currently this suppresses reports based on locations of bugs. class LikelyFalsePositiveSuppressionBRVisitor final - : public BugReporterVisitorImpl { + : public BugReporterVisitor { public: static void *getTag() { static int Tag = 0; @@ -282,8 +251,7 @@ public: /// /// As a result, BugReporter will not prune the path through the function even /// if the region's contents are not modified/accessed by the call. -class UndefOrNullArgVisitor final - : public BugReporterVisitorImpl { +class UndefOrNullArgVisitor final : public BugReporterVisitor { /// The interesting memory region this visitor is tracking. const MemRegion *R; @@ -302,8 +270,7 @@ public: BugReport &BR) override; }; -class SuppressInlineDefensiveChecksVisitor final - : public BugReporterVisitorImpl { +class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor { /// The symbolic value for which we are tracking constraints. /// This value is constrained to null in the end of path. DefinedSVal V; @@ -333,8 +300,7 @@ public: BugReport &BR) override; }; -class CXXSelfAssignmentBRVisitor final - : public BugReporterVisitorImpl { +class CXXSelfAssignmentBRVisitor final : public BugReporterVisitor { bool Satisfied = false; public: @@ -350,7 +316,7 @@ public: /// The bug visitor prints a diagnostic message at the location where a given /// variable was tainted. -class TaintBugVisitor final : public BugReporterVisitorImpl { +class TaintBugVisitor final : public BugReporterVisitor { private: const SVal V; @@ -367,8 +333,7 @@ public: /// The bug visitor will walk all the nodes in a path and collect all the /// constraints. When it reaches the root node, will create a refutation /// manager and check if the constraints are satisfiable -class FalsePositiveRefutationBRVisitor final - : public BugReporterVisitorImpl { +class FalsePositiveRefutationBRVisitor final : public BugReporterVisitor { private: /// Holds the constraints in a given path // TODO: should we use a set? diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 244cbfea9e..cca977de88 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -811,7 +811,7 @@ public: bool isWithinCall() const { return !pathStack.empty(); } - void setEndOfPath(std::unique_ptr EndPiece) { + void setEndOfPath(std::shared_ptr EndPiece) { assert(!Loc.isValid() && "End location already set!"); Loc = EndPiece->getLocation(); assert(Loc.isValid() && "Invalid location for end-of-path piece"); @@ -824,12 +824,6 @@ public: VerboseDesc += S; } - void resetPath() { - pathStack.clear(); - pathImpl.clear(); - Loc = PathDiagnosticLocation(); - } - /// If the last piece of the report point to the header file, resets /// the location of the report to be the last location in the main source /// file. @@ -865,7 +859,6 @@ public: filesmap_iterator executedLines_end() const { return ExecutedLines->end(); } PathDiagnosticLocation getLocation() const { - assert(Loc.isValid() && "No report location set yet!"); return Loc; } diff --git a/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp b/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp index 53632b41df..d3489282ab 100644 --- a/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp @@ -39,7 +39,7 @@ class DeleteWithNonVirtualDtorChecker : public Checker> { mutable std::unique_ptr BT; - class DeleteBugVisitor : public BugReporterVisitorImpl { + class DeleteBugVisitor : public BugReporterVisitor { public: DeleteBugVisitor() : Satisfied(false) {} void Profile(llvm::FoldingSetNodeID &ID) const override { diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp index 109897be29..4e4d81cd67 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp @@ -38,8 +38,7 @@ class DynamicTypeChecker : public Checker> { new BugType(this, "Dynamic and static type mismatch", "Type Error")); } - class DynamicTypeBugVisitor - : public BugReporterVisitorImpl { + class DynamicTypeBugVisitor : public BugReporterVisitor { public: DynamicTypeBugVisitor(const MemRegion *Reg) : Reg(Reg) {} diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 71dbe2f4b7..126e57645a 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -74,7 +74,7 @@ class DynamicTypePropagation: new BugType(this, "Generics", categories::CoreFoundationObjectiveC)); } - class GenericsBugVisitor : public BugReporterVisitorImpl { + class GenericsBugVisitor : public BugReporterVisitor { public: GenericsBugVisitor(SymbolRef S) : Sym(S) {} diff --git a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index bfdb511e74..849b1193c0 100644 --- a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -113,8 +113,7 @@ NonLocalizedStringChecker::NonLocalizedStringChecker() { } namespace { -class NonLocalizedStringBRVisitor final - : public BugReporterVisitorImpl { +class NonLocalizedStringBRVisitor final : public BugReporterVisitor { const MemRegion *NonLocalizedString; bool Satisfied; diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h index 0ee91cca47..40eb0631d7 100644 --- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h +++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h @@ -78,7 +78,7 @@ private: /// Bug visitor class to find the node where the request region was previously /// used in order to include it into the BugReport path. - class RequestNodeVisitor : public BugReporterVisitorImpl { + class RequestNodeVisitor : public BugReporterVisitor { public: RequestNodeVisitor(const MemRegion *const MemoryRegion, const std::string &ErrText) diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index 8ba0bcbcee..b8ef6701c0 100644 --- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -120,8 +120,7 @@ private: /// The bug visitor which allows us to print extra diagnostics along the /// BugReport path. For example, showing the allocation site of the leaked /// region. - class SecKeychainBugVisitor - : public BugReporterVisitorImpl { + class SecKeychainBugVisitor : public BugReporterVisitor { protected: // The allocated region symbol tracked by the main analysis. SymbolRef Sym; diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 2ab817a1cc..b008bcdf4e 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -431,8 +431,7 @@ private: /// The bug visitor which allows us to print extra diagnostics along the /// BugReport path. For example, showing the allocation site of the leaked /// region. - class MallocBugVisitor final - : public BugReporterVisitorImpl { + class MallocBugVisitor final : public BugReporterVisitor { protected: enum NotificationMode { Normal, @@ -511,7 +510,7 @@ private: BugReporterContext &BRC, BugReport &BR) override; - std::unique_ptr + std::shared_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) override { if (!IsLeak) @@ -521,7 +520,7 @@ private: PathDiagnosticLocation::createEndOfPath(EndPathNode, BRC.getSourceManager()); // Do not add the statement itself as a range in case of leak. - return llvm::make_unique(L, BR.getDescription(), + return std::make_shared(L, BR.getDescription(), false); } diff --git a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp index c6493fed8a..258eb05ca7 100644 --- a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp @@ -61,7 +61,7 @@ public: private: enum MisuseKind {MK_FunCall, MK_Copy, MK_Move}; - class MovedBugVisitor : public BugReporterVisitorImpl { + class MovedBugVisitor : public BugReporterVisitor { public: MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {} diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index 94be72b048..7d1ca61c97 100644 --- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -128,8 +128,7 @@ public: DefaultBool NeedTracking; private: - class NullabilityBugVisitor - : public BugReporterVisitorImpl { + class NullabilityBugVisitor : public BugReporterVisitor { public: NullabilityBugVisitor(const MemRegion *M) : Region(M) {} diff --git a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp index 69b19a7859..fcba3b33f3 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp @@ -62,9 +62,7 @@ private: REGISTER_SET_WITH_PROGRAMSTATE(CalledSuperDealloc, SymbolRef) namespace { -class SuperDeallocBRVisitor final - : public BugReporterVisitorImpl { - +class SuperDeallocBRVisitor final : public BugReporterVisitor { SymbolRef ReceiverSymbol; bool Satisfied; diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 589054bdaf..78e4b8f250 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1788,8 +1788,7 @@ namespace { //===---------===// // Bug Reports. // //===---------===// - - class CFRefReportVisitor : public BugReporterVisitorImpl { + class CFRefReportVisitor : public BugReporterVisitor { protected: SymbolRef Sym; const SummaryLogTy &SummaryLog; @@ -1810,7 +1809,7 @@ namespace { BugReporterContext &BRC, BugReport &BR) override; - std::unique_ptr getEndPath(BugReporterContext &BRC, + std::shared_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) override; }; @@ -1821,18 +1820,9 @@ namespace { const SummaryLogTy &log) : CFRefReportVisitor(sym, GCEnabled, log) {} - std::unique_ptr getEndPath(BugReporterContext &BRC, + std::shared_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) override; - - std::unique_ptr clone() const override { - // The curiously-recurring template pattern only works for one level of - // subclassing. Rather than make a new template base for - // CFRefReportVisitor, we simply override clone() to do the right thing. - // This could be trouble someday if BugReporterVisitorImpl is ever - // used for something else besides a convenient implementation of clone(). - return llvm::make_unique(*this); - } }; class CFRefReport : public BugReport { @@ -2365,14 +2355,14 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N, InterestingMethodContext); } -std::unique_ptr +std::shared_ptr CFRefReportVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *EndN, BugReport &BR) { BR.markInteresting(Sym); return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR); } -std::unique_ptr +std::shared_ptr CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *EndN, BugReport &BR) { @@ -2459,7 +2449,7 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC, os << " is not referenced later in this execution path and has a retain " "count of +" << RV->getCount(); - return llvm::make_unique(L, os.str()); + return std::make_shared(L, os.str()); } void CFRefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) { diff --git a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp index b83dea772b..eac743349d 100644 --- a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp @@ -55,7 +55,7 @@ public: } }; -class DivisionBRVisitor : public BugReporterVisitorImpl { +class DivisionBRVisitor : public BugReporterVisitor { private: SymbolRef ZeroSymbol; const StackFrameContext *SFC; diff --git a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp index 039bc08c5c..bd657340fc 100644 --- a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -69,7 +69,7 @@ private: bool IsCopy) const; void checkVAListEndCall(const CallEvent &Call, CheckerContext &C) const; - class ValistBugVisitor : public BugReporterVisitorImpl { + class ValistBugVisitor : public BugReporterVisitor { public: ValistBugVisitor(const MemRegion *Reg, bool IsLeak = false) : Reg(Reg), IsLeak(IsLeak) {} @@ -78,7 +78,7 @@ private: ID.AddPointer(&X); ID.AddPointer(Reg); } - std::unique_ptr + std::shared_ptr getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) override { if (!IsLeak) @@ -87,8 +87,7 @@ private: PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath( EndPathNode, BRC.getSourceManager()); // Do not add the statement itself as a range in case of leak. - return llvm::make_unique(L, BR.getDescription(), - false); + return std::make_shared(L, BR.getDescription(), false); } std::shared_ptr VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp index c5010f5378..71703d6cd1 100644 --- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -57,7 +57,7 @@ private: void reportBug(StringRef Msg, bool PureError, const MemRegion *Reg, CheckerContext &C) const; - class VirtualBugVisitor : public BugReporterVisitorImpl { + class VirtualBugVisitor : public BugReporterVisitor { private: const MemRegion *ObjectRegion; bool Found; diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 94d08b4935..2a53d57d6c 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -343,21 +343,9 @@ static void removePiecesWithInvalidLocations(PathPieces &Pieces) { namespace { -class NodeMapClosure : public BugReport::NodeResolver { - InterExplodedGraphMap &M; - -public: - NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} - - const ExplodedNode *getOriginalNode(const ExplodedNode *N) override { - return M.lookup(N); - } -}; - class PathDiagnosticBuilder : public BugReporterContext { BugReport *R; PathDiagnosticConsumer *PDC; - NodeMapClosure NMC; public: const LocationContext *LC; @@ -365,7 +353,7 @@ public: PathDiagnosticBuilder(GRBugReporter &br, BugReport *r, InterExplodedGraphMap &Backmap, PathDiagnosticConsumer *pdc) - : BugReporterContext(br), R(r), PDC(pdc), NMC(Backmap), + : BugReporterContext(br, Backmap), R(r), PDC(pdc), LC(r->getErrorNode()->getLocationContext()) {} PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N); @@ -383,8 +371,6 @@ public: return getParentMap().getParent(S); } - NodeMapClosure& getNodeResolver() override { return NMC; } - PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const { @@ -1021,6 +1007,9 @@ static const char StrLoopRangeEmpty[] = static const char StrLoopCollectionEmpty[] = "Loop body skipped when collection is empty"; +static std::unique_ptr +findExecutedLines(SourceManager &SM, const ExplodedNode *N); + /// Generate diagnostics for the node \p N, /// and write it into \p PD. /// \p AddPathEdges Whether diagnostic consumer can generate path arrows @@ -1259,83 +1248,15 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N, } } -/// There are two path diagnostics generation modes: with adding edges (used -/// for plists) and without (used for HTML and text). -/// When edges are added (\p ActiveScheme is Extensive), -/// the path is modified to insert artificially generated -/// edges. -/// Otherwise, more detailed diagnostics is emitted for block edges, explaining -/// the transitions in words. -static bool generatePathDiagnostics( - PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef> visitors, - BugReport *R, - PathDiagnosticConsumer::PathGenerationScheme ActiveScheme) { - const ExplodedNode *LastNode = N; - BugReport *report = PDB.getBugReport(); - StackDiagVector CallStack; - InterestingExprs IE; - bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive); - bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None); - - PathDiagnosticLocation PrevLoc = GenerateDiagnostics ? - PD.getLocation() : PathDiagnosticLocation(); - - const ExplodedNode *NextNode = N->getFirstPred(); - while (NextNode) { - N = NextNode; - NextNode = N->getFirstPred(); - - if (GenerateDiagnostics) - generatePathDiagnosticsForNode( - N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); - - if (!NextNode) { - for (auto &V : visitors) { - V->finalizeVisitor(PDB, LastNode, *R); - } - continue; - } - - // Add pieces from custom visitors. - llvm::FoldingSet DeduplicationSet; - for (auto &V : visitors) { - if (auto p = V->VisitNode(N, NextNode, PDB, *report)) { - - if (!GenerateDiagnostics) - continue; - - if (DeduplicationSet.GetOrInsertNode(p.get()) != p.get()) - continue; - - if (AddPathEdges) - addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); - updateStackPiecesWithMessage(*p, CallStack); - PD.getActivePath().push_front(std::move(p)); - } - } - } - - if (AddPathEdges) { - // Add an edge to the start of the function. - // We'll prune it out later, but it helps make diagnostics more uniform. - const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); - const Decl *D = CalleeLC->getDecl(); - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, PDB.getSourceManager()), - CalleeLC); - } - - if (!report->isValid()) - return false; - - // After constructing the full PathDiagnostic, do a pass over it to compact - // PathDiagnosticPieces that occur within a macro. - if (!AddPathEdges && GenerateDiagnostics) - CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); - - return true; +static std::unique_ptr +generateEmptyDiagnosticForReport(BugReport *R, SourceManager &SM) { + BugType &BT = R->getBugType(); + return llvm::make_unique( + R->getBugType().getCheckName(), R->getDeclWithIssue(), + R->getBugType().getName(), R->getDescription(), + R->getShortDescription(/*Fallback=*/false), BT.getCategory(), + R->getUniqueingLocation(), R->getUniqueingDecl(), + findExecutedLines(SM, R->getErrorNode())); } static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { @@ -1957,6 +1878,129 @@ static void dropFunctionEntryEdge(PathPieces &Path, LocationContextMap &LCM, Path.pop_front(); } +using VisitorsDiagnosticsTy = llvm::DenseMap>>; + +/// This function is responsible for generating diagnostic pieces that are +/// *not* provided by bug report visitors. +/// These diagnostics may differ depending on the consumer's settings, +/// and are therefore constructed separately for each consumer. +/// +/// There are two path diagnostics generation modes: with adding edges (used +/// for plists) and without (used for HTML and text). +/// When edges are added (\p ActiveScheme is Extensive), +/// the path is modified to insert artificially generated +/// edges. +/// Otherwise, more detailed diagnostics is emitted for block edges, explaining +/// the transitions in words. +static std::unique_ptr generatePathDiagnosticForConsumer( + PathDiagnosticConsumer::PathGenerationScheme ActiveScheme, + PathDiagnosticBuilder &PDB, + const ExplodedNode *ErrorNode, + const VisitorsDiagnosticsTy &VisitorsDiagnostics) { + + bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None); + bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive); + SourceManager &SM = PDB.getSourceManager(); + BugReport *R = PDB.getBugReport(); + AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions(); + StackDiagVector CallStack; + InterestingExprs IE; + LocationContextMap LCM; + std::unique_ptr PD = generateEmptyDiagnosticForReport(R, SM); + + if (GenerateDiagnostics) { + auto EndNotes = VisitorsDiagnostics.find(ErrorNode); + std::shared_ptr LastPiece; + if (EndNotes != VisitorsDiagnostics.end()) { + assert(!EndNotes->second.empty()); + LastPiece = EndNotes->second[0]; + } else { + LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, ErrorNode, *R); + } + PD->setEndOfPath(LastPiece); + } + + PathDiagnosticLocation PrevLoc = PD->getLocation(); + const ExplodedNode *NextNode = ErrorNode->getFirstPred(); + while (NextNode) { + if (GenerateDiagnostics) + generatePathDiagnosticsForNode( + NextNode, *PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges); + + auto VisitorNotes = VisitorsDiagnostics.find(NextNode); + NextNode = NextNode->getFirstPred(); + if (!GenerateDiagnostics || VisitorNotes == VisitorsDiagnostics.end()) + continue; + + // This is a workaround due to inability to put shared PathDiagnosticPiece + // into a FoldingSet. + std::set DeduplicationSet; + + // Add pieces from custom visitors. + for (const auto &Note : VisitorNotes->second) { + llvm::FoldingSetNodeID ID; + Note->Profile(ID); + auto P = DeduplicationSet.insert(ID); + if (!P.second) + continue; + + if (AddPathEdges) + addEdgeToPath(PD->getActivePath(), PrevLoc, Note->getLocation(), + PDB.LC); + updateStackPiecesWithMessage(*Note, CallStack); + PD->getActivePath().push_front(Note); + } + } + + if (AddPathEdges) { + // Add an edge to the start of the function. + // We'll prune it out later, but it helps make diagnostics more uniform. + const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); + const Decl *D = CalleeLC->getDecl(); + addEdgeToPath(PD->getActivePath(), PrevLoc, + PathDiagnosticLocation::createBegin(D, SM), CalleeLC); + } + + if (!AddPathEdges && GenerateDiagnostics) + CompactPathDiagnostic(PD->getMutablePieces(), SM); + + // Finally, prune the diagnostic path of uninteresting stuff. + if (!PD->path.empty()) { + if (R->shouldPrunePath() && Opts.shouldPrunePaths()) { + bool stillHasNotes = + removeUnneededCalls(PD->getMutablePieces(), R, LCM); + assert(stillHasNotes); + (void)stillHasNotes; + } + + // Redirect all call pieces to have valid locations. + adjustCallLocations(PD->getMutablePieces()); + removePiecesWithInvalidLocations(PD->getMutablePieces()); + + if (AddPathEdges) { + + // Reduce the number of edges from a very conservative set + // to an aesthetically pleasing subset that conveys the + // necessary information. + OptimizedCallsSet OCS; + while (optimizeEdges(PD->getMutablePieces(), SM, OCS, LCM)) {} + + // Drop the very first function-entry edge. It's not really necessary + // for top-level functions. + dropFunctionEntryEdge(PD->getMutablePieces(), LCM, SM); + } + + // Remove messages that are basically the same, and edges that may not + // make sense. + // We have to do this after edge optimization in the Extensive mode. + removeRedundantMsgs(PD->getMutablePieces()); + removeEdgesToDefaultInitializers(PD->getMutablePieces()); + } + return PD; +} + + //===----------------------------------------------------------------------===// // Methods for BugType and subclasses. //===----------------------------------------------------------------------===// @@ -1979,14 +2023,17 @@ void BugReport::addVisitor(std::unique_ptr visitor) { llvm::FoldingSetNodeID ID; visitor->Profile(ID); - void *InsertPos; - if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) + void *InsertPos = nullptr; + if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { return; + } - CallbacksSet.InsertNode(visitor.get(), InsertPos); Callbacks.push_back(std::move(visitor)); - ++ConfigurationChangeToken; +} + +void BugReport::clearVisitors() { + Callbacks.clear(); } BugReport::~BugReport() { @@ -2032,9 +2079,7 @@ void BugReport::markInteresting(SymbolRef sym) { if (!sym) return; - // If the symbol wasn't already in our set, note a configuration change. - if (getInterestingSymbols().insert(sym).second) - ++ConfigurationChangeToken; + getInterestingSymbols().insert(sym); if (const auto *meta = dyn_cast(sym)) getInterestingRegions().insert(meta->getRegion()); @@ -2044,10 +2089,8 @@ void BugReport::markInteresting(const MemRegion *R) { if (!R) return; - // If the base region wasn't already in our set, note a configuration change. R = R->getBaseRegion(); - if (getInterestingRegions().insert(R).second) - ++ConfigurationChangeToken; + getInterestingRegions().insert(R); if (const auto *SR = dyn_cast(R)) getInterestingSymbols().insert(SR->getSymbol()); @@ -2487,36 +2530,70 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { path.insert(path.end(), Pieces.begin(), Pieces.end()); } -bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, - PathDiagnosticConsumer &PC, - ArrayRef &bugReports) { - assert(!bugReports.empty()); +/// Generate notes from all visitors. +/// Notes associated with {@code ErrorNode} are generated using +/// {@code getEndPath}, and the rest are generated with {@code VisitNode}. +static std::unique_ptr +generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode, + BugReporterContext &BRC) { + auto Notes = llvm::make_unique(); + BugReport::VisitorList visitors; - bool HasValid = false; - bool HasInvalid = false; - SmallVector errorNodes; - for (const auto I : bugReports) { - if (I->isValid()) { - HasValid = true; - errorNodes.push_back(I->getErrorNode()); - } else { - // Keep the errorNodes list in sync with the bugReports list. - HasInvalid = true; - errorNodes.push_back(nullptr); + // Run visitors on all nodes starting from the node *before* the last one. + // The last node is reserved for notes generated with {@code getEndPath}. + const ExplodedNode *NextNode = ErrorNode->getFirstPred(); + while (NextNode) { + + // At each iteration, move all visitors from report to visitor list. + for (BugReport::visitor_iterator I = R->visitor_begin(), + E = R->visitor_end(); + I != E; ++I) { + visitors.push_back(std::move(*I)); } - } + R->clearVisitors(); - // If all the reports have been marked invalid by a previous path generation, - // we're done. - if (!HasValid) - return false; + const ExplodedNode *Pred = NextNode->getFirstPred(); + if (!Pred) { + std::shared_ptr LastPiece; + for (auto &V : visitors) { + V->finalizeVisitor(BRC, ErrorNode, *R); - using PathGenerationScheme = PathDiagnosticConsumer::PathGenerationScheme; + if (auto Piece = V->getEndPath(BRC, ErrorNode, *R)) { + assert(!LastPiece && + "There can only be one final piece in a diagnostic."); + LastPiece = std::move(Piece); + llvm::errs() << "Writing to last piece" << "\n"; + (*Notes)[ErrorNode].push_back(LastPiece); + } + } + break; + } - PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); + for (auto &V : visitors) { + auto P = V->VisitNode(NextNode, Pred, BRC, *R); + if (P) + (*Notes)[NextNode].push_back(std::move(P)); + } - TrimmedGraph TrimG(&getGraph(), errorNodes); - ReportGraph ErrorGraph; + if (!R->isValid()) + break; + + NextNode = Pred; + } + + return Notes; +} + +/// Find a non-invalidated report for a given equivalence class, +/// and return together with a cache of visitors notes. +/// If none found, return a nullptr paired with an empty cache. +static +std::pair> findValidReport( + TrimmedGraph &TrimG, + ReportGraph &ErrorGraph, + ArrayRef &bugReports, + AnalyzerOptions &Opts, + GRBugReporter &Reporter) { while (TrimG.popNextReportGraph(ErrorGraph)) { // Find the BugReport with the original location. @@ -2524,15 +2601,12 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, BugReport *R = bugReports[ErrorGraph.Index]; assert(R && "No original report found for sliced graph."); assert(R->isValid() && "Report selected by trimmed graph marked invalid."); - - // Start building the path diagnostic... - PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, &PC); - const ExplodedNode *N = ErrorGraph.ErrorNode; + const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode; // Register refutation visitors first, if they mark the bug invalid no // further analysis is required R->addVisitor(llvm::make_unique()); - if (getAnalyzerOptions().shouldCrosscheckWithZ3()) + if (Opts.shouldCrosscheckWithZ3()) R->addVisitor(llvm::make_unique()); // Register additional node visitors. @@ -2540,101 +2614,59 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, R->addVisitor(llvm::make_unique()); R->addVisitor(llvm::make_unique()); - BugReport::VisitorList visitors; - unsigned origReportConfigToken, finalReportConfigToken; - LocationContextMap LCM; - - // While generating diagnostics, it's possible the visitors will decide - // new symbols and regions are interesting, or add other visitors based on - // the information they find. If they do, we need to regenerate the path - // based on our new report configuration. - do { - // Get a clean copy of all the visitors. - for (BugReport::visitor_iterator I = R->visitor_begin(), - E = R->visitor_end(); I != E; ++I) - visitors.push_back((*I)->clone()); - - // Clear out the active path from any previous work. - PD.resetPath(); - origReportConfigToken = R->getConfigurationChangeToken(); - - // Generate the very last diagnostic piece - the piece is visible before - // the trace is expanded. - std::unique_ptr LastPiece; - for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); - I != E; ++I) { - if (std::unique_ptr Piece = - (*I)->getEndPath(PDB, N, *R)) { - assert(!LastPiece && - "There can only be one final piece in a diagnostic."); - LastPiece = std::move(Piece); - } - } + BugReporterContext BRC(Reporter, ErrorGraph.BackMap); - if (ActiveScheme != PathDiagnosticConsumer::None) { - if (!LastPiece) - LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); - assert(LastPiece); - PD.setEndOfPath(std::move(LastPiece)); - } - - // Make sure we get a clean location context map so we don't - // hold onto old mappings. - LCM.clear(); - - generatePathDiagnostics(PD, PDB, N, LCM, visitors, R, ActiveScheme); - - // Clean up the visitors we used. - visitors.clear(); + // Run all visitors on a given graph, once. + std::unique_ptr visitorNotes = + generateVisitorsDiagnostics(R, ErrorNode, BRC); - // Did anything change while generating this path? - finalReportConfigToken = R->getConfigurationChangeToken(); - } while (finalReportConfigToken != origReportConfigToken); - - if (!R->isValid()) - continue; - - // Finally, prune the diagnostic path of uninteresting stuff. - if (!PD.path.empty()) { - if (R->shouldPrunePath() && getAnalyzerOptions().shouldPrunePaths()) { - bool stillHasNotes = removeUnneededCalls(PD.getMutablePieces(), R, LCM); - assert(stillHasNotes); - (void)stillHasNotes; - } + if (R->isValid()) + return std::make_pair(R, std::move(visitorNotes)); + } + return std::make_pair(nullptr, llvm::make_unique()); +} - // Redirect all call pieces to have valid locations. - adjustCallLocations(PD.getMutablePieces()); - removePiecesWithInvalidLocations(PD.getMutablePieces()); +std::unique_ptr +GRBugReporter::generatePathDiagnostics( + ArrayRef consumers, + ArrayRef &bugReports) { + assert(!bugReports.empty()); - if (ActiveScheme == PathDiagnosticConsumer::Extensive) { - SourceManager &SM = getSourceManager(); + auto Out = llvm::make_unique(); + bool HasValid = false; + SmallVector errorNodes; + for (const auto I : bugReports) { + if (I->isValid()) { + HasValid = true; + errorNodes.push_back(I->getErrorNode()); + } else { + // Keep the errorNodes list in sync with the bugReports list. + errorNodes.push_back(nullptr); + } + } - // Reduce the number of edges from a very conservative set - // to an aesthetically pleasing subset that conveys the - // necessary information. - OptimizedCallsSet OCS; - while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {} + // If all the reports have been marked invalid by a previous path generation, + // we're done. + if (!HasValid) + return Out; - // Drop the very first function-entry edge. It's not really necessary - // for top-level functions. - dropFunctionEntryEdge(PD.getMutablePieces(), LCM, SM); - } + TrimmedGraph TrimG(&getGraph(), errorNodes); + ReportGraph ErrorGraph; + auto ReportInfo = findValidReport(TrimG, ErrorGraph, bugReports, + getAnalyzerOptions(), *this); + BugReport *R = ReportInfo.first; - // Remove messages that are basically the same, and edges that may not - // make sense. - // We have to do this after edge optimization in the Extensive mode. - removeRedundantMsgs(PD.getMutablePieces()); - removeEdgesToDefaultInitializers(PD.getMutablePieces()); + if (R && R->isValid()) { + const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode; + for (PathDiagnosticConsumer *PC : consumers) { + PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, PC); + std::unique_ptr PD = generatePathDiagnosticForConsumer( + PC->getGenerationScheme(), PDB, ErrorNode, *ReportInfo.second); + (*Out)[PC] = std::move(PD); } - - // We found a report and didn't suppress it. - return true; } - // We suppressed all the reports in this equivalence class. - assert(!HasInvalid && "Inconsistent suppression"); - (void)HasInvalid; - return false; + return Out; } void BugReporter::Register(BugType *BT) { @@ -2893,11 +2925,55 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ, void BugReporter::FlushReport(BugReportEquivClass& EQ) { SmallVector bugReports; - BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports); - if (exampleReport) { - for (PathDiagnosticConsumer *PDC : getPathDiagnosticConsumers()) { - FlushReport(exampleReport, *PDC, bugReports); + BugReport *report = FindReportInEquivalenceClass(EQ, bugReports); + if (!report) + return; + + ArrayRef Consumers = getPathDiagnosticConsumers(); + std::unique_ptr Diagnostics = + generateDiagnosticForConsumerMap(report, Consumers, bugReports); + + for (auto &P : *Diagnostics) { + PathDiagnosticConsumer *Consumer = P.first; + std::unique_ptr &PD = P.second; + + // If the path is empty, generate a single step path with the location + // of the issue. + if (PD->path.empty()) { + PathDiagnosticLocation L = report->getLocation(getSourceManager()); + auto piece = llvm::make_unique( + L, report->getDescription()); + for (SourceRange Range : report->getRanges()) + piece->addRange(Range); + PD->setEndOfPath(std::move(piece)); + } + + PathPieces &Pieces = PD->getMutablePieces(); + if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) { + // For path diagnostic consumers that don't support extra notes, + // we may optionally convert those to path notes. + for (auto I = report->getNotes().rbegin(), + E = report->getNotes().rend(); I != E; ++I) { + PathDiagnosticNotePiece *Piece = I->get(); + auto ConvertedPiece = std::make_shared( + Piece->getLocation(), Piece->getString()); + for (const auto &R: Piece->getRanges()) + ConvertedPiece->addRange(R); + + Pieces.push_front(std::move(ConvertedPiece)); + } + } else { + for (auto I = report->getNotes().rbegin(), + E = report->getNotes().rend(); I != E; ++I) + Pieces.push_front(*I); } + + // Get the meta data. + const BugReport::ExtraTextList &Meta = report->getExtraText(); + for (const auto &i : Meta) + PD->addMeta(i); + + Consumer->HandlePathDiagnostic(std::move(PD)); } } @@ -2974,79 +3050,41 @@ findExecutedLines(SourceManager &SM, const ExplodedNode *N) { return ExecutedLines; } -void BugReporter::FlushReport(BugReport *exampleReport, - PathDiagnosticConsumer &PD, - ArrayRef bugReports) { - // FIXME: Make sure we use the 'R' for the path that was actually used. - // Probably doesn't make a difference in practice. - BugType& BT = exampleReport->getBugType(); - - auto D = llvm::make_unique( - exampleReport->getBugType().getCheckName(), - exampleReport->getDeclWithIssue(), exampleReport->getBugType().getName(), - exampleReport->getDescription(), - exampleReport->getShortDescription(/*Fallback=*/false), BT.getCategory(), - exampleReport->getUniqueingLocation(), exampleReport->getUniqueingDecl(), - findExecutedLines(getSourceManager(), exampleReport->getErrorNode())); +std::unique_ptr +BugReporter::generateDiagnosticForConsumerMap( + BugReport *report, ArrayRef consumers, + ArrayRef bugReports) { - if (exampleReport->isPathSensitive()) { - // Generate the full path diagnostic, using the generation scheme - // specified by the PathDiagnosticConsumer. Note that we have to generate - // path diagnostics even for consumers which do not support paths, because - // the BugReporterVisitors may mark this bug as a false positive. - assert(!bugReports.empty()); + if (!report->isPathSensitive()) { + auto Out = llvm::make_unique(); + for (auto *Consumer : consumers) + (*Out)[Consumer] = generateEmptyDiagnosticForReport(report, + getSourceManager()); + return Out; + } - MaxBugClassSize.updateMax(bugReports.size()); + // Generate the full path sensitive diagnostic, using the generation scheme + // specified by the PathDiagnosticConsumer. Note that we have to generate + // path diagnostics even for consumers which do not support paths, because + // the BugReporterVisitors may mark this bug as a false positive. + assert(!bugReports.empty()); + MaxBugClassSize.updateMax(bugReports.size()); + std::unique_ptr Out = + generatePathDiagnostics(consumers, bugReports); - if (!generatePathDiagnostic(*D.get(), PD, bugReports)) - return; + if (Out->empty()) + return Out; - MaxValidBugClassSize.updateMax(bugReports.size()); + MaxValidBugClassSize.updateMax(bugReports.size()); - // Examine the report and see if the last piece is in a header. Reset the - // report location to the last piece in the main source file. - AnalyzerOptions &Opts = getAnalyzerOptions(); + // Examine the report and see if the last piece is in a header. Reset the + // report location to the last piece in the main source file. + AnalyzerOptions &Opts = getAnalyzerOptions(); + for (auto const &P : *Out) if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll) - D->resetDiagnosticLocationToMainFile(); - } - - // If the path is empty, generate a single step path with the location - // of the issue. - if (D->path.empty()) { - PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); - auto piece = llvm::make_unique( - L, exampleReport->getDescription()); - for (SourceRange Range : exampleReport->getRanges()) - piece->addRange(Range); - D->setEndOfPath(std::move(piece)); - } - - PathPieces &Pieces = D->getMutablePieces(); - if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) { - // For path diagnostic consumers that don't support extra notes, - // we may optionally convert those to path notes. - for (auto I = exampleReport->getNotes().rbegin(), - E = exampleReport->getNotes().rend(); I != E; ++I) { - PathDiagnosticNotePiece *Piece = I->get(); - auto ConvertedPiece = std::make_shared( - Piece->getLocation(), Piece->getString()); - for (const auto &R: Piece->getRanges()) - ConvertedPiece->addRange(R); - - Pieces.push_front(std::move(ConvertedPiece)); - } - } else { - for (auto I = exampleReport->getNotes().rbegin(), - E = exampleReport->getNotes().rend(); I != E; ++I) - Pieces.push_front(*I); - } - - // Get the meta data. - const BugReport::ExtraTextList &Meta = exampleReport->getExtraText(); - for (const auto &i : Meta) - D->addMeta(i); + P.second->resetDiagnosticLocationToMainFile(); - PD.HandlePathDiagnostic(std::move(D)); + return Out; } void BugReporter::EmitBasicReport(const Decl *DeclWithIssue, diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index fc31d3c1fb..cd13412301 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -177,7 +177,7 @@ const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// -std::unique_ptr +std::shared_ptr BugReporterVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { return nullptr; @@ -188,7 +188,7 @@ BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {} -std::unique_ptr BugReporterVisitor::getDefaultEndPath( +std::shared_ptr BugReporterVisitor::getDefaultEndPath( BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); @@ -197,12 +197,12 @@ std::unique_ptr BugReporterVisitor::getDefaultEndPath( // Only add the statement itself as a range if we didn't specify any // special ranges for this report. - auto P = llvm::make_unique( + auto P = std::make_shared( L, BR.getDescription(), Ranges.begin() == Ranges.end()); for (SourceRange Range : Ranges) P->addRange(Range); - return std::move(P); + return P; } /// \return name of the macro inside the location \p Loc. @@ -234,8 +234,7 @@ namespace { /// for which the region of interest \p RegionOfInterest was passed into, /// but not written inside, and it has caused an undefined read or a null /// pointer dereference outside. -class NoStoreFuncVisitor final - : public BugReporterVisitorImpl { +class NoStoreFuncVisitor final : public BugReporterVisitor { const SubRegion *RegionOfInterest; static constexpr const char *DiagnosticsMsg = "Returning without writing to '"; @@ -526,8 +525,7 @@ private: } }; -class MacroNullReturnSuppressionVisitor final - : public BugReporterVisitorImpl { +class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor { const SubRegion *RegionOfInterest; public: @@ -609,7 +607,7 @@ private: /// /// This visitor is intended to be used when another visitor discovers that an /// interesting value comes from an inlined function call. -class ReturnVisitor : public BugReporterVisitorImpl { +class ReturnVisitor : public BugReporterVisitor { const StackFrameContext *StackFrame; enum { Initial, diff --git a/test/Analysis/null-deref-path-notes.c b/test/Analysis/null-deref-path-notes.c index 3fd559df29..c73f64066b 100644 --- a/test/Analysis/null-deref-path-notes.c +++ b/test/Analysis/null-deref-path-notes.c @@ -24,14 +24,14 @@ void f2(char *source) { } void f3(char *source) { - char *destination = 0; // FIXME: There should be a note here as well. + char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}} destination = destination + 0; // expected-note{{Null pointer value stored to 'destination'}} memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}} // expected-note@-1{{Null pointer argument in call to memory copy function}} } void f4(char *source) { - char *destination = 0; // FIXME: There should be a note here as well. + char *destination = 0; // expected-note{{'destination' initialized to a null pointer value}} destination = destination - 0; // expected-note{{Null pointer value stored to 'destination'}} memcpy(destination, source, 10); // expected-warning{{Null pointer argument in call to memory copy function}} // expected-note@-1{{Null pointer argument in call to memory copy function}} -- GitLab From cb07cbc35642cf045606463bc9c7882834a75392 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Tue, 26 Jun 2018 22:09:48 +0000 Subject: [PATCH 0289/1023] [MachineOutliner] Emit a warning when using -moutline on unsupported targets Instead of just saying "flag unused", we should tell the user that the outliner isn't (at least officially) supported for some given architecture. This adds a warning that will state something like The 'blah' architecture does not support -moutline; flag ignored when we call -moutline with the 'blah' architecture. Since the outliner is still mostly an AArch64 thing, any architecture other than AArch64 will emit this warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335672 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticDriverKinds.td | 4 +++ lib/Driver/ToolChains/Clang.cpp | 33 ++++++++++++-------- test/Driver/aarch64-outliner.c | 3 ++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index ef7b0db89f..5526ad4bd5 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -385,4 +385,8 @@ def warn_drv_experimental_isel_incomplete : Warning< def warn_drv_experimental_isel_incomplete_opt : Warning< "-fexperimental-isel support is incomplete for this architecture at the current optimization level">, InGroup; + +def warn_drv_moutline_unsupported_opt : Warning< + "The '%0' architecture does not support -moutline; flag ignored">, + InGroup; } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 327fa6b57b..1f08f30345 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1476,19 +1476,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, else CmdArgs.push_back("-aarch64-enable-global-merge=true"); } - - if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); - - // The outliner shouldn't compete with linkers that dedupe linkonceodr - // functions in LTO. Enable that behaviour by default when compiling with - // LTO. - if (getToolChain().getDriver().isUsingLTO()) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-linkonceodr-outlining"); - } - } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -4814,6 +4801,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); + if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { + // We only support -moutline in AArch64 right now. If we're not compiling + // for AArch64, emit a warning and ignore the flag. Otherwise, add the + // proper mllvm flags. + if (Triple.getArch() != llvm::Triple::aarch64) { + D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); + } else { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner"); + + // The outliner shouldn't compete with linkers that dedupe linkonceodr + // functions in LTO. Enable that behaviour by default when compiling with + // LTO. + if (getToolChain().getDriver().isUsingLTO()) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-linkonceodr-outlining"); + } + } + } + // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c index dd2ae2a66c..a02722df21 100644 --- a/test/Driver/aarch64-outliner.c +++ b/test/Driver/aarch64-outliner.c @@ -7,3 +7,6 @@ // FLTO: "-mllvm" "-enable-linkonceodr-outlining" // RUN: %clang -target aarch64 -moutline -flto=full -S %s -### 2>&1 | FileCheck %s -check-prefix=TLTO // TLTO: "-mllvm" "-enable-linkonceodr-outlining" +// RUN: %clang -target x86_64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=WARN +// WARN: warning: The 'x86_64' architecture does not support -moutline; flag ignored [-Woption-ignored] +// WARN-NOT: "-mllvm" "-enable-machine-outliner" -- GitLab From b4bc5a9541197e57a3f26a4590898ea6d1d7372b Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 26 Jun 2018 23:10:05 +0000 Subject: [PATCH 0290/1023] [analyzer] Minor cleanups for BugReporter, expose a getter for AnalyzerOptions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335683 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../StaticAnalyzer/Core/BugReporter/BugReporter.h | 8 ++++---- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 2 +- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 14 ++++---------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 9f0a83d255..111e1d1e8e 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -519,10 +519,6 @@ public: ~GRBugReporter() override; - /// getEngine - Return the analysis engine used to analyze a given - /// function or method. - ExprEngine &getEngine() { return Eng; } - /// getGraph - Get the exploded graph created by the analysis engine /// for the analyzed method or function. ExplodedGraph &getGraph(); @@ -590,6 +586,10 @@ public: return BR.getSourceManager(); } + AnalyzerOptions &getAnalyzerOptions() { + return BR.getAnalyzerOptions(); + } + NodeMapClosure& getNodeResolver() { return NMC; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index e469df0d15..3c0ab4d752 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -537,7 +537,7 @@ public: void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex); - std::pair + static std::pair geteagerlyAssumeBinOpBifurcationTags(); SVal evalMinus(SVal X) { diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index cd13412301..a4ac93d59b 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -769,8 +769,7 @@ public: // If we have counter-suppression enabled, make sure we keep visiting // future nodes. We want to emit a path note as well, in case // the report is resurrected as valid later on. - ExprEngine &Eng = BRC.getBugReporter().getEngine(); - AnalyzerOptions &Options = Eng.getAnalysisManager().options; + AnalyzerOptions &Options = BRC.getAnalyzerOptions(); if (EnableNullFPSuppression && hasCounterSuppression(Options)) Mode = MaybeUnsuppress; @@ -808,8 +807,7 @@ public: visitNodeMaybeUnsuppress(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { #ifndef NDEBUG - ExprEngine &Eng = BRC.getBugReporter().getEngine(); - AnalyzerOptions &Options = Eng.getAnalysisManager().options; + AnalyzerOptions &Options = BRC.getAnalyzerOptions(); assert(hasCounterSuppression(Options)); #endif @@ -1756,11 +1754,8 @@ ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, } if (Optional PS = progPoint.getAs()) { - // FIXME: Assuming that BugReporter is a GRBugReporter is a layering - // violation. const std::pair &tags = - cast(BRC.getBugReporter()). - getEngine().geteagerlyAssumeBinOpBifurcationTags(); + ExprEngine::geteagerlyAssumeBinOpBifurcationTags(); const ProgramPointTag *tag = PS->getTag(); if (tag == tags.first) @@ -2152,8 +2147,7 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor( BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { // Here we suppress false positives coming from system headers. This list is // based on known issues. - ExprEngine &Eng = BRC.getBugReporter().getEngine(); - AnalyzerOptions &Options = Eng.getAnalysisManager().options; + AnalyzerOptions &Options = BRC.getAnalyzerOptions(); const Decl *D = N->getLocationContext()->getDecl(); if (AnalysisDeclContext::isInStdNamespace(D)) { -- GitLab From 7e4eef1df5e17710530c1e65b0d1956f2d5a11ad Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 26 Jun 2018 23:10:48 +0000 Subject: [PATCH 0291/1023] Revert "[MS] Use mangled names and comdats for string merging with ASan" Depends on r334313, which has been reverted in r335681. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335684 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 35e9dea37a..7752dbcc7c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -4155,13 +4155,15 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef GlobalVariableName; llvm::GlobalValue::LinkageTypes LT; - // Mangle the string literal if that's how the ABI merges duplicate strings. - // Don't do it if they are writable, since we don't want writes in one TU to - // affect strings in another. - if (getCXXABI().getMangleContext().shouldMangleStringLiteral(S) && - !LangOpts.WritableStrings) { + // Mangle the string literal if the ABI allows for it. However, we cannot + // do this if we are compiling with ASan or -fwritable-strings because they + // rely on strings having normal linkage. + if (!LangOpts.WritableStrings && + !LangOpts.Sanitize.has(SanitizerKind::Address) && + getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) { llvm::raw_svector_ostream Out(MangledNameBuffer); getCXXABI().getMangleContext().mangleStringLiteral(S, Out); + LT = llvm::GlobalValue::LinkOnceODRLinkage; GlobalVariableName = MangledNameBuffer; } else { -- GitLab From 5e73e9b7755fb6744bccefe9afdd333762a6c9ef Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 26 Jun 2018 23:17:35 +0000 Subject: [PATCH 0292/1023] [analyzer] [tests] Include statistics in tests. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335685 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/analyzer/SATestBuild.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index 8f765b9546..b76df748d0 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -274,7 +274,13 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): SBOptions += "-plist-html -o '%s' " % SBOutputDir SBOptions += "-enable-checker " + AllCheckers + " " SBOptions += "--keep-empty " - SBOptions += "-analyzer-config 'stable-report-filename=true' " + AnalyzerConfig = { + "stable-report-filename": "true", + "serialize-stats": "true" + } + + SBOptions += "-analyzer-config '%s' " % ( + ",".join("%s=%s" for key, value in AnalyzerConfig.iteritems())) # Always use ccc-analyze to ensure that we can locate the failures # directory. SBOptions += "--override-compiler " -- GitLab From 4f1497d921592ead6bd4f3c411fe49f3aeb08228 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Tue, 26 Jun 2018 23:18:59 +0000 Subject: [PATCH 0293/1023] [clang] Add test dependency on llvm-as r335618 added tests that invoke llvm-as, so we should also ensure that running clang tests rebuilds llvm-as. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335686 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d6db5348e..d86c60c4fd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -94,6 +94,7 @@ if( NOT CLANG_BUILT_STANDALONE ) llvm-config FileCheck count not llc + llvm-as llvm-bcanalyzer llvm-cat llvm-dis -- GitLab From 8eed7850fc5371ab68fc1ac46bfb9f30097775e1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 26 Jun 2018 23:20:26 +0000 Subject: [PATCH 0294/1023] Diagnose missing 'template' keywords in more cases. We track when we see a name-shaped expression followed by a '<' token and parse the '<' as a comparison. Then: * if we see a token sequence that cannot possibly be an expression but can be a template argument (in particular, a type-id) that follows either a ',' or the '<', diagnose that the '<' was supposed to start a template argument list, and * if we see '>()', diagnose that the '<' was supposed to start a template argument list. This only changes the diagnostic for error cases, and in practice appears to catch the most common cases where a missing 'template' keyword leads to parse errors within a template. Differential Revision: https://reviews.llvm.org/D48571 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335687 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BitmaskEnum.h | 25 +++++ include/clang/Parse/Parser.h | 97 ++++++++++++++++++- include/clang/Parse/RAIIObjectsForParser.h | 1 + include/clang/Sema/Sema.h | 21 +++- lib/CodeGen/CGOpenMPRuntime.cpp | 2 +- lib/Parse/ParseCXXInlineMethods.cpp | 8 ++ lib/Parse/ParseDeclCXX.cpp | 2 + lib/Parse/ParseExpr.cpp | 63 ++++++++++-- lib/Parse/ParseExprCXX.cpp | 2 + lib/Parse/ParseStmt.cpp | 2 + lib/Sema/SemaTemplate.cpp | 33 +++++-- .../dependent-template-recover.cpp | 54 ++++++++++- 12 files changed, 280 insertions(+), 30 deletions(-) create mode 100644 include/clang/Basic/BitmaskEnum.h diff --git a/include/clang/Basic/BitmaskEnum.h b/include/clang/Basic/BitmaskEnum.h new file mode 100644 index 0000000000..12ff3cf207 --- /dev/null +++ b/include/clang/Basic/BitmaskEnum.h @@ -0,0 +1,25 @@ +//===--- BitmaskEnum.h - wrapper of LLVM's bitmask enum facility-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Provides LLVM's BitmaskEnum facility to enumeration types declared in +/// namespace clang. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_BITMASKENUM_H +#define LLVM_CLANG_BASIC_BITMASKENUM_H + +#include "llvm/ADT/BitmaskEnum.h" + +namespace clang { + LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); +} + +#endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 6e911230b2..df803c52f1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_PARSE_PARSER_H #include "clang/AST/Availability.h" +#include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Basic/Specifiers.h" @@ -247,6 +248,90 @@ class Parser : public CodeCompletionHandler { /// Identifiers which have been declared within a tentative parse. SmallVector TentativelyDeclaredIdentifiers; + /// Tracker for '<' tokens that might have been intended to be treated as an + /// angle bracket instead of a less-than comparison. + /// + /// This happens when the user intends to form a template-id, but typoes the + /// template-name or forgets a 'template' keyword for a dependent template + /// name. + /// + /// We track these locations from the point where we see a '<' with a + /// name-like expression on its left until we see a '>' or '>>' that might + /// match it. + struct AngleBracketTracker { + /// Flags used to rank candidate template names when there is more than one + /// '<' in a scope. + enum Priority : unsigned short { + /// A non-dependent name that is a potential typo for a template name. + PotentialTypo = 0x0, + /// A dependent name that might instantiate to a template-name. + DependentName = 0x2, + + /// A space appears before the '<' token. + SpaceBeforeLess = 0x0, + /// No space before the '<' token + NoSpaceBeforeLess = 0x1, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ DependentName) + }; + + struct Loc { + Expr *TemplateName; + SourceLocation LessLoc; + AngleBracketTracker::Priority Priority; + unsigned short ParenCount, BracketCount, BraceCount; + + bool isActive(Parser &P) const { + return P.ParenCount == ParenCount && P.BracketCount == BracketCount && + P.BraceCount == BraceCount; + } + + bool isActiveOrNested(Parser &P) const { + return isActive(P) || P.ParenCount > ParenCount || + P.BracketCount > BracketCount || P.BraceCount > BraceCount; + } + }; + + SmallVector Locs; + + /// Add an expression that might have been intended to be a template name. + /// In the case of ambiguity, we arbitrarily select the innermost such + /// expression, for example in 'foo < bar < baz', 'bar' is the current + /// candidate. No attempt is made to track that 'foo' is also a candidate + /// for the case where we see a second suspicious '>' token. + void add(Parser &P, Expr *TemplateName, SourceLocation LessLoc, + Priority Prio) { + if (!Locs.empty() && Locs.back().isActive(P)) { + if (Locs.back().Priority <= Prio) { + Locs.back().TemplateName = TemplateName; + Locs.back().LessLoc = LessLoc; + Locs.back().Priority = Prio; + } + } else { + Locs.push_back({TemplateName, LessLoc, Prio, + P.ParenCount, P.BracketCount, P.BraceCount}); + } + } + + /// Mark the current potential missing template location as having been + /// handled (this happens if we pass a "corresponding" '>' or '>>' token + /// or leave a bracket scope). + void clear(Parser &P) { + while (!Locs.empty() && Locs.back().isActiveOrNested(P)) + Locs.pop_back(); + } + + /// Get the current enclosing expression that might hve been intended to be + /// a template name. + Loc *getCurrent(Parser &P) { + if (!Locs.empty() && Locs.back().isActive(P)) + return &Locs.back(); + return nullptr; + } + }; + + AngleBracketTracker AngleBrackets; + IdentifierInfo *getSEHExceptKeyword(); /// True if we are within an Objective-C container while parsing C-like decls. @@ -426,8 +511,10 @@ private: assert(isTokenParen() && "wrong consume method"); if (Tok.getKind() == tok::l_paren) ++ParenCount; - else if (ParenCount) + else if (ParenCount) { + AngleBrackets.clear(*this); --ParenCount; // Don't let unbalanced )'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); return PrevTokLocation; @@ -439,8 +526,10 @@ private: assert(isTokenBracket() && "wrong consume method"); if (Tok.getKind() == tok::l_square) ++BracketCount; - else if (BracketCount) + else if (BracketCount) { + AngleBrackets.clear(*this); --BracketCount; // Don't let unbalanced ]'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); @@ -453,8 +542,10 @@ private: assert(isTokenBrace() && "wrong consume method"); if (Tok.getKind() == tok::l_brace) ++BraceCount; - else if (BraceCount) + else if (BraceCount) { + AngleBrackets.clear(*this); --BraceCount; // Don't let unbalanced }'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); diff --git a/include/clang/Parse/RAIIObjectsForParser.h b/include/clang/Parse/RAIIObjectsForParser.h index 1b5332437d..f45d643483 100644 --- a/include/clang/Parse/RAIIObjectsForParser.h +++ b/include/clang/Parse/RAIIObjectsForParser.h @@ -331,6 +331,7 @@ namespace clang { BraceCount(p.BraceCount) { } ~ParenBraceBracketBalancer() { + P.AngleBrackets.clear(P); P.ParenCount = ParenCount; P.BracketCount = BracketCount; P.BraceCount = BraceCount; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5780cc01d7..93b24297d3 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -21,6 +21,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/LocInfoType.h" @@ -1829,14 +1830,24 @@ public: getTemplateNameKindForDiagnostics(TemplateName Name); /// Determine whether it's plausible that E was intended to be a - /// template-name. - bool mightBeIntendedToBeTemplateName(ExprResult E) { - if (!getLangOpts().CPlusPlus || E.isInvalid()) + /// template-name. Updates E to denote the template name expression. + bool mightBeIntendedToBeTemplateName(ExprResult &ER, bool &Dependent) { + if (!getLangOpts().CPlusPlus || ER.isInvalid()) return false; - if (auto *DRE = dyn_cast(E.get())) + Expr *E = ER.get()->IgnoreImplicit(); + while (auto *BO = dyn_cast(E)) + E = BO->getRHS()->IgnoreImplicit(); + ER = E; + Dependent = false; + if (auto *DRE = dyn_cast(E)) return !DRE->hasExplicitTemplateArgs(); - if (auto *ME = dyn_cast(E.get())) + if (auto *ME = dyn_cast(E)) return !ME->hasExplicitTemplateArgs(); + Dependent = true; + if (auto *DSDRE = dyn_cast(E)) + return !DSDRE->hasExplicitTemplateArgs(); + if (auto *DSME = dyn_cast(E)) + return !DSME->hasExplicitTemplateArgs(); // Any additional cases recognized here should also be handled by // diagnoseExprIntendedAsTemplateName. return false; diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 7373331a63..1e37c894ee 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -19,8 +19,8 @@ #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/AST/Decl.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/BitmaskEnum.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitmaskEnum.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DerivedTypes.h" diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index bccf4239c1..77f2dccfed 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -312,6 +312,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); std::unique_ptr Toks = std::move(LM.DefaultArgs[I].Toks); if (Toks) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Mark the end of the default argument so that we know when to stop when // we parse it later on. Token LastDefaultArgToken = Toks->back(); @@ -384,6 +386,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Parse a delayed exception-specification, if there is one. if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Add the 'stop' token. Token LastExceptionSpecToken = Toks->back(); Token ExceptionSpecEnd; @@ -489,6 +493,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ++CurTemplateDepthTracker; } + ParenBraceBracketBalancer BalancerRAIIObj(*this); + assert(!LM.Toks.empty() && "Empty body!"); Token LastBodyToken = LM.Toks.back(); Token BodyEnd; @@ -609,6 +615,8 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { if (!MI.Field || MI.Field->isInvalidDecl()) return; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Append the current token at the end of the new token stream so that it // doesn't get lost. MI.Toks.push_back(Tok); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 4a1280e7f8..de759c8c94 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -3009,6 +3009,8 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs, DeclSpec::TST TagType, Decl *TagDecl) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + switch (Tok.getKind()) { case tok::kw___if_exists: case tok::kw___if_not_exists: diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8d51bc82d3..94e56e9d8a 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -302,6 +302,59 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { if (OpToken.is(tok::caretcaret)) { return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or)); } + + // If we have a name-shaped expression followed by '<', track it in case we + // later find we're probably supposed to be in a template-id. + ExprResult TemplateName = LHS; + bool DependentTemplateName = false; + if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName( + TemplateName, DependentTemplateName)) { + AngleBracketTracker::Priority Priority = + (DependentTemplateName ? AngleBracketTracker::DependentName + : AngleBracketTracker::PotentialTypo) | + (OpToken.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess + : AngleBracketTracker::NoSpaceBeforeLess); + AngleBrackets.add(*this, TemplateName.get(), OpToken.getLocation(), + Priority); + } + + // If we're potentially in a template-id, we may now be able to determine + // whether we're actually in one or not. + if (auto *Info = AngleBrackets.getCurrent(*this)) { + // If an operator is followed by a type that can be a template argument + // and cannot be an expression, then this is ill-formed, but might be + // intended to be part of a template-id. Likewise if this is <>. + if ((OpToken.isOneOf(tok::less, tok::comma) && + isKnownToBeDeclarationSpecifier()) || + (OpToken.is(tok::less) && + Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater))) { + if (diagnoseUnknownTemplateId(Info->TemplateName, Info->LessLoc)) { + AngleBrackets.clear(*this); + return ExprError(); + } + } + + // If a context that looks like a template-id is followed by '()', then + // this is ill-formed, but might be intended to be a template-id followed + // by '()'. + if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) && + NextToken().is(tok::r_paren)) { + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), Info->TemplateName, Info->LessLoc, + OpToken.getLocation()); + AngleBrackets.clear(*this); + return ExprError(); + } + } + + // After a '>' (etc), we're no longer potentially in a construct that's + // intended to be treated as a template-id. + if (OpToken.is(tok::greater) || + (getLangOpts().CPlusPlus11 && + OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater))) + AngleBrackets.clear(*this); + // Bail out when encountering a comma followed by a token which can't // possibly be the start of an expression. For instance: // int f() { return 1, } @@ -313,16 +366,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } - // If a '<' token is followed by a type that can be a template argument and - // cannot be an expression, then this is ill-formed, but might be intended - // to be a template-id. - if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && - (isKnownToBeDeclarationSpecifier() || - Tok.isOneOf(tok::greater, tok::greatergreater, - tok::greatergreatergreater)) && - diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) - return ExprError(); - // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 12aee8cff3..a5a340ad22 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1735,6 +1735,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, Sema::ConditionKind CK) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); cutOffParsing(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 44406002c0..8c4a3056ec 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1621,6 +1621,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { attrs, attrs.Range.getEnd()); ForRange = true; } else if (isForInitDeclaration()) { // for (int X = 4; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8f316024cc..68a5196f6b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -508,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, DeclContext *LookupCtx = nullptr; NamedDecl *Found = nullptr; + bool MissingTemplateKeyword = false; // Figure out what name we looked up. - if (auto *ME = dyn_cast(TemplateName.get())) { + if (auto *DRE = dyn_cast(TemplateName.get())) { + NameInfo = DRE->getNameInfo(); + SS.Adopt(DRE->getQualifierLoc()); + LookupKind = LookupOrdinaryName; + Found = DRE->getFoundDecl(); + } else if (auto *ME = dyn_cast(TemplateName.get())) { NameInfo = ME->getMemberNameInfo(); SS.Adopt(ME->getQualifierLoc()); LookupKind = LookupMemberName; LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); Found = ME->getMemberDecl(); + } else if (auto *DSDRE = + dyn_cast(TemplateName.get())) { + NameInfo = DSDRE->getNameInfo(); + SS.Adopt(DSDRE->getQualifierLoc()); + MissingTemplateKeyword = true; + } else if (auto *DSME = + dyn_cast(TemplateName.get())) { + NameInfo = DSME->getMemberNameInfo(); + SS.Adopt(DSME->getQualifierLoc()); + MissingTemplateKeyword = true; } else { - auto *DRE = cast(TemplateName.get()); - NameInfo = DRE->getNameInfo(); - SS.Adopt(DRE->getQualifierLoc()); - LookupKind = LookupOrdinaryName; - Found = DRE->getFoundDecl(); + llvm_unreachable("unexpected kind of potential template name"); + } + + // If this is a dependent-scope lookup, diagnose that the 'template' keyword + // was missing. + if (MissingTemplateKeyword) { + Diag(NameInfo.getLocStart(), diag::err_template_kw_missing) + << "" << NameInfo.getName().getAsString() + << SourceRange(Less, Greater); + return; } // Try to correct the name by looking for templates and C++ named casts. diff --git a/test/SemaTemplate/dependent-template-recover.cpp b/test/SemaTemplate/dependent-template-recover.cpp index ac16230417..617950a4da 100644 --- a/test/SemaTemplate/dependent-template-recover.cpp +++ b/test/SemaTemplate/dependent-template-recover.cpp @@ -5,18 +5,59 @@ struct X { t->f0(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}} t->f0(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}} - t->operator+(); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}} - t->f1(); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} + t->operator+(1); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}} + t->f1(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} + t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}} T::getAs(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} t->T::getAs(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} - // FIXME: We can't recover from these yet - (*t).f2(); // expected-error{{expected expression}} - (*t).f2<0>(); // expected-error{{expected expression}} + (*t).f2(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} + (*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} + T::f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} + T::f2<0, int>(0); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}} + + T::foo= 4>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + + // If there are multiple potential template names, pick the one where there + // is no whitespace between the name and the '<'. + T::foo(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + T::foo < T::bar<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}} + + // Prefer to diagonse a missing 'template' keyword rather than finding a non-template name. + xyz < T::foo < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + T::foo < xyz < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + + // ... even if the whitespace suggests the other name is the template name. + // FIXME: Is this the right heuristic? + xyz(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + T::foo < xyz<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} } + + int xyz; }; +template void not_missing_template(T t) { + (T::n < 0) > ( + ) // expected-error {{expected expression}} + ; + + int a = T::x < 3; + int b = T::y > (); // expected-error {{expected expression}} + + void c(int = T::x < 3); + void d(int = T::y > ()); // expected-error {{expected expression}} + + for (int x = t < 3 ? 1 : 2; t > (); ++t) { // expected-error {{expected expression}} + } + + // FIXME: We shouldn't treat 'T::t' as a potential template-name here, + // because that would leave a '?' with no matching ':'. + // We should probably generally treat '?' ... ':' as a bracket-like + // construct. + bool k = T::t < 3 ? 1 > () : false; // expected-error {{missing 'template' keyword}} expected-error +{{}} expected-note +{{}} +} + struct MrsBadcrumble { friend MrsBadcrumble operator<(void (*)(int), MrsBadcrumble); friend void operator>(MrsBadcrumble, int); @@ -30,6 +71,9 @@ template void f(T t) { // Note: no diagnostic here, this is actually valid as a comparison between // the decayed pointer to Y::g<> and mb! T::g(0); + + // ... but this one must be a template-id. + T::g(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}} } struct Y { -- GitLab From affe61a68001370fed6047bec14f7c33519f3731 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 27 Jun 2018 00:02:16 +0000 Subject: [PATCH 0295/1023] [mips] Explicitly specify the linker emulation for MIPS on FreeBSD. FreeBSD's mips64 builds O32 binaries for /usr/lib32 by default and thus needs to be able to link O32 binaries which requires an explicit linker emulation. Go ahead and list all the linker emulation variants for MIPS so that any supported MIPS ABI binary can be linked by any linker supporting MIPS. Reviewed By: atanasyan Differential Revision: https://reviews.llvm.org/D48507 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335691 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/FreeBSD.cpp | 35 +++++++++++++++++++++++++------ test/Driver/freebsd.c | 21 +++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index b6c4e8fdd9..9626ea906f 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -165,16 +165,39 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--enable-new-dtags"); } - // When building 32-bit code on FreeBSD/amd64, we have to explicitly - // instruct ld in the base system to link 32-bit code. - if (Arch == llvm::Triple::x86) { + // Explicitly set the linker emulation for platforms that might not + // be the default emulation for the linker. + switch (Arch) { + case llvm::Triple::x86: CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386_fbsd"); - } - - if (Arch == llvm::Triple::ppc) { + break; + case llvm::Triple::ppc: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_fbsd"); + break; + case llvm::Triple::mips: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32btsmip_fbsd"); + break; + case llvm::Triple::mipsel: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32ltsmip_fbsd"); + break; + case llvm::Triple::mips64: + CmdArgs.push_back("-m"); + if (tools::mips::hasMipsAbiArg(Args, "n32")) + CmdArgs.push_back("elf32btsmipn32_fbsd"); + else + CmdArgs.push_back("elf64btsmip_fbsd"); + break; + case llvm::Triple::mips64el: + CmdArgs.push_back("-m"); + if (tools::mips::hasMipsAbiArg(Args, "n32")) + CmdArgs.push_back("elf32ltsmipn32_fbsd"); + else + CmdArgs.push_back("elf64ltsmip_fbsd"); + break; } if (Arg *A = Args.getLastArg(options::OPT_G)) { diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c index b6493823bc..48f7c8e7f2 100644 --- a/test/Driver/freebsd.c +++ b/test/Driver/freebsd.c @@ -42,6 +42,27 @@ // RUN: --sysroot=%S/Inputs/multiarch_freebsd64_tree -print-search-dirs 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LIB32PATHS %s // +// Check that MIPS passes the correct linker emulation. +// +// RUN: %clang -target mips-freebsd %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPS-LD %s +// CHECK-MIPS-LD: ld{{.*}}" {{.*}} "-m" "elf32btsmip_fbsd" +// RUN: %clang -target mipsel-freebsd %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPSEL-LD %s +// CHECK-MIPSEL-LD: ld{{.*}}" {{.*}} "-m" "elf32ltsmip_fbsd" +// RUN: %clang -target mips64-freebsd %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPS64-LD %s +// CHECK-MIPS64-LD: ld{{.*}}" {{.*}} "-m" "elf64btsmip_fbsd" +// RUN: %clang -target mips64el-freebsd %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-LD %s +// CHECK-MIPS64EL-LD: ld{{.*}}" {{.*}} "-m" "elf64ltsmip_fbsd" +// RUN: %clang -target mips64-freebsd -mabi=n32 %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPSN32-LD %s +// CHECK-MIPSN32-LD: ld{{.*}}" {{.*}} "-m" "elf32btsmipn32_fbsd" +// RUN: %clang -target mips64el-freebsd -mabi=n32 %s -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPSN32EL-LD %s +// CHECK-MIPSN32EL-LD: ld{{.*}}" {{.*}} "-m" "elf32ltsmipn32_fbsd" +// // Check that the new linker flags are passed to FreeBSD // RUN: %clang -no-canonical-prefixes -target x86_64-pc-freebsd8 -m32 %s \ // RUN: --sysroot=%S/Inputs/multiarch_freebsd64_tree -### 2>&1 \ -- GitLab From 2f412f2b9817c1b159472cb3c18438ffdb4a5407 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 27 Jun 2018 01:32:04 +0000 Subject: [PATCH 0296/1023] Diagnose missing 'template' keywords in contexts where a comma is not a binary operator. Factor out the checking for a comma within potential angle brackets and also call it from contexts where we parse a comma-separated list of arguments or initializers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335699 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 8 ++ include/clang/Sema/Sema.h | 18 ++- lib/Parse/ParseExpr.cpp | 91 +++------------ lib/Parse/ParseExprCXX.cpp | 11 +- lib/Parse/ParseTemplate.cpp | 108 ++++++++++++++++++ .../dependent-template-recover.cpp | 10 ++ 6 files changed, 157 insertions(+), 89 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index df803c52f1..29cd9e82d7 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1607,6 +1607,14 @@ private: } bool diagnoseUnknownTemplateId(ExprResult TemplateName, SourceLocation Less); + void checkPotentialAngleBracket(ExprResult &PotentialTemplateName); + bool checkPotentialAngleBracketDelimiter(const AngleBracketTracker::Loc &, + const Token &OpToken); + bool checkPotentialAngleBracketDelimiter(const Token &OpToken) { + if (auto *Info = AngleBrackets.getCurrent(*this)) + return checkPotentialAngleBracketDelimiter(*Info, OpToken); + return false; + } ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); ExprResult ParseUnaryExprOrTypeTraitExpression(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 93b24297d3..4897a2613e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1830,23 +1830,19 @@ public: getTemplateNameKindForDiagnostics(TemplateName Name); /// Determine whether it's plausible that E was intended to be a - /// template-name. Updates E to denote the template name expression. - bool mightBeIntendedToBeTemplateName(ExprResult &ER, bool &Dependent) { - if (!getLangOpts().CPlusPlus || ER.isInvalid()) + /// template-name. + bool mightBeIntendedToBeTemplateName(ExprResult E, bool &Dependent) { + if (!getLangOpts().CPlusPlus || E.isInvalid()) return false; - Expr *E = ER.get()->IgnoreImplicit(); - while (auto *BO = dyn_cast(E)) - E = BO->getRHS()->IgnoreImplicit(); - ER = E; Dependent = false; - if (auto *DRE = dyn_cast(E)) + if (auto *DRE = dyn_cast(E.get())) return !DRE->hasExplicitTemplateArgs(); - if (auto *ME = dyn_cast(E)) + if (auto *ME = dyn_cast(E.get())) return !ME->hasExplicitTemplateArgs(); Dependent = true; - if (auto *DSDRE = dyn_cast(E)) + if (auto *DSDRE = dyn_cast(E.get())) return !DSDRE->hasExplicitTemplateArgs(); - if (auto *DSME = dyn_cast(E)) + if (auto *DSME = dyn_cast(E.get())) return !DSME->hasExplicitTemplateArgs(); // Any additional cases recognized here should also be handled by // diagnoseExprIntendedAsTemplateName. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 94e56e9d8a..619fd222fd 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -246,30 +246,6 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } -/// We've parsed something that could plausibly be intended to be a template -/// name (\p LHS) followed by a '<' token, and the following code can't possibly -/// be an expression. Determine if this is likely to be a template-id and if so, -/// diagnose it. -bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { - TentativeParsingAction TPA(*this); - // FIXME: We could look at the token sequence in a lot more detail here. - if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, - StopAtSemi | StopBeforeMatch)) { - TPA.Commit(); - - SourceLocation Greater; - ParseGreaterThanInTemplateList(Greater, true, false); - Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, - Less, Greater); - return true; - } - - // There's no matching '>' token, this probably isn't supposed to be - // interpreted as a template-id. Parse it as an (ill-formed) comparison. - TPA.Revert(); - return false; -} - bool Parser::isFoldOperator(prec::Level Level) const { return Level > prec::Unknown && Level != prec::Conditional && Level != prec::Spaceship; @@ -303,57 +279,12 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or)); } - // If we have a name-shaped expression followed by '<', track it in case we - // later find we're probably supposed to be in a template-id. - ExprResult TemplateName = LHS; - bool DependentTemplateName = false; - if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName( - TemplateName, DependentTemplateName)) { - AngleBracketTracker::Priority Priority = - (DependentTemplateName ? AngleBracketTracker::DependentName - : AngleBracketTracker::PotentialTypo) | - (OpToken.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess - : AngleBracketTracker::NoSpaceBeforeLess); - AngleBrackets.add(*this, TemplateName.get(), OpToken.getLocation(), - Priority); - } - // If we're potentially in a template-id, we may now be able to determine // whether we're actually in one or not. - if (auto *Info = AngleBrackets.getCurrent(*this)) { - // If an operator is followed by a type that can be a template argument - // and cannot be an expression, then this is ill-formed, but might be - // intended to be part of a template-id. Likewise if this is <>. - if ((OpToken.isOneOf(tok::less, tok::comma) && - isKnownToBeDeclarationSpecifier()) || - (OpToken.is(tok::less) && - Tok.isOneOf(tok::greater, tok::greatergreater, - tok::greatergreatergreater))) { - if (diagnoseUnknownTemplateId(Info->TemplateName, Info->LessLoc)) { - AngleBrackets.clear(*this); - return ExprError(); - } - } - - // If a context that looks like a template-id is followed by '()', then - // this is ill-formed, but might be intended to be a template-id followed - // by '()'. - if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) && - NextToken().is(tok::r_paren)) { - Actions.diagnoseExprIntendedAsTemplateName( - getCurScope(), Info->TemplateName, Info->LessLoc, - OpToken.getLocation()); - AngleBrackets.clear(*this); - return ExprError(); - } - } - - // After a '>' (etc), we're no longer potentially in a construct that's - // intended to be treated as a template-id. - if (OpToken.is(tok::greater) || - (getLangOpts().CPlusPlus11 && - OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater))) - AngleBrackets.clear(*this); + if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater, + tok::greatergreatergreater) && + checkPotentialAngleBracketDelimiter(OpToken)) + return ExprError(); // Bail out when encountering a comma followed by a token which can't // possibly be the start of an expression. For instance: @@ -879,6 +810,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); ConsumeAnnotationToken(); + if (!Res.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(Res); break; case tok::kw___super: @@ -1098,11 +1031,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, isAddressOfOperand, std::move(Validator), /*IsInlineAsmIdentifier=*/false, Tok.is(tok::r_paren) ? nullptr : &Replacement); - if (!Res.isInvalid() && !Res.get()) { + if (!Res.isInvalid() && Res.isUnset()) { UnconsumeToken(Replacement); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } + if (!Res.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(Res); break; } case tok::char_constant: // constant: character-constant @@ -1841,6 +1776,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); + if (!LHS.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(LHS); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' @@ -2878,7 +2815,10 @@ bool Parser::ParseExpressionList(SmallVectorImpl &Exprs, if (Tok.isNot(tok::comma)) break; // Move to the next argument, remember where the comma was. + Token Comma = Tok; CommaLocs.push_back(ConsumeToken()); + + checkPotentialAngleBracketDelimiter(Comma); } if (SawError) { // Ensure typos get diagnosed when errors were encountered while parsing the @@ -2913,7 +2853,10 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl &Exprs, return false; // Move to the next argument, remember where the comma was. + Token Comma = Tok; CommaLocs.push_back(ConsumeToken()); + + checkPotentialAngleBracketDelimiter(Comma); } } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a5a340ad22..77f758b159 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -561,10 +561,13 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe if (isAddressOfOperand && isPostfixExpressionSuffixStart()) isAddressOfOperand = false; - return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, - Tok.is(tok::l_paren), isAddressOfOperand, - nullptr, /*IsInlineAsmIdentifier=*/false, - &Replacement); + ExprResult E = Actions.ActOnIdExpression( + getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren), + isAddressOfOperand, nullptr, /*IsInlineAsmIdentifier=*/false, + &Replacement); + if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less)) + checkPotentialAngleBracket(E); + return E; } /// ParseCXXIdExpression - Handle id-expression. diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index d1d53b07e0..5d47161ff5 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1474,3 +1474,111 @@ void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { } } } + +/// We've parsed something that could plausibly be intended to be a template +/// name (\p LHS) followed by a '<' token, and the following code can't possibly +/// be an expression. Determine if this is likely to be a template-id and if so, +/// diagnose it. +bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { + TentativeParsingAction TPA(*this); + // FIXME: We could look at the token sequence in a lot more detail here. + if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, + StopAtSemi | StopBeforeMatch)) { + TPA.Commit(); + + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, + Less, Greater); + return true; + } + + // There's no matching '>' token, this probably isn't supposed to be + // interpreted as a template-id. Parse it as an (ill-formed) comparison. + TPA.Revert(); + return false; +} + +void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) { + assert(Tok.is(tok::less) && "not at a potential angle bracket"); + + bool DependentTemplateName = false; + if (!Actions.mightBeIntendedToBeTemplateName(PotentialTemplateName, + DependentTemplateName)) + return; + + // OK, this might be a name that the user intended to be parsed as a + // template-name, followed by a '<' token. Check for some easy cases. + + // If we have potential_template<>, then it's supposed to be a template-name. + if (NextToken().is(tok::greater) || + (getLangOpts().CPlusPlus11 && + NextToken().isOneOf(tok::greatergreater, tok::greatergreatergreater))) { + SourceLocation Less = ConsumeToken(); + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), PotentialTemplateName, Less, Greater); + // FIXME: Perform error recovery. + PotentialTemplateName = ExprError(); + return; + } + + // If we have 'potential_template' later on. + { + // FIXME: Avoid the tentative parse when NextToken() can't begin a type. + TentativeParsingAction TPA(*this); + SourceLocation Less = ConsumeToken(); + if (isTypeIdUnambiguously() && + diagnoseUnknownTemplateId(PotentialTemplateName, Less)) { + TPA.Commit(); + // FIXME: Perform error recovery. + PotentialTemplateName = ExprError(); + return; + } + TPA.Revert(); + } + + // Otherwise, remember that we saw this in case we see a potentially-matching + // '>' token later on. + AngleBracketTracker::Priority Priority = + (DependentTemplateName ? AngleBracketTracker::DependentName + : AngleBracketTracker::PotentialTypo) | + (Tok.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess + : AngleBracketTracker::NoSpaceBeforeLess); + AngleBrackets.add(*this, PotentialTemplateName.get(), Tok.getLocation(), + Priority); +} + +bool Parser::checkPotentialAngleBracketDelimiter( + const AngleBracketTracker::Loc &LAngle, const Token &OpToken) { + // If a comma in an expression context is followed by a type that can be a + // template argument and cannot be an expression, then this is ill-formed, + // but might be intended to be part of a template-id. + if (OpToken.is(tok::comma) && isTypeIdUnambiguously() && + diagnoseUnknownTemplateId(LAngle.TemplateName, LAngle.LessLoc)) { + AngleBrackets.clear(*this); + return true; + } + + // If a context that looks like a template-id is followed by '()', then + // this is ill-formed, but might be intended to be a template-id + // followed by '()'. + if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) && + NextToken().is(tok::r_paren)) { + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), LAngle.TemplateName, LAngle.LessLoc, + OpToken.getLocation()); + AngleBrackets.clear(*this); + return true; + } + + // After a '>' (etc), we're no longer potentially in a construct that's + // intended to be treated as a template-id. + if (OpToken.is(tok::greater) || + (getLangOpts().CPlusPlus11 && + OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater))) + AngleBrackets.clear(*this); + return false; +} diff --git a/test/SemaTemplate/dependent-template-recover.cpp b/test/SemaTemplate/dependent-template-recover.cpp index 617950a4da..37a8faa705 100644 --- a/test/SemaTemplate/dependent-template-recover.cpp +++ b/test/SemaTemplate/dependent-template-recover.cpp @@ -32,6 +32,16 @@ struct X { // FIXME: Is this the right heuristic? xyz(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} T::foo < xyz<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + + sizeof T::foo < 123 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + f(t->foo<1, 2>(), // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + t->bar<3, 4>()); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}} + + int arr[] = { + t->baz<1, 2>(1 + 1), // ok, two comparisons + t->foo<1, 2>(), // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}} + t->bar<3, 4>() // FIXME: we don't recover from the previous error so don't diagnose this + }; } int xyz; -- GitLab From ed4073379365a1219dbc4374a4e6ff38d6a14087 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 27 Jun 2018 01:51:36 +0000 Subject: [PATCH 0297/1023] [analyzer] [NFC] Add -verify to malloc checker test Differential Revision: https://reviews.llvm.org/D48514 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335700 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/malloc-plist.c | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c index ce50758571..1f2870863c 100644 --- a/test/Analysis/malloc-plist.c +++ b/test/Analysis/malloc-plist.c @@ -1,5 +1,5 @@ // RUN: rm -f %t -// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -o %t %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -analyzer-output=plist -verify -o %t %s // RUN: FileCheck -input-file %t %s typedef __typeof(sizeof(int)) size_t; @@ -19,8 +19,8 @@ void diagnosticTest(int in) { void myArrayAllocation() { int **A; A = malloc(2*sizeof(int*)); - A[0] = 0;// expected-warning {{leak}} -} + A[0] = 0; +}//expected-warning{{Potential leak}} void reallocDiagnostics() { char * buf = malloc(100); @@ -44,7 +44,7 @@ void *wrapper() { void test_wrapper() { void *buf = wrapper(); (void) buf; -} +}//expected-warning{{Potential leak}} // Test what happens when the same call frees and allocated memory. // Also tests the stack hint for parameters, when they are passed directly or via pointer. @@ -60,7 +60,7 @@ void my_malloc_and_free(void **x) { void *test_double_action_call() { void *buf; my_malloc_and_free(&buf); - return buf; + return buf; //expected-warning{{Use of memory after it is freed}} } // Test stack hint for 'reallocation failed'. @@ -75,7 +75,7 @@ char *my_realloc(char *buf) { void reallocIntra() { char *buf = (char *)malloc(100); buf = my_realloc(buf); - free(buf); + free(buf);//expected-warning{{Potential leak}} } // Test stack hint when returning a result. @@ -85,7 +85,7 @@ static char *malloc_wrapper_ret() { void use_ret() { char *v; v = malloc_wrapper_ret(); -} +}//expected-warning{{Potential leak}} // Passing a block as a parameter to an inlined call for which we generate // a stack hint message caused crashes. @@ -99,7 +99,7 @@ void call_myfree_takingblock() { int *p = malloc(sizeof(int)); myfree_takingblock(some_block, p); - *p = 3; + *p = 3;//expected-warning{{Use of memory after it is freed}} } // Test that we refer to the last symbol used in the leak diagnostic. @@ -112,13 +112,13 @@ void LeakedSymbol(int in) { m = p; p = 0; (*m)++; - in++; + in++;//expected-warning{{Potential leak}} } // Tests that exercise running remove dead bindings at Call exit. static void function_with_leak1() { char *x = (char*)malloc(12); -} +} //expected-warning{{Potential leak}} void use_function_with_leak1() { function_with_leak1(); int y = 0; @@ -126,7 +126,7 @@ void use_function_with_leak1() { static void function_with_leak2() { char *x = (char*)malloc(12); - int m = 0; + int m = 0; //expected-warning{{Potential leak}} } void use_function_with_leak2() { function_with_leak2(); @@ -136,7 +136,7 @@ static void function_with_leak3(int y) { char *x = (char*)malloc(12); if (y) y++; -} +}//expected-warning{{Potential leak}} void use_function_with_leak3(int y) { function_with_leak3(y); } @@ -146,7 +146,7 @@ static void function_with_leak4(int y) { if (y) y++; else - y--; + y--;//expected-warning{{Potential leak}} } void use_function_with_leak4(int y) { function_with_leak4(y); @@ -157,7 +157,7 @@ int anotherFunction5() { } static int function_with_leak5() { char *x = (char*)malloc(12); - return anotherFunction5(); + return anotherFunction5();//expected-warning{{Potential leak}} } void use_function_with_leak5() { function_with_leak5(); @@ -168,7 +168,7 @@ void anotherFunction6(int m) { } static void function_with_leak6() { char *x = (char*)malloc(12); - anotherFunction6(3); + anotherFunction6(3);//expected-warning{{Potential leak}} } void use_function_with_leak6() { function_with_leak6(); @@ -184,7 +184,7 @@ static char *function_with_leak7() { } void use_function_with_leak7() { function_with_leak7(); -} +}//expected-warning{{Potential memory leak}} // Test that we do not print the name of a variable not visible from where // the issue is reported. @@ -194,7 +194,7 @@ int *my_malloc() { } void testOnlyRefferToVisibleVariables() { my_malloc(); -} // expected-warning {{Potential leak of memory}} +} // expected-warning{{Potential memory leak}} struct PointerWrapper{ int*p; @@ -205,8 +205,8 @@ int *my_malloc_into_struct() { return w.p; } void testMyMalloc() { - my_malloc_into_struct(); // expected-warning {{Potential leak of memory}} -} + my_malloc_into_struct(); +} // expected-warning{{Potential memory leak}} // CHECK: diagnostics // CHECK-NEXT: -- GitLab From 33876347514a9d3b3500c04d2321eebf4b6cdcb7 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 27 Jun 2018 01:51:55 +0000 Subject: [PATCH 0298/1023] [analyzer] [NFC] A convenient getter for getting a current stack frame Differential Revision: https://reviews.llvm.org/D44756 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335701 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/AnalysisDeclContext.h | 2 +- include/clang/Analysis/ProgramPoint.h | 4 +++ .../Core/PathSensitive/CoreEngine.h | 2 +- .../Core/PathSensitive/ExplodedGraph.h | 2 +- lib/Analysis/AnalysisDeclContext.cpp | 4 +-- .../Checkers/CXXSelfAssignmentChecker.cpp | 2 +- .../Checkers/ExprInspectionChecker.cpp | 4 +-- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 4 +-- .../Checkers/NSErrorChecker.cpp | 3 +- .../Checkers/RetainCountChecker.cpp | 6 ++-- .../Checkers/StackAddrEscapeChecker.cpp | 5 ++-- .../Checkers/VirtualCallChecker.cpp | 6 ++-- lib/StaticAnalyzer/Core/BugReporter.cpp | 6 ++-- .../Core/BugReporterVisitors.cpp | 17 ++++++----- lib/StaticAnalyzer/Core/CallEvent.cpp | 2 +- lib/StaticAnalyzer/Core/CoreEngine.cpp | 2 +- lib/StaticAnalyzer/Core/Environment.cpp | 2 +- lib/StaticAnalyzer/Core/ExprEngine.cpp | 28 +++++++++---------- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 8 +++--- .../Core/ExprEngineCallAndReturn.cpp | 14 ++++------ lib/StaticAnalyzer/Core/LoopWidening.cpp | 2 +- lib/StaticAnalyzer/Core/MemRegion.cpp | 10 +++---- lib/StaticAnalyzer/Core/SymbolManager.cpp | 2 +- lib/StaticAnalyzer/Core/WorkList.cpp | 4 +-- 24 files changed, 70 insertions(+), 71 deletions(-) diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h index 2cfd74dbaf..d6eb5e4d5f 100644 --- a/include/clang/Analysis/AnalysisDeclContext.h +++ b/include/clang/Analysis/AnalysisDeclContext.h @@ -264,7 +264,7 @@ public: return Ctx->getSelfDecl(); } - const StackFrameContext *getCurrentStackFrame() const; + const StackFrameContext *getStackFrame() const; /// Return true if the current LocationContext has no caller context. virtual bool inTopFrame() const; diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 10890f277b..e8f0d61617 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -181,6 +181,10 @@ public: return L.getPointer(); } + const StackFrameContext *getStackFrame() const { + return getLocationContext()->getStackFrame(); + } + // For use with DenseMap. This hash is probably slow. unsigned getHashValue() const { llvm::FoldingSetNodeID ID; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 84a6203eda..5755818cd9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -211,7 +211,7 @@ struct NodeBuilderContext { /// visited on the exploded graph path. unsigned blockCount() const { return Eng.WList->getBlockCounter().getNumVisited( - LC->getCurrentStackFrame(), + LC->getStackFrame(), Block->getBlockID()); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 579a066126..c12198db65 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -147,7 +147,7 @@ public: } const StackFrameContext *getStackFrame() const { - return getLocationContext()->getCurrentStackFrame(); + return getLocation().getStackFrame(); } const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index 2bdcac4ce7..e746e8dfa5 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -442,7 +442,7 @@ LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx, // LocationContext methods. //===----------------------------------------------------------------------===// -const StackFrameContext *LocationContext::getCurrentStackFrame() const { +const StackFrameContext *LocationContext::getStackFrame() const { const LocationContext *LC = this; while (LC) { if (const auto *SFC = dyn_cast(LC)) @@ -453,7 +453,7 @@ const StackFrameContext *LocationContext::getCurrentStackFrame() const { } bool LocationContext::inTopFrame() const { - return getCurrentStackFrame()->inTopFrame(); + return getStackFrame()->inTopFrame(); } bool LocationContext::isParentOf(const LocationContext *LC) const { diff --git a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp index 668e772fe1..d1d37c75df 100644 --- a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp @@ -48,7 +48,7 @@ void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const { auto &State = C.getState(); auto &SVB = C.getSValBuilder(); auto ThisVal = - State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); + State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame())); auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx)); auto ParamVal = State->getSVal(Param); ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx); diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp index 0005ec470d..8de653c10f 100644 --- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -149,7 +149,7 @@ void ExprInspectionChecker::analyzerEval(const CallExpr *CE, // A specific instantiation of an inlined function may have more constrained // values than can generally be assumed. Skip the check. - if (LC->getCurrentStackFrame()->getParent() != nullptr) + if (LC->getStackFrame()->getParent() != nullptr) return; reportBug(getArgumentValueString(CE, C), C); @@ -178,7 +178,7 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE, // when we are analyzing it as an inlined function. This means that // clang_analyzer_checkInlined(true) should always print TRUE, but // clang_analyzer_checkInlined(false) should never actually print anything. - if (LC->getCurrentStackFrame()->getParent() == nullptr) + if (LC->getStackFrame()->getParent() == nullptr) return; reportBug(getArgumentValueString(CE, C), C); diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index b008bcdf4e..1fa2e3b53e 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2258,7 +2258,7 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, // Do not show local variables belonging to a function other than // where the error is reported. if (!VR || - (VR->getStackFrame() == LeakContext->getCurrentStackFrame())) + (VR->getStackFrame() == LeakContext->getStackFrame())) ReferenceRegion = MR; } } @@ -2919,7 +2919,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( // reference counting operations within it (see the code above), // and if so, we'd conclude that it likely is a reference counting // pointer destructor. - ReleaseDestructorLC = LC->getCurrentStackFrame(); + ReleaseDestructorLC = LC->getStackFrame(); // It is unlikely that releasing memory is delegated to a destructor // inside a destructor of a shared pointer, because it's fairly hard // to pass the information that the pointer indeed needs to be diff --git a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index 559c75d7a5..2bd68b625c 100644 --- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -186,8 +186,7 @@ static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C) { } static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) { - const StackFrameContext * - SFC = C.getLocationContext()->getCurrentStackFrame(); + const StackFrameContext * SFC = C.getStackFrame(); if (Optional X = val.getAs()) { const MemRegion* R = X->getRegion(); if (const VarRegion *VR = R->getAs()) diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 78e4b8f250..54e87d4094 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1968,8 +1968,8 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, const Stmt *S = N->getLocation().castAs().getStmt(); if (isa(S) && - isSynthesizedAccessor(LCtx->getCurrentStackFrame())) { - S = LCtx->getCurrentStackFrame()->getCallSite(); + isSynthesizedAccessor(LCtx->getStackFrame())) { + S = LCtx->getStackFrame()->getCallSite(); } if (isa(S)) { @@ -2297,7 +2297,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N, const VarRegion *VR = R->getBaseRegion()->getAs(); // Do not show local variables belonging to a function other than // where the error is reported. - if (!VR || VR->getStackFrame() == LeakContext->getCurrentStackFrame()) + if (!VR || VR->getStackFrame() == LeakContext->getStackFrame()) FirstBinding = R; } diff --git a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index fb639adcc1..86936cadd5 100644 --- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -120,7 +120,7 @@ bool StackAddrEscapeChecker::isArcManagedBlock(const MemRegion *R, bool StackAddrEscapeChecker::isNotInCurrentFrame(const MemRegion *R, CheckerContext &C) { const StackSpaceRegion *S = cast(R->getMemorySpace()); - return S->getStackFrame() != C.getLocationContext()->getCurrentStackFrame(); + return S->getStackFrame() != C.getStackFrame(); } bool StackAddrEscapeChecker::isSemaphoreCaptured(const BlockDecl &B) const { @@ -303,8 +303,7 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const { public: SmallVector, 10> V; - CallBack(CheckerContext &CC) - : Ctx(CC), CurSFC(CC.getLocationContext()->getCurrentStackFrame()) {} + CallBack(CheckerContext &CC) : Ctx(CC), CurSFC(CC.getStackFrame()) {} bool HandleBinding(StoreManager &SMgr, Store S, const MemRegion *Region, SVal Val) override { diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp index 71703d6cd1..ec5afa5134 100644 --- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -108,7 +108,7 @@ VirtualCallChecker::VirtualBugVisitor::VisitNode(const ExplodedNode *N, if (!MD) return nullptr; auto ThiSVal = - State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); + State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame())); const MemRegion *Reg = ThiSVal.castAs().getRegion(); if (!Reg) return nullptr; @@ -230,7 +230,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction, // Enter a constructor, set the corresponding memregion be true. if (isa(MD)) { auto ThiSVal = - State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); + State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame())); const MemRegion *Reg = ThiSVal.getAsRegion(); if (IsBeginFunction) State = State->set(Reg, ObjectState::CtorCalled); @@ -244,7 +244,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction, // Enter a Destructor, set the corresponding memregion be true. if (isa(MD)) { auto ThiSVal = - State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); + State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame())); const MemRegion *Reg = ThiSVal.getAsRegion(); if (IsBeginFunction) State = State->set(Reg, ObjectState::DtorCalled); diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2a53d57d6c..30d7edb9c6 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -865,7 +865,7 @@ static void reversePropagateInterestingSymbols(BugReport &R, const LocationContext *CallerCtx) { // FIXME: Handle non-CallExpr-based CallEvents. - const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); + const StackFrameContext *Callee = CalleeCtx->getStackFrame(); const Stmt *CallSite = Callee->getCallSite(); if (const auto *CE = dyn_cast_or_null(CallSite)) { if (const auto *FD = dyn_cast(CalleeCtx->getDecl())) { @@ -1956,7 +1956,7 @@ static std::unique_ptr generatePathDiagnosticForConsumer( if (AddPathEdges) { // Add an edge to the start of the function. // We'll prune it out later, but it helps make diagnostics more uniform. - const StackFrameContext *CalleeLC = PDB.LC->getCurrentStackFrame(); + const StackFrameContext *CalleeLC = PDB.LC->getStackFrame(); const Decl *D = CalleeLC->getDecl(); addEdgeToPath(PD->getActivePath(), PrevLoc, PathDiagnosticLocation::createBegin(D, SM), CalleeLC); @@ -2051,7 +2051,7 @@ const Decl *BugReport::getDeclWithIssue() const { return nullptr; const LocationContext *LC = N->getLocationContext(); - return LC->getCurrentStackFrame()->getDecl(); + return LC->getStackFrame()->getDecl(); } void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index a4ac93d59b..468f2184bd 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -264,7 +264,7 @@ public: BugReport &BR) override { const LocationContext *Ctx = N->getLocationContext(); - const StackFrameContext *SCtx = Ctx->getCurrentStackFrame(); + const StackFrameContext *SCtx = Ctx->getStackFrame(); ProgramStateRef State = N->getState(); auto CallExitLoc = N->getLocationAs(); @@ -319,7 +319,7 @@ private: /// The calculation is cached in FramesModifyingRegion. bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) { const LocationContext *Ctx = N->getLocationContext(); - const StackFrameContext *SCtx = Ctx->getCurrentStackFrame(); + const StackFrameContext *SCtx = Ctx->getStackFrame(); if (!FramesModifyingCalculated.count(SCtx)) findModifyingFrames(N); return FramesModifyingRegion.count(SCtx); @@ -333,7 +333,7 @@ private: ProgramStateRef LastReturnState = N->getState(); SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest); const LocationContext *Ctx = N->getLocationContext(); - const StackFrameContext *OriginalSCtx = Ctx->getCurrentStackFrame(); + const StackFrameContext *OriginalSCtx = Ctx->getStackFrame(); do { ProgramStateRef State = N->getState(); @@ -344,16 +344,15 @@ private: } FramesModifyingCalculated.insert( - N->getLocationContext()->getCurrentStackFrame()); + N->getLocationContext()->getStackFrame()); if (wasRegionOfInterestModifiedAt(N, LastReturnState, ValueAtReturn)) { - const StackFrameContext *SCtx = - N->getLocationContext()->getCurrentStackFrame(); + const StackFrameContext *SCtx = N->getStackFrame(); while (!SCtx->inTopFrame()) { auto p = FramesModifyingRegion.insert(SCtx); if (!p.second) break; // Frame and all its parents already inserted. - SCtx = SCtx->getParent()->getCurrentStackFrame(); + SCtx = SCtx->getParent()->getStackFrame(); } } @@ -913,7 +912,7 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) { assert(VR->getDecl()->hasLocalStorage()); const LocationContext *LCtx = N->getLocationContext(); - return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame(); + return FrameSpace->getStackFrame() == LCtx->getStackFrame(); } /// Show diagnostics for initializing or declaring a region \p R with a bad value. @@ -2310,7 +2309,7 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ, const auto Param = State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx)); const auto This = - State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame())); + State->getSVal(SVB.getCXXThis(Met, LCtx->getStackFrame())); auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager()); diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 2b2de16dbd..8db7b06f18 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -1221,7 +1221,7 @@ CallEventRef<> CallEventManager::getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State) { const LocationContext *ParentCtx = CalleeCtx->getParent(); - const LocationContext *CallerCtx = ParentCtx->getCurrentStackFrame(); + const LocationContext *CallerCtx = ParentCtx->getStackFrame(); assert(CallerCtx && "This should not be used for top-level stack frames"); const Stmt *CallSite = CalleeCtx->getCallSite(); diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index 416b8e65dc..c17b6aae37 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -256,7 +256,7 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L, const LocationContext *LC = Pred->getLocationContext(); unsigned BlockId = L.getBlock()->getBlockID(); BlockCounter Counter = WList->getBlockCounter(); - Counter = BCounterFactory.IncrementCount(Counter, LC->getCurrentStackFrame(), + Counter = BCounterFactory.IncrementCount(Counter, LC->getStackFrame(), BlockId); WList->setBlockCounter(Counter); diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index 67b37a3bc4..eccaee292c 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -67,7 +67,7 @@ static const Stmt *ignoreTransparentExprs(const Stmt *S) { EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L) : std::pair(ignoreTransparentExprs(S), - L ? L->getCurrentStackFrame() + L ? L->getStackFrame() : nullptr) {} SVal Environment::lookupExpr(const EnvironmentEntry &E) const { diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8ec78cf810..54139c229d 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -282,7 +282,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) { // Precondition: 'this' is always non-null upon entry to the // top-level function. This is our starting assumption for // analyzing an "open" program. - const StackFrameContext *SFC = InitLoc->getCurrentStackFrame(); + const StackFrameContext *SFC = InitLoc->getStackFrame(); if (SFC->getParent() == nullptr) { loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC); SVal V = state->getSVal(L); @@ -450,7 +450,7 @@ ProgramStateRef ExprEngine::addObjectUnderConstruction( ProgramStateRef State, llvm::PointerUnion P, const LocationContext *LC, SVal V) { - ConstructedObjectKey Key(P, LC->getCurrentStackFrame()); + ConstructedObjectKey Key(P, LC->getStackFrame()); // FIXME: Currently the state might already contain the marker due to // incorrect handling of temporaries bound to default parameters. assert(!State->get(Key) || @@ -462,7 +462,7 @@ Optional ExprEngine::getObjectUnderConstruction( ProgramStateRef State, llvm::PointerUnion P, const LocationContext *LC) { - ConstructedObjectKey Key(P, LC->getCurrentStackFrame()); + ConstructedObjectKey Key(P, LC->getStackFrame()); return Optional::create(State->get(Key)); } @@ -470,7 +470,7 @@ ProgramStateRef ExprEngine::finishObjectConstruction( ProgramStateRef State, llvm::PointerUnion P, const LocationContext *LC) { - ConstructedObjectKey Key(P, LC->getCurrentStackFrame()); + ConstructedObjectKey Key(P, LC->getStackFrame()); assert(State->contains(Key)); return State->remove(Key); } @@ -640,7 +640,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, LC = LC->getParent(); } - const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : nullptr; + const StackFrameContext *SFC = LC ? LC->getStackFrame() : nullptr; SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager()); for (auto I : CleanedState->get()) { @@ -963,7 +963,7 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, const auto *CurDtor = cast(LCtx->getDecl()); Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor, - LCtx->getCurrentStackFrame()); + LCtx->getStackFrame()); SVal ThisVal = Pred->getState()->getSVal(ThisPtr); // Create the base object region. @@ -985,7 +985,7 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, const auto *CurDtor = cast(LCtx->getDecl()); Loc ThisVal = getSValBuilder().getCXXThis(CurDtor, - LCtx->getCurrentStackFrame()); + LCtx->getStackFrame()); SVal FieldVal = State->getLValue(Member, State->getSVal(ThisVal).castAs()); @@ -1758,8 +1758,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, bool ExprEngine::replayWithoutInlining(ExplodedNode *N, const LocationContext *CalleeLC) { - const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame(); - const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame(); + const StackFrameContext *CalleeSF = CalleeLC->getStackFrame(); + const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame(); assert(CalleeSF && CallerSF); ExplodedNode *BeforeProcessingCall = nullptr; const Stmt *CE = CalleeSF->getCallSite(); @@ -1771,7 +1771,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, N = N->pred_empty() ? nullptr : *(N->pred_begin()); // Skip the nodes corresponding to the inlined code. - if (L.getLocationContext()->getCurrentStackFrame() != CallerSF) + if (L.getStackFrame() != CallerSF) continue; // We reached the caller. Find the node right before we started // processing the call. @@ -1870,10 +1870,10 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, // Check if we stopped at the top level function or not. // Root node should have the location context of the top most function. const LocationContext *CalleeLC = Pred->getLocation().getLocationContext(); - const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame(); + const LocationContext *CalleeSF = CalleeLC->getStackFrame(); const LocationContext *RootLC = (*G.roots_begin())->getLocation().getLocationContext(); - if (RootLC->getCurrentStackFrame() != CalleeSF) { + if (RootLC->getStackFrame() != CalleeSF) { Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl()); // Re-run the call evaluation without inlining it, by storing the @@ -2190,7 +2190,7 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, NodeBuilder Bldr(Pred, CleanUpObjects, BC); ProgramStateRef State = Pred->getState(); const LocationContext *FromLC = Pred->getLocationContext(); - const LocationContext *ToLC = FromLC->getCurrentStackFrame()->getParent(); + const LocationContext *ToLC = FromLC->getStackFrame()->getParent(); const LocationContext *LC = FromLC; while (LC != ToLC) { assert(LC && "ToLC must be a parent of FromLC!"); @@ -2353,7 +2353,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, // variable should be captured. if (const FieldDecl *FD = LambdaCaptureFields[VD]) { Loc CXXThis = - svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame()); + svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame()); SVal CXXThisVal = state->getSVal(CXXThis); VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType()); } diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 45c8ed1772..f85bfc6e49 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -139,7 +139,7 @@ std::pair ExprEngine::prepareForObjectConstruction( assert(Init->isAnyMemberInitializer()); const CXXMethodDecl *CurCtor = cast(LCtx->getDecl()); Loc ThisPtr = - getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame()); + getSValBuilder().getCXXThis(CurCtor, LCtx->getStackFrame()); SVal ThisVal = State->getSVal(ThisPtr); const ValueDecl *Field; @@ -185,7 +185,7 @@ std::pair ExprEngine::prepareForObjectConstruction( // The temporary is to be managed by the parent stack frame. // So build it in the parent stack frame if we're not in the // top frame of the analysis. - const StackFrameContext *SFC = LCtx->getCurrentStackFrame(); + const StackFrameContext *SFC = LCtx->getStackFrame(); if (const LocationContext *CallerLCtx = SFC->getParent()) { auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()] .getAs(); @@ -289,7 +289,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, case CXXConstructExpr::CK_VirtualBase: // Make sure we are not calling virtual base class initializers twice. // Only the most-derived object should initialize virtual base classes. - if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) { + if (const Stmt *Outer = LCtx->getStackFrame()->getCallSite()) { const CXXConstructExpr *OuterCtor = dyn_cast(Outer); if (OuterCtor) { switch (OuterCtor->getConstructionKind()) { @@ -327,7 +327,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, case CXXConstructExpr::CK_Delegating: { const CXXMethodDecl *CurCtor = cast(LCtx->getDecl()); Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, - LCtx->getCurrentStackFrame()); + LCtx->getStackFrame()); SVal ThisVal = State->getSVal(ThisPtr); if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index e15871c7a2..3ee67f3d68 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -74,15 +74,14 @@ static std::pair getLastStmt(const ExplodedNode *Node) { const Stmt *S = nullptr; const CFGBlock *Blk = nullptr; - const StackFrameContext *SF = - Node->getLocation().getLocationContext()->getCurrentStackFrame(); + const StackFrameContext *SF = Node->getStackFrame(); // Back up through the ExplodedGraph until we reach a statement node in this // stack frame. while (Node) { const ProgramPoint &PP = Node->getLocation(); - if (PP.getLocationContext()->getCurrentStackFrame() == SF) { + if (PP.getStackFrame() == SF) { if (Optional SP = PP.getAs()) { S = SP->getStmt(); break; @@ -204,13 +203,12 @@ static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, void ExprEngine::processCallExit(ExplodedNode *CEBNode) { // Step 1 CEBNode was generated before the call. PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext()); - const StackFrameContext *calleeCtx = - CEBNode->getLocationContext()->getCurrentStackFrame(); + const StackFrameContext *calleeCtx = CEBNode->getStackFrame(); // The parent context might not be a stack frame, so make sure we // look up the first enclosing stack frame. const StackFrameContext *callerCtx = - calleeCtx->getParent()->getCurrentStackFrame(); + calleeCtx->getParent()->getStackFrame(); const Stmt *CE = calleeCtx->getCallSite(); ProgramStateRef state = CEBNode->getState(); @@ -418,7 +416,7 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, assert(D); const LocationContext *CurLC = Pred->getLocationContext(); - const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame(); + const StackFrameContext *CallerSFC = CurLC->getStackFrame(); const LocationContext *ParentOfCallee = CallerSFC; if (Call.getKind() == CE_Block && !cast(Call).isConversionFromLambda()) { @@ -612,7 +610,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, AnalyzerOptions &Opts, const ExprEngine::EvalCallOptions &CallOpts) { const LocationContext *CurLC = Pred->getLocationContext(); - const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame(); + const StackFrameContext *CallerSFC = CurLC->getStackFrame(); switch (Call.getKind()) { case CE_Function: case CE_Block: diff --git a/lib/StaticAnalyzer/Core/LoopWidening.cpp b/lib/StaticAnalyzer/Core/LoopWidening.cpp index fa14f7a18f..9192f49eac 100644 --- a/lib/StaticAnalyzer/Core/LoopWidening.cpp +++ b/lib/StaticAnalyzer/Core/LoopWidening.cpp @@ -56,7 +56,7 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, // being so inprecise. When the invalidation is improved, the handling // of nested loops will also need to be improved. ASTContext &ASTCtx = LCtx->getAnalysisDeclContext()->getASTContext(); - const StackFrameContext *STC = LCtx->getCurrentStackFrame(); + const StackFrameContext *STC = LCtx->getStackFrame(); MemRegionManager &MRMgr = PrevState->getStateManager().getRegionManager(); const MemRegion *Regions[] = {MRMgr.getStackLocalsRegion(STC), MRMgr.getStackArgumentsRegion(STC), diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 9507ea0e08..cb2122c774 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -921,7 +921,7 @@ MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, if (LC) { // FIXME: Once we implement scope handling, we want the parent region // to be the scope. - const StackFrameContext *STC = LC->getCurrentStackFrame(); + const StackFrameContext *STC = LC->getStackFrame(); assert(STC); sReg = getStackLocalsRegion(STC); } @@ -949,7 +949,7 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, if (CL->isFileScope()) sReg = getGlobalsRegion(); else { - const StackFrameContext *STC = LC->getCurrentStackFrame(); + const StackFrameContext *STC = LC->getStackFrame(); assert(STC); sReg = getStackLocalsRegion(STC); } @@ -1014,7 +1014,7 @@ MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, const CXXTempObjectRegion* MemRegionManager::getCXXTempObjectRegion(Expr const *E, LocationContext const *LC) { - const StackFrameContext *SFC = LC->getCurrentStackFrame(); + const StackFrameContext *SFC = LC->getStackFrame(); assert(SFC); return getSubRegion(E, getStackLocalsRegion(SFC)); } @@ -1078,7 +1078,7 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy, LC = LC->getParent(); D = dyn_cast(LC->getDecl()); } - const StackFrameContext *STC = LC->getCurrentStackFrame(); + const StackFrameContext *STC = LC->getStackFrame(); assert(STC); return getSubRegion(PT, getStackArgumentsRegion(STC)); } @@ -1086,7 +1086,7 @@ MemRegionManager::getCXXThisRegion(QualType thisPointerTy, const AllocaRegion* MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, const LocationContext *LC) { - const StackFrameContext *STC = LC->getCurrentStackFrame(); + const StackFrameContext *STC = LC->getStackFrame(); assert(STC); return getSubRegion(E, cnt, getStackLocalsRegion(STC)); } diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index d18f83cb06..3efbd8331b 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -542,7 +542,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ if (!LCtx) return false; - const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame(); + const StackFrameContext *CurrentContext = LCtx->getStackFrame(); if (VarContext == CurrentContext) { // If no statement is provided, everything is live. diff --git a/lib/StaticAnalyzer/Core/WorkList.cpp b/lib/StaticAnalyzer/Core/WorkList.cpp index 833fdf2f58..4b227375da 100644 --- a/lib/StaticAnalyzer/Core/WorkList.cpp +++ b/lib/StaticAnalyzer/Core/WorkList.cpp @@ -158,7 +158,7 @@ public: } else { LocIdentifier LocId = std::make_pair( BE->getBlock()->getBlockID(), - N->getLocationContext()->getCurrentStackFrame()); + N->getLocationContext()->getStackFrame()); auto InsertInfo = Reachable.insert(LocId); if (InsertInfo.second) { @@ -234,7 +234,7 @@ public: if (auto BE = N->getLocation().getAs()) { LocIdentifier LocId = std::make_pair( BE->getBlock()->getBlockID(), - N->getLocationContext()->getCurrentStackFrame()); + N->getLocationContext()->getStackFrame()); NumVisited = NumReached[LocId]++; } -- GitLab From aa26656cf20562f2ed87cfae2d8593116cafae6a Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 27 Jun 2018 02:49:22 +0000 Subject: [PATCH 0299/1023] Fix warning about unhandled enumeration in switch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335702 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/FreeBSD.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index 9626ea906f..d3d82e4d3f 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -198,6 +198,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("elf64ltsmip_fbsd"); break; + default: + break; } if (Arg *A = Args.getLastArg(options::OPT_G)) { -- GitLab From 90a853e223f17de43319e0e90e4e380978666e93 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 27 Jun 2018 03:35:53 +0000 Subject: [PATCH 0300/1023] [CMake] Provide direct support for building sanitized runtimes This avoids having to rely on magic separators and special parsing. Differential Revision: https://reviews.llvm.org/D48061 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335704 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 39af3ecb0c..d2a3cbe20b 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -46,7 +46,9 @@ foreach(target x86_64;aarch64) set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") endforeach() -set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia;x86_64-fuchsia-asan:x86_64-fuchsia;aarch64-fuchsia-asan:aarch64-fuchsia" CACHE STRING "") +set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") +set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") +set(LLVM_RUNTIME_SANITIZER_Address_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") # Set the default target runtimes options. if(NOT APPLE) @@ -81,11 +83,6 @@ foreach(target x86_64;aarch64) set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "") - - set(RUNTIMES_${target}-fuchsia-asan_LLVM_USE_SANITIZER Address CACHE STRING "") - set(RUNTIMES_${target}-fuchsia-asan_LLVM_RUNTIMES_PREFIX "${target}-fuchsia/" CACHE STRING "") - set(RUNTIMES_${target}-fuchsia-asan_LLVM_RUNTIMES_LIBDIR_SUFFIX "/asan" CACHE STRING "") - set(RUNTIMES_${target}-fuchsia-asan_LIBCXX_INSTALL_HEADERS OFF CACHE BOOL "") endforeach() # Setup toolchain. -- GitLab From 0c5b8db8036eff40e5430da5fe33c7ed20d03ceb Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 27 Jun 2018 05:50:43 +0000 Subject: [PATCH 0301/1023] [CMake] Support passing FUCHSIA_SDK as the only variable Now that the structure of Fuchsia SDK has been formalized, we no longer need to pass all the different CFLAGS/LDFLAGS to the CMake build separately, we can simply set the FUCHSIA_SDK variable and derive all the necessary variables from that one inside the cache file. Differential Revision: https://reviews.llvm.org/D48564 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335708 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index d2a3cbe20b..07ef48db04 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -31,18 +31,26 @@ set(FUCHSIA_BUILTINS_BUILD_TYPE Release CACHE STRING "") set(FUCHSIA_RUNTIMES_BUILD_TYPE Release CACHE STRING "") set(FUCHSIA_RUNTIMES_ENABLE_ASSERTIONS ON CACHE BOOL "") +set(FUCHSIA_aarch64_NAME arm64) +set(FUCHSIA_x86_64_NAME x64) +foreach(target x86_64;aarch64) + set(FUCHSIA_${target}_COMPILER_FLAGS "-I${FUCHSIA_SDK}/pkg/fdio/include") + set(FUCHSIA_${target}_LINKER_FLAGS "-L${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/lib") + set(FUCHSIA_${target}_SYSROOT "${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/sysroot") +endforeach() + set(LLVM_BUILTIN_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") # Set the per-target builtins options. foreach(target x86_64;aarch64) set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE ${FUCHSIA_BUILTINS_BUILD_TYPE} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_C_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_C_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_CXX_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") endforeach() @@ -70,12 +78,12 @@ foreach(target x86_64;aarch64) set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE ${FUCHSIA_RUNTIMES_BUILD_TYPE} CACHE STRING "") set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_C_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_C_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_CXX_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ${FUCHSIA_RUNTIMES_ENABLE_ASSERTIONS} CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") -- GitLab From 6c38f6689223684909d506debcfab3c76b09b1e4 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 27 Jun 2018 12:05:06 +0000 Subject: [PATCH 0302/1023] Add regression test for PR37935. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335725 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/cxx-deprecated.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/SemaCXX/cxx-deprecated.cpp b/test/SemaCXX/cxx-deprecated.cpp index 47accd4ae1..aa4501d531 100644 --- a/test/SemaCXX/cxx-deprecated.cpp +++ b/test/SemaCXX/cxx-deprecated.cpp @@ -24,3 +24,6 @@ void g() { } namespace M = N; // expected-warning {{'N' is deprecated}} + +// Shouldn't diag: +[[nodiscard, deprecated("")]] int PR37935(); -- GitLab From 5e1a89912d37a21c3b49ccf30600d7f498dffa9c Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 27 Jun 2018 12:42:48 +0000 Subject: [PATCH 0303/1023] [Analyzer] Moved RangeConstraintManager to header. NFC. Summary: While at it, added a dump method to RangeSet. Reviewers: george.karpenkov, NoQ Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D48561 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335726 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PathSensitive/RangedConstraintManager.h | 88 ++++++++++++++++++- .../Core/RangeConstraintManager.cpp | 83 ----------------- 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h index 1147466d70..6a903dbc46 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -117,6 +117,8 @@ public: void print(raw_ostream &os) const; + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + bool operator==(const RangeSet &other) const { return ranges == other.ranges; } @@ -207,8 +209,90 @@ private: static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment); }; -} // end GR namespace +class RangeConstraintManager : public RangedConstraintManager { +public: + RangeConstraintManager(SubEngine *SE, SValBuilder &SVB) + : RangedConstraintManager(SE, SVB) {} + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + bool canReasonAbout(SVal X) const override; + + ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; + + const llvm::APSInt *getSymVal(ProgramStateRef State, + SymbolRef Sym) const override; + + ProgramStateRef removeDeadBindings(ProgramStateRef State, + SymbolReaper &SymReaper) override; + + void print(ProgramStateRef State, raw_ostream &Out, const char *nl, + const char *sep) override; + + //===------------------------------------------------------------------===// + // Implementation for interface from RangedConstraintManager. + //===------------------------------------------------------------------===// + + ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymWithinInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymOutsideInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; + + RangeSet::Factory &getRangeSetFactory() { return F; } + +private: + RangeSet::Factory F; + + RangeSet getRange(ProgramStateRef State, SymbolRef Sym); + + RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymLERange(llvm::function_ref RS, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); +}; + +} // namespace ento -} // end clang namespace +} // namespace clang #endif diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index c081a65002..c7bbc25594 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -189,89 +189,6 @@ void RangeSet::print(raw_ostream &os) const { os << " }"; } -namespace { -class RangeConstraintManager : public RangedConstraintManager { -public: - RangeConstraintManager(SubEngine *SE, SValBuilder &SVB) - : RangedConstraintManager(SE, SVB) {} - - //===------------------------------------------------------------------===// - // Implementation for interface from ConstraintManager. - //===------------------------------------------------------------------===// - - bool canReasonAbout(SVal X) const override; - - ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; - - const llvm::APSInt *getSymVal(ProgramStateRef State, - SymbolRef Sym) const override; - - ProgramStateRef removeDeadBindings(ProgramStateRef State, - SymbolReaper &SymReaper) override; - - void print(ProgramStateRef State, raw_ostream &Out, const char *nl, - const char *sep) override; - - //===------------------------------------------------------------------===// - // Implementation for interface from RangedConstraintManager. - //===------------------------------------------------------------------===// - - ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymWithinInclusiveRange( - ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymOutsideInclusiveRange( - ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; - -private: - RangeSet::Factory F; - - RangeSet getRange(ProgramStateRef State, SymbolRef Sym); - - RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymLERange(llvm::function_ref RS, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); -}; - -} // end anonymous namespace - std::unique_ptr ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { return llvm::make_unique(Eng, StMgr.getSValBuilder()); -- GitLab From e16472dc5371b575ca75fe695d19b8541bc0c855 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Wed, 27 Jun 2018 13:32:50 +0000 Subject: [PATCH 0304/1023] Re-apply: [ASTImporter] Import the whole redecl chain of functions Summary: With this patch when any `FunctionDecl` of a redeclaration chain is imported then we bring in the whole declaration chain. This involves functions and function template specializations. Also friend functions are affected. The chain is imported as it is in the "from" tu, the order of the redeclarations are kept. I also changed the lookup logic in order to find friends, but first making them visible in their declaration context. We may have long redeclaration chains if all TU contains the same prototype, but our measurements shows no degradation in time of CTU analysis (Tmux, Xerces, Bitcoin, Protobuf). Also, as further work we could squash redundant prototypes, but first ensure that functionality is working properly; then should we optimize. This may seem like a huge patch, sorry about that. But, most of the changes are new tests, changes in the production code is not that much. I also tried to create a smaller patch which does not affect specializations, but that patch failed to pass some of the `clang-import-test`s because there we import function specializations. Also very importantly, we can't just change the import of `FunctionDecl`s without changing the import of function template specializations because they are handled as `FunctionDecl`s. Reviewers: a.sidorin, r.stahl, xazax.hun, balazske, a_sidorin Reviewed By: a_sidorin Subscribers: labath, aprantl, a_sidorin, rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47532 Re-apply commit rC335480 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335731 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTImporter.h | 9 + include/clang/AST/DeclBase.h | 6 +- lib/AST/ASTImporter.cpp | 165 +++++-- lib/AST/DeclBase.cpp | 6 + test/ASTMerge/class/test.cpp | 8 +- unittests/AST/ASTImporterTest.cpp | 714 +++++++++++++++++++++++++++--- 6 files changed, 796 insertions(+), 112 deletions(-) diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 42f99f3f3f..de3bfbdf04 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -43,6 +43,15 @@ class TagDecl; class TypeSourceInfo; class Attr; + // \brief Returns with a list of declarations started from the canonical decl + // then followed by subsequent decls in the translation unit. + // This gives a canonical list for each entry in the redecl chain. + // `Decl::redecls()` gives a list of decls which always start from the + // previous decl and the next item is actually the previous item in the order + // of source locations. Thus, `Decl::redecls()` gives different lists for + // the different entries in a given redecl chain. + llvm::SmallVector getCanonicalForwardRedeclChain(Decl* D); + /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 229e7cd839..8307be90e8 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -1779,10 +1779,14 @@ public: /// Removes a declaration from this context. void removeDecl(Decl *D); - + /// Checks whether a declaration is in this context. bool containsDecl(Decl *D) const; + /// Checks whether a declaration is in this context. + /// This also loads the Decls from the external source before the check. + bool containsDeclAndLoad(Decl *D) const; + using lookup_result = DeclContextLookupResult; using lookup_iterator = lookup_result::iterator; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 6f14ab02ea..5fa222cf4a 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -71,6 +71,25 @@ namespace clang { + template + SmallVector + getCanonicalForwardRedeclChain(Redeclarable* D) { + SmallVector Redecls; + for (auto *R : D->getFirstDecl()->redecls()) { + if (R != D->getFirstDecl()) + Redecls.push_back(R); + } + Redecls.push_back(D->getFirstDecl()); + std::reverse(Redecls.begin(), Redecls.end()); + return Redecls; + } + + SmallVector getCanonicalForwardRedeclChain(Decl* D) { + // Currently only FunctionDecl is supported + auto FD = cast(D); + return getCanonicalForwardRedeclChain(FD); + } + class ASTNodeImporter : public TypeVisitor, public DeclVisitor, public StmtVisitor { @@ -195,6 +214,12 @@ namespace clang { const InContainerTy &Container, TemplateArgumentListInfo &Result); + using TemplateArgsTy = SmallVector; + using OptionalTemplateArgsTy = Optional; + std::tuple + ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD); + bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -408,6 +433,8 @@ namespace clang { // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); + + FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); }; template @@ -437,6 +464,25 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo< From.arguments(), Result); } +std::tuple +ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD) { + assert(FromFD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization); + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null( + Importer.Import(FTSInfo->getTemplate())); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + TemplateArgsTy ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) // Error during import. + return std::make_tuple(Template, OptionalTemplateArgsTy()); + + return std::make_tuple(Template, ToTemplArgs); +} + } // namespace clang //---------------------------------------------------------------------------- @@ -2275,23 +2321,17 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, } case FunctionDecl::TK_FunctionTemplateSpecialization: { - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); - auto *Template = cast_or_null( - Importer.Import(FTSInfo->getTemplate())); - if (!Template) - return true; - TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); - - // Import template arguments. - auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - SmallVector ToTemplArgs; - if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - ToTemplArgs)) + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) return true; TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( - Importer.getToContext(), ToTemplArgs); + Importer.getToContext(), *ToTemplArgs); + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) @@ -2300,6 +2340,7 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); ToFD->setFunctionTemplateSpecialization( Template, ToTAList, /* InsertPos= */ nullptr, TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); @@ -2335,7 +2376,31 @@ bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, llvm_unreachable("All cases should be covered!"); } +FunctionDecl * +ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) + return nullptr; + + void *InsertPos = nullptr; + auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); + return FoundSpec; +} + Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { + + SmallVector Redecls = getCanonicalForwardRedeclChain(D); + auto RedeclIt = Redecls.begin(); + // Import the first part of the decl chain. I.e. import all previous + // declarations starting from the canonical decl. + for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) + if (!Importer.Import(*RedeclIt)) + return nullptr; + assert(*RedeclIt == D); + // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2346,13 +2411,27 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; - const FunctionDecl *FoundWithoutBody = nullptr; - + const FunctionDecl *FoundByLookup = nullptr; + + // If this is a function template specialization, then try to find the same + // existing specialization in the "to" context. The localUncachedLookup + // below will not find any specialization, but would find the primary + // template; thus, we have to skip normal lookup in case of specializations. + // FIXME handle member function templates (TK_MemberSpecialization) similarly? + if (D->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization) { + if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody()) + return Importer.Imported(D, FoundFunction); + FoundByLookup = FoundFunction; + } + } // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. - if (!LexicalDC->isFunctionOrMethod()) { + else if (!LexicalDC->isFunctionOrMethod()) { SmallVector ConflictingDecls; - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; SmallVector FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { @@ -2364,15 +2443,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { - // FIXME: Actually try to merge the body and other attributes. - const FunctionDecl *FromBodyDecl = nullptr; - D->hasBody(FromBodyDecl); - if (D == FromBodyDecl && !FoundFunction->hasBody()) { - // This function is needed to merge completely. - FoundWithoutBody = FoundFunction; + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody()) + return Importer.Imported(D, FoundFunction); + FoundByLookup = FoundFunction; break; - } - return Importer.Imported(D, FoundFunction); } // FIXME: Check for overloading more carefully, e.g., by boosting @@ -2522,9 +2597,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setParams(Parameters); - if (FoundWithoutBody) { + if (FoundByLookup) { auto *Recent = const_cast( - FoundWithoutBody->getMostRecentDecl()); + FoundByLookup->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); } @@ -2546,10 +2621,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(T); } - // Import the body, if any. - if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); + if (D->doesThisDeclarationHaveABody()) { + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); + } } } @@ -2559,14 +2635,29 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ImportTemplateInformation(D, ToFunction)) return nullptr; - // Add this function to the lexical context. - // NOTE: If the function is templated declaration, it should be not added into - // LexicalDC. But described template is imported during import of - // FunctionTemplateDecl (it happens later). So, we use source declaration - // to determine if we should add the result function. - if (!D->getDescribedFunctionTemplate()) + bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); + + // TODO Can we generalize this approach to other AST nodes as well? + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(ToFunction); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) LexicalDC->addDeclInternal(ToFunction); + // Friend declaration's lexical context is the befriending class, but the + // semantic context is the enclosing scope of the befriending class. + // We want the friend functions to be found in the semantic context by lookup. + // FIXME should we handle this generically in VisitFriendDecl? + // In Other cases when LexicalDC != DC we don't want it to be added, + // e.g out-of-class definitions like void B::f() {} . + if (LexicalDC != DC && IsFriend) { + DC->makeDeclVisibleInContext(ToFunction); + } + + // Import the rest of the chain. I.e. import all subsequent declarations. + for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) + if (!Importer.Import(*RedeclIt)) + return nullptr; + if (auto *FromCXXMethod = dyn_cast(D)) ImportOverrides(cast(ToFunction), FromCXXMethod); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 7b7febdc41..e3817c0abc 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1347,6 +1347,12 @@ bool DeclContext::containsDecl(Decl *D) const { (D->NextInContextAndBits.getPointer() || D == LastDecl)); } +bool DeclContext::containsDeclAndLoad(Decl *D) const { + if (hasExternalLexicalStorage()) + LoadLexicalDeclsFromExternalStorage(); + return containsDecl(D); +} + /// shouldBeHidden - Determine whether a declaration which was declared /// within its semantic context should be invisible to qualified name lookup. static bool shouldBeHidden(NamedDecl *D) { diff --git a/test/ASTMerge/class/test.cpp b/test/ASTMerge/class/test.cpp index 99926b649b..ba553af407 100644 --- a/test/ASTMerge/class/test.cpp +++ b/test/ASTMerge/class/test.cpp @@ -13,12 +13,12 @@ // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here -// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units -// CHECK: class1.cpp:39:3: note: friend declared here -// CHECK: class2.cpp:30:8: note: no corresponding friend here - // CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units // CHECK: class1.cpp:46:3: note: friend declared here // CHECK: class2.cpp:36:8: note: no corresponding friend here +// CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units +// CHECK: class1.cpp:39:3: note: friend declared here +// CHECK: class2.cpp:30:8: note: no corresponding friend here + // CHECK: 4 warnings generated. diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 77dbd43a7d..69611a4624 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -20,7 +20,7 @@ #include "DeclMatcher.h" #include "Language.h" -#include "gtest/gtest.h" +#include "gmock/gmock.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -428,6 +428,48 @@ struct ImportExpr : TestImportBase {}; struct ImportType : TestImportBase {}; struct ImportDecl : TestImportBase {}; +struct CanonicalRedeclChain : ASTImporterTestBase {}; + +TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { + Decl *FromTU = getTuDecl("void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + + auto Redecls = getCanonicalForwardRedeclChain(D0); + ASSERT_EQ(Redecls.size(), 1u); + EXPECT_EQ(D0, Redecls[0]); +} + +TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { + Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + auto *D2 = LastDeclMatcher().match(FromTU, Pattern); + FunctionDecl *D1 = D2->getPreviousDecl(); + + auto Redecls = getCanonicalForwardRedeclChain(D0); + ASSERT_EQ(Redecls.size(), 3u); + EXPECT_EQ(D0, Redecls[0]); + EXPECT_EQ(D1, Redecls[1]); + EXPECT_EQ(D2, Redecls[2]); +} + +TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { + Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + auto *D0 = FirstDeclMatcher().match(FromTU, Pattern); + auto *D2 = LastDeclMatcher().match(FromTU, Pattern); + FunctionDecl *D1 = D2->getPreviousDecl(); + + auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); + auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); + auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); + + EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); + EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); +} + + TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier Verifier; testImport("void declToImport() { \"foo\"; }", @@ -1672,34 +1714,6 @@ TEST_P( struct ImportFunctions : ASTImporterTestBase {}; -TEST_P(ImportFunctions, - PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { - Decl *FromTU = getTuDecl("void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); -} - -TEST_P(ImportFunctions, - PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) { - Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - FunctionDecl *FromD = // Prototype - FirstDeclMatcher().match(FromTU, Pattern); - - Decl *ImportedD = Import(FromD, Lang_CXX); - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); -} - TEST_P(ImportFunctions, DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); @@ -1710,7 +1724,7 @@ TEST_P(ImportFunctions, Decl *ImportedD = Import(FromD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } @@ -1727,30 +1741,40 @@ TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); } -TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) { +TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - FunctionDecl *PrototypeFD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *From = + FirstDeclMatcher().match(FromTU, Pattern); // Proto - Decl *ImportedD = Import(PrototypeFD, Lang_CXX); + Decl *ImportedD = Import(From, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - FunctionDecl *DefinitionFD = - LastDeclMatcher().match(FromTU, Pattern); + auto *From = + LastDeclMatcher().match(FromTU, Pattern); // Def - Decl *ImportedD = Import(DefinitionFD, Lang_CXX); + Decl *ImportedD = Import(From, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportPrototypes) { @@ -1759,23 +1783,48 @@ TEST_P(ImportFunctions, ImportPrototypes) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } - Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - ImportedD1 = Import(FromD, Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctions, ImportDefinitions) { + auto Pattern = functionDecl(hasName("f")); + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_EQ(ImportedD, ImportedD1); - EXPECT_TRUE(!cast(ImportedD)->doesThisDeclarationHaveABody()); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { @@ -1784,23 +1833,24 @@ TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { Decl *ImportedD; { Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } - Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - ImportedD1 = Import(FromD, Lang_CXX); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); - EXPECT_EQ(ImportedD, ImportedD1); - EXPECT_TRUE(cast(ImportedD)->doesThisDeclarationHaveABody()); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); } TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { @@ -1823,38 +1873,40 @@ TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } -TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) { +TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { auto Pattern = functionDecl(hasName("f")); { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); - + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); Import(FromD, Lang_CXX); } { Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - FunctionDecl *FromD = - FirstDeclMatcher().match(FromTU, Pattern); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 3u); FunctionDecl *ProtoD = FirstDeclMatcher().match(ToTU, Pattern); - EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); + FunctionDecl *DefinitionD = LastDeclMatcher().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); + + EXPECT_TRUE(DefinitionD->getPreviousDecl()); + EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); + EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); } TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { @@ -1894,6 +1946,202 @@ TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { EXPECT_TRUE(To->isVirtual()); } +TEST_P(ImportFunctions, + ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { + Decl *ToTU = getToTuDecl( + R"( + void f() {} + void f(); + )", + Lang_CXX); + ASSERT_EQ(1u, + DeclCounterWithPredicate([](const FunctionDecl *FD) { + return FD->doesThisDeclarationHaveABody(); + }).match(ToTU, functionDecl())); + + Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, functionDecl()); + + Import(FromD, Lang_CXX); + + EXPECT_EQ(1u, + DeclCounterWithPredicate([](const FunctionDecl *FD) { + return FD->doesThisDeclarationHaveABody(); + }).match(ToTU, functionDecl())); +} + +struct ImportFriendFunctions : ImportFunctions {}; + +TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(); };" + "void f();", + Lang_CXX, + "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, + ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("void f();" + "struct X { friend void f(); };", + Lang_CXX, "input0.cc"); + auto FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(){} };" + "void f();", + Lang_CXX, + "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +TEST_P(ImportFriendFunctions, + ImportFriendFunctionRedeclChainDef_OutOfClassDef) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl("struct X { friend void f(); };" + "void f(){}", + Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *ToFD = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); +} + +// This test is disabled, because ATM we create a redundant FunctionDecl. We +// start the import with the definition of `f` then we continue with the import +// of the type of `f` which involves `X`. During the import of `X` we start +// again the import of the definition of `f` and then finally we create the +// node. But then in the first frame of `VisitFunctionDecl` we create a node +// again since we do not check if such a node exists yet or not. This is being +// fixed in a separate patch: https://reviews.llvm.org/D47632 +// FIXME enable this test once the above patch is approved. +TEST_P(ImportFriendFunctions, + DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl( + R"( + class X; + void f(X *x){} + class X{ + friend void f(X *x); + }; + )", + Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + auto *InClassFD = cast(FirstDeclMatcher() + .match(ToTU, friendDecl()) + ->getFriendDecl()); + EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); + // The parameters must refer the same type + EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), + (*ImportedD->param_begin())->getOriginalType()); +} + +// This test is disabled, because ATM we create a redundant FunctionDecl. We +// start the import with the definition of `f` then we continue with the import +// of the type of `f` which involves `X`. During the import of `X` we start +// again the import of the definition of `f` and then finally we create the +// node. But then in the first frame of `VisitFunctionDecl` we create a node +// again since we do not check if such a node exists yet or not. This is being +// fixed in a separate patch: https://reviews.llvm.org/D47632 +// FIXME enable this test once the above patch is approved. +TEST_P(ImportFriendFunctions, + DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { + auto Pattern = functionDecl(hasName("f")); + + Decl *FromTU = getTuDecl( + R"( + class X; + void f(X *x){} + class X{ + friend void f(X *x); + }; + )", + Lang_CXX, "input0.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + + auto *ImportedD = cast(Import(FromD, Lang_CXX)); + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); + auto *OutOfClassFD = FirstDeclMatcher().match( + ToTU, functionDecl(unless(hasParent(friendDecl())))); + + EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); + // The parameters must refer the same type + EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), + (*ImportedD->param_begin())->getOriginalType()); +} + +TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { + auto Pattern = functionDecl(hasName("f")); + + FunctionDecl *ImportedD; + { + Decl *FromTU = + getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = cast(Import(FromD, Lang_CXX)); + } + FunctionDecl *ImportedD1; + { + Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD1 = cast(Import(FromD, Lang_CXX)); + } + + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + ASSERT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); + EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); +} + AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher, InnerMatcher) { if (auto *Typedef = Node.getTypedefNameForAnonDecl()) @@ -2024,9 +2272,328 @@ TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { EXPECT_FALSE(NS->containsDecl(Spec)); } +struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {}; + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldNotContainFunctionTemplateImplicitInstantiation) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + void foo() { f(); } + )", + Lang_CXX, "input0.cc"); + + // Check that the function template instantiation is NOT the child of the TU. + auto Pattern = translationUnitDecl( + unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + auto *Foo = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + ASSERT_TRUE(Import(Foo, Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldNotContainFunctionTemplateExplicitInstantiation) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template int f(); + )", + Lang_CXX, "input0.cc"); + + // Check that the function template instantiation is NOT the child of the TU. + auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); + auto Pattern = translationUnitDecl(unless(has(Instantiation))); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + ASSERT_TRUE( + Import(FirstDeclMatcher().match(FromTU, Instantiation), Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + TUshouldContainFunctionTemplateSpecialization) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template <> int f() { return 4; } + )", + Lang_CXX, "input0.cc"); + + // Check that the function template specialization is the child of the TU. + auto Specialization = + functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Pattern = translationUnitDecl(has(Specialization)); + ASSERT_TRUE(MatchVerifier{}.match(FromTU, Pattern)); + + ASSERT_TRUE( + Import(FirstDeclMatcher().match(FromTU, Specialization), Lang_CXX)); + + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_TRUE(MatchVerifier{}.match(ToTU, Pattern)); +} + +TEST_P(ImportFunctionTemplateSpecializations, + FunctionTemplateSpecializationRedeclChain) { + + Decl *FromTU = getTuDecl( + R"( + template + int f() { return 0; } + template <> int f() { return 4; } + )", + Lang_CXX, "input0.cc"); + + auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), + hasParent(translationUnitDecl())); + auto *FromSpecD = FirstDeclMatcher().match(FromTU, Spec); + { + auto *TU = FromTU; + auto *SpecD = FromSpecD; + auto *TemplateD = FirstDeclMatcher().match( + TU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + ASSERT_EQ(SpecD, FirstSpecD); + ASSERT_TRUE(SpecD->getPreviousDecl()); + ASSERT_FALSE(cast(SpecD->getPreviousDecl()) + ->doesThisDeclarationHaveABody()); + } + + ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); + + { + auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); + auto *SpecD = FirstDeclMatcher().match(TU, Spec); + auto *TemplateD = FirstDeclMatcher().match( + TU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + EXPECT_EQ(SpecD, FirstSpecD); + ASSERT_TRUE(SpecD->getPreviousDecl()); + EXPECT_FALSE(cast(SpecD->getPreviousDecl()) + ->doesThisDeclarationHaveABody()); + } +} + +TEST_P(ImportFunctionTemplateSpecializations, + MatchNumberOfFunctionTemplateSpecializations) { + + Decl *FromTU = getTuDecl( + R"( + template constexpr int f() { return 0; } + template <> constexpr int f() { return 4; } + void foo() { + static_assert(f() == 0, ""); + static_assert(f() == 4, ""); + } + )", + Lang_CXX11, "input0.cc"); + auto *FromD = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + Import(FromD, Lang_CXX11); + auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); + EXPECT_EQ( + DeclCounter().match(FromTU, functionDecl(hasName("f"))), + DeclCounter().match(ToTU, functionDecl(hasName("f")))); +} + +TEST_P(ImportFunctionTemplateSpecializations, + ImportPrototypes) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Proto of the specialization. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD = LastDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + // Check that they are part of the same redecl chain. + EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); +} + +TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization and definition. + template <> + void f() {} + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 1u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + + auto *TemplateD = FirstDeclMatcher().match( + ToTU, functionTemplateDecl()); + auto *FirstSpecD = *(TemplateD->spec_begin()); + EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); +} + +TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization proto. + template <> + void f(); + // Specialization proto. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization proto. + template <> + void f(); + // Specialization definition. + template <> + void f() {} + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); + EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + +TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { + auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); + auto Code = + R"( + // Proto of the primary template. + template + void f(); + // Specialization definition. + template <> + void f() {} + // Specialization proto. + template <> + void f(); + )"; + + Decl *ImportedD; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); + } + + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter().match(ToTU, Pattern), 2u); + auto *To0 = FirstDeclMatcher().match(ToTU, Pattern); + auto *To1 = LastDeclMatcher().match(ToTU, Pattern); + EXPECT_TRUE(ImportedD == To0); + EXPECT_TRUE(ImportedD != To1); + EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); + EXPECT_EQ(To1->getPreviousDecl(), To0); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, ::testing::Values(ArgVector()), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, CanonicalRedeclChain, + ::testing::Values(ArgVector()),); + auto DefaultTestValuesForRunOptions = ::testing::Values( ArgVector(), ArgVector{"-fdelayed-template-parsing"}, @@ -2048,5 +2615,12 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, + DefaultTestValuesForRunOptions, ); + +INSTANTIATE_TEST_CASE_P(ParameterizedTests, + ImportFunctionTemplateSpecializations, + DefaultTestValuesForRunOptions, ); + } // end namespace ast_matchers } // end namespace clang -- GitLab From f040667a18602c722bc2313da0bad26f961c7292 Mon Sep 17 00:00:00 2001 From: "Ivan A. Kosarev" Date: Wed, 27 Jun 2018 13:58:43 +0000 Subject: [PATCH 0305/1023] [NEON] Support vldNq intrinsics in AArch32 (Clang part) This patch reworks the support for dup NEON intrinsics as described in D48439. Differential Revision: https://reviews.llvm.org/D48440 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335734 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 18 +- lib/CodeGen/CGBuiltin.cpp | 79 +- test/CodeGen/aarch64-neon-ldst-one.c | 1174 -------------------------- test/CodeGen/arm-neon-vld.c | 1087 ++++++++++++++++++++++++ test/CodeGen/arm_neon_intrinsics.c | 315 ------- test/CodeGen/vld_dup.c | 50 -- 6 files changed, 1112 insertions(+), 1611 deletions(-) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 170fbfb061..ed0bad5bee 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -364,9 +364,12 @@ def VST1_LANE : WInst<"vst1_lane", "vpdi", def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; -def VLD2_DUP : WInst<"vld2_dup", "2c", "UcUsUiUlcsilhfPcPs">; -def VLD3_DUP : WInst<"vld3_dup", "3c", "UcUsUiUlcsilhfPcPs">; -def VLD4_DUP : WInst<"vld4_dup", "4c", "UcUsUiUlcsilhfPcPs">; +def VLD2_DUP : WInst<"vld2_dup", "2c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; +def VLD3_DUP : WInst<"vld3_dup", "3c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; +def VLD4_DUP : WInst<"vld4_dup", "4c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; @@ -601,12 +604,9 @@ def ST3_LANE : WInst<"vst3_lane", "vp3i", "lUlQcQUcQPcQlQUldQdPlQPl">; def ST4_LANE : WInst<"vst4_lane", "vp4i", "lUlQcQUcQPcQlQUldQdPlQPl">; def LD1_DUP : WInst<"vld1_dup", "dc", "dQdPlQPl">; -def LD2_DUP : WInst<"vld2_dup", "2c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; -def LD3_DUP : WInst<"vld3_dup", "3c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; -def LD4_DUP : WInst<"vld4_dup", "4c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; +def LD2_DUP : WInst<"vld2_dup", "2c", "dQdPlQPl">; +def LD3_DUP : WInst<"vld3_dup", "3c", "dQdPlQPl">; +def LD4_DUP : WInst<"vld4_dup", "4c", "dQdPlQPl">; def VLDRQ : WInst<"vldrq", "sc", "Pk">; def VSTRQ : WInst<"vstrq", "vps", "Pk">; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 09edfa7568..309528404f 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -4081,16 +4081,22 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = { NEONMAP1(vld1q_x2_v, arm_neon_vld1x2, 0), NEONMAP1(vld1q_x3_v, arm_neon_vld1x3, 0), NEONMAP1(vld1q_x4_v, arm_neon_vld1x4, 0), + NEONMAP1(vld2_dup_v, arm_neon_vld2dup, 0), NEONMAP1(vld2_lane_v, arm_neon_vld2lane, 0), NEONMAP1(vld2_v, arm_neon_vld2, 0), + NEONMAP1(vld2q_dup_v, arm_neon_vld2dup, 0), NEONMAP1(vld2q_lane_v, arm_neon_vld2lane, 0), NEONMAP1(vld2q_v, arm_neon_vld2, 0), + NEONMAP1(vld3_dup_v, arm_neon_vld3dup, 0), NEONMAP1(vld3_lane_v, arm_neon_vld3lane, 0), NEONMAP1(vld3_v, arm_neon_vld3, 0), + NEONMAP1(vld3q_dup_v, arm_neon_vld3dup, 0), NEONMAP1(vld3q_lane_v, arm_neon_vld3lane, 0), NEONMAP1(vld3q_v, arm_neon_vld3, 0), + NEONMAP1(vld4_dup_v, arm_neon_vld4dup, 0), NEONMAP1(vld4_lane_v, arm_neon_vld4lane, 0), NEONMAP1(vld4_v, arm_neon_vld4, 0), + NEONMAP1(vld4q_dup_v, arm_neon_vld4dup, 0), NEONMAP1(vld4q_lane_v, arm_neon_vld4lane, 0), NEONMAP1(vld4q_v, arm_neon_vld4, 0), NEONMAP2(vmax_v, arm_neon_vmaxu, arm_neon_vmaxs, Add1ArgType | UnsignedAlts), @@ -4980,7 +4986,13 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vld3_v: case NEON::BI__builtin_neon_vld3q_v: case NEON::BI__builtin_neon_vld4_v: - case NEON::BI__builtin_neon_vld4q_v: { + case NEON::BI__builtin_neon_vld4q_v: + case NEON::BI__builtin_neon_vld2_dup_v: + case NEON::BI__builtin_neon_vld2q_dup_v: + case NEON::BI__builtin_neon_vld3_dup_v: + case NEON::BI__builtin_neon_vld3q_dup_v: + case NEON::BI__builtin_neon_vld4_dup_v: + case NEON::BI__builtin_neon_vld4q_dup_v: { llvm::Type *Tys[] = {Ty, Int8PtrTy}; Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys); Value *Align = getAlignmentValue32(PtrOp1); @@ -5866,8 +5878,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vld4_lane_v: case NEON::BI__builtin_neon_vld4q_lane_v: case NEON::BI__builtin_neon_vld2_dup_v: + case NEON::BI__builtin_neon_vld2q_dup_v: case NEON::BI__builtin_neon_vld3_dup_v: + case NEON::BI__builtin_neon_vld3q_dup_v: case NEON::BI__builtin_neon_vld4_dup_v: + case NEON::BI__builtin_neon_vld4q_dup_v: // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); @@ -6044,68 +6059,6 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, Value *Ld = Builder.CreateLoad(PtrOp0); return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane"); } - case NEON::BI__builtin_neon_vld2_dup_v: - case NEON::BI__builtin_neon_vld3_dup_v: - case NEON::BI__builtin_neon_vld4_dup_v: { - // Handle 64-bit elements as a special-case. There is no "dup" needed. - if (VTy->getElementType()->getPrimitiveSizeInBits() == 64) { - switch (BuiltinID) { - case NEON::BI__builtin_neon_vld2_dup_v: - Int = Intrinsic::arm_neon_vld2; - break; - case NEON::BI__builtin_neon_vld3_dup_v: - Int = Intrinsic::arm_neon_vld3; - break; - case NEON::BI__builtin_neon_vld4_dup_v: - Int = Intrinsic::arm_neon_vld4; - break; - default: llvm_unreachable("unknown vld_dup intrinsic?"); - } - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Function *F = CGM.getIntrinsic(Int, Tys); - llvm::Value *Align = getAlignmentValue32(PtrOp1); - Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, "vld_dup"); - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } - switch (BuiltinID) { - case NEON::BI__builtin_neon_vld2_dup_v: - Int = Intrinsic::arm_neon_vld2lane; - break; - case NEON::BI__builtin_neon_vld3_dup_v: - Int = Intrinsic::arm_neon_vld3lane; - break; - case NEON::BI__builtin_neon_vld4_dup_v: - Int = Intrinsic::arm_neon_vld4lane; - break; - default: llvm_unreachable("unknown vld_dup intrinsic?"); - } - llvm::Type *Tys[] = {Ty, Int8PtrTy}; - Function *F = CGM.getIntrinsic(Int, Tys); - llvm::StructType *STy = cast(F->getReturnType()); - - SmallVector Args; - Args.push_back(Ops[1]); - Args.append(STy->getNumElements(), UndefValue::get(Ty)); - - llvm::Constant *CI = ConstantInt::get(Int32Ty, 0); - Args.push_back(CI); - Args.push_back(getAlignmentValue32(PtrOp1)); - - Ops[1] = Builder.CreateCall(F, Args, "vld_dup"); - // splat lane 0 to all elts in each vector of the result. - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Value *Val = Builder.CreateExtractValue(Ops[1], i); - Value *Elt = Builder.CreateBitCast(Val, Ty); - Elt = EmitNeonSplat(Elt, CI); - Elt = Builder.CreateBitCast(Elt, Val->getType()); - Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i); - } - Ty = llvm::PointerType::getUnqual(Ops[1]->getType()); - Ops[0] = Builder.CreateBitCast(Ops[0], Ty); - return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]); - } case NEON::BI__builtin_neon_vqrshrn_n_v: Int = usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns; diff --git a/test/CodeGen/aarch64-neon-ldst-one.c b/test/CodeGen/aarch64-neon-ldst-one.c index 5d775ce6dd..592b2ceffa 100644 --- a/test/CodeGen/aarch64-neon-ldst-one.c +++ b/test/CodeGen/aarch64-neon-ldst-one.c @@ -300,58 +300,6 @@ poly64x1_t test_vld1_dup_p64(poly64_t *a) { return vld1_dup_p64(a); } -// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld2q_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x2_t, %struct.uint8x16x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint8x16x2_t [[TMP4]] -uint8x16x2_t test_vld2q_dup_u8(uint8_t *a) { - return vld2q_dup_u8(a); -} - -// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld2q_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint16x8x2_t [[TMP6]] -uint16x8x2_t test_vld2q_dup_u16(uint16_t *a) { - return vld2q_dup_u16(a); -} - -// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld2q_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint32x4x2_t [[TMP6]] -uint32x4x2_t test_vld2q_dup_u32(uint32_t *a) { - return vld2q_dup_u32(a); -} - // CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_dup_u64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align 16 @@ -370,58 +318,6 @@ uint64x2x2_t test_vld2q_dup_u64(uint64_t *a) { return vld2q_dup_u64(a); } -// CHECK-LABEL: define %struct.int8x16x2_t @test_vld2q_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x16x2_t, %struct.int8x16x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int8x16x2_t [[TMP4]] -int8x16x2_t test_vld2q_dup_s8(int8_t *a) { - return vld2q_dup_s8(a); -} - -// CHECK-LABEL: define %struct.int16x8x2_t @test_vld2q_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int16x8x2_t [[TMP6]] -int16x8x2_t test_vld2q_dup_s16(int16_t *a) { - return vld2q_dup_s16(a); -} - -// CHECK-LABEL: define %struct.int32x4x2_t @test_vld2q_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int32x4x2_t [[TMP6]] -int32x4x2_t test_vld2q_dup_s32(int32_t *a) { - return vld2q_dup_s32(a); -} - // CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_dup_s64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align 16 @@ -440,42 +336,6 @@ int64x2x2_t test_vld2q_dup_s64(int64_t *a) { return vld2q_dup_s64(a); } -// CHECK-LABEL: define %struct.float16x8x2_t @test_vld2q_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2r.v8f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half> }* -// CHECK: store { <8 x half>, <8 x half> } [[VLD2]], { <8 x half>, <8 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x8x2_t, %struct.float16x8x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float16x8x2_t [[TMP6]] -float16x8x2_t test_vld2q_dup_f16(float16_t *a) { - return vld2q_dup_f16(a); -} - -// CHECK-LABEL: define %struct.float32x4x2_t @test_vld2q_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.aarch64.neon.ld2r.v4f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }* -// CHECK: store { <4 x float>, <4 x float> } [[VLD2]], { <4 x float>, <4 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float32x4x2_t [[TMP6]] -float32x4x2_t test_vld2q_dup_f32(float32_t *a) { - return vld2q_dup_f32(a); -} - // CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16 @@ -494,40 +354,6 @@ float64x2x2_t test_vld2q_dup_f64(float64_t *a) { return vld2q_dup_f64(a); } -// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld2q_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x2_t, %struct.poly8x16x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly8x16x2_t [[TMP4]] -poly8x16x2_t test_vld2q_dup_p8(poly8_t *a) { - return vld2q_dup_p8(a); -} - -// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld2q_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly16x8x2_t [[TMP6]] -poly16x8x2_t test_vld2q_dup_p16(poly16_t *a) { - return vld2q_dup_p16(a); -} - // CHECK-LABEL: define %struct.poly64x2x2_t @test_vld2q_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16 @@ -546,182 +372,6 @@ poly64x2x2_t test_vld2q_dup_p64(poly64_t *a) { return vld2q_dup_p64(a); } -// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld2_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint8x8x2_t [[TMP4]] -uint8x8x2_t test_vld2_dup_u8(uint8_t *a) { - return vld2_dup_u8(a); -} - -// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld2_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint16x4x2_t [[TMP6]] -uint16x4x2_t test_vld2_dup_u16(uint16_t *a) { - return vld2_dup_u16(a); -} - -// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld2_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint32x2x2_t [[TMP6]] -uint32x2x2_t test_vld2_dup_u32(uint32_t *a) { - return vld2_dup_u32(a); -} - -// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld2_dup_u64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x2_t, %struct.uint64x1x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint64x1x2_t [[TMP6]] -uint64x1x2_t test_vld2_dup_u64(uint64_t *a) { - return vld2_dup_u64(a); -} - -// CHECK-LABEL: define %struct.int8x8x2_t @test_vld2_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x8x2_t, %struct.int8x8x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int8x8x2_t [[TMP4]] -int8x8x2_t test_vld2_dup_s8(int8_t *a) { - return vld2_dup_s8(a); -} - -// CHECK-LABEL: define %struct.int16x4x2_t @test_vld2_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int16x4x2_t [[TMP6]] -int16x4x2_t test_vld2_dup_s16(int16_t *a) { - return vld2_dup_s16(a); -} - -// CHECK-LABEL: define %struct.int32x2x2_t @test_vld2_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int32x2x2_t [[TMP6]] -int32x2x2_t test_vld2_dup_s32(int32_t *a) { - return vld2_dup_s32(a); -} - -// CHECK-LABEL: define %struct.int64x1x2_t @test_vld2_dup_s64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int64x1x2_t, %struct.int64x1x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int64x1x2_t [[TMP6]] -int64x1x2_t test_vld2_dup_s64(int64_t *a) { - return vld2_dup_s64(a); -} - -// CHECK-LABEL: define %struct.float16x4x2_t @test_vld2_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2r.v4f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half> }* -// CHECK: store { <4 x half>, <4 x half> } [[VLD2]], { <4 x half>, <4 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x4x2_t, %struct.float16x4x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float16x4x2_t [[TMP6]] -float16x4x2_t test_vld2_dup_f16(float16_t *a) { - return vld2_dup_f16(a); -} - -// CHECK-LABEL: define %struct.float32x2x2_t @test_vld2_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.aarch64.neon.ld2r.v2f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }* -// CHECK: store { <2 x float>, <2 x float> } [[VLD2]], { <2 x float>, <2 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float32x2x2_t [[TMP6]] -float32x2x2_t test_vld2_dup_f32(float32_t *a) { - return vld2_dup_f32(a); -} - // CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8 @@ -740,40 +390,6 @@ float64x1x2_t test_vld2_dup_f64(float64_t *a) { return vld2_dup_f64(a); } -// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld2_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 16, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly8x8x2_t [[TMP4]] -poly8x8x2_t test_vld2_dup_p8(poly8_t *a) { - return vld2_dup_p8(a); -} - -// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld2_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 16, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly16x4x2_t [[TMP6]] -poly16x4x2_t test_vld2_dup_p16(poly16_t *a) { - return vld2_dup_p16(a); -} - // CHECK-LABEL: define %struct.poly64x1x2_t @test_vld2_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8 @@ -792,61 +408,6 @@ poly64x1x2_t test_vld2_dup_p64(poly64_t *a) { return vld2_dup_p64(a); } -// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld3q_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 48, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x3_t, %struct.uint8x16x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint8x16x3_t [[TMP4]] -uint8x16x3_t test_vld3q_dup_u8(uint8_t *a) { - return vld3q_dup_u8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld3q_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x3_t, %struct.uint16x8x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint16x8x3_t [[TMP6]] -uint16x8x3_t test_vld3q_dup_u16(uint16_t *a) { - return vld3q_dup_u16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld3q_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x3_t, %struct.uint32x4x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint32x4x3_t [[TMP6]] -uint32x4x3_t test_vld3q_dup_u32(uint32_t *a) { - return vld3q_dup_u32(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_dup_u64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align 16 @@ -866,61 +427,6 @@ uint64x2x3_t test_vld3q_dup_u64(uint64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.int8x16x3_t @test_vld3q_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 48, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x16x3_t, %struct.int8x16x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int8x16x3_t [[TMP4]] -int8x16x3_t test_vld3q_dup_s8(int8_t *a) { - return vld3q_dup_s8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int16x8x3_t @test_vld3q_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x8x3_t, %struct.int16x8x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int16x8x3_t [[TMP6]] -int16x8x3_t test_vld3q_dup_s16(int16_t *a) { - return vld3q_dup_s16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int32x4x3_t @test_vld3q_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x4x3_t, %struct.int32x4x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int32x4x3_t [[TMP6]] -int32x4x3_t test_vld3q_dup_s32(int32_t *a) { - return vld3q_dup_s32(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_dup_s64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align 16 @@ -940,44 +446,6 @@ int64x2x3_t test_vld3q_dup_s64(int64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.float16x8x3_t @test_vld3q_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3r.v8f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half> }* -// CHECK: store { <8 x half>, <8 x half>, <8 x half> } [[VLD3]], { <8 x half>, <8 x half>, <8 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x8x3_t, %struct.float16x8x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float16x8x3_t [[TMP6]] -float16x8x3_t test_vld3q_dup_f16(float16_t *a) { - return vld3q_dup_f16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.float32x4x3_t @test_vld3q_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3r.v4f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }* -// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x4x3_t, %struct.float32x4x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float32x4x3_t [[TMP6]] -float32x4x3_t test_vld3q_dup_f32(float32_t *a) { - return vld3q_dup_f32(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16 @@ -997,42 +465,6 @@ float64x2x3_t test_vld3q_dup_f64(float64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld3q_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 48, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x3_t, %struct.poly8x16x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly8x16x3_t [[TMP4]] -poly8x16x3_t test_vld3q_dup_p8(poly8_t *a) { - return vld3q_dup_p8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld3q_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 48, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x3_t, %struct.poly16x8x3_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly16x8x3_t [[TMP6]] -poly16x8x3_t test_vld3q_dup_p16(poly16_t *a) { - return vld3q_dup_p16(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.poly64x2x3_t @test_vld3q_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16 @@ -1052,192 +484,6 @@ poly64x2x3_t test_vld3q_dup_p64(poly64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld3_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 24, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint8x8x3_t [[TMP4]] -uint8x8x3_t test_vld3_dup_u8(uint8_t *a) { - return vld3_dup_u8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld3_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x3_t, %struct.uint16x4x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint16x4x3_t [[TMP6]] -uint16x4x3_t test_vld3_dup_u16(uint16_t *a) { - return vld3_dup_u16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld3_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x3_t, %struct.uint32x2x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint32x2x3_t [[TMP6]] -uint32x2x3_t test_vld3_dup_u32(uint32_t *a) { - return vld3_dup_u32(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld3_dup_u64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x3_t, %struct.uint64x1x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint64x1x3_t [[TMP6]] -uint64x1x3_t test_vld3_dup_u64(uint64_t *a) { - return vld3_dup_u64(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int8x8x3_t @test_vld3_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 24, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x8x3_t, %struct.int8x8x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int8x8x3_t [[TMP4]] -int8x8x3_t test_vld3_dup_s8(int8_t *a) { - return vld3_dup_s8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int16x4x3_t @test_vld3_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x4x3_t, %struct.int16x4x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int16x4x3_t [[TMP6]] -int16x4x3_t test_vld3_dup_s16(int16_t *a) { - return vld3_dup_s16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int32x2x3_t @test_vld3_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x2x3_t, %struct.int32x2x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int32x2x3_t [[TMP6]] -int32x2x3_t test_vld3_dup_s32(int32_t *a) { - return vld3_dup_s32(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.int64x1x3_t @test_vld3_dup_s64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int64x1x3_t, %struct.int64x1x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int64x1x3_t [[TMP6]] -int64x1x3_t test_vld3_dup_s64(int64_t *a) { - return vld3_dup_s64(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.float16x4x3_t @test_vld3_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3r.v4f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half> }* -// CHECK: store { <4 x half>, <4 x half>, <4 x half> } [[VLD3]], { <4 x half>, <4 x half>, <4 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x4x3_t, %struct.float16x4x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float16x4x3_t [[TMP6]] -float16x4x3_t test_vld3_dup_f16(float16_t *a) { - return vld3_dup_f16(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.float32x2x3_t @test_vld3_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld3r.v2f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }* -// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x2x3_t, %struct.float32x2x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float32x2x3_t [[TMP6]] -float32x2x3_t test_vld3_dup_f32(float32_t *a) { - return vld3_dup_f32(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8 @@ -1257,42 +503,6 @@ float64x1x3_t test_vld3_dup_f64(float64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld3_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 24, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly8x8x3_t [[TMP4]] -poly8x8x3_t test_vld3_dup_p8(poly8_t *a) { - return vld3_dup_p8(a); - // [{{x[0-9]+|sp}}] -} - -// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld3_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 24, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x3_t, %struct.poly16x4x3_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly16x4x3_t [[TMP6]] -poly16x4x3_t test_vld3_dup_p16(poly16_t *a) { - return vld3_dup_p16(a); - // [{{x[0-9]+|sp}}] -} - // CHECK-LABEL: define %struct.poly64x1x3_t @test_vld3_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8 @@ -1312,58 +522,6 @@ poly64x1x3_t test_vld3_dup_p64(poly64_t *a) { // [{{x[0-9]+|sp}}] } -// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld4q_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 64, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x16x4_t, %struct.uint8x16x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint8x16x4_t [[TMP4]] -uint8x16x4_t test_vld4q_dup_u8(uint8_t *a) { - return vld4q_dup_u8(a); -} - -// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld4q_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x8x4_t, %struct.uint16x8x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint16x8x4_t [[TMP6]] -uint16x8x4_t test_vld4q_dup_u16(uint16_t *a) { - return vld4q_dup_u16(a); -} - -// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld4q_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x4x4_t, %struct.uint32x4x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.uint32x4x4_t [[TMP6]] -uint32x4x4_t test_vld4q_dup_u32(uint32_t *a) { - return vld4q_dup_u32(a); -} - // CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_dup_u64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align 16 @@ -1382,58 +540,6 @@ uint64x2x4_t test_vld4q_dup_u64(uint64_t *a) { return vld4q_dup_u64(a); } -// CHECK-LABEL: define %struct.int8x16x4_t @test_vld4q_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 64, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x16x4_t, %struct.int8x16x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int8x16x4_t [[TMP4]] -int8x16x4_t test_vld4q_dup_s8(int8_t *a) { - return vld4q_dup_s8(a); -} - -// CHECK-LABEL: define %struct.int16x8x4_t @test_vld4q_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x8x4_t, %struct.int16x8x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int16x8x4_t [[TMP6]] -int16x8x4_t test_vld4q_dup_s16(int16_t *a) { - return vld4q_dup_s16(a); -} - -// CHECK-LABEL: define %struct.int32x4x4_t @test_vld4q_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* -// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x4x4_t, %struct.int32x4x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.int32x4x4_t [[TMP6]] -int32x4x4_t test_vld4q_dup_s32(int32_t *a) { - return vld4q_dup_s32(a); -} - // CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_dup_s64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align 16 @@ -1452,42 +558,6 @@ int64x2x4_t test_vld4q_dup_s64(int64_t *a) { return vld4q_dup_s64(a); } -// CHECK-LABEL: define %struct.float16x8x4_t @test_vld4q_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4r.v8f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* -// CHECK: store { <8 x half>, <8 x half>, <8 x half>, <8 x half> } [[VLD4]], { <8 x half>, <8 x half>, <8 x half>, <8 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x8x4_t, %struct.float16x8x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float16x8x4_t [[TMP6]] -float16x8x4_t test_vld4q_dup_f16(float16_t *a) { - return vld4q_dup_f16(a); -} - -// CHECK-LABEL: define %struct.float32x4x4_t @test_vld4q_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld4r.v4f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* -// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x4x4_t, %struct.float32x4x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.float32x4x4_t [[TMP6]] -float32x4x4_t test_vld4q_dup_f32(float32_t *a) { - return vld4q_dup_f32(a); -} - // CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16 @@ -1506,40 +576,6 @@ float64x2x4_t test_vld4q_dup_f64(float64_t *a) { return vld4q_dup_f64(a); } -// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld4q_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* -// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP2]], i8* align 16 [[TMP3]], i64 64, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x16x4_t, %struct.poly8x16x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly8x16x4_t [[TMP4]] -poly8x16x4_t test_vld4q_dup_p8(poly8_t *a) { - return vld4q_dup_p8(a); -} - -// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld4q_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* -// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP4]], i8* align 16 [[TMP5]], i64 64, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x8x4_t, %struct.poly16x8x4_t* [[RETVAL]], align 16 -// CHECK: ret %struct.poly16x8x4_t [[TMP6]] -poly16x8x4_t test_vld4q_dup_p16(poly16_t *a) { - return vld4q_dup_p16(a); -} - // CHECK-LABEL: define %struct.poly64x2x4_t @test_vld4q_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16 @@ -1558,182 +594,6 @@ poly64x2x4_t test_vld4q_dup_p64(poly64_t *a) { return vld4q_dup_p64(a); } -// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld4_dup_u8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint8x8x4_t [[TMP4]] -uint8x8x4_t test_vld4_dup_u8(uint8_t *a) { - return vld4_dup_u8(a); -} - -// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld4_dup_u16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint16x4x4_t, %struct.uint16x4x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint16x4x4_t [[TMP6]] -uint16x4x4_t test_vld4_dup_u16(uint16_t *a) { - return vld4_dup_u16(a); -} - -// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld4_dup_u32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint32x2x4_t, %struct.uint32x2x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint32x2x4_t [[TMP6]] -uint32x2x4_t test_vld4_dup_u32(uint32_t *a) { - return vld4_dup_u32(a); -} - -// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld4_dup_u64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.uint64x1x4_t, %struct.uint64x1x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.uint64x1x4_t [[TMP6]] -uint64x1x4_t test_vld4_dup_u64(uint64_t *a) { - return vld4_dup_u64(a); -} - -// CHECK-LABEL: define %struct.int8x8x4_t @test_vld4_dup_s8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.int8x8x4_t, %struct.int8x8x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int8x8x4_t [[TMP4]] -int8x8x4_t test_vld4_dup_s8(int8_t *a) { - return vld4_dup_s8(a); -} - -// CHECK-LABEL: define %struct.int16x4x4_t @test_vld4_dup_s16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int16x4x4_t, %struct.int16x4x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int16x4x4_t [[TMP6]] -int16x4x4_t test_vld4_dup_s16(int16_t *a) { - return vld4_dup_s16(a); -} - -// CHECK-LABEL: define %struct.int32x2x4_t @test_vld4_dup_s32(i32* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* -// CHECK: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* -// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int32x2x4_t, %struct.int32x2x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int32x2x4_t [[TMP6]] -int32x2x4_t test_vld4_dup_s32(int32_t *a) { - return vld4_dup_s32(a); -} - -// CHECK-LABEL: define %struct.int64x1x4_t @test_vld4_dup_s64(i64* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* -// CHECK: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* -// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.int64x1x4_t, %struct.int64x1x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.int64x1x4_t [[TMP6]] -int64x1x4_t test_vld4_dup_s64(int64_t *a) { - return vld4_dup_s64(a); -} - -// CHECK-LABEL: define %struct.float16x4x4_t @test_vld4_dup_f16(half* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* -// CHECK: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4r.v4f16.p0f16(half* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* -// CHECK: store { <4 x half>, <4 x half>, <4 x half>, <4 x half> } [[VLD4]], { <4 x half>, <4 x half>, <4 x half>, <4 x half> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float16x4x4_t, %struct.float16x4x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float16x4x4_t [[TMP6]] -float16x4x4_t test_vld4_dup_f16(float16_t *a) { - return vld4_dup_f16(a); -} - -// CHECK-LABEL: define %struct.float32x2x4_t @test_vld4_dup_f32(float* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* -// CHECK: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld4r.v2f32.p0f32(float* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* -// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.float32x2x4_t, %struct.float32x2x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.float32x2x4_t [[TMP6]] -float32x2x4_t test_vld4_dup_f32(float32_t *a) { - return vld4_dup_f32(a); -} - // CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_dup_f64(double* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8 @@ -1752,40 +612,6 @@ float64x1x4_t test_vld4_dup_f64(float64_t *a) { return vld4_dup_f64(a); } -// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld4_dup_p8(i8* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %a) -// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* -// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] -// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], i64 32, i1 false) -// CHECK: [[TMP4:%.*]] = load %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly8x8x4_t [[TMP4]] -poly8x8x4_t test_vld4_dup_p8(poly8_t *a) { - return vld4_dup_p8(a); -} - -// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld4_dup_p16(i16* %a) #0 { -// CHECK: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* -// CHECK: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) -// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* -// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] -// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[RETVAL]] to i8* -// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8* -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], i64 32, i1 false) -// CHECK: [[TMP6:%.*]] = load %struct.poly16x4x4_t, %struct.poly16x4x4_t* [[RETVAL]], align 8 -// CHECK: ret %struct.poly16x4x4_t [[TMP6]] -poly16x4x4_t test_vld4_dup_p16(poly16_t *a) { - return vld4_dup_p16(a); -} - // CHECK-LABEL: define %struct.poly64x1x4_t @test_vld4_dup_p64(i64* %a) #0 { // CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8 // CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8 diff --git a/test/CodeGen/arm-neon-vld.c b/test/CodeGen/arm-neon-vld.c index 0eba8ded5c..2bf55bb1c6 100644 --- a/test/CodeGen/arm-neon-vld.c +++ b/test/CodeGen/arm-neon-vld.c @@ -1409,3 +1409,1090 @@ uint8x16x3_t test_vld1q_u8_x3(uint8_t const *a) { uint8x16x4_t test_vld1q_u8_x4(uint8_t const *a) { return vld1q_u8_x4(a); } + +// CHECK-LABEL: @test_vld2_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x half>, <4 x half> } @llvm.aarch64.neon.ld2r.v4f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]> }* +// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD2]], { <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_f16(float16x4x2_t *dest, const float16_t *src) { + *dest = vld2_dup_f16(src); +} + +// CHECK-LABEL: @test_vld2_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.aarch64.neon.ld2r.v2f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <2 x float>, <2 x float> } @llvm.arm.neon.vld2dup.v2f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }* +// CHECK: store { <2 x float>, <2 x float> } [[VLD2]], { <2 x float>, <2 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_f32(float32x2x2_t *dest, const float32_t *src) { + *dest = vld2_dup_f32(src); +} + +// CHECK-LABEL: @test_vld2_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_p16(poly16x4x2_t *dest, const poly16_t *src) { + *dest = vld2_dup_p16(src); +} + +// CHECK-LABEL: @test_vld2_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_p8(poly8x8x2_t *dest, poly8_t *src) { + *dest = vld2_dup_p8(src); +} + +// CHECK-LABEL: @test_vld2_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_s16(int16x4x2_t *dest, const int16_t *src) { + *dest = vld2_dup_s16(src); +} + +// CHECK-LABEL: @test_vld2_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_s32(int32x2x2_t *dest, const int32_t *src) { + *dest = vld2_dup_s32(src); +} + +// CHECK-LABEL: @test_vld2_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_s8(int8x8x2_t *dest, int8_t *src) { + *dest = vld2_dup_s8(src); +} + +// CHECK-LABEL: @test_vld2_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld2r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2]], { <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_u16(uint16x4x2_t *dest, const uint16_t *src) { + *dest = vld2_dup_u16(src); +} + +// CHECK-LABEL: @test_vld2_dup_u32( +// CHECK: entry: +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld2r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2]], { <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_u32(uint32x2x2_t *dest, const uint32_t *src) { + *dest = vld2_dup_u32(src); +} + +// CHECK-LABEL: @test_vld2_dup_s64( +// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_s64(int64x1x2_t *dest, const int64_t *src) { + *dest = vld2_dup_s64(src); +} + +// CHECK-LABEL: @test_vld2_dup_u64( +// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld2r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2]], { <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_u64(uint64x1x2_t *dest, const uint64_t *src) { + *dest = vld2_dup_u64(src); +} + +// CHECK-LABEL: @test_vld2_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2]], { <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 16, i1 false) +// CHECK: ret void +void test_vld2_dup_u8(uint8x8x2_t *dest, const uint8_t *src) { + *dest = vld2_dup_u8(src); +} + +// CHECK-LABEL: @test_vld3_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld3r.v4f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* +// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD3]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_f16(float16x4x3_t *dest, float16_t *src) { + *dest = vld3_dup_f16(src); +} + +// CHECK-LABEL: @test_vld3_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld3r.v2f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld3dup.v2f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }* +// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_f32(float32x2x3_t *dest, const float32_t *src) { + *dest = vld3_dup_f32(src); +} + +// CHECK-LABEL: @test_vld3_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_p16(poly16x4x3_t *dest, const poly16_t *src) { + *dest = vld3_dup_p16(src); +} + +// CHECK-LABEL: @test_vld3_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_p8(poly8x8x3_t *dest, const poly8_t *src) { + *dest = vld3_dup_p8(src); +} + +// CHECK-LABEL: @test_vld3_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_s16(int16x4x3_t *dest, const int16_t *src) { + *dest = vld3_dup_s16(src); +} + +// CHECK-LABEL: @test_vld3_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_s32(int32x2x3_t *dest, const int32_t *src) { + *dest = vld3_dup_s32(src); +} + +// CHECK-LABEL: @test_vld3_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_s8(int8x8x3_t *dest, const int8_t *src) { + *dest = vld3_dup_s8(src); +} + +// CHECK-LABEL: @test_vld3_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld3r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_u16(uint16x4x3_t *dest, const uint16_t *src) { + *dest = vld3_dup_u16(src); +} + +// CHECK-LABEL: @test_vld3_dup_u32( +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld3r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_u32(uint32x2x3_t *dest, const uint32_t *src) { + *dest = vld3_dup_u32(src); +} + +// CHECK-LABEL: @test_vld3_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld3r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_u8(uint8x8x3_t *dest, const uint8_t *src) { + *dest = vld3_dup_u8(src); +} + +// CHECK-LABEL: @test_vld3_dup_s64( +// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_s64(int64x1x3_t *dest, const int64_t *src) { + *dest = vld3_dup_s64(src); +} + +// CHECK-LABEL: @test_vld3_dup_u64( +// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld3r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD3]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 24, i1 false) +// CHECK: ret void +void test_vld3_dup_u64(uint64x1x3_t *dest, const uint64_t *src) { + *dest = vld3_dup_u64(src); +} + +// CHECK-LABEL: @test_vld4_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x half>, <4 x half>, <4 x half>, <4 x half> } @llvm.aarch64.neon.ld4r.v4f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* +// CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD4]], { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_f16(float16x4x4_t *dest, const float16_t *src) { + *dest = vld4_dup_f16(src); +} + +// CHECK-LABEL: @test_vld4_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.aarch64.neon.ld4r.v2f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld4dup.v2f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* +// CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD4]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_f32(float32x2x4_t *dest, const float32_t *src) { + *dest = vld4_dup_f32(src); +} + +// CHECK-LABEL: @test_vld4_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_p16(poly16x4x4_t *dest, const poly16_t *src) { + *dest = vld4_dup_p16(src); +} + +// CHECK-LABEL: @test_vld4_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_p8(poly8x8x4_t *dest, const poly8_t *src) { + *dest = vld4_dup_p8(src); +} + +// CHECK-LABEL: @test_vld4_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_s16(int16x4x4_t *dest, const int16_t *src) { + *dest = vld4_dup_s16(src); +} + +// CHECK-LABEL: @test_vld4_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_s32(int32x2x4_t *dest, const int32_t *src) { + *dest = vld4_dup_s32(src); +} + +// CHECK-LABEL: @test_vld4_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_s8(int8x8x4_t *dest, const int8_t *src) { + *dest = vld4_dup_s8(src); +} + +// CHECK-LABEL: @test_vld4_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4r.v4i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4dup.v4i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* +// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD4]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_u16(uint16x4x4_t *dest, const uint16_t *src) { + *dest = vld4_dup_u16(src); +} + +// CHECK-LABEL: @test_vld4_dup_u32( +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.aarch64.neon.ld4r.v2i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4dup.v2i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* +// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD4]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_u32(uint32x2x4_t *dest, const uint32_t *src) { + *dest = vld4_dup_u32(src); +} + +// CHECK-LABEL: @test_vld4_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld4r.v8i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4dup.v8i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* +// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD4]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP2]], i8* align 8 [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_u8(uint8x8x4_t *dest, const uint8_t *src) { + *dest = vld4_dup_u8(src); +} + +// CHECK-LABEL: @test_vld4_dup_s64( +// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_s64(int64x1x4_t *dest, const int64_t *src) { + *dest = vld4_dup_s64(src); +} + +// CHECK-LABEL: @test_vld4_dup_u64( +// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8 +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i64* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i64* +// CHECK-A64: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.aarch64.neon.ld4r.v1i64.p0i64(i64* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4dup.v1i64.p0i8(i8* [[TMP1]], i32 8) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* +// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD4]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align 8 [[TMP4]], i8* align 8 [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld4_dup_u64(uint64x1x4_t *dest, const uint64_t *src) { + *dest = vld4_dup_u64(src); +} + +// CHECK-LABEL: @test_vld2q_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x half>, <8 x half> } @llvm.aarch64.neon.ld2r.v8f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]> }* +// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD2]], { <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_f16(float16x8x2_t *dest, const float16_t *src) { + *dest = vld2q_dup_f16(src); +} + +// CHECK-LABEL: @test_vld2q_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.aarch64.neon.ld2r.v4f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x float>, <4 x float> } @llvm.arm.neon.vld2dup.v4f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }* +// CHECK: store { <4 x float>, <4 x float> } [[VLD2]], { <4 x float>, <4 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_f32(float32x4x2_t *dest, const float32_t *src) { + *dest = vld2q_dup_f32(src); +} + +// CHECK-LABEL: @test_vld2q_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_p16(poly16x8x2_t *dest, const poly16_t *src) { + *dest = vld2q_dup_p16(src); +} + +// CHECK-LABEL: @test_vld2q_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_p8(poly8x16x2_t *dest, const poly8_t *src) { + *dest = vld2q_dup_p8(src); +} + +// CHECK-LABEL: @test_vld2q_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_s16(int16x8x2_t *dest, const int16_t *src) { + *dest = vld2q_dup_s16(src); +} + +// CHECK-LABEL: @test_vld2q_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_s32(int32x4x2_t *dest, const int32_t *src) { + *dest = vld2q_dup_s32(src); +} + +// CHECK-LABEL: @test_vld2q_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_s8(int8x16x2_t *dest, const int8_t *src) { + *dest = vld2q_dup_s8(src); +} + +// CHECK-LABEL: @test_vld2q_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld2r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2]], { <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_u16(uint16x8x2_t *dest, const uint16_t *src) { + *dest = vld2q_dup_u16(src); +} + +// CHECK-LABEL: @test_vld2q_dup_u32( +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2]], { <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_u32(uint32x4x2_t *dest, const uint32_t *src) { + *dest = vld2q_dup_u32(src); +} + +// CHECK-LABEL: @test_vld2q_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8* +// CHECK-A64: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld2r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD2:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2]], { <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 32, i1 false) +// CHECK: ret void +void test_vld2q_dup_u8(uint8x16x2_t *dest, const uint8_t *src) { + *dest = vld2q_dup_u8(src); +} + +// CHECK-LABEL: @test_vld3q_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld3r.v8f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* +// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD3]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_f16(float16x8x3_t *dest, const float16_t *src) { + *dest = vld3q_dup_f16(src); +} + +// CHECK-LABEL: @test_vld3q_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld3r.v4f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3dup.v4f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }* +// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_f32(float32x4x3_t *dest, const float32_t *src) { + *dest = vld3q_dup_f32(src); +} + +// CHECK-LABEL: @test_vld3q_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_p16(poly16x8x3_t *dest, const poly16_t *src) { + *dest = vld3q_dup_p16(src); +} + +// CHECK-LABEL: @test_vld3q_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_p8(poly8x16x3_t *dest, const poly8_t *src) { + *dest = vld3q_dup_p8(src); +} + +// CHECK-LABEL: @test_vld3q_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_s16(int16x8x3_t *dest, const int16_t *src) { + *dest = vld3q_dup_s16(src); +} + +// CHECK-LABEL: @test_vld3q_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_s32(int32x4x3_t *dest, const int32_t *src) { + *dest = vld3q_dup_s32(src); +} + +// CHECK-LABEL: @test_vld3q_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_s8(int8x16x3_t *dest, const int8_t *src) { + *dest = vld3q_dup_s8(src); +} + +// CHECK-LABEL: @test_vld3q_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld3r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_u16(uint16x8x3_t *dest, const uint16_t *src) { + *dest = vld3q_dup_u16(src); +} + +// CHECK-LABEL: @test_vld3q_dup_u32( +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD3:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_u32(uint32x4x3_t *dest, const uint32_t *src) { + *dest = vld3q_dup_u32(src); +} + +// CHECK-LABEL: @test_vld3q_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8* +// CHECK-A64: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld3r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD3:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD3]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 48, i1 false) +// CHECK: ret void +void test_vld3q_dup_u8(uint8x16x3_t *dest, const uint8_t *src) { + *dest = vld3q_dup_u8(src); +} + +// CHECK-LABEL: @test_vld4q_dup_f16( +// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast half* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to half* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x half>, <8 x half>, <8 x half>, <8 x half> } @llvm.aarch64.neon.ld4r.v8f16.p0f16(half* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* +// CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD4]], { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_f16(float16x8x4_t *dest, const float16_t *src) { + *dest = vld4q_dup_f16(src); +} + +// CHECK-LABEL: @test_vld4q_dup_f32( +// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast float* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to float* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.aarch64.neon.ld4r.v4f32.p0f32(float* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld4dup.v4f32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* +// CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD4]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_f32(float32x4x4_t *dest, const float32_t *src) { + *dest = vld4q_dup_f32(src); +} + +// CHECK-LABEL: @test_vld4q_dup_p16( +// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_p16(poly16x8x4_t *dest, const poly16_t *src) { + *dest = vld4q_dup_p16(src); +} + +// CHECK-LABEL: @test_vld4q_dup_p8( +// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_p8(poly8x16x4_t *dest, const poly8_t *src) { + *dest = vld4q_dup_p8(src); +} + +// CHECK-LABEL: @test_vld4q_dup_s16( +// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_s16(int16x8x4_t *dest, const int16_t *src) { + *dest = vld4q_dup_s16(src); +} + +// CHECK-LABEL: @test_vld4q_dup_s32( +// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_s32(int32x4x4_t *dest, const int32_t *src) { + *dest = vld4q_dup_s32(src); +} + +// CHECK-LABEL: @test_vld4q_dup_s8( +// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_s8(int8x16x4_t *dest, const int8_t *src) { + *dest = vld4q_dup_s8(src); +} + +// CHECK-LABEL: @test_vld4q_dup_u16( +// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i16* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i16* +// CHECK-A64: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.aarch64.neon.ld4r.v8i16.p0i16(i16* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4dup.v8i16.p0i8(i8* [[TMP1]], i32 2) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* +// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD4]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_u16(uint16x8x4_t *dest, const uint16_t *src) { + *dest = vld4q_dup_u16(src); +} + +// CHECK-LABEL: @test_vld4q_dup_u32( +// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* +// CHECK: [[TMP1:%.*]] = bitcast i32* %src to i8* +// CHECK-A64: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +// CHECK-A64: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4r.v4i32.p0i32(i32* [[TMP2]]) +// CHECK-A32: [[VLD4:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4dup.v4i32.p0i8(i8* [[TMP1]], i32 4) +// CHECK: [[TMP3:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* +// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD4]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP3]] +// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* %dest to i8* +// CHECK: [[TMP5:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP4]], i8* align {{16|8}} [[TMP5]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_u32(uint32x4x4_t *dest, const uint32_t *src) { + *dest = vld4q_dup_u32(src); +} + +// CHECK-LABEL: @test_vld4q_dup_u8( +// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align {{16|8}} +// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8* +// CHECK-A64: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.aarch64.neon.ld4r.v16i8.p0i8(i8* %src) +// CHECK-A32: [[VLD4:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4dup.v16i8.p0i8(i8* %src, i32 1) +// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* +// CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD4]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]] +// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* %dest to i8* +// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}(i8* align {{16|8}} [[TMP2]], i8* align {{16|8}} [[TMP3]], {{i64|i32}} 64, i1 false) +// CHECK: ret void +void test_vld4q_dup_u8(uint8x16x4_t *dest, const uint8_t *src) { + *dest = vld4q_dup_u8(src); +} diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c index 95ac3dca7a..f6305062e8 100644 --- a/test/CodeGen/arm_neon_intrinsics.c +++ b/test/CodeGen/arm_neon_intrinsics.c @@ -4732,111 +4732,6 @@ poly16x4x2_t test_vld2_p16(poly16_t const * a) { return vld2_p16(a); } -// CHECK-LABEL: @test_vld2_dup_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8> -uint8x8x2_t test_vld2_dup_u8(uint8_t const * a) { - return vld2_dup_u8(a); -} - -// CHECK-LABEL: @test_vld2_dup_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16> -uint16x4x2_t test_vld2_dup_u16(uint16_t const * a) { - return vld2_dup_u16(a); -} - -// CHECK-LABEL: @test_vld2_dup_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32> -uint32x2x2_t test_vld2_dup_u32(uint32_t const * a) { - return vld2_dup_u32(a); -} - -// CHECK-LABEL: @test_vld2_dup_u64( -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64> -uint64x1x2_t test_vld2_dup_u64(uint64_t const * a) { - return vld2_dup_u64(a); -} - -// CHECK-LABEL: @test_vld2_dup_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8> -int8x8x2_t test_vld2_dup_s8(int8_t const * a) { - return vld2_dup_s8(a); -} - -// CHECK-LABEL: @test_vld2_dup_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16> -int16x4x2_t test_vld2_dup_s16(int16_t const * a) { - return vld2_dup_s16(a); -} - -// CHECK-LABEL: @test_vld2_dup_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32> -int32x2x2_t test_vld2_dup_s32(int32_t const * a) { - return vld2_dup_s32(a); -} - -// CHECK-LABEL: @test_vld2_dup_s64( -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64> -int64x1x2_t test_vld2_dup_s64(int64_t const * a) { - return vld2_dup_s64(a); -} - -// CHECK-LABEL: @test_vld2_dup_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16> -float16x4x2_t test_vld2_dup_f16(float16_t const * a) { - return vld2_dup_f16(a); -} - -// CHECK-LABEL: @test_vld2_dup_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float> -float32x2x2_t test_vld2_dup_f32(float32_t const * a) { - return vld2_dup_f32(a); -} - -// CHECK-LABEL: @test_vld2_dup_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8> -poly8x8x2_t test_vld2_dup_p8(poly8_t const * a) { - return vld2_dup_p8(a); -} - -// CHECK-LABEL: @test_vld2_dup_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16> -poly16x4x2_t test_vld2_dup_p16(poly16_t const * a) { - return vld2_dup_p16(a); -} - // CHECK-LABEL: @test_vld2q_lane_u16( // CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16 @@ -5473,111 +5368,6 @@ poly16x4x3_t test_vld3_p16(poly16_t const * a) { return vld3_p16(a); } -// CHECK-LABEL: @test_vld3_dup_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> -uint8x8x3_t test_vld3_dup_u8(uint8_t const * a) { - return vld3_dup_u8(a); -} - -// CHECK-LABEL: @test_vld3_dup_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> -uint16x4x3_t test_vld3_dup_u16(uint16_t const * a) { - return vld3_dup_u16(a); -} - -// CHECK-LABEL: @test_vld3_dup_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> -uint32x2x3_t test_vld3_dup_u32(uint32_t const * a) { - return vld3_dup_u32(a); -} - -// CHECK-LABEL: @test_vld3_dup_u64( -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> -uint64x1x3_t test_vld3_dup_u64(uint64_t const * a) { - return vld3_dup_u64(a); -} - -// CHECK-LABEL: @test_vld3_dup_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> -int8x8x3_t test_vld3_dup_s8(int8_t const * a) { - return vld3_dup_s8(a); -} - -// CHECK-LABEL: @test_vld3_dup_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> -int16x4x3_t test_vld3_dup_s16(int16_t const * a) { - return vld3_dup_s16(a); -} - -// CHECK-LABEL: @test_vld3_dup_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> -int32x2x3_t test_vld3_dup_s32(int32_t const * a) { - return vld3_dup_s32(a); -} - -// CHECK-LABEL: @test_vld3_dup_s64( -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> -int64x1x3_t test_vld3_dup_s64(int64_t const * a) { - return vld3_dup_s64(a); -} - -// CHECK-LABEL: @test_vld3_dup_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> -float16x4x3_t test_vld3_dup_f16(float16_t const * a) { - return vld3_dup_f16(a); -} - -// CHECK-LABEL: @test_vld3_dup_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float>, <2 x float> -float32x2x3_t test_vld3_dup_f32(float32_t const * a) { - return vld3_dup_f32(a); -} - -// CHECK-LABEL: @test_vld3_dup_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> -poly8x8x3_t test_vld3_dup_p8(poly8_t const * a) { - return vld3_dup_p8(a); -} - -// CHECK-LABEL: @test_vld3_dup_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> -poly16x4x3_t test_vld3_dup_p16(poly16_t const * a) { - return vld3_dup_p16(a); -} - // CHECK-LABEL: @test_vld3q_lane_u16( // CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16 @@ -6293,111 +6083,6 @@ poly16x4x4_t test_vld4_p16(poly16_t const * a) { return vld4_p16(a); } -// CHECK-LABEL: @test_vld4_dup_u8( -// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> -uint8x8x4_t test_vld4_dup_u8(uint8_t const * a) { - return vld4_dup_u8(a); -} - -// CHECK-LABEL: @test_vld4_dup_u16( -// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> -uint16x4x4_t test_vld4_dup_u16(uint16_t const * a) { - return vld4_dup_u16(a); -} - -// CHECK-LABEL: @test_vld4_dup_u32( -// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> -uint32x2x4_t test_vld4_dup_u32(uint32_t const * a) { - return vld4_dup_u32(a); -} - -// CHECK-LABEL: @test_vld4_dup_u64( -// CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> -uint64x1x4_t test_vld4_dup_u64(uint64_t const * a) { - return vld4_dup_u64(a); -} - -// CHECK-LABEL: @test_vld4_dup_s8( -// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> -int8x8x4_t test_vld4_dup_s8(int8_t const * a) { - return vld4_dup_s8(a); -} - -// CHECK-LABEL: @test_vld4_dup_s16( -// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> -int16x4x4_t test_vld4_dup_s16(int16_t const * a) { - return vld4_dup_s16(a); -} - -// CHECK-LABEL: @test_vld4_dup_s32( -// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i32* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> -int32x2x4_t test_vld4_dup_s32(int32_t const * a) { - return vld4_dup_s32(a); -} - -// CHECK-LABEL: @test_vld4_dup_s64( -// CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i64* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> -int64x1x4_t test_vld4_dup_s64(int64_t const * a) { - return vld4_dup_s64(a); -} - -// CHECK-LABEL: @test_vld4_dup_f16( -// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast half* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> -float16x4x4_t test_vld4_dup_f16(float16_t const * a) { - return vld4_dup_f16(a); -} - -// CHECK-LABEL: @test_vld4_dup_f32( -// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast float* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> -float32x2x4_t test_vld4_dup_f32(float32_t const * a) { - return vld4_dup_f32(a); -} - -// CHECK-LABEL: @test_vld4_dup_p8( -// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> -poly8x8x4_t test_vld4_dup_p8(poly8_t const * a) { - return vld4_dup_p8(a); -} - -// CHECK-LABEL: @test_vld4_dup_p16( -// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK: [[TMP0:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8* -// CHECK: [[TMP1:%.*]] = bitcast i16* %a to i8* -// CHECK: [[VLD_DUP:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> -poly16x4x4_t test_vld4_dup_p16(poly16_t const * a) { - return vld4_dup_p16(a); -} - // CHECK-LABEL: @test_vld4q_lane_u16( // CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16 // CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16 diff --git a/test/CodeGen/vld_dup.c b/test/CodeGen/vld_dup.c index d910c82966..e69de29bb2 100644 --- a/test/CodeGen/vld_dup.c +++ b/test/CodeGen/vld_dup.c @@ -1,50 +0,0 @@ -// REQUIRES: arm-registered-target -// RUN: %clang_cc1 -triple armv7a-linux-gnueabi \ -// RUN: -target-cpu cortex-a8 \ -// RUN: -emit-llvm -o - %s | FileCheck %s -#include -int main(){ - int32_t v0[3]; - int32x2x3_t v1; - int32_t v2[4]; - int32x2x4_t v3; - int64x1x3_t v4; - int64x1x4_t v5; - int64_t v6[3]; - int64_t v7[4]; - - v1 = vld3_dup_s32(v0); -// CHECK: [[T168:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* {{.*}}, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 {{[0-9]+}}, i32 {{[0-9]+}}) -// CHECK-NEXT: [[T169:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T168]], 0 -// CHECK-NEXT: [[T170:%.*]] = shufflevector <2 x i32> [[T169]], <2 x i32> [[T169]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T171:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T168]], <2 x i32> [[T170]], 0 -// CHECK-NEXT: [[T172:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T171]], 1 -// CHECK-NEXT: [[T173:%.*]] = shufflevector <2 x i32> [[T172]], <2 x i32> [[T172]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T174:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T171]], <2 x i32> [[T173]], 1 -// CHECK-NEXT: [[T175:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T174]], 2 -// CHECK-NEXT: [[T176:%.*]] = shufflevector <2 x i32> [[T175]], <2 x i32> [[T175]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T177:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[T174]], <2 x i32> [[T176]], 2 - - v3 = vld4_dup_s32(v2); -// CHECK: [[T178:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* {{.*}}, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 {{[0-9]+}}, i32 {{[0-9]+}}) -// CHECK-NEXT: [[T179:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T178]], 0 -// CHECK-NEXT: [[T180:%.*]] = shufflevector <2 x i32> [[T179]], <2 x i32> [[T179]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T181:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T178]], <2 x i32> [[T180]], 0 -// CHECK-NEXT: [[T182:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T181]], 1 -// CHECK-NEXT: [[T183:%.*]] = shufflevector <2 x i32> [[T182]], <2 x i32> [[T182]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T184:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T181]], <2 x i32> [[T183]], 1 -// CHECK-NEXT: [[T185:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T184]], 2 -// CHECK-NEXT: [[T186:%.*]] = shufflevector <2 x i32> [[T185]], <2 x i32> [[T185]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T187:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T184]], <2 x i32> [[T186]], 2 -// CHECK-NEXT: [[T188:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T187]], 3 -// CHECK-NEXT: [[T189:%.*]] = shufflevector <2 x i32> [[T188]], <2 x i32> [[T188]], <2 x i32> zeroinitializer -// CHECK-NEXT: [[T190:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[T187]], <2 x i32> [[T189]], 3 - - v4 = vld3_dup_s64(v6); -// CHECK: {{%.*}} = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* {{.*}}, i32 {{[0-9]+}}) - - v5 = vld4_dup_s64(v7); -// CHECK: {{%.*}} = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* {{.*}}, i32 {{[0-9]+}}) - - return 0; -} -- GitLab From c5df29be09959e98bdc85bcdc325a07f9d78199a Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 27 Jun 2018 14:39:41 +0000 Subject: [PATCH 0306/1023] [analyzer] Fix string not being formatted with extra arguments Signed-off-by: Mikhail Ramalho git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335739 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/analyzer/SATestBuild.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index b76df748d0..3137b48a78 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -280,7 +280,8 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): } SBOptions += "-analyzer-config '%s' " % ( - ",".join("%s=%s" for key, value in AnalyzerConfig.iteritems())) + ",".join("%s=%s" % (key, value) for key, value in AnalyzerConfig.iteritems())) + # Always use ccc-analyze to ensure that we can locate the failures # directory. SBOptions += "--override-compiler " -- GitLab From cac78d347177e10966daa3aaf2f63049138ce88f Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Wed, 27 Jun 2018 14:56:12 +0000 Subject: [PATCH 0307/1023] [analyzer] Allow registering custom statically-linked analyzer checkers Summary: Add an extension point to allow registration of statically-linked Clang Static Analyzer checkers that are not a part of the Clang tree. This extension point employs the mechanism used when checkers are registered from dynamically loaded plugins. Reviewers: george.karpenkov, NoQ, xazax.hun, dcoughlin Reviewed By: george.karpenkov Subscribers: mgorny, mikhail.ramalho, rnkovacs, xazax.hun, szepet, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D45718 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335740 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Frontend/AnalysisConsumer.h | 15 ++++ .../Frontend/CheckerRegistration.h | 10 ++- .../Frontend/AnalysisConsumer.cpp | 11 ++- .../Frontend/CheckerRegistration.cpp | 13 ++- .../StaticAnalyzer/AnalyzerOptionsTest.cpp | 2 +- unittests/StaticAnalyzer/CMakeLists.txt | 5 +- .../RegisterCustomCheckersTest.cpp | 80 +++++++++++++++++++ 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h index a9dad6c5e9..59fbbc3ca8 100644 --- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/Basic/LLVM.h" +#include #include namespace clang { @@ -29,10 +30,24 @@ class CompilerInstance; namespace ento { class PathDiagnosticConsumer; class CheckerManager; +class CheckerRegistry; class AnalysisASTConsumer : public ASTConsumer { public: virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0; + + /// This method allows registering statically linked custom checkers that are + /// not a part of the Clang tree. It employs the same mechanism that is used + /// by plugins. + /// + /// Example: + /// + /// Consumer->AddCheckerRegistrationFn([] (CheckerRegistry& Registry) { + /// Registry.addChecker("example.MyCustomChecker", + /// "Description"); + /// }); + virtual void + AddCheckerRegistrationFn(std::function Fn) = 0; }; /// CreateAnalysisConsumer - Creates an ASTConsumer to run various code diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 2985b7c117..216a2359ef 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H #include "clang/Basic/LLVM.h" +#include #include #include @@ -21,10 +22,13 @@ namespace clang { namespace ento { class CheckerManager; + class CheckerRegistry; - std::unique_ptr - createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts, - ArrayRef plugins, DiagnosticsEngine &diags); + std::unique_ptr createCheckerManager( + AnalyzerOptions &opts, const LangOptions &langOpts, + ArrayRef plugins, + ArrayRef> checkerRegistrationFns, + DiagnosticsEngine &diags); } // end ento namespace diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 81f6943686..44abde5da6 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -164,6 +164,8 @@ class AnalysisConsumer : public AnalysisASTConsumer, /// Bug Reporter to use while recursively visiting Decls. BugReporter *RecVisitorBR; + std::vector> CheckerRegistrationFns; + public: ASTContext *Ctx; const Preprocessor &PP; @@ -293,8 +295,9 @@ public: void Initialize(ASTContext &Context) override { Ctx = &Context; - checkerMgr = createCheckerManager(*Opts, PP.getLangOpts(), Plugins, - PP.getDiagnostics()); + checkerMgr = + createCheckerManager(*Opts, PP.getLangOpts(), Plugins, + CheckerRegistrationFns, PP.getDiagnostics()); Mgr = llvm::make_unique( *Ctx, PP.getDiagnostics(), PP.getLangOpts(), PathConsumers, @@ -385,6 +388,10 @@ public: PathConsumers.push_back(Consumer); } + void AddCheckerRegistrationFn(std::function Fn) override { + CheckerRegistrationFns.push_back(std::move(Fn)); + } + private: void storeTopLevelDecls(DeclGroupRef DG); std::string getFunctionName(const Decl *D); diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 6792f89876..a260c2d85b 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -111,16 +111,21 @@ getCheckerOptList(const AnalyzerOptions &opts) { return checkerOpts; } -std::unique_ptr -ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts, - ArrayRef plugins, - DiagnosticsEngine &diags) { +std::unique_ptr ento::createCheckerManager( + AnalyzerOptions &opts, const LangOptions &langOpts, + ArrayRef plugins, + ArrayRef> checkerRegistrationFns, + DiagnosticsEngine &diags) { std::unique_ptr checkerMgr( new CheckerManager(langOpts, opts)); SmallVector checkerOpts = getCheckerOptList(opts); ClangCheckerRegistry allCheckers(plugins, &diags); + + for (const auto &Fn : checkerRegistrationFns) + Fn(allCheckers); + allCheckers.initializeManager(*checkerMgr, checkerOpts); allCheckers.validateCheckerOptions(opts, diags); checkerMgr->finishedCheckerRegistration(); diff --git a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp index cd2289d4f2..3d8332554f 100644 --- a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp +++ b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp @@ -1,4 +1,4 @@ -//===- unittest/Analysis/AnalyzerOptionsTest.cpp - SA Options test --------===// +//===- unittest/StaticAnalyzer/AnalyzerOptionsTest.cpp - SA Options test --===// // // The LLVM Compiler Infrastructure // diff --git a/unittests/StaticAnalyzer/CMakeLists.txt b/unittests/StaticAnalyzer/CMakeLists.txt index 4ca0be50e5..117a5d9ae4 100644 --- a/unittests/StaticAnalyzer/CMakeLists.txt +++ b/unittests/StaticAnalyzer/CMakeLists.txt @@ -4,11 +4,14 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(StaticAnalysisTests AnalyzerOptionsTest.cpp + RegisterCustomCheckersTest.cpp ) target_link_libraries(StaticAnalysisTests PRIVATE clangBasic clangAnalysis - clangStaticAnalyzerCore + clangStaticAnalyzerCore + clangStaticAnalyzerFrontend + clangTooling ) diff --git a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp new file mode 100644 index 0000000000..82887a1daf --- /dev/null +++ b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp @@ -0,0 +1,80 @@ +//===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/CompilerInstance.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" +#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +namespace clang { +namespace ento { +namespace { + +class CustomChecker : public Checker { +public: + void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, + BugReporter &BR) const { + BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError, + "Custom diagnostic description", + PathDiagnosticLocation(D, Mgr.getSourceManager()), {}); + } +}; + +class TestAction : public ASTFrontendAction { + class DiagConsumer : public PathDiagnosticConsumer { + llvm::raw_ostream &Output; + + public: + DiagConsumer(llvm::raw_ostream &Output) : Output(Output) {} + void FlushDiagnosticsImpl(std::vector &Diags, + FilesMade *filesMade) override { + for (const auto *PD : Diags) + Output << PD->getCheckName() << ":" << PD->getShortDescription(); + } + + StringRef getName() const override { return "Test"; } + }; + + llvm::raw_ostream &DiagsOutput; + +public: + TestAction(llvm::raw_ostream &DiagsOutput) : DiagsOutput(DiagsOutput) {} + + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef File) override { + std::unique_ptr AnalysisConsumer = + CreateAnalysisConsumer(Compiler); + AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput)); + Compiler.getAnalyzerOpts()->CheckersControlList = { + {"custom.CustomChecker", true}}; + AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { + Registry.addChecker("custom.CustomChecker", "Description"); + }); + return AnalysisConsumer; + } +}; + + +TEST(RegisterCustomCheckers, RegisterChecker) { + std::string Diags; + { + llvm::raw_string_ostream OS(Diags); + EXPECT_TRUE(tooling::runToolOnCode(new TestAction(OS), "void f() {;}")); + } + EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description"); +} + +} +} +} -- GitLab From 8631eadc2482657ee16b6f82703ba6e605deeb8f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Jun 2018 15:57:57 +0000 Subject: [PATCH 0308/1023] [X86] Rename llvm.x86.avx512.mask.fpclass.p* to exclude 'mask.' from the name to match llvm. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335745 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 12 ++++++------ test/CodeGen/avx512dq-builtins.c | 8 ++++---- test/CodeGen/avx512vldq-builtins.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 309528404f..14bf0a78ad 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10087,22 +10087,22 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: llvm_unreachable("Unsupported intrinsic!"); case X86::BI__builtin_ia32_fpclassps128_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_ps_128; + ID = Intrinsic::x86_avx512_fpclass_ps_128; break; case X86::BI__builtin_ia32_fpclassps256_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_ps_256; + ID = Intrinsic::x86_avx512_fpclass_ps_256; break; case X86::BI__builtin_ia32_fpclassps512_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_ps_512; + ID = Intrinsic::x86_avx512_fpclass_ps_512; break; case X86::BI__builtin_ia32_fpclasspd128_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_pd_128; + ID = Intrinsic::x86_avx512_fpclass_pd_128; break; case X86::BI__builtin_ia32_fpclasspd256_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_pd_256; + ID = Intrinsic::x86_avx512_fpclass_pd_256; break; case X86::BI__builtin_ia32_fpclasspd512_mask: - ID = Intrinsic::x86_avx512_mask_fpclass_pd_512; + ID = Intrinsic::x86_avx512_fpclass_pd_512; break; } diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c index f5c4b2633b..242b9d3995 100644 --- a/test/CodeGen/avx512dq-builtins.c +++ b/test/CodeGen/avx512dq-builtins.c @@ -1234,25 +1234,25 @@ __m512i test_mm512_maskz_inserti64x2(__mmask8 __U, __m512i __A, __m128i __B) { } __mmask8 test_mm512_mask_fpclass_pd_mask(__mmask8 __U, __m512d __A) { // CHECK-LABEL: @test_mm512_mask_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.512 + // CHECK: @llvm.x86.avx512.fpclass.pd.512 return _mm512_mask_fpclass_pd_mask(__U, __A, 4); } __mmask8 test_mm512_fpclass_pd_mask(__m512d __A) { // CHECK-LABEL: @test_mm512_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.512 + // CHECK: @llvm.x86.avx512.fpclass.pd.512 return _mm512_fpclass_pd_mask(__A, 4); } __mmask16 test_mm512_mask_fpclass_ps_mask(__mmask16 __U, __m512 __A) { // CHECK-LABEL: @test_mm512_mask_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.512 + // CHECK: @llvm.x86.avx512.fpclass.ps.512 return _mm512_mask_fpclass_ps_mask(__U, __A, 4); } __mmask16 test_mm512_fpclass_ps_mask(__m512 __A) { // CHECK-LABEL: @test_mm512_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.512 + // CHECK: @llvm.x86.avx512.fpclass.ps.512 return _mm512_fpclass_ps_mask(__A, 4); } diff --git a/test/CodeGen/avx512vldq-builtins.c b/test/CodeGen/avx512vldq-builtins.c index 31ae623fee..b21b665eb9 100644 --- a/test/CodeGen/avx512vldq-builtins.c +++ b/test/CodeGen/avx512vldq-builtins.c @@ -1104,48 +1104,48 @@ __m256i test_mm256_maskz_inserti64x2(__mmask8 __U, __m256i __A, __m128i __B) { __mmask8 test_mm_mask_fpclass_pd_mask(__mmask8 __U, __m128d __A) { // CHECK-LABEL: @test_mm_mask_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.128 + // CHECK: @llvm.x86.avx512.fpclass.pd.128 return _mm_mask_fpclass_pd_mask(__U, __A, 2); } __mmask8 test_mm_fpclass_pd_mask(__m128d __A) { // CHECK-LABEL: @test_mm_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.128 + // CHECK: @llvm.x86.avx512.fpclass.pd.128 return _mm_fpclass_pd_mask(__A, 2); } __mmask8 test_mm256_mask_fpclass_pd_mask(__mmask8 __U, __m256d __A) { // CHECK-LABEL: @test_mm256_mask_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.256 + // CHECK: @llvm.x86.avx512.fpclass.pd.256 return _mm256_mask_fpclass_pd_mask(__U, __A, 2); } __mmask8 test_mm256_fpclass_pd_mask(__m256d __A) { // CHECK-LABEL: @test_mm256_fpclass_pd_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.pd.256 + // CHECK: @llvm.x86.avx512.fpclass.pd.256 return _mm256_fpclass_pd_mask(__A, 2); } __mmask8 test_mm_mask_fpclass_ps_mask(__mmask8 __U, __m128 __A) { // CHECK-LABEL: @test_mm_mask_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.128 + // CHECK: @llvm.x86.avx512.fpclass.ps.128 return _mm_mask_fpclass_ps_mask(__U, __A, 2); } __mmask8 test_mm_fpclass_ps_mask(__m128 __A) { // CHECK-LABEL: @test_mm_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.128 + // CHECK: @llvm.x86.avx512.fpclass.ps.128 return _mm_fpclass_ps_mask(__A, 2); } __mmask8 test_mm256_mask_fpclass_ps_mask(__mmask8 __U, __m256 __A) { // CHECK-LABEL: @test_mm256_mask_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.256 + // CHECK: @llvm.x86.avx512.fpclass.ps.256 return _mm256_mask_fpclass_ps_mask(__U, __A, 2); } __mmask8 test_mm256_fpclass_ps_mask(__m256 __A) { // CHECK-LABEL: @test_mm256_fpclass_ps_mask - // CHECK: @llvm.x86.avx512.mask.fpclass.ps.256 + // CHECK: @llvm.x86.avx512.fpclass.ps.256 return _mm256_fpclass_ps_mask(__A, 2); } -- GitLab From 8e5cbd6fc4c8a7dd5d73aa04c6b13b0d24e20f89 Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih Date: Wed, 27 Jun 2018 16:17:32 +0000 Subject: [PATCH 0309/1023] [NEON] Remove empty test file from r335734 Fails on Green Dragon: http://green.lab.llvm.org/green/job/clang-stage1-cmake-RA-incremental/50174/consoleFull UNRESOLVED: Clang :: CodeGen/vld_dup.c (5546 of 38947) ******************** TEST 'Clang :: CodeGen/vld_dup.c' FAILED ******************** Test has no run line! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335750 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/vld_dup.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/CodeGen/vld_dup.c diff --git a/test/CodeGen/vld_dup.c b/test/CodeGen/vld_dup.c deleted file mode 100644 index e69de29bb2..0000000000 -- GitLab From 0783eeef9af7c906aa2574353976cd94559aa4b1 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 27 Jun 2018 16:45:58 +0000 Subject: [PATCH 0310/1023] Revert "[Analyzer] Moved RangeConstraintManager to header. NFC." This broke a number of bots. This reverts commit 5e1a89912d37a21c3b49ccf30600d7f498dffa9c. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335752 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PathSensitive/RangedConstraintManager.h | 88 +------------------ .../Core/RangeConstraintManager.cpp | 83 +++++++++++++++++ 2 files changed, 85 insertions(+), 86 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h index 6a903dbc46..1147466d70 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -117,8 +117,6 @@ public: void print(raw_ostream &os) const; - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } - bool operator==(const RangeSet &other) const { return ranges == other.ranges; } @@ -209,90 +207,8 @@ private: static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment); }; -class RangeConstraintManager : public RangedConstraintManager { -public: - RangeConstraintManager(SubEngine *SE, SValBuilder &SVB) - : RangedConstraintManager(SE, SVB) {} - - //===------------------------------------------------------------------===// - // Implementation for interface from ConstraintManager. - //===------------------------------------------------------------------===// - - bool canReasonAbout(SVal X) const override; - - ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; - - const llvm::APSInt *getSymVal(ProgramStateRef State, - SymbolRef Sym) const override; - - ProgramStateRef removeDeadBindings(ProgramStateRef State, - SymbolReaper &SymReaper) override; - - void print(ProgramStateRef State, raw_ostream &Out, const char *nl, - const char *sep) override; - - //===------------------------------------------------------------------===// - // Implementation for interface from RangedConstraintManager. - //===------------------------------------------------------------------===// - - ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &V, - const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymWithinInclusiveRange( - ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; - - ProgramStateRef assumeSymOutsideInclusiveRange( - ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; - - RangeSet::Factory &getRangeSetFactory() { return F; } - -private: - RangeSet::Factory F; - - RangeSet getRange(ProgramStateRef State, SymbolRef Sym); - - RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymLERange(llvm::function_ref RS, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); - RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, - const llvm::APSInt &Int, - const llvm::APSInt &Adjustment); -}; - -} // namespace ento +} // end GR namespace -} // namespace clang +} // end clang namespace #endif diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index c7bbc25594..c081a65002 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -189,6 +189,89 @@ void RangeSet::print(raw_ostream &os) const { os << " }"; } +namespace { +class RangeConstraintManager : public RangedConstraintManager { +public: + RangeConstraintManager(SubEngine *SE, SValBuilder &SVB) + : RangedConstraintManager(SE, SVB) {} + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + bool canReasonAbout(SVal X) const override; + + ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; + + const llvm::APSInt *getSymVal(ProgramStateRef State, + SymbolRef Sym) const override; + + ProgramStateRef removeDeadBindings(ProgramStateRef State, + SymbolReaper &SymReaper) override; + + void print(ProgramStateRef State, raw_ostream &Out, const char *nl, + const char *sep) override; + + //===------------------------------------------------------------------===// + // Implementation for interface from RangedConstraintManager. + //===------------------------------------------------------------------===// + + ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymWithinInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; + + ProgramStateRef assumeSymOutsideInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; + +private: + RangeSet::Factory F; + + RangeSet getRange(ProgramStateRef State, SymbolRef Sym); + + RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymLERange(llvm::function_ref RS, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); + RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, + const llvm::APSInt &Int, + const llvm::APSInt &Adjustment); +}; + +} // end anonymous namespace + std::unique_ptr ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { return llvm::make_unique(Eng, StMgr.getSValBuilder()); -- GitLab From baa2648969e9ae86ed2b15fbd636e84454ee02ab Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 27 Jun 2018 17:31:59 +0000 Subject: [PATCH 0311/1023] [DebugInfo] Emit ObjC methods as part of interface As brought up during the discussion of the DWARF5 accelerator tables, there is currently no way to associate Objective-C methods with the interface they belong to, other than the .apple_objc accelerator table. After due consideration we came to the conclusion that it makes more sense to follow Pavel's suggestion of just emitting this information in the .debug_info section. One concern was that categories were emitted in the .apple_names as well, but it turns out that LLDB doesn't rely on the accelerator tables for this information. This patch changes the codegen behavior to emit subprograms for structure types, like we do for C++. This will result in the DW_TAG_subprogram being nested as a child under its DW_TAG_structure_type. This behavior is only enabled for DWARF5 and later, so we can have a unique code path in LLDB with regards to obtaining the class methods. This was tested on the LLDB side and doesn't lead to a regression. There's already code in place to deal with member functions in C++, which deals with this transparently. For more background please refer to the discussion on the mailing list: http://lists.llvm.org/pipermail/llvm-dev/2018-June/123986.html Differential revision: https://reviews.llvm.org/D48241 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335757 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 44 ++++++++++++++++++++++ lib/CodeGen/CGDebugInfo.h | 4 ++ test/CodeGenObjC/debug-info-category.m | 52 ++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 test/CodeGenObjC/debug-info-category.m diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index a0d5fd6236..5a527cbde3 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -3346,6 +3346,27 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, if (HasDecl && isa(D)) DeclCache[D->getCanonicalDecl()].reset(SP); + if (CGM.getCodeGenOpts().DwarfVersion >= 5) { + // Starting with DWARF V5 method declarations are emitted as children of + // the interface type. + if (const auto *OMD = dyn_cast_or_null(D)) { + const ObjCInterfaceDecl *ID = OMD->getClassInterface(); + QualType QTy(ID->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + if (It != TypeCache.end()) { + llvm::DICompositeType *InterfaceDecl = + cast(It->second); + llvm::DISubprogram *FD = DBuilder.createFunction( + InterfaceDecl, Name, LinkageName, Unit, LineNo, + getOrCreateFunctionType(D, FnType, Unit), Fn->hasLocalLinkage(), + false /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize, + TParamsArray.get()); + DBuilder.finalizeSubprogram(FD); + ObjCMethodCache[ID].push_back(FD); + } + } + } + // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); @@ -4213,6 +4234,29 @@ void CGDebugInfo::finalize() { DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty); } + if (CGM.getCodeGenOpts().DwarfVersion >= 5) { + // Add methods to interface. + for (auto P : ObjCMethodCache) { + if (P.second.empty()) + continue; + + QualType QTy(P.first->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + assert(It != TypeCache.end()); + + llvm::DICompositeType *InterfaceDecl = + cast(It->second); + + SmallVector EltTys; + auto CurrenetElts = InterfaceDecl->getElements(); + EltTys.append(CurrenetElts.begin(), CurrenetElts.end()); + for (auto &MD : P.second) + EltTys.push_back(MD); + llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); + DBuilder.replaceArrays(InterfaceDecl, Elements); + } + } + for (auto p : ReplaceMap) { assert(p.second); auto *Ty = cast(p.second); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index a692babef5..9f5e639d98 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -98,6 +98,10 @@ class CGDebugInfo { /// Cache of previously constructed interfaces which may change. llvm::SmallVector ObjCInterfaceCache; + /// Cache of forward declarations for methods belonging to the interface. + llvm::DenseMap> + ObjCMethodCache; + /// Cache of references to clang modules and precompiled headers. llvm::DenseMap ModuleCache; diff --git a/test/CodeGenObjC/debug-info-category.m b/test/CodeGenObjC/debug-info-category.m new file mode 100644 index 0000000000..faca3a49c2 --- /dev/null +++ b/test/CodeGenObjC/debug-info-category.m @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefix CHECK --check-prefix DWARF5 +// RUN: %clang_cc1 -dwarf-version=4 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefix CHECK --check-prefix DWARF4 + +@interface Foo { + int integer; +} + +- (int)integer; +- (id)integer:(int)_integer; +@end + +@implementation Foo +- (int)integer { + return integer; +} + +- (id)integer:(int)_integer { + integer = _integer; + return self; +} +@end + +@interface Foo (Bar) ++ (id)zero:(Foo *)zeroend; +- (id)add:(Foo *)addend; +@end + +@implementation Foo (Bar) ++ (id)zero:(Foo *)zeroend { + return [self integer:0]; +} +- (id)add:(Foo *)addend { + return [self integer:[self integer] + [addend integer]]; +} +@end + +// CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + +// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false + +// DWARF4-NOT: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF4-NOT: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF4-NOT: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}}isDefinition: false +// DWARF4-NOT: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}}isDefinition: false + +// CHECK: = distinct !DISubprogram(name: "-[Foo integer]"{{.*}}isDefinition: true +// CHECK: = distinct !DISubprogram(name: "-[Foo integer:]"{{.*}}isDefinition: true +// CHECK: = distinct !DISubprogram(name: "+[Foo(Bar) zero:]"{{.*}}isDefinition: true +// CHECK: = distinct !DISubprogram(name: "-[Foo(Bar) add:]"{{.*}}isDefinition: true -- GitLab From 8821a24acbcc05574ab65f3a49200d8f8b67f43b Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Wed, 27 Jun 2018 18:24:46 +0000 Subject: [PATCH 0312/1023] [UBSan] Add silence_unsigned_overflow flag. Summary: Setting UBSAN_OPTIONS=silence_unsigned_overflow=1 will silence all UIO reports. This feature, combined with -fsanitize-recover=unsigned-integer-overflow, is useful for providing fuzzing signal without the excessive log output. Helps with https://github.com/google/oss-fuzz/issues/910. Reviewers: kcc, vsk Reviewed By: vsk Subscribers: vsk, kubamracek, Dor1s, llvm-commits Differential Revision: https://reviews.llvm.org/D48660 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335762 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/UndefinedBehaviorSanitizer.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index e9f85c24dd..8dd9157e81 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -180,6 +180,13 @@ will need to: ``UBSAN_OPTIONS=print_stacktrace=1``. #. Make sure ``llvm-symbolizer`` binary is in ``PATH``. +Silencing Unsigned Integer Overflow +=================================== +To silence reports from unsigned integer overflow, you can set +``UBSAN_OPTIONS=silence_unsigned_overflow=1``. This feature, combined with +``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for +providing fuzzing signal without blowing up logs. + Issue Suppression ================= -- GitLab From 9185e52f3e18192b2a680494e9cee3851f5cc024 Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Wed, 27 Jun 2018 18:32:51 +0000 Subject: [PATCH 0313/1023] [CUDA] Use atexit() to call module destructor. This matches the way NVCC does it. Doing module cleanup at global destructor phase used to work, but is, apparently, too late for the CUDA runtime in CUDA-9.2, which ends up crashing with double-free. Differential Revision: https://reviews.llvm.org/D48613 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335763 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCUDANV.cpp | 13 +++++++++++++ lib/CodeGen/CodeGenModule.cpp | 5 ++--- test/CodeGenCUDA/device-stub.cu | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index 7322095594..f8a7825f0a 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -472,6 +472,19 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { CtorBuilder.CreateCall(RegisterLinkedBinaryFunc, Args); } + // Create destructor and register it with atexit() the way NVCC does it. Doing + // it during regular destructor phase worked in CUDA before 9.2 but results in + // double-free in 9.2. + if (llvm::Function *CleanupFn = makeModuleDtorFunction()) { + // extern "C" int atexit(void (*f)(void)); + llvm::FunctionType *AtExitTy = + llvm::FunctionType::get(IntTy, CleanupFn->getType(), false); + llvm::Constant *AtExitFunc = + CGM.CreateRuntimeFunction(AtExitTy, "atexit", llvm::AttributeList(), + /*Local=*/true); + CtorBuilder.CreateCall(AtExitFunc, CleanupFn); + } + CtorBuilder.CreateRetVoid(); return ModuleCtorFunc; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 7752dbcc7c..13afd4bdb8 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -404,10 +404,9 @@ void CodeGenModule::Release() { AddGlobalCtor(ObjCInitFunction); if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice && CUDARuntime) { - if (llvm::Function *CudaCtorFunction = CUDARuntime->makeModuleCtorFunction()) + if (llvm::Function *CudaCtorFunction = + CUDARuntime->makeModuleCtorFunction()) AddGlobalCtor(CudaCtorFunction); - if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction()) - AddGlobalDtor(CudaDtorFunction); } if (OpenMPRuntime) { if (llvm::Function *OpenMPRegistrationFunction = diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu index 3798b8cf73..7aae4fb3ec 100644 --- a/test/CodeGenCUDA/device-stub.cu +++ b/test/CodeGenCUDA/device-stub.cu @@ -86,8 +86,6 @@ void use_pointers() { // HIPRDC-SAME: c"[[MODULE_ID:.+]]\00", section "__hip_module_id", align 32 // * Make sure our constructor was added to global ctor list. // ALL: @llvm.global_ctors = appending global {{.*}}@__[[PREFIX]]_module_ctor -// * In separate mode we also register a destructor. -// NORDC: @llvm.global_dtors = appending global {{.*}}@__[[PREFIX]]_module_dtor // * Alias to global symbol containing the NVModuleID. // RDC: @__fatbinwrap[[MODULE_ID]] = alias { i32, i32, i8*, i8* } // RDC-SAME: { i32, i32, i8*, i8* }* @__[[PREFIX]]_fatbin_wrapper @@ -127,6 +125,8 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); } // NORDC-NEXT: store{{.*}}__[[PREFIX]]_gpubin_handle // .. and then calls __[[PREFIX]]_register_globals // NORDC-NEXT: call void @__[[PREFIX]]_register_globals +// * In separate mode we also register a destructor. +// NORDC-NEXT: call i32 @atexit(void (i8*)* @__[[PREFIX]]_module_dtor) // With relocatable device code we call __[[PREFIX]]RegisterLinkedBinary%NVModuleID% // RDC: call{{.*}}__[[PREFIX]]RegisterLinkedBinary[[MODULE_ID]]( -- GitLab From 53d8fcb5c281832f3c4bd5ae5dcdf1d23ac95656 Mon Sep 17 00:00:00 2001 From: Aaron Enye Shi Date: Wed, 27 Jun 2018 18:58:55 +0000 Subject: [PATCH 0314/1023] [HIP] Support flush denormals bitcode Summary: Use oclc_daz_opt_on.amdgcn.bc bitcode when option fcuda-flush-denormal-to-zero is enabled, otherwise use oclc_daz_opt_off.amdgcn.bc bitcode. Added lit tests to verify that the correct bitcode is linked when -fcuda-flush-denormal-to-zero option is enabled or disabled. Reviewers: yaxunl, scchan, b-sumner Reviewed By: yaxunl, scchan, b-sumner Subscribers: cfe-commits, yaxunl Differential Revision: https://reviews.llvm.org/D48493 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335765 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/HIP.cpp | 8 +++++- test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc | 0 test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc | 0 .../oclc_correctly_rounded_sqrt_on.amdgcn.bc | 0 .../hip_dev_lib/oclc_daz_opt_off.amdgcn.bc | 0 .../hip_dev_lib/oclc_daz_opt_on.amdgcn.bc | 0 .../oclc_finite_only_off.amdgcn.bc | 0 .../oclc_isa_version_803.amdgcn.bc | 0 .../oclc_isa_version_900.amdgcn.bc | 0 .../oclc_unsafe_math_off.amdgcn.bc | 0 test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc | 0 .../Inputs/hip_dev_lib/opencl.amdgcn.bc | 0 test/Driver/hip-device-libs.hip | 27 +++++++++++++++++++ 13 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc create mode 100644 test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc create mode 100644 test/Driver/hip-device-libs.hip diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 38dfb0e192..2aa7cacd6b 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -75,10 +75,16 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( std::string ISAVerBC = "oclc_isa_version_" + SubArchName.drop_front(3).str() + ".amdgcn.bc"; + llvm::StringRef FlushDenormalControlBC; + if (Args.hasArg(options::OPT_fcuda_flush_denormals_to_zero)) + FlushDenormalControlBC = "oclc_daz_opt_on.amdgcn.bc"; + else + FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc"; + BCLibs.append({"opencl.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc", "ocml.amdgcn.bc", "oclc_finite_only_off.amdgcn.bc", - "oclc_daz_opt_off.amdgcn.bc", + FlushDenormalControlBC, "oclc_correctly_rounded_sqrt_on.amdgcn.bc", "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC}); } diff --git a/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/irif.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/ockl.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_correctly_rounded_sqrt_on.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_off.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_daz_opt_on.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_finite_only_off.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_803.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_isa_version_900.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/oclc_unsafe_math_off.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/ocml.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc b/test/Driver/Inputs/hip_dev_lib/opencl.amdgcn.bc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/hip-device-libs.hip b/test/Driver/hip-device-libs.hip new file mode 100644 index 0000000000..74a3e7bf0f --- /dev/null +++ b/test/Driver/hip-device-libs.hip @@ -0,0 +1,27 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// Test flush-denormals-to-zero enabled uses oclc_daz_opt_on + +// RUN: %clang -### -target x86_64-linux-gnu \ +// RUN: -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: -fcuda-flush-denormals-to-zero \ +// RUN: %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD + +// Test flush-denormals-to-zero disabled uses oclc_daz_opt_off + +// RUN: %clang -### -target x86_64-linux-gnu \ +// RUN: -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD + + +// COM: [[LLVM_LINK:"*.llvm-link"]] +// FLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_on.amdgcn.bc" +// NOFLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_off.amdgcn.bc" +// COM-SAME: {{.*}} "-o" "{{.*}}-gfx900-linked-{{.*bc}}" + -- GitLab From 81c2075695490183408d1a3f29feefba63069f81 Mon Sep 17 00:00:00 2001 From: Aaron Enye Shi Date: Wed, 27 Jun 2018 19:51:42 +0000 Subject: [PATCH 0315/1023] [HIP] Fix ordering of device-libs linking Summary: HIP should link the bitcodes with caller functions before callee functions. Also added lit test to check the ordering of the linked bitcodes is matches. Reviewers: yaxunl, b-sumner Reviewed By: yaxunl, b-sumner Subscribers: cfe-commits, yaxunl, b-sumner, scchan Differential Revision: https://reviews.llvm.org/D48667 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335774 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/HIP.cpp | 2 +- test/Driver/hip-device-libs.hip | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 2aa7cacd6b..df12faddcf 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -82,7 +82,7 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc"; BCLibs.append({"opencl.amdgcn.bc", - "ockl.amdgcn.bc", "irif.amdgcn.bc", "ocml.amdgcn.bc", + "ocml.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc", "oclc_finite_only_off.amdgcn.bc", FlushDenormalControlBC, "oclc_correctly_rounded_sqrt_on.amdgcn.bc", diff --git a/test/Driver/hip-device-libs.hip b/test/Driver/hip-device-libs.hip index 74a3e7bf0f..04afab1b73 100644 --- a/test/Driver/hip-device-libs.hip +++ b/test/Driver/hip-device-libs.hip @@ -21,6 +21,7 @@ // COM: [[LLVM_LINK:"*.llvm-link"]] +// COM-SAME: {{.*}} "{{.*}}ocml.amdgcn.bc" "{{.*}}ockl.amdgcn.bc" "{{.*}}irif.amdgcn.bc" // FLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_on.amdgcn.bc" // NOFLUSHD-SAME: {{.*}} "{{.*}}oclc_daz_opt_off.amdgcn.bc" // COM-SAME: {{.*}} "-o" "{{.*}}-gfx900-linked-{{.*bc}}" -- GitLab From 54d0e05c9eb208e28db0ef10822c6d9f01395eb1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 27 Jun 2018 20:29:32 +0000 Subject: [PATCH 0316/1023] DR1213: Ignore implicit conversions when determining if an operand of an array subscript expression is an array prvalue. Also apply DR1213 to vector prvalues for consistency. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335779 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 18 ++++++++++++++---- test/CXX/drs/dr12xx.cpp | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 88059e9466..74f84862e6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4385,10 +4385,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Per C++ core issue 1213, the result is an xvalue if either operand is // a non-lvalue array, and an lvalue otherwise. - if (getLangOpts().CPlusPlus11 && - ((LHSExp->getType()->isArrayType() && !LHSExp->isLValue()) || - (RHSExp->getType()->isArrayType() && !RHSExp->isLValue()))) - VK = VK_XValue; + if (getLangOpts().CPlusPlus11) { + for (auto *Op : {LHSExp, RHSExp}) { + Op = Op->IgnoreImplicit(); + if (Op->getType()->isArrayType() && !Op->isLValue()) + VK = VK_XValue; + } + } // Perform default conversions. if (!LHSExp->getType()->getAs()) { @@ -4449,6 +4452,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, } else if (const VectorType *VTy = LHSTy->getAs()) { BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; + // We apply C++ DR1213 to vector subscripting too. + if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) { + ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); + if (Materialized.isInvalid()) + return ExprError(); + LHSExp = Materialized.get(); + } VK = LHSExp->getValueKind(); if (VK != VK_RValue) OK = OK_VectorComponent; diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp index 24039a1cd2..1bc4c39734 100644 --- a/test/CXX/drs/dr12xx.cpp +++ b/test/CXX/drs/dr12xx.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1213 { // dr1213: 4 +namespace dr1213 { // dr1213: 7 #if __cplusplus >= 201103L using T = int[3]; int &&r = T{}[1]; @@ -11,6 +11,19 @@ namespace dr1213 { // dr1213: 4 using T = decltype((T{})); using U = decltype((T{}[2])); using U = int &&; + + // Same thing but in a case where we consider overloaded operator[]. + struct ConvertsToInt { + operator int(); + }; + struct X { int array[1]; }; + using U = decltype(X().array[ConvertsToInt()]); + + // We apply the same rule to vector subscripting. + typedef int V4Int __attribute__((__vector_size__(sizeof(int) * 4))); + typedef int EV4Int __attribute__((__ext_vector_type__(4))); + using U = decltype(V4Int()[0]); + using U = decltype(EV4Int()[0]); #endif } -- GitLab From 4dc93bb1e15647d01cec2ef51f6bd53d20e7ea82 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 27 Jun 2018 20:29:36 +0000 Subject: [PATCH 0317/1023] [Modules][ObjC] Warn on the use of '@import' in framework headers Using @import in framework headers inhibit the use of such headers when not using modules, this is specially bad for headers that end up in the SDK (or any other system framework). Add a warning to give users some indication that this is discouraged. rdar://problem/39192894 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335780 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticParseKinds.td | 5 +++++ lib/Parse/Parser.cpp | 12 ++++++++++++ .../A.framework/Headers/A.h | 2 ++ .../A.framework/Modules/module.modulemap | 4 ++++ .../module.modulemap | 2 ++ test/Modules/at-import-in-framework-header.m | 17 +++++++++++++++++ test/VFS/umbrella-mismatch.m | 4 ++-- 8 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h create mode 100644 test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/at-import-in-framework-header/module.modulemap create mode 100644 test/Modules/at-import-in-framework-header.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 56384db124..a7fe5032df 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -34,6 +34,7 @@ def AutoImport : DiagGroup<"auto-import">; def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def FrameworkIncludePrivateFromPublic : DiagGroup<"framework-include-private-from-public">; +def FrameworkHdrAtImport : DiagGroup<"atimport-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index ee9ca7118b..c2a1f095f1 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -248,6 +248,11 @@ def err_unexpected_at : Error<"unexpected '@' in program">; def err_atimport : Error< "use of '@import' when modules are disabled">; +def warn_atimport_in_framework_header : Warning< + "use of '@import' in framework header is discouraged, " + "including this header requires -fmodules">, + InGroup; + def err_invalid_reference_qualifier_application : Error< "'%0' qualifier may not be applied to a reference">; def err_illegal_decl_reference_to_reference : Error< diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d9255109d7..d1c35352ae 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -20,6 +20,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Path.h" using namespace clang; @@ -2123,6 +2124,7 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import) : Tok.isObjCAtKeyword(tok::objc_import)) && "Improper start to module import"); + bool IsObjCAtImport = Tok.isObjCAtKeyword(tok::objc_import); SourceLocation ImportLoc = ConsumeToken(); SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc; @@ -2146,6 +2148,16 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { if (Import.isInvalid()) return nullptr; + // Using '@import' in framework headers requires modules to be enabled so that + // the header is parseable. Emit a warning to make the user aware. + if (IsObjCAtImport && AtLoc.isValid()) { + auto &SrcMgr = PP.getSourceManager(); + auto *FE = SrcMgr.getFileEntryForID(SrcMgr.getFileID(AtLoc)); + if (FE && llvm::sys::path::parent_path(FE->getDir()->getName()) + .endswith(".framework")) + Diags.Report(AtLoc, diag::warn_atimport_in_framework_header); + } + return Import.get(); } diff --git a/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h new file mode 100644 index 0000000000..6949a872fc --- /dev/null +++ b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Headers/A.h @@ -0,0 +1,2 @@ +@import B; +int foo(); diff --git a/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..126cf26ec9 --- /dev/null +++ b/test/Modules/Inputs/at-import-in-framework-header/A.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +// at-import-in-framework-header/A.framework/Modules/module.modulemap +framework module A { + header "A.h" +} diff --git a/test/Modules/Inputs/at-import-in-framework-header/module.modulemap b/test/Modules/Inputs/at-import-in-framework-header/module.modulemap new file mode 100644 index 0000000000..a38d66863e --- /dev/null +++ b/test/Modules/Inputs/at-import-in-framework-header/module.modulemap @@ -0,0 +1,2 @@ +// at-import-in-framework-header/module.modulemap +module B {} diff --git a/test/Modules/at-import-in-framework-header.m b/test/Modules/at-import-in-framework-header.m new file mode 100644 index 0000000000..fe36638120 --- /dev/null +++ b/test/Modules/at-import-in-framework-header.m @@ -0,0 +1,17 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ +// RUN: -F%S/Inputs/at-import-in-framework-header -I%S/Inputs/at-import-in-framework-header \ +// RUN: -Watimport-in-framework-header -fsyntax-only %s \ +// RUN: 2>%t/stderr +// RUN: FileCheck --input-file=%t/stderr %s + +// CHECK: use of '@import' in framework header is discouraged + +#import + +int bar() { return foo(); } + diff --git a/test/VFS/umbrella-mismatch.m b/test/VFS/umbrella-mismatch.m index fc51802416..8167a21f48 100644 --- a/test/VFS/umbrella-mismatch.m +++ b/test/VFS/umbrella-mismatch.m @@ -1,7 +1,7 @@ // RUN: rm -rf %t // RUN: sed -e "s;INPUT_DIR;%/S/Inputs;g" -e "s;OUT_DIR;%/S/Inputs;g" %S/Inputs/vfsoverlay.yaml > %t.yaml -// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only %s -verify -// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs -fsyntax-only %s -verify +// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ivfsoverlay %t.yaml -F %S/Inputs -fsyntax-only %s -Wno-atimport-in-framework-header -verify +// RUN: %clang_cc1 -Werror -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs -fsyntax-only %s -Wno-atimport-in-framework-header -verify // expected-no-diagnostics @import UsesFoo; -- GitLab From 34df83c150fac5090394a2d60540c363a44f46a7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 27 Jun 2018 20:30:34 +0000 Subject: [PATCH 0318/1023] DR1687: When overload resolution selects a built-in operator, implicit conversions are only applied to operands of class type, and the second standard conversion sequence is not applied. When diagnosing an invalid builtin binary operator, talk about the original types rather than the converted types. If these differ by a user-defined conversion, tell the user what happened. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335781 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 4 ++ include/clang/Basic/DiagnosticSemaKinds.td | 2 + include/clang/Sema/Sema.h | 9 ++++- lib/AST/Expr.cpp | 41 ++++++++++++++------ lib/Sema/SemaExpr.cpp | 45 ++++++++++++++++++++-- lib/Sema/SemaExprCXX.cpp | 12 +++++- lib/Sema/SemaExprObjC.cpp | 14 ++++--- lib/Sema/SemaOverload.cpp | 27 ++++++------- test/CXX/drs/dr15xx.cpp | 18 ++++----- test/CXX/drs/dr16xx.cpp | 22 ++++++++++- test/CXX/over/over.built/p15.cpp | 44 +++++++++------------ test/Misc/diag-macro-backtrace2.c | 2 +- test/SemaOpenCL/logical-ops.cl | 2 +- 13 files changed, 168 insertions(+), 74 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d71fda7430..df3cd182e0 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2850,6 +2850,10 @@ public: return const_cast(this)->getSubExprAsWritten(); } + /// If this cast applies a user-defined conversion, retrieve the conversion + /// function that it invokes. + NamedDecl *getConversionFunction() const; + typedef CXXBaseSpecifier **path_iterator; typedef const CXXBaseSpecifier * const *path_const_iterator; bool path_empty() const { return CastExprBits.BasePathSize == 0; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f08cd00c62..c02e7d2780 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5802,6 +5802,8 @@ def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; +def note_typecheck_invalid_operands_converted : Note< + "%select{first|second}0 operand was implicitly converted to type %1">; def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error< "logical expression with vector %select{type %1 and non-vector type %2|types" " %1 and %2}0 is only supported in C++">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4897a2613e..527c376bd2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -9316,9 +9316,16 @@ public: /// A functional-style cast. CCK_FunctionalCast, /// A cast other than a C-style cast. - CCK_OtherCast + CCK_OtherCast, + /// A conversion for an operand of a builtin overloaded operator. + CCK_ForBuiltinOverloadedOp }; + static bool isCast(CheckedConversionKind CCK) { + return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast || + CCK == CCK_OtherCast; + } + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 47cf026e28..3d11619ec4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1673,23 +1673,22 @@ const char *CastExpr::getCastKindName(CastKind CK) { } namespace { - Expr *skipImplicitTemporary(Expr *expr) { + const Expr *skipImplicitTemporary(const Expr *E) { // Skip through reference binding to temporary. - if (MaterializeTemporaryExpr *Materialize - = dyn_cast(expr)) - expr = Materialize->GetTemporaryExpr(); + if (auto *Materialize = dyn_cast(E)) + E = Materialize->GetTemporaryExpr(); // Skip any temporary bindings; they're implicit. - if (CXXBindTemporaryExpr *Binder = dyn_cast(expr)) - expr = Binder->getSubExpr(); + if (auto *Binder = dyn_cast(E)) + E = Binder->getSubExpr(); - return expr; + return E; } } Expr *CastExpr::getSubExprAsWritten() { - Expr *SubExpr = nullptr; - CastExpr *E = this; + const Expr *SubExpr = nullptr; + const CastExpr *E = this; do { SubExpr = skipImplicitTemporary(E->getSubExpr()); @@ -1702,15 +1701,33 @@ Expr *CastExpr::getSubExprAsWritten() { assert((isa(SubExpr) || isa(SubExpr)) && "Unexpected SubExpr for CK_UserDefinedConversion."); - if (isa(SubExpr)) - SubExpr = cast(SubExpr)->getImplicitObjectArgument(); + if (auto *MCE = dyn_cast(SubExpr)) + SubExpr = MCE->getImplicitObjectArgument(); } // If the subexpression we're left with is an implicit cast, look // through that, too. } while ((E = dyn_cast(SubExpr))); - return SubExpr; + return const_cast(SubExpr); +} + +NamedDecl *CastExpr::getConversionFunction() const { + const Expr *SubExpr = nullptr; + + for (const CastExpr *E = this; E; E = dyn_cast(SubExpr)) { + SubExpr = skipImplicitTemporary(E->getSubExpr()); + + if (E->getCastKind() == CK_ConstructorConversion) + return cast(SubExpr)->getConstructor(); + + if (E->getCastKind() == CK_UserDefinedConversion) { + if (auto *MCE = dyn_cast(SubExpr)) + return MCE->getMethodDecl(); + } + } + + return nullptr; } CXXBaseSpecifier **CastExpr::path_buffer() { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 74f84862e6..a438480a4b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8130,18 +8130,57 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, RHS = E; return Compatible; } - + if (ConvertRHS) RHS = ImpCastExprToType(E, Ty, Kind); } return result; } +namespace { +/// The original operand to an operator, prior to the application of the usual +/// arithmetic conversions and converting the arguments of a builtin operator +/// candidate. +struct OriginalOperand { + explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) { + if (auto *MTE = dyn_cast(Op)) + Op = MTE->GetTemporaryExpr(); + if (auto *BTE = dyn_cast(Op)) + Op = BTE->getSubExpr(); + if (auto *ICE = dyn_cast(Op)) { + Orig = ICE->getSubExprAsWritten(); + Conversion = ICE->getConversionFunction(); + } + } + + QualType getType() const { return Orig->getType(); } + + Expr *Orig; + NamedDecl *Conversion; +}; +} + QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS) { + OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get()); + Diag(Loc, diag::err_typecheck_invalid_operands) - << LHS.get()->getType() << RHS.get()->getType() + << OrigLHS.getType() << OrigRHS.getType() << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + + // If a user-defined conversion was applied to either of the operands prior + // to applying the built-in operator rules, tell the user about it. + if (OrigLHS.Conversion) { + Diag(OrigLHS.Conversion->getLocation(), + diag::note_typecheck_invalid_operands_converted) + << 0 << LHS.get()->getType(); + } + if (OrigRHS.Conversion) { + Diag(OrigRHS.Conversion->getLocation(), + diag::note_typecheck_invalid_operands_converted) + << 1 << RHS.get()->getType(); + } + return QualType(); } @@ -9887,7 +9926,7 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S, // type E, the operator yields the result of converting the operands // to the underlying type of E and applying <=> to the converted operands. if (!S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) { - S.InvalidOperands(Loc, LHSStripped, RHSStripped); + S.InvalidOperands(Loc, LHS, RHS); return QualType(); } QualType IntType = diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 02cb78b9de..db47931348 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3767,6 +3767,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK) { + // C++ [over.match.oper]p7: [...] operands of class type are converted [...] + if (CCK == CCK_ForBuiltinOverloadedOp && !From->getType()->isRecordType()) + return From; + switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: { ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, @@ -3826,6 +3830,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, From = CastArg.get(); + // C++ [over.match.oper]p7: + // [...] the second standard conversion sequence of a user-defined + // conversion sequence is not applied. + if (CCK == CCK_ForBuiltinOverloadedOp) + return From; + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, AA_Converting, CCK); } @@ -4289,7 +4299,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // If this conversion sequence succeeded and involved implicitly converting a // _Nullable type to a _Nonnull one, complain. - if (CCK == CCK_ImplicitConversion) + if (!isCast(CCK)) diagnoseNullableToNonnullConversion(ToType, InitialFromType, From->getLocStart()); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ce73e222b6..bf9d081bb9 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -3498,6 +3498,7 @@ static void addFixitForObjCARCConversion(Sema &S, // We handle C-style and implicit casts here. switch (CCK) { case Sema::CCK_ImplicitConversion: + case Sema::CCK_ForBuiltinOverloadedOp: case Sema::CCK_CStyleCast: case Sema::CCK_OtherCast: break; @@ -3651,11 +3652,13 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin()); SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; + unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1; + // Bridge from an ARC type to a CF type. if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { S.Diag(loc, diag::err_arc_cast_requires_bridge) - << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << convKindForDiag << 2 // of C pointer type << castExprType << unsigned(castType->isBlockPointerType()) // to ObjC|block type @@ -3697,7 +3700,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { bool br = S.isKnownName("CFBridgingRetain"); S.Diag(loc, diag::err_arc_cast_requires_bridge) - << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << convKindForDiag << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type << castExprType << 2 // to C pointer type @@ -3734,7 +3737,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, } S.Diag(loc, diag::err_arc_mismatched_cast) - << (CCK != Sema::CCK_ImplicitConversion) + << !convKindForDiag << srcKind << castExprType << castType << castRange << castExpr->getSourceRange(); } @@ -4187,7 +4190,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr) return ACR_okay; if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && - CCK != CCK_ImplicitConversion) + isCast(CCK)) return ACR_okay; switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { @@ -4212,8 +4215,7 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, // If this is a non-implicit cast from id or block type to a // CoreFoundation type, delay complaining in case the cast is used // in an acceptable context. - if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && - CCK != CCK_ImplicitConversion) + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && isCast(CCK)) return ACR_unbridged; // Issue a diagnostic about a missing @-sign when implicit casting a cstring diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index d730bb27a1..e9d2eb6cc5 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -12191,7 +12191,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, // break out so that we will build the appropriate built-in // operator node. ExprResult InputRes = PerformImplicitConversion( - Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing); + Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing, + CCK_ForBuiltinOverloadedOp); if (InputRes.isInvalid()) return ExprError(); Input = InputRes.get(); @@ -12435,16 +12436,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult ArgsRes0 = PerformImplicitConversion( + Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); - ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], - Best->Conversions[1], AA_Passing); + ExprResult ArgsRes1 = PerformImplicitConversion( + Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); @@ -12647,16 +12648,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult ArgsRes0 = PerformImplicitConversion( + Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); - ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], - Best->Conversions[1], AA_Passing); + ExprResult ArgsRes1 = PerformImplicitConversion( + Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp index 2060047571..cca4509fa0 100644 --- a/test/CXX/drs/dr15xx.cpp +++ b/test/CXX/drs/dr15xx.cpp @@ -112,9 +112,9 @@ namespace dr1512 { // dr1512: 4 #endif } - template struct Wrap { operator T(); }; - void test_overload() { #if __cplusplus >= 201103L + template struct Wrap { operator T(); }; // expected-note 4{{converted to type 'nullptr_t'}} expected-note 4{{converted to type 'int *'}} + void test_overload() { using nullptr_t = decltype(nullptr); void(Wrap() == Wrap()); void(Wrap() != Wrap()); @@ -123,16 +123,16 @@ namespace dr1512 { // dr1512: 4 void(Wrap() <= Wrap()); // expected-error {{invalid operands}} void(Wrap() >= Wrap()); // expected-error {{invalid operands}} - // The wording change fails to actually disallow this. This is valid - // via the builtin operator<(int*, int*) etc. + // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*) + // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'. void(Wrap() == Wrap()); void(Wrap() != Wrap()); - void(Wrap() < Wrap()); - void(Wrap() > Wrap()); - void(Wrap() <= Wrap()); - void(Wrap() >= Wrap()); -#endif + void(Wrap() < Wrap()); // expected-error {{invalid operands to binary expression ('Wrap' and 'Wrap')}} + void(Wrap() > Wrap()); // expected-error {{invalid operands}} + void(Wrap() <= Wrap()); // expected-error {{invalid operands}} + void(Wrap() >= Wrap()); // expected-error {{invalid operands}} } +#endif } namespace dr1518 { // dr1518: 4 diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index 898672ab80..e0af95ac39 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -1,7 +1,8 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors #if __cplusplus < 201103L // expected-error@+1 {{variadic macro}} @@ -249,3 +250,22 @@ namespace dr1672 { // dr1672: 7 static_assert(!__is_standard_layout(Y), ""); static_assert(!__is_standard_layout(Y), ""); } + +namespace dr1687 { // dr1687: 7 + template struct To { + operator T(); // expected-note 2{{first operand was implicitly converted to type 'int *'}} + // expected-note@-1 {{second operand was implicitly converted to type 'double'}} +#if __cplusplus > 201703L + // expected-note@-3 2{{operand was implicitly converted to type 'dr1687::E}} +#endif + }; + + int *a = To() + 100.0; // expected-error {{invalid operands to binary expression ('To' and 'double')}} + int *b = To() + To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}} + +#if __cplusplus > 201703L + enum E1 {}; + enum E2 {}; + auto c = To() <=> To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}} +#endif +} diff --git a/test/CXX/over/over.built/p15.cpp b/test/CXX/over/over.built/p15.cpp index 64ed3e7b83..9b223bcbc2 100644 --- a/test/CXX/over/over.built/p15.cpp +++ b/test/CXX/over/over.built/p15.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare -struct A { operator decltype(nullptr)(); }; -struct B { operator const int *(); }; +struct A { operator decltype(nullptr)(); }; // expected-note 16{{implicitly converted}} +struct B { operator const int *(); }; // expected-note 8{{implicitly converted}} void f(A a, B b, volatile int *pi) { (void)(a == a); (void)(a != a); @@ -12,39 +12,31 @@ void f(A a, B b, volatile int *pi) { (void)(a == b); (void)(a != b); - // FIXME: These cases were intended to be made ill-formed by N3624, but it - // fails to actually achieve this goal. - (void)(a < b); - (void)(a > b); - (void)(a <= b); - (void)(a >= b); + (void)(a < b); // expected-error {{invalid operands}} + (void)(a > b); // expected-error {{invalid operands}} + (void)(a <= b); // expected-error {{invalid operands}} + (void)(a >= b); // expected-error {{invalid operands}} (void)(b == a); (void)(b != a); - // FIXME: These cases were intended to be made ill-formed by N3624, but it - // fails to actually achieve this goal. - (void)(b < a); - (void)(b > a); - (void)(b <= a); - (void)(b >= a); + (void)(b < a); // expected-error {{invalid operands}} + (void)(b > a); // expected-error {{invalid operands}} + (void)(b <= a); // expected-error {{invalid operands}} + (void)(b >= a); // expected-error {{invalid operands}} (void)(a == pi); (void)(a != pi); - // FIXME: These cases were intended to be made ill-formed by N3624, but it - // fails to actually achieve this goal. - (void)(a < pi); - (void)(a > pi); - (void)(a <= pi); - (void)(a >= pi); + (void)(a < pi); // expected-error {{invalid operands}} + (void)(a > pi); // expected-error {{invalid operands}} + (void)(a <= pi); // expected-error {{invalid operands}} + (void)(a >= pi); // expected-error {{invalid operands}} (void)(pi == a); (void)(pi != a); - // FIXME: These cases were intended to be made ill-formed by N3624, but it - // fails to actually achieve this goal. - (void)(pi < a); - (void)(pi > a); - (void)(pi <= a); - (void)(pi >= a); + (void)(pi < a); // expected-error {{invalid operands}} + (void)(pi > a); // expected-error {{invalid operands}} + (void)(pi <= a); // expected-error {{invalid operands}} + (void)(pi >= a); // expected-error {{invalid operands}} (void)(b == pi); (void)(b != pi); diff --git a/test/Misc/diag-macro-backtrace2.c b/test/Misc/diag-macro-backtrace2.c index af79bbde60..64fc5f6307 100644 --- a/test/Misc/diag-macro-backtrace2.c +++ b/test/Misc/diag-macro-backtrace2.c @@ -14,7 +14,7 @@ void PR16799() { const char str[] = "string"; a(str); // CHECK: :15:3: error: invalid operands to binary expression - // CHECK: ('const char *' and 'int') + // CHECK: ('const char [7]' and 'int') // CHECK: a(str); // CHECK: ^~~~~~ // CHECK: :3:11: note: expanded from macro 'a' diff --git a/test/SemaOpenCL/logical-ops.cl b/test/SemaOpenCL/logical-ops.cl index 42501b1441..f6972c46e2 100644 --- a/test/SemaOpenCL/logical-ops.cl +++ b/test/SemaOpenCL/logical-ops.cl @@ -29,7 +29,7 @@ kernel void float_ops() { #if __OPENCL_C_VERSION__ < 120 // expected-error@-2{{invalid operands}} #endif - float ibaf = 0 & 0.0f; // expected-error {{invalid operands}} + float ibaf = 0 & 0.0f; // expected-error {{invalid operands to binary expression ('int' and 'float')}} float ibof = 0 | 0.0f; // expected-error {{invalid operands}} float bnf = ~0.0f;// expected-error {{invalid argument type}} float lnf = !0.0f; -- GitLab From 4617d8caa1293bb9e27bef7d57beb120e71619f8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 27 Jun 2018 20:30:36 +0000 Subject: [PATCH 0319/1023] [www] Update cxx_dr_status for recent DR fixes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335782 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/cxx_dr_status.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index 4d9a726296..e47dbd6921 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -303,7 +303,7 @@ 44 CD1 Member specializations - Superseded by 727 + Superseded by 727 45 @@ -4387,7 +4387,7 @@ and POD class 727 C++17 In-class explicit specializations - SVN + Partial 728 @@ -7093,7 +7093,7 @@ and POD class 1213 CD3 Array subscripting and xvalues - Clang 4 + SVN 1214 @@ -9937,7 +9937,7 @@ and POD class 1687 C++14 Conversions of operands of built-in operators - Unknown + SVN 1688 -- GitLab From 3cbd1a48a081e370855d09357298eb8210d29294 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Wed, 27 Jun 2018 22:05:09 +0000 Subject: [PATCH 0320/1023] [analyzer] Add clangFrontend to target_link_libraries Without this, builds with `-DSHARED_LIB=ON` fail. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335791 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/StaticAnalyzer/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/StaticAnalyzer/CMakeLists.txt b/unittests/StaticAnalyzer/CMakeLists.txt index 117a5d9ae4..ff041452df 100644 --- a/unittests/StaticAnalyzer/CMakeLists.txt +++ b/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(StaticAnalysisTests PRIVATE clangBasic clangAnalysis + clangFrontend clangStaticAnalyzerCore clangStaticAnalyzerFrontend clangTooling -- GitLab From f5fb3f3b81b10888ec0f219628d3df3f7782c65b Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:04:54 +0000 Subject: [PATCH 0321/1023] [CFG] [analyzer] Add construction contexts that explain pre-C++17 copy elision. Before C++17 copy elision was optional, even if the elidable copy/move constructor had arbitrary side effects. The elidable constructor is present in the AST, but marked as elidable. In these cases CFG now contains additional information that allows its clients to figure out if a temporary object is only being constructed so that to pass it to an elidable constructor. If so, it includes a reference to the elidable constructor's construction context, so that the client could elide the elidable constructor and construct the object directly at its final destination. Differential Revision: https://reviews.llvm.org/D47616 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335795 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/AnalysisDeclContext.h | 1 + include/clang/Analysis/CFG.h | 1 + include/clang/Analysis/ConstructionContext.h | 80 +++++++++++++++-- .../StaticAnalyzer/Core/AnalyzerOptions.h | 10 +++ lib/Analysis/AnalysisDeclContext.cpp | 4 +- lib/Analysis/CFG.cpp | 77 ++++++++++------ lib/Analysis/ConstructionContext.cpp | 56 +++++++++++- lib/StaticAnalyzer/Core/AnalysisManager.cpp | 1 + lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 6 ++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 6 +- test/Analysis/analyzer-config.c | 3 +- test/Analysis/analyzer-config.cpp | 3 +- test/Analysis/cfg-rich-constructors.cpp | 90 +++++++++++++------ test/Analysis/temp-obj-dtors-cfg-output.cpp | 34 +++---- 14 files changed, 285 insertions(+), 87 deletions(-) diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h index d6eb5e4d5f..8c391b5ee1 100644 --- a/include/clang/Analysis/AnalysisDeclContext.h +++ b/include/clang/Analysis/AnalysisDeclContext.h @@ -451,6 +451,7 @@ public: bool addStaticInitBranches = false, bool addCXXNewAllocator = true, bool addRichCXXConstructors = true, + bool markElidedCXXConstructors = true, CodeInjector *injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 580cbd6ee3..f25789822d 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -1025,6 +1025,7 @@ public: bool AddCXXNewAllocator = false; bool AddCXXDefaultInitExprInCtors = false; bool AddRichCXXConstructors = false; + bool MarkElidedCXXConstructors = false; BuildOptions() = default; diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h index 8df95a8ada..40cb0e7e5d 100644 --- a/include/clang/Analysis/ConstructionContext.h +++ b/include/clang/Analysis/ConstructionContext.h @@ -107,7 +107,10 @@ public: INITIALIZER_BEGIN = SimpleConstructorInitializerKind, INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, NewAllocatedObjectKind, - TemporaryObjectKind, + SimpleTemporaryObjectKind, + ElidedTemporaryObjectKind, + TEMPORARY_BEGIN = SimpleTemporaryObjectKind, + TEMPORARY_END = ElidedTemporaryObjectKind, SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind, RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, @@ -305,16 +308,15 @@ class TemporaryObjectConstructionContext : public ConstructionContext { const CXXBindTemporaryExpr *BTE; const MaterializeTemporaryExpr *MTE; - friend class ConstructionContext; // Allows to create<>() itself. - +protected: explicit TemporaryObjectConstructionContext( - const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) - : ConstructionContext(ConstructionContext::TemporaryObjectKind), - BTE(BTE), MTE(MTE) { + ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, + const MaterializeTemporaryExpr *MTE) + : ConstructionContext(K), BTE(BTE), MTE(MTE) { // Both BTE and MTE can be null here, all combinations possible. // Even though for now at least one should be non-null, we simply haven't - // implemented this case yet (this would be a temporary in the middle of - // nowhere that doesn't have a non-trivial destructor). + // implemented the other case yet (this would be a temporary in the middle + // of nowhere that doesn't have a non-trivial destructor). } public: @@ -334,7 +336,67 @@ public: } static bool classof(const ConstructionContext *CC) { - return CC->getKind() == TemporaryObjectKind; + return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; + } +}; + +/// Represents a temporary object that is not constructed for the purpose of +/// being immediately copied/moved by an elidable copy/move-constructor. +/// This includes temporary objects "in the middle of nowhere" like T(123) and +/// lifetime-extended temporaries. +class SimpleTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) + : TemporaryObjectConstructionContext( + ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleTemporaryObjectKind; + } +}; + +/// Represents a temporary object that is constructed for the sole purpose +/// of being immediately copied by an elidable copy/move constructor. +/// For example, T t = T(123); includes a temporary T(123) that is immediately +/// copied to variable t. In such cases the elidable copy can (but not +/// necessarily should) be omitted ("elided") accodring to the rules of the +/// language; the constructor would then construct variable t directly. +/// This construction context contains information of the elidable constructor +/// and its respective construction context. +class ElidedTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + const CXXConstructExpr *ElidedCE; + const ConstructionContext *ElidedCC; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit ElidedTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, + const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) + : TemporaryObjectConstructionContext( + ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), + ElidedCE(ElidedCE), ElidedCC(ElidedCC) { + // Elided constructor and its context should be either both specified + // or both unspecified. In the former case, the constructor must be + // elidable. + assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); + } + +public: + const CXXConstructExpr *getConstructorAfterElision() const { + return ElidedCE; + } + + const ConstructionContext *getConstructionContextAfterElision() const { + return ElidedCC; + } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == ElidedTemporaryObjectKind; } }; diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index a3f4c38944..367591ae1f 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -327,6 +327,9 @@ private: /// \sa naiveCTUEnabled Optional NaiveCTU; + /// \sa shouldElideConstructors + Optional ElideConstructors; + /// A helper function that retrieves option for a given full-qualified /// checker name. @@ -703,6 +706,13 @@ public: /// This is an experimental feature to inline functions from another /// translation units. bool naiveCTUEnabled(); + + /// Returns true if elidable C++ copy-constructors and move-constructors + /// should be actually elided during analysis. Both behaviors are allowed + /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding. + /// Starting with C++17 some elisions become mandatory, and in these cases + /// the option will be ignored. + bool shouldElideConstructors(); }; using AnalyzerOptionsRef = IntrusiveRefCntPtr; diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index e746e8dfa5..486fffbe12 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -71,7 +71,8 @@ AnalysisDeclContextManager::AnalysisDeclContextManager( bool addInitializers, bool addTemporaryDtors, bool addLifetime, bool addLoopExit, bool addScopes, bool synthesizeBodies, bool addStaticInitBranch, bool addCXXNewAllocator, - bool addRichCXXConstructors, CodeInjector *injector) + bool addRichCXXConstructors, bool markElidedCXXConstructors, + CodeInjector *injector) : Injector(injector), FunctionBodyFarm(ASTCtx, injector), SynthesizeBodies(synthesizeBodies) { cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; @@ -84,6 +85,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager( cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors; + cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors; } void AnalysisDeclContextManager::clear() { Contexts.clear(); } diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b02fbe1071..62803f4ba5 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1252,10 +1252,22 @@ void CFGBuilder::findConstructionContexts( if (!Child) return; + auto withExtraLayer = [this, Layer](Stmt *S) { + return ConstructionContextLayer::create(cfg->getBumpVectorContext(), S, + Layer); + }; + switch(Child->getStmtClass()) { case Stmt::CXXConstructExprClass: case Stmt::CXXTemporaryObjectExprClass: { - consumeConstructionContext(Layer, cast(Child)); + // Support pre-C++17 copy elision AST. + auto *CE = cast(Child); + if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) { + assert(CE->getNumArgs() == 1); + findConstructionContexts(withExtraLayer(CE), CE->getArg(0)); + } + + consumeConstructionContext(Layer, CE); break; } // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr. @@ -1294,10 +1306,21 @@ void CFGBuilder::findConstructionContexts( } case Stmt::CXXBindTemporaryExprClass: { auto *BTE = cast(Child); - findConstructionContexts( - ConstructionContextLayer::create(cfg->getBumpVectorContext(), - BTE, Layer), - BTE->getSubExpr()); + findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr()); + break; + } + case Stmt::MaterializeTemporaryExprClass: { + // Normally we don't want to search in MaterializeTemporaryExpr because + // it indicates the beginning of a temporary object construction context, + // so it shouldn't be found in the middle. However, if it is the beginning + // of an elidable copy or move construction context, we need to include it. + if (const auto *CE = + dyn_cast_or_null(Layer->getTriggerStmt())) { + if (CE->isElidable()) { + auto *MTE = cast(Child); + findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr()); + } + } break; } case Stmt::ConditionalOperatorClass: { @@ -4931,7 +4954,7 @@ static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC) { - const Stmt *S1 = nullptr, *S2 = nullptr; + SmallVector Stmts; switch (CC->getKind()) { case ConstructionContext::SimpleConstructorInitializerKind: { OS << ", "; @@ -4944,52 +4967,56 @@ static void print_construction_context(raw_ostream &OS, const auto *CICC = cast(CC); print_initializer(OS, Helper, CICC->getCXXCtorInitializer()); - S2 = CICC->getCXXBindTemporaryExpr(); + Stmts.push_back(CICC->getCXXBindTemporaryExpr()); break; } case ConstructionContext::SimpleVariableKind: { const auto *SDSCC = cast(CC); - S1 = SDSCC->getDeclStmt(); + Stmts.push_back(SDSCC->getDeclStmt()); break; } case ConstructionContext::CXX17ElidedCopyVariableKind: { const auto *CDSCC = cast(CC); - S1 = CDSCC->getDeclStmt(); - S2 = CDSCC->getCXXBindTemporaryExpr(); + Stmts.push_back(CDSCC->getDeclStmt()); + Stmts.push_back(CDSCC->getCXXBindTemporaryExpr()); break; } case ConstructionContext::NewAllocatedObjectKind: { const auto *NECC = cast(CC); - S1 = NECC->getCXXNewExpr(); + Stmts.push_back(NECC->getCXXNewExpr()); break; } case ConstructionContext::SimpleReturnedValueKind: { const auto *RSCC = cast(CC); - S1 = RSCC->getReturnStmt(); + Stmts.push_back(RSCC->getReturnStmt()); break; } case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { const auto *RSCC = cast(CC); - S1 = RSCC->getReturnStmt(); - S2 = RSCC->getCXXBindTemporaryExpr(); + Stmts.push_back(RSCC->getReturnStmt()); + Stmts.push_back(RSCC->getCXXBindTemporaryExpr()); break; } - case ConstructionContext::TemporaryObjectKind: { - const auto *TOCC = cast(CC); - S1 = TOCC->getCXXBindTemporaryExpr(); - S2 = TOCC->getMaterializedTemporaryExpr(); + case ConstructionContext::SimpleTemporaryObjectKind: { + const auto *TOCC = cast(CC); + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); break; } + case ConstructionContext::ElidedTemporaryObjectKind: { + const auto *TOCC = cast(CC); + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); + Stmts.push_back(TOCC->getConstructorAfterElision()); + break; } - if (S1) { - OS << ", "; - Helper.handledStmt(const_cast(S1), OS); - } - if (S2) { - OS << ", "; - Helper.handledStmt(const_cast(S2), OS); } + for (auto I: Stmts) + if (I) { + OS << ", "; + Helper.handledStmt(const_cast(I), OS); + } } static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, diff --git a/lib/Analysis/ConstructionContext.cpp b/lib/Analysis/ConstructionContext.cpp index 9db6f214be..de00375336 100644 --- a/lib/Analysis/ConstructionContext.cpp +++ b/lib/Analysis/ConstructionContext.cpp @@ -61,7 +61,6 @@ const ConstructionContext *ConstructionContext::createFromLayers( // For temporaries with destructors, there may or may not be // lifetime extension on the parent layer. if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) { - assert(ParentLayer->isLast()); // C++17 *requires* elision of the constructor at the return site // and at variable/member initialization site, while previous standards // were allowing an optional elidable constructor. @@ -77,8 +76,33 @@ const ConstructionContext *ConstructionContext::createFromLayers( // both destruction and materialization info attached to it in the AST. if ((MTE = dyn_cast( ParentLayer->getTriggerStmt()))) { - return create(C, BTE, MTE); + // Handle pre-C++17 copy and move elision. + const CXXConstructExpr *ElidedCE = nullptr; + const ConstructionContext *ElidedCC = nullptr; + if (const ConstructionContextLayer *ElidedLayer = + ParentLayer->getParent()) { + ElidedCE = cast(ElidedLayer->getTriggerStmt()); + assert(ElidedCE->isElidable()); + // We're creating a construction context that might have already + // been created elsewhere. Maybe we should unique our construction + // contexts. That's what we often do, but in this case it's unlikely + // to bring any benefits. + ElidedCC = createFromLayers(C, ElidedLayer->getParent()); + if (!ElidedCC) { + // We may fail to create the elided construction context. + // In this case, skip copy elision entirely. + return create(C, BTE, + MTE); + } else { + return create( + C, BTE, MTE, ElidedCE, ElidedCC); + } + } + assert(ParentLayer->isLast()); + return create(C, BTE, MTE); } + assert(ParentLayer->isLast()); + // This is a constructor into a function argument. Not implemented yet. if (isa(ParentLayer->getTriggerStmt())) return nullptr; @@ -99,7 +123,11 @@ const ConstructionContext *ConstructionContext::createFromLayers( llvm_unreachable("Unexpected construction context with destructor!"); } // A temporary object that doesn't require materialization. - return create(C, BTE, /*MTE=*/nullptr); + // In particular, it shouldn't require copy elision, because + // copy/move constructors take a reference, which requires + // materialization to obtain the glvalue. + return create(C, BTE, + /*MTE=*/nullptr); } if (const auto *MTE = dyn_cast(S)) { // If the object requires destruction and is not lifetime-extended, @@ -110,8 +138,28 @@ const ConstructionContext *ConstructionContext::createFromLayers( MTE->getStorageDuration() != SD_FullExpression)) return nullptr; + // Handle pre-C++17 copy and move elision. + const CXXConstructExpr *ElidedCE = nullptr; + const ConstructionContext *ElidedCC = nullptr; + if (const ConstructionContextLayer *ElidedLayer = TopLayer->getParent()) { + ElidedCE = cast(ElidedLayer->getTriggerStmt()); + assert(ElidedCE->isElidable()); + // We're creating a construction context that might have already + // been created elsewhere. Maybe we should unique our construction + // contexts. That's what we often do, but in this case it's unlikely + // to bring any benefits. + ElidedCC = createFromLayers(C, ElidedLayer->getParent()); + if (!ElidedCC) { + // We may fail to create the elided construction context. + // In this case, skip copy elision entirely. + return create(C, nullptr, + MTE); + } + return create( + C, nullptr, MTE, ElidedCE, ElidedCC); + } assert(TopLayer->isLast()); - return create(C, nullptr, MTE); + return create(C, nullptr, MTE); } if (const auto *RS = dyn_cast(S)) { assert(TopLayer->isLast()); diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp index af107ab224..dc0d3ec849 100644 --- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -31,6 +31,7 @@ AnalysisManager::AnalysisManager( Options.shouldConditionalizeStaticInitializers(), /*addCXXNewAllocator=*/true, Options.includeRichConstructorsInCFG(), + Options.shouldElideConstructors(), injector), Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index bddd4435a7..6fa5fec528 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -321,6 +321,12 @@ bool AnalyzerOptions::shouldSerializeStats() { /* Default = */ false); } +bool AnalyzerOptions::shouldElideConstructors() { + return getBooleanOption(ElideConstructors, + "elide-constructors", + /* Default = */ true); +} + int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal, const CheckerBase *C, bool SearchInParents) { diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index f85bfc6e49..497e1fa556 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -209,7 +209,11 @@ std::pair ExprEngine::prepareForObjectConstruction( } llvm_unreachable("Unhandled return value construction context!"); } - case ConstructionContext::TemporaryObjectKind: { + case ConstructionContext::ElidedTemporaryObjectKind: + assert(AMgr.getAnalyzerOptions().shouldElideConstructors()); + // FALL-THROUGH + case ConstructionContext::SimpleTemporaryObjectKind: { + // TODO: Copy elision implementation goes here. const auto *TCC = cast(CC); const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c index 40f86e1504..2105a4faf4 100644 --- a/test/Analysis/analyzer-config.c +++ b/test/Analysis/analyzer-config.c @@ -18,6 +18,7 @@ void foo() { // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true +// CHECK-NEXT: elide-constructors = true // CHECK-NEXT: exploration_strategy = unexplored_first_queue // CHECK-NEXT: faux-bodies = true // CHECK-NEXT: graph-trim-interval = 1000 @@ -35,4 +36,4 @@ void foo() { // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 23 +// CHECK-NEXT: num-entries = 24 diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp index 888cd77eef..0eaefe2abf 100644 --- a/test/Analysis/analyzer-config.cpp +++ b/test/Analysis/analyzer-config.cpp @@ -32,6 +32,7 @@ public: // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true +// CHECK-NEXT: elide-constructors = true // CHECK-NEXT: experimental-enable-naive-ctu-analysis = false // CHECK-NEXT: exploration_strategy = unexplored_first_queue // CHECK-NEXT: faux-bodies = true @@ -50,4 +51,4 @@ public: // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 30 +// CHECK-NEXT: num-entries = 31 diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp index 42fe8539a4..a07bdc7b87 100644 --- a/test/Analysis/cfg-rich-constructors.cpp +++ b/test/Analysis/cfg-rich-constructors.cpp @@ -1,7 +1,11 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11 %s +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ELIDE,CXX11-ELIDE %s // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17 %s +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,ELIDE,CXX17-ELIDE %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w -analyzer-config elide-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,NOELIDE,CXX11-NOELIDE %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w -analyzer-config elide-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,NOELIDE,CXX17-NOELIDE %s class C { public: @@ -99,10 +103,12 @@ void simpleVariableWithOperatorNewInBraces() { // CHECK: void simpleVariableInitializedByValue() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] // CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C) // CXX11-NEXT: 6: C c = C::get(); +// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX17-NEXT: 4: C c = C::get(); void simpleVariableInitializedByValue() { C c = C::get(); @@ -122,17 +128,21 @@ void simpleVariableInitializedByValue() { // CHECK: [B2] // CHECK-NEXT: 1: C::get // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) +// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5]) +// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) // CXX11-NEXT: 4: [B2.3] -// CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 3: [B2.2]() // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) -// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) +// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B3.4] -// CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, class C) // CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK: [B4] @@ -146,7 +156,9 @@ void simpleVariableWithTernaryOperator(bool coin) { // CHECK: void simpleVariableWithElidableCopy() // CHECK: 1: 0 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) -// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) // CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B1.4] // CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) @@ -185,14 +197,16 @@ void referenceVariableWithInitializer() { // CHECK: [B2] // CHECK-NEXT: 1: C::get // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) +// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5]) +// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) // CXX11-NEXT: 4: [B2.3] // CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C) // CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3]) // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) -// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) +// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B3.4] // CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C) @@ -242,7 +256,8 @@ public: // CHECK-NEXT: 7: CFGNewAllocator(C *) // CHECK-NEXT: 8: C::get // CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11]) +// CXX11-ELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11], [B1.12]) +// CXX11-NOELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11]) // CXX11-NEXT: 11: [B1.10] // CXX11-NEXT: 12: [B1.11] (CXXConstructExpr, [B1.13], class C) // CXX11-NEXT: 13: new C([B1.12]) @@ -270,7 +285,8 @@ public: // CHECK: F() // CHECK: 1: E::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class ctor_initializers::E (*)( -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) // CXX11-NEXT: 4: [B1.3] (BindTemporary) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class ctor_initializers::E) // CXX11-NEXT: 6: [B1.5] @@ -326,10 +342,12 @@ C returnBracesWithMultipleItems() { } // CHECK: C returnTemporary() -// CHECK: 1: C() (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B1.2], class C) // CXX11-NEXT: 2: [B1.1] // CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C) // CXX11-NEXT: 4: return [B1.3]; +// CXX17: 1: C() (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 2: return [B1.1]; C returnTemporary() { return C(); @@ -338,7 +356,9 @@ C returnTemporary() { // CHECK: C returnTemporaryWithArgument() // CHECK: 1: nullptr // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) -// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) // CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B1.4] // CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) @@ -352,10 +372,12 @@ C returnTemporaryWithArgument() { // CHECK: C returnTemporaryConstructedByFunction() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] // CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C) // CXX11-NEXT: 6: return [B1.5]; +// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX17-NEXT: 4: return [B1.3]; C returnTemporaryConstructedByFunction() { return C::get(); @@ -364,9 +386,11 @@ C returnTemporaryConstructedByFunction() { // CHECK: C returnChainOfCopies() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] -// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C) +// CXX11-ELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], [B1.8], class C) +// CXX11-NOELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C) // CXX11-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 7: [B1.6] // CXX11-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C) @@ -390,7 +414,8 @@ public: // FIXME: There should be no temporary destructor in C++17. // CHECK: return_stmt_with_dtor::D returnTemporary() -// CXX11: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D) +// CXX11-ELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class return_stmt_with_dtor::D) +// CXX11-NOELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D) // CXX11-NEXT: 2: [B1.1] (BindTemporary) // CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D) // CXX11-NEXT: 4: [B1.3] @@ -409,7 +434,8 @@ D returnTemporary() { // CHECK: void returnByValueIntoVariable() // CHECK: 1: returnTemporary // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class return_stmt_with_dtor::D (*)(void)) -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) // CXX11-NEXT: 4: [B1.3] (BindTemporary) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D) // CXX11-NEXT: 6: [B1.5] @@ -451,7 +477,8 @@ void temporaryInCondition() { } // CHECK: void temporaryInConditionVariable() -// CHECK: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c = C(); @@ -461,6 +488,7 @@ void temporaryInCondition() { // CXX11-NEXT: 8: [B2.6] // CXX11-NEXT: 9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX11-NEXT: T: if [B2.9] +// CXX17: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX17-NEXT: 2: C c = C(); // CXX17-NEXT: 3: c // CXX17-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class C) @@ -475,7 +503,8 @@ void temporaryInConditionVariable() { // CHECK: void temporaryInForLoopConditionVariable() // CHECK: [B2] -// CXX11-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c2 = C(); @@ -494,7 +523,8 @@ void temporaryInConditionVariable() { // CXX17-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX17-NEXT: T: for (...; [B2.7]; ) // CHECK: [B3] -// CXX11-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C) +// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], [B3.3], class C) +// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C) // CXX11-NEXT: 2: [B3.1] // CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.4], class C) // CXX11-NEXT: 4: C c1 = C(); @@ -505,9 +535,9 @@ void temporaryInForLoopConditionVariable() { } -// FIXME: Find construction context for the loop condition variable. // CHECK: void temporaryInWhileLoopConditionVariable() -// CXX11: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c = C(); @@ -603,7 +633,8 @@ void referenceVariableWithInitializer() { // CXX11: [B5] // CXX11-NEXT: 1: D::get // CXX11-NEXT: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void)) -// CXX11-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6]) +// CXX11-ELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6], [B5.7]) +// CXX11-NOELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6]) // CXX11-NEXT: 4: [B5.3] (BindTemporary) // CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B5.5] @@ -611,7 +642,8 @@ void referenceVariableWithInitializer() { // CXX11-NEXT: 8: [B5.7] (BindTemporary) // CXX11: [B6] // CXX11-NEXT: 1: 0 -// CXX11-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D) +// CXX11-ELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], [B6.7], class temporary_object_expr_with_dtors::D) +// CXX11-NOELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 3: [B6.2] (BindTemporary) // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) @@ -699,7 +731,8 @@ public: // CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A) // CXX11-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A) // CXX11-NEXT: 3: [B1.2] -// CXX11-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B) +// CXX11-ELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], [B1.9], class implicit_constructor_conversion::B) +// CXX11-NOELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B) // CXX11-NEXT: 6: [B1.5] (BindTemporary) // CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B) @@ -724,7 +757,8 @@ void implicitConstructionConversionFromTemporary() { // CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5]) // CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A) // CHECK-NEXT: 5: [B1.4] -// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B) +// CXX11-ELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], [B1.11], class implicit_constructor_conversion::B) +// CXX11-NOELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B) // CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B) // CXX11-NEXT: 8: [B1.7] (BindTemporary) // CXX11-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B) diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index 29d327e383..a0e5015535 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -235,7 +235,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -295,7 +295,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -550,12 +550,12 @@ const C &bar3(bool coin) { // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], [B8.5], class A) // CHECK: 2: [B8.1] (BindTemporary) // CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B8.3] // WARNINGS: 5: [B8.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], class A) +// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], [B7.4], class A) // CHECK: 6: [B8.5] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -570,13 +570,13 @@ const C &bar3(bool coin) { // CHECK: 7: [B9.6] (ImplicitCastExpr, NoOp, const class A) // CHECK: 8: [B9.7] // WARNINGS: 9: [B9.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], class A) +// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], [B9.14], class A) // CHECK: 10: [B9.9] (BindTemporary) // CHECK: 11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) // CHECK: 12: [B9.11] (ImplicitCastExpr, NoOp, const class A) // CHECK: 13: [B9.12] // WARNINGS: 14: [B9.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], class A) +// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], [B7.4], class A) // CHECK: 15: [B9.14] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -680,7 +680,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B0 // CHECK: [B4] // WARNINGS: 1: C() (CXXConstructExpr, struct C) -// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], struct C) +// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], [B4.5], struct C) // CHECK: 2: [B4.1] (BindTemporary) // CHECK: 3: [B4.2] (ImplicitCastExpr, NoOp, const struct C) // CHECK: 4: [B4.3] @@ -733,7 +733,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B0 // CHECK: [B3] // CXX98-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], struct D) +// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], [B3.4], struct D) // CXX98: 2: [B3.1] (ImplicitCastExpr, NoOp, const struct D) // CXX98: 3: [B3.2] // CXX98-WARNINGS: 4: [B3.3] (CXXConstructExpr, struct D) @@ -745,7 +745,7 @@ const C &bar3(bool coin) { // CXX98: 9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX98: T: if [B3.9] // CXX11-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) +// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], [B3.3], struct D) // CXX11: 2: [B3.1] // CXX11-WARNINGS: 3: [B3.2] (CXXConstructExpr, struct D) // CXX11-ANALYZER: 3: [B3.2] (CXXConstructExpr, [B3.4], struct D) @@ -789,7 +789,7 @@ const C &bar3(bool coin) { // CHECK: Succs (2): B3 B2 // CHECK: [B5] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B5.2], [B5.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B5.2], [B5.4], [B5.5], class A) // CHECK: 2: [B5.1] (BindTemporary) // CHECK: 3: [B5.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B5.3] @@ -809,7 +809,7 @@ const C &bar3(bool coin) { // CHECK: 7: [B6.6] (ImplicitCastExpr, NoOp, const class A) // CHECK: 8: [B6.7] // WARNINGS: 9: [B6.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B6.8] (CXXConstructExpr, [B6.10], [B6.13], class A) +// ANALYZER: 9: [B6.8] (CXXConstructExpr, [B6.10], [B6.13], [B6.14], class A) // CHECK: 10: [B6.9] (BindTemporary) // CHECK: 11: A([B6.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) // CHECK: 12: [B6.11] (ImplicitCastExpr, NoOp, const class A) @@ -852,7 +852,7 @@ const C &bar3(bool coin) { // CHECK: Succs (2): B9 B8 // CHECK: [B11] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B11.2], [B11.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B11.2], [B11.4], [B11.5], class A) // CHECK: 2: [B11.1] (BindTemporary) // CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B11.3] @@ -872,7 +872,7 @@ const C &bar3(bool coin) { // CHECK: 7: [B12.6] (ImplicitCastExpr, NoOp, const class A) // CHECK: 8: [B12.7] // WARNINGS: 9: [B12.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B12.8] (CXXConstructExpr, [B12.10], [B12.13], class A) +// ANALYZER: 9: [B12.8] (CXXConstructExpr, [B12.10], [B12.13], [B12.14], class A) // CHECK: 10: [B12.9] (BindTemporary) // CHECK: 11: A([B12.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) // CHECK: 12: [B12.11] (ImplicitCastExpr, NoOp, const class A) @@ -935,7 +935,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A) // CHECK: 2: [B6.1] (BindTemporary) // CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B6.3] @@ -1001,7 +1001,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A) // CHECK: 2: [B6.1] (BindTemporary) // CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B6.3] @@ -1086,7 +1086,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -1130,7 +1130,7 @@ const C &bar3(bool coin) { // CHECK: 1: A::make // CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) // WARNINGS: 3: [B1.2]() -// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) // CHECK: 4: [B1.3] (BindTemporary) // CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 6: [B1.5] -- GitLab From 22d5fd239a3ecd5736f04fd60a38d06af17cad38 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:11:42 +0000 Subject: [PATCH 0322/1023] [analyzer] Re-enable lifetime extension for temporaries without destructors. When an object's class provides no destructor, it's less important to materialize that object properly because we don't have to model the destructor correctly, so previously we skipped the support for these syntax patterns. Additionally, fix support for construction contexts of "static temporaries" (temporaries that are lifetime-extended by static references) because it turned out that we only had tests for them without destructors, which caused us to regress when we re-introduced the construction context for such temporaries. Differential Revision: https://reviews.llvm.org/D47658 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 16 ++++---- test/Analysis/lifetime-extension.cpp | 39 +++++++++++++------- test/Analysis/temporaries-callback-order.cpp | 7 +--- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 497e1fa556..2e8e14a7a0 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -218,12 +218,6 @@ std::pair ExprEngine::prepareForObjectConstruction( const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); - if (!BTE) { - // FIXME: Lifetime extension for temporaries without destructors - // is not implemented yet. - MTE = nullptr; - } - if (MTE) { if (const ValueDecl *VD = MTE->getExtendingDecl()) { assert(MTE->getStorageDuration() != SD_FullExpression); @@ -238,16 +232,20 @@ std::pair ExprEngine::prepareForObjectConstruction( } } + SVal V = UnknownVal(); if (MTE && MTE->getStorageDuration() != SD_FullExpression) { // If the temporary is lifetime-extended, don't save the BTE, // because we don't need a temporary destructor, but an automatic // destructor. BTE = nullptr; + + if (MTE->getStorageDuration() == SD_Static || + MTE->getStorageDuration() == SD_Thread) + V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E)); } - // FIXME: Support temporaries lifetime-extended via static references. - // They'd need a getCXXStaticTempObjectRegion(). - SVal V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); + if (V.isUnknown()) + V = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); if (BTE) State = addObjectUnderConstruction(State, BTE, LCtx, V); diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp index 1bad166d2d..ee55107838 100644 --- a/test/Analysis/lifetime-extension.cpp +++ b/test/Analysis/lifetime-extension.cpp @@ -234,25 +234,24 @@ void f2() { } // end namespace maintain_original_object_address_on_move namespace maintain_address_of_copies { -class C; -struct AddressVector { - C *buf[10]; +template struct AddressVector { + const T *buf[10]; int len; AddressVector() : len(0) {} - void push(C *c) { - buf[len] = c; + void push(const T *t) { + buf[len] = t; ++len; } }; class C { - AddressVector &v; + AddressVector &v; public: - C(AddressVector &v) : v(v) { v.push(this); } + C(AddressVector &v) : v(v) { v.push(this); } ~C() { v.push(this); } #ifdef MOVES @@ -268,11 +267,11 @@ public: #endif } // no-warning - static C make(AddressVector &v) { return C(v); } + static C make(AddressVector &v) { return C(v); } }; void f1() { - AddressVector v; + AddressVector v; { C c = C(v); } @@ -296,7 +295,7 @@ void f1() { } void f2() { - AddressVector v; + AddressVector v; { const C &c = C::make(v); } @@ -320,7 +319,7 @@ void f2() { } void f3() { - AddressVector v; + AddressVector v; { C &&c = C::make(v); } @@ -343,12 +342,12 @@ void f3() { #endif } -C doubleMake(AddressVector &v) { +C doubleMake(AddressVector &v) { return C::make(v); } void f4() { - AddressVector v; + AddressVector v; { C c = doubleMake(v); } @@ -382,4 +381,18 @@ void f4() { // expected-warning@-12{{UNKNOWN}} #endif } + +class NoDtor { + AddressVector &v; + +public: + NoDtor(AddressVector &v) : v(v) { v.push(this); } +}; + +void f5() { + AddressVector v; + const NoDtor &N = NoDtor(v); + clang_analyzer_eval(v.buf[0] == &N); // expected-warning{{TRUE}} +} + } // end namespace maintain_address_of_copies diff --git a/test/Analysis/temporaries-callback-order.cpp b/test/Analysis/temporaries-callback-order.cpp index df916cc4e7..120fabc104 100644 --- a/test/Analysis/temporaries-callback-order.cpp +++ b/test/Analysis/temporaries-callback-order.cpp @@ -8,11 +8,7 @@ struct Sub : Super { }; void testTemporaries() { - // This triggers RegionChanges twice: - // - Once for zero-initialization of the structure. - // - Once for creating a temporary region and copying the structure there. - // FIXME: This code shouldn't really produce the extra temporary, however - // that's how we behave for now. + // This triggers RegionChanges once for zero-initialization of the structure. Sub().m(); } @@ -29,7 +25,6 @@ void seeIfCheckBindWorks() { // testTemporaries(): // CHECK-NEXT: RegionChanges -// CHECK-NEXT: RegionChanges // Make sure there's no further output. // CHECK-NOT: Bind -- GitLab From c3d3ed8659fa146ca98cb364560cfba1469d108b Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:18:52 +0000 Subject: [PATCH 0323/1023] [CFG] [analyzer] Simplify lifetime-extended temporary construction contexts. When a temporary object is materialized and through that obtain lifetime that is longer than the duration of the full-expression, it does not require a temporary object destructor; it will be destroyed in a different manner. Therefore it's not necessary to include CXXBindTemporaryExpr into the construction context for such temporary in the CFG only to make clients throw it away. Differential Revision: https://reviews.llvm.org/D47667 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335798 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ConstructionContext.cpp | 7 +++++++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 9 +-------- test/Analysis/auto-obj-dtors-cfg-output.cpp | 12 ++++++------ test/Analysis/cfg-rich-constructors.cpp | 14 +++++++------- test/Analysis/temp-obj-dtors-cfg-output.cpp | 8 ++++---- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/Analysis/ConstructionContext.cpp b/lib/Analysis/ConstructionContext.cpp index de00375336..ed1e632432 100644 --- a/lib/Analysis/ConstructionContext.cpp +++ b/lib/Analysis/ConstructionContext.cpp @@ -76,6 +76,13 @@ const ConstructionContext *ConstructionContext::createFromLayers( // both destruction and materialization info attached to it in the AST. if ((MTE = dyn_cast( ParentLayer->getTriggerStmt()))) { + if (MTE->getStorageDuration() != SD_FullExpression) { + // If the temporary is lifetime-extended, don't save the BTE, + // because we don't need a temporary destructor, but an automatic + // destructor. + BTE = nullptr; + } + // Handle pre-C++17 copy and move elision. const CXXConstructExpr *ElidedCE = nullptr; const ConstructionContext *ElidedCC = nullptr; diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 2e8e14a7a0..5d0428ac65 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -217,6 +217,7 @@ std::pair ExprEngine::prepareForObjectConstruction( const auto *TCC = cast(CC); const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); + SVal V = UnknownVal(); if (MTE) { if (const ValueDecl *VD = MTE->getExtendingDecl()) { @@ -230,14 +231,6 @@ std::pair ExprEngine::prepareForObjectConstruction( CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true; } } - } - - SVal V = UnknownVal(); - if (MTE && MTE->getStorageDuration() != SD_FullExpression) { - // If the temporary is lifetime-extended, don't save the BTE, - // because we don't need a temporary destructor, but an automatic - // destructor. - BTE = nullptr; if (MTE->getStorageDuration() == SD_Static || MTE->getStorageDuration() == SD_Thread) diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp index cd87d3c443..7e678a1ec7 100644 --- a/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -56,7 +56,7 @@ extern const bool UV; // CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class A) // CHECK-NEXT: 5: const A &b = a; // WARNINGS-NEXT: 6: A() (CXXConstructExpr, class A) -// ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.7], [B1.9], class A) +// ANALYZER-NEXT: 6: A() (CXXConstructExpr, [B1.9], class A) // CHECK-NEXT: 7: [B1.6] (BindTemporary) // CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A) // CHECK-NEXT: 9: [B1.8] @@ -78,7 +78,7 @@ void test_const_ref() { // CHECK: [B1] // WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) // CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A) -// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) +// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.3], class A) // CHECK-NEXT: 2: [B1.1] (BindTemporary) // CXX98-NEXT: 3: [B1.2].x // CXX98-NEXT: 4: [B1.3] @@ -102,7 +102,7 @@ void test_const_ref_to_field() { // CHECK: [B1] // WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) // CXX98-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], class A) -// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) +// CXX11-ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.3], class A) // CHECK-NEXT: 2: [B1.1] (BindTemporary) // CXX98-NEXT: 3: A::x // CXX98-NEXT: 4: &[B1.3] @@ -130,20 +130,20 @@ void test_pointer_to_member() { // CHECK-NEXT: Succs (1): B1 // CHECK: [B1] // WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) -// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.4], class A) // CHECK-NEXT: 2: [B1.1] (BindTemporary) // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 5: {[B1.4]} // CHECK-NEXT: 6: B b = {A()}; // WARNINGS-NEXT: 7: A() (CXXConstructExpr, class A) -// ANALYZER-NEXT: 7: A() (CXXConstructExpr, [B1.8], [B1.10], class A) +// ANALYZER-NEXT: 7: A() (CXXConstructExpr, [B1.10], class A) // CHECK-NEXT: 8: [B1.7] (BindTemporary) // CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class A) // CHECK-NEXT: 10: [B1.9] // CHECK-NEXT: 11: {[B1.10]} // WARNINGS-NEXT: 12: A() (CXXConstructExpr, class A) -// ANALYZER-NEXT: 12: A() (CXXConstructExpr, [B1.13], [B1.15], class A) +// ANALYZER-NEXT: 12: A() (CXXConstructExpr, [B1.15], class A) // CHECK-NEXT: 13: [B1.12] (BindTemporary) // CHECK-NEXT: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A) // CHECK-NEXT: 15: [B1.14] diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp index a07bdc7b87..3944141b92 100644 --- a/test/Analysis/cfg-rich-constructors.cpp +++ b/test/Analysis/cfg-rich-constructors.cpp @@ -597,7 +597,7 @@ void temporaryInCondition() { // CHECK: void referenceVariableWithConstructor() // CHECK: 1: 0 -// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], [B1.4], const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.4], const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 3: [B1.2] (BindTemporary) // CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 5: const temporary_object_expr_with_dtors::D &d(0); @@ -607,7 +607,7 @@ void referenceVariableWithConstructor() { } // CHECK: void referenceVariableWithInitializer() -// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], [B1.4], class temporary_object_expr_with_dtors::D) +// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.4], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 2: [B1.1] (BindTemporary) // CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 4: [B1.3] @@ -638,7 +638,7 @@ void referenceVariableWithInitializer() { // CXX11-NEXT: 4: [B5.3] (BindTemporary) // CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B5.5] -// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B5.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 8: [B5.7] (BindTemporary) // CXX11: [B6] // CXX11-NEXT: 1: 0 @@ -648,7 +648,7 @@ void referenceVariableWithInitializer() { // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B6.5] -// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B6.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 8: [B6.7] (BindTemporary) // CXX11: [B7] // CXX11-NEXT: 1: coin @@ -663,11 +663,11 @@ void referenceVariableWithInitializer() { // CXX17: [B2] // CXX17-NEXT: 1: D::get // CXX17-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void)) -// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B1.3]) +// CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3]) // CXX17-NEXT: 4: [B2.3] (BindTemporary) // CXX17: [B3] // CXX17-NEXT: 1: 0 -// CXX17-NEXT: 2: [B3.1] (CXXConstructExpr, [B3.3], [B1.3], class temporary_object_expr_with_dtors::D) +// CXX17-NEXT: 2: [B3.1] (CXXConstructExpr, [B1.3], class temporary_object_expr_with_dtors::D) // CXX17-NEXT: 3: [B3.2] (BindTemporary) // CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CXX17: [B4] @@ -680,7 +680,7 @@ void referenceVariableWithTernaryOperator(bool coin) { // CHECK: void referenceWithFunctionalCast() // CHECK: 1: 1 -// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], [B1.5], class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.5], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 3: [B1.2] (BindTemporary) // CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B1.3]) (CXXFunctionalCastExpr, ConstructorCon // CHECK-NEXT: 5: [B1.4] diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index a0e5015535..e2c6267630 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -857,7 +857,7 @@ const C &bar3(bool coin) { // CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B11.3] // WARNINGS: 5: [B11.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B11.6], [B10.3], class A) +// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B10.3], class A) // CHECK: 6: [B11.5] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 @@ -878,7 +878,7 @@ const C &bar3(bool coin) { // CHECK: 12: [B12.11] (ImplicitCastExpr, NoOp, const class A) // CHECK: 13: [B12.12] // WARNINGS: 14: [B12.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B12.13] (CXXConstructExpr, [B12.15], [B10.3], class A) +// ANALYZER: 14: [B12.13] (CXXConstructExpr, [B10.3], class A) // CHECK: 15: [B12.14] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 @@ -1104,7 +1104,7 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.4], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -1150,7 +1150,7 @@ const C &bar3(bool coin) { // CHECK: 1: A::make // CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) // WARNINGS: 3: [B1.2]() -// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.6]) // CHECK: 4: [B1.3] (BindTemporary) // CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 6: [B1.5] -- GitLab From 9d345ab5b4a4a760b15f1526310e19b84117c401 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:30:18 +0000 Subject: [PATCH 0324/1023] [analyzer] Add support for pre-C++17 copy elision. r335795 adds copy elision information to CFG. This commit allows static analyzer to elide elidable copy constructors by constructing the objects that were previously subject to elidable copy directly in the target region of the copy. The chain of elided constructors may potentially be indefinitely long. This only happens when the object is being returned from a function which in turn is returned from another function, etc. NRVO is not supported yet. Differential Revision: https://reviews.llvm.org/D47671 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335800 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/ExprEngine.h | 23 ++- lib/StaticAnalyzer/Core/ExprEngine.cpp | 146 ++++++++++---- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 47 ++++- test/Analysis/cxx17-mandatory-elision.cpp | 30 ++- test/Analysis/gtest.cpp | 6 +- .../inlining/temp-dtors-path-notes.cpp | 9 +- test/Analysis/lifetime-extension.cpp | 158 +++++---------- test/Analysis/temporaries.cpp | 188 ++++-------------- 8 files changed, 286 insertions(+), 321 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 3c0ab4d752..25849e94c8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -780,9 +780,30 @@ private: llvm::PointerUnion P, const LocationContext *LC); + /// If the given expression corresponds to a temporary that was used for + /// passing into an elidable copy/move constructor and that constructor + /// was actually elided, track that we also need to elide the destructor. + static ProgramStateRef elideDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + + /// Stop tracking the destructor that corresponds to an elided constructor. + static ProgramStateRef + cleanupElidedDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + + /// Returns true if the given expression corresponds to a temporary that + /// was constructed for passing into an elidable copy/move constructor + /// and that constructor was actually elided. + static bool isDestructorElided(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + /// Check if all objects under construction have been fully constructed /// for the given context range (including FromLC, not including ToLC). - /// This is useful for assertions. + /// This is useful for assertions. Also checks if elided destructors + /// were cleaned up. static bool areAllObjectsFullyConstructed(ProgramStateRef State, const LocationContext *FromLC, const LocationContext *ToLC); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 54139c229d..c3f5b42a9f 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -139,7 +139,8 @@ public: // encountered. This list may be expanded when new actions are implemented. assert(getCXXCtorInitializer() || isa(getStmt()) || isa(getStmt()) || isa(getStmt()) || - isa(getStmt())); + isa(getStmt()) || + isa(getStmt())); } const Stmt *getStmt() const { @@ -183,6 +184,14 @@ typedef llvm::ImmutableMap REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) +// Additionally, track a set of destructors that correspond to elided +// constructors when copy elision occurs. +typedef std::pair + ElidedDestructorItem; +typedef llvm::ImmutableSet + ElidedDestructorSet; +REGISTER_TRAIT_WITH_PROGRAMSTATE(ElidedDestructors, + ElidedDestructorSet); //===----------------------------------------------------------------------===// // Engine construction and deletion. @@ -358,14 +367,12 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, // a new temporary region out of thin air and copy the contents of the object // (which are currently present in the Environment, because Init is an rvalue) // into that region. This is not correct, but it is better than nothing. - bool FoundOriginalMaterializationRegion = false; const TypedValueRegion *TR = nullptr; if (const auto *MT = dyn_cast(Result)) { if (Optional V = getObjectUnderConstruction(State, MT, LC)) { - FoundOriginalMaterializationRegion = true; - TR = cast(V->getAsRegion()); - assert(TR); State = finishObjectConstruction(State, MT, LC); + State = State->BindExpr(Result, LC, *V); + return State; } else { StorageDuration SD = MT->getStorageDuration(); // If this object is bound to a reference with static storage duration, we @@ -402,35 +409,33 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, } } - if (!FoundOriginalMaterializationRegion) { - // What remains is to copy the value of the object to the new region. - // FIXME: In other words, what we should always do is copy value of the - // Init expression (which corresponds to the bigger object) to the whole - // temporary region TR. However, this value is often no longer present - // in the Environment. If it has disappeared, we instead invalidate TR. - // Still, what we can do is assign the value of expression Ex (which - // corresponds to the sub-object) to the TR's sub-region Reg. At least, - // values inside Reg would be correct. - SVal InitVal = State->getSVal(Init, LC); - if (InitVal.isUnknown()) { - InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(), - currBldrCtx->blockCount()); - State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false); - - // Then we'd need to take the value that certainly exists and bind it - // over. - if (InitValWithAdjustments.isUnknown()) { - // Try to recover some path sensitivity in case we couldn't - // compute the value. - InitValWithAdjustments = getSValBuilder().conjureSymbolVal( - Result, LC, InitWithAdjustments->getType(), - currBldrCtx->blockCount()); - } - State = - State->bindLoc(Reg.castAs(), InitValWithAdjustments, LC, false); - } else { - State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false); + // What remains is to copy the value of the object to the new region. + // FIXME: In other words, what we should always do is copy value of the + // Init expression (which corresponds to the bigger object) to the whole + // temporary region TR. However, this value is often no longer present + // in the Environment. If it has disappeared, we instead invalidate TR. + // Still, what we can do is assign the value of expression Ex (which + // corresponds to the sub-object) to the TR's sub-region Reg. At least, + // values inside Reg would be correct. + SVal InitVal = State->getSVal(Init, LC); + if (InitVal.isUnknown()) { + InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(), + currBldrCtx->blockCount()); + State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false); + + // Then we'd need to take the value that certainly exists and bind it + // over. + if (InitValWithAdjustments.isUnknown()) { + // Try to recover some path sensitivity in case we couldn't + // compute the value. + InitValWithAdjustments = getSValBuilder().conjureSymbolVal( + Result, LC, InitWithAdjustments->getType(), + currBldrCtx->blockCount()); } + State = + State->bindLoc(Reg.castAs(), InitValWithAdjustments, LC, false); + } else { + State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false); } // The result expression would now point to the correct sub-region of the @@ -438,10 +443,8 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, // correctly in case (Result == Init). State = State->BindExpr(Result, LC, Reg); - if (!FoundOriginalMaterializationRegion) { - // Notify checkers once for two bindLoc()s. - State = processRegionChange(State, TR, LC); - } + // Notify checkers once for two bindLoc()s. + State = processRegionChange(State, TR, LC); return State; } @@ -475,6 +478,30 @@ ProgramStateRef ExprEngine::finishObjectConstruction( return State->remove(Key); } +ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC) { + ElidedDestructorItem I(BTE, LC); + assert(!State->contains(I)); + return State->add(I); +} + +ProgramStateRef +ExprEngine::cleanupElidedDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC) { + ElidedDestructorItem I(BTE, LC); + assert(State->contains(I)); + return State->remove(I); +} + +bool ExprEngine::isDestructorElided(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC) { + ElidedDestructorItem I(BTE, LC); + return State->contains(I); +} + bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State, const LocationContext *FromLC, const LocationContext *ToLC) { @@ -485,6 +512,10 @@ bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State, if (I.first.getLocationContext() == LC) return false; + for (auto I: State->get()) + if (I.second == LC) + return false; + LC = LC->getParent(); } return true; @@ -529,6 +560,14 @@ static void printObjectsUnderConstructionForContext(raw_ostream &Out, Key.print(Out, nullptr, PP); Out << " : " << Value << NL; } + + for (auto I : State->get()) { + if (I.second != LC) + continue; + Out << '(' << I.second << ',' << (const void *)I.first << ") "; + I.first->printPretty(Out, nullptr, PP); + Out << " : (constructor elided)" << NL; + } } void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State, @@ -1003,10 +1042,11 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst) { - ExplodedNodeSet CleanDtorState; - StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx); + const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr(); ProgramStateRef State = Pred->getState(); + const LocationContext *LC = Pred->getLocationContext(); const MemRegion *MR = nullptr; + if (Optional V = getObjectUnderConstruction(State, D.getBindTemporaryExpr(), Pred->getLocationContext())) { @@ -1017,6 +1057,21 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, Pred->getLocationContext()); MR = V->getAsRegion(); } + + // If copy elision has occured, and the constructor corresponding to the + // destructor was elided, we need to skip the destructor as well. + if (isDestructorElided(State, BTE, LC)) { + State = cleanupElidedDestructor(State, BTE, LC); + NodeBuilder Bldr(Pred, Dst, *currBldrCtx); + PostImplicitCall PP(D.getDestructorDecl(getContext()), + D.getBindTemporaryExpr()->getLocStart(), + Pred->getLocationContext()); + Bldr.generateNode(PP, State, Pred); + return; + } + + ExplodedNodeSet CleanDtorState; + StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx); StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State); QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType(); @@ -2201,8 +2256,21 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, // it must be a separate problem. assert(isa(I.first.getStmt())); State = State->remove(I.first); + // Also cleanup the elided destructor info. + ElidedDestructorItem Item( + cast(I.first.getStmt()), + I.first.getLocationContext()); + State = State->remove(Item); } + // Also suppress the assertion for elided destructors when temporary + // destructors are not provided at all by the CFG, because there's no + // good place to clean them up. + if (!AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG()) + for (auto I : State->get()) + if (I.second == LC) + State = State->remove(I); + LC = LC->getParent(); } if (State != Pred->getState()) { diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 5d0428ac65..dc124fc3ff 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -209,12 +209,37 @@ std::pair ExprEngine::prepareForObjectConstruction( } llvm_unreachable("Unhandled return value construction context!"); } - case ConstructionContext::ElidedTemporaryObjectKind: + case ConstructionContext::ElidedTemporaryObjectKind: { assert(AMgr.getAnalyzerOptions().shouldElideConstructors()); - // FALL-THROUGH + const auto *TCC = cast(CC); + const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); + const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); + const CXXConstructExpr *CE = TCC->getConstructorAfterElision(); + + // Support pre-C++17 copy elision. We'll have the elidable copy + // constructor in the AST and in the CFG, but we'll skip it + // and construct directly into the final object. This call + // also sets the CallOpts flags for us. + SVal V; + std::tie(State, V) = prepareForObjectConstruction( + CE, State, LCtx, TCC->getConstructionContextAfterElision(), CallOpts); + + // Remember that we've elided the constructor. + State = addObjectUnderConstruction(State, CE, LCtx, V); + + // Remember that we've elided the destructor. + if (BTE) + State = elideDestructor(State, BTE, LCtx); + + // Instead of materialization, shamelessly return + // the final object destination. + if (MTE) + State = addObjectUnderConstruction(State, MTE, LCtx, V); + + return std::make_pair(State, V); + } case ConstructionContext::SimpleTemporaryObjectKind: { - // TODO: Copy elision implementation goes here. - const auto *TCC = cast(CC); + const auto *TCC = cast(CC); const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); SVal V = UnknownVal(); @@ -266,6 +291,20 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, SVal Target = UnknownVal(); + if (Optional ElidedTarget = + getObjectUnderConstruction(State, CE, LCtx)) { + // We've previously modeled an elidable constructor by pretending that it in + // fact constructs into the correct target. This constructor can therefore + // be skipped. + Target = *ElidedTarget; + StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); + State = finishObjectConstruction(State, CE, LCtx); + if (auto L = Target.getAs()) + State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); + Bldr.generateNode(CE, Pred, State); + return; + } + // FIXME: Handle arrays, which run the same constructor for every element. // For now, we just run the first constructor (which should still invalidate // the entire array). diff --git a/test/Analysis/cxx17-mandatory-elision.cpp b/test/Analysis/cxx17-mandatory-elision.cpp index e826105279..cf77912ea6 100644 --- a/test/Analysis/cxx17-mandatory-elision.cpp +++ b/test/Analysis/cxx17-mandatory-elision.cpp @@ -1,5 +1,17 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -analyzer-config elide-constructors=false -DNO_ELIDE_FLAG -verify %s + +// Copy elision always occurs in C++17, otherwise it's under +// an on-by-default flag. +#if __cplusplus >= 201703L + #define ELIDE 1 +#else + #ifndef NO_ELIDE_FLAG + #define ELIDE 1 + #endif +#endif void clang_analyzer_eval(bool); @@ -39,9 +51,9 @@ public: C() : t(T(4)) { S s = {1, 2, 3}; t.s = s; - // FIXME: Should be TRUE in C++11 as well. + // FIXME: Should be TRUE regardless of copy elision. clang_analyzer_eval(t.w == 4); -#if __cplusplus >= 201703L +#ifdef ELIDE // expected-warning@-2{{TRUE}} #else // expected-warning@-4{{UNKNOWN}} @@ -149,7 +161,7 @@ void testMultipleReturns() { AddressVector v; ClassWithoutDestructor c = make3(v); -#if __cplusplus >= 201703L +#if ELIDE clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} clang_analyzer_eval(v.buf[0] == &c); // expected-warning{{TRUE}} #else @@ -184,13 +196,13 @@ void testVariable() { ClassWithDestructor c = ClassWithDestructor(v); // Check if the last destructor is an automatic destructor. // A temporary destructor would have fired by now. -#if __cplusplus >= 201703L +#if ELIDE clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} #else clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}} #endif } -#if __cplusplus >= 201703L +#if ELIDE // 0. Construct the variable. // 1. Destroy the variable. clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} @@ -218,13 +230,13 @@ void testCtorInitializer() { TestCtorInitializer t(v); // Check if the last destructor is an automatic destructor. // A temporary destructor would have fired by now. -#if __cplusplus >= 201703L +#if ELIDE clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} #else clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}} #endif } -#if __cplusplus >= 201703L +#if ELIDE // 0. Construct the member variable. // 1. Destroy the member variable. clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} @@ -257,14 +269,14 @@ void testMultipleReturnsWithDestructors() { ClassWithDestructor c = make3(v); // Check if the last destructor is an automatic destructor. // A temporary destructor would have fired by now. -#if __cplusplus >= 201703L +#if ELIDE clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}} #else clang_analyzer_eval(v.len == 9); // expected-warning{{TRUE}} #endif } -#if __cplusplus >= 201703L +#if ELIDE // 0. Construct the variable. Yes, constructor in make1() constructs // the variable 'c'. // 1. Destroy the variable. diff --git a/test/Analysis/gtest.cpp b/test/Analysis/gtest.cpp index 1c6e01a617..e68303d549 100644 --- a/test/Analysis/gtest.cpp +++ b/test/Analysis/gtest.cpp @@ -154,13 +154,11 @@ void testConstrainState(int p) { void testAssertSymbolicPtr(const bool *b) { ASSERT_TRUE(*b); // no-crash - // FIXME: Our solver doesn't handle this well yet. - clang_analyzer_eval(*b); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(*b); // expected-warning{{TRUE}} } void testAssertSymbolicRef(const bool &b) { ASSERT_TRUE(b); // no-crash - // FIXME: Our solver doesn't handle this well yet. - clang_analyzer_eval(b); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(b); // expected-warning{{TRUE}} } diff --git a/test/Analysis/inlining/temp-dtors-path-notes.cpp b/test/Analysis/inlining/temp-dtors-path-notes.cpp index 6d1a42ff50..40b26b5c91 100644 --- a/test/Analysis/inlining/temp-dtors-path-notes.cpp +++ b/test/Analysis/inlining/temp-dtors-path-notes.cpp @@ -30,19 +30,14 @@ public: }; void test(int coin) { - // We'd divide by zero in the temporary destructor that goes after the - // elidable copy-constructor from C(0) to the lifetime-extended temporary. - // So in fact this example has nothing to do with lifetime extension. - // Actually, it would probably be better to elide the constructor, and - // put the note for the destructor call at the closing brace after nop. + // We'd divide by zero in the automatic destructor for variable 'c'. const C &c = coin ? C(1) : C(0); // expected-note {{Assuming 'coin' is 0}} // expected-note@-1{{'?' condition is false}} // expected-note@-2{{Passing the value 0 via 1st parameter 'x'}} // expected-note@-3{{Calling constructor for 'C'}} // expected-note@-4{{Returning from constructor for 'C'}} - // expected-note@-5{{Calling '~C'}} c.nop(); -} +} // expected-note{{Calling '~C'}} } // end namespace test_lifetime_extended_temporary namespace test_bug_after_dtor { diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp index ee55107838..4337632b31 100644 --- a/test/Analysis/lifetime-extension.cpp +++ b/test/Analysis/lifetime-extension.cpp @@ -97,13 +97,10 @@ void f1() { void f2() { C *after, *before; - C c = C(1, &after, &before); - clang_analyzer_eval(after == before); -#ifdef TEMPORARIES - // expected-warning@-2{{TRUE}} -#else - // expected-warning@-4{{UNKNOWN}} -#endif + { + C c = C(1, &after, &before); + } + clang_analyzer_eval(after == before); // expected-warning{{TRUE}} } void f3(bool coin) { @@ -129,6 +126,7 @@ void f4(bool coin) { // operator. Ideally also add support for the binary conditional operator in // C++. Because for now it calls the constructor for the condition twice. if (coin) { + // FIXME: Should not warn. clang_analyzer_eval(after == before); #ifdef TEMPORARIES // expected-warning@-2{{The left operand of '==' is a garbage value}} @@ -136,13 +134,12 @@ void f4(bool coin) { // expected-warning@-4{{UNKNOWN}} #endif } else { + // FIXME: Should be TRUE. clang_analyzer_eval(after == before); #ifdef TEMPORARIES - // Seems to work at the moment, but also seems accidental. - // Feel free to break. - // expected-warning@-4{{TRUE}} + // expected-warning@-2{{FALSE}} #else - // expected-warning@-6{{UNKNOWN}} + // expected-warning@-4{{UNKNOWN}} #endif } } @@ -234,24 +231,25 @@ void f2() { } // end namespace maintain_original_object_address_on_move namespace maintain_address_of_copies { +class C; -template struct AddressVector { - const T *buf[10]; +struct AddressVector { + C *buf[10]; int len; AddressVector() : len(0) {} - void push(const T *t) { - buf[len] = t; + void push(C *c) { + buf[len] = c; ++len; } }; class C { - AddressVector &v; + AddressVector &v; public: - C(AddressVector &v) : v(v) { v.push(this); } + C(AddressVector &v) : v(v) { v.push(this); } ~C() { v.push(this); } #ifdef MOVES @@ -267,132 +265,70 @@ public: #endif } // no-warning - static C make(AddressVector &v) { return C(v); } + static C make(AddressVector &v) { return C(v); } }; void f1() { - AddressVector v; + AddressVector v; { C c = C(v); } - // 0. Create the original temporary and lifetime-extend it into variable 'c' - // construction argument. - // 1. Construct variable 'c' (elidable copy/move). - // 2. Destroy the temporary. - // 3. Destroy variable 'c'. - clang_analyzer_eval(v.len == 4); - clang_analyzer_eval(v.buf[0] == v.buf[2]); - clang_analyzer_eval(v.buf[1] == v.buf[3]); -#ifdef TEMPORARIES - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} -#else - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} -#endif + // 0. Construct variable 'c' (copy/move elided). + // 1. Destroy variable 'c'. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} } void f2() { - AddressVector v; + AddressVector v; { const C &c = C::make(v); } - // 0. Construct the original temporary within make(), - // 1. Construct the return value of make() (elidable copy/move) and - // lifetime-extend it via reference 'c', - // 2. Destroy the temporary within make(), - // 3. Destroy the temporary lifetime-extended by 'c'. - clang_analyzer_eval(v.len == 4); - clang_analyzer_eval(v.buf[0] == v.buf[2]); - clang_analyzer_eval(v.buf[1] == v.buf[3]); + // 0. Construct the return value of make() (copy/move elided) and + // lifetime-extend it directly via reference 'c', + // 1. Destroy the temporary lifetime-extended by 'c'. + clang_analyzer_eval(v.len == 2); + clang_analyzer_eval(v.buf[0] == v.buf[1]); #ifdef TEMPORARIES - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} #else - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} #endif } void f3() { - AddressVector v; + AddressVector v; { C &&c = C::make(v); } - // 0. Construct the original temporary within make(), - // 1. Construct the return value of make() (elidable copy/move) and - // lifetime-extend it via reference 'c', - // 2. Destroy the temporary within make(), - // 3. Destroy the temporary lifetime-extended by 'c'. - clang_analyzer_eval(v.len == 4); - clang_analyzer_eval(v.buf[0] == v.buf[2]); - clang_analyzer_eval(v.buf[1] == v.buf[3]); + // 0. Construct the return value of make() (copy/move elided) and + // lifetime-extend it directly via reference 'c', + // 1. Destroy the temporary lifetime-extended by 'c'. + clang_analyzer_eval(v.len == 2); + clang_analyzer_eval(v.buf[0] == v.buf[1]); #ifdef TEMPORARIES - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} - // expected-warning@-4{{TRUE}} + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} #else - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} - // expected-warning@-8{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} #endif } -C doubleMake(AddressVector &v) { +C doubleMake(AddressVector &v) { return C::make(v); } void f4() { - AddressVector v; + AddressVector v; { C c = doubleMake(v); } - // 0. Construct the original temporary within make(), - // 1. Construct the return value of make() (elidable copy/move) and - // lifetime-extend it into the return value constructor argument within - // doubleMake(), - // 2. Destroy the temporary within make(), - // 3. Construct the return value of doubleMake() (elidable copy/move) and - // lifetime-extend it into the variable 'c' constructor argument, - // 4. Destroy the return value of make(), - // 5. Construct variable 'c' (elidable copy/move), - // 6. Destroy the return value of doubleMake(), - // 7. Destroy variable 'c'. - clang_analyzer_eval(v.len == 8); - clang_analyzer_eval(v.buf[0] == v.buf[2]); - clang_analyzer_eval(v.buf[1] == v.buf[4]); - clang_analyzer_eval(v.buf[3] == v.buf[6]); - clang_analyzer_eval(v.buf[5] == v.buf[7]); -#ifdef TEMPORARIES - // expected-warning@-6{{TRUE}} - // expected-warning@-6{{TRUE}} - // expected-warning@-6{{TRUE}} - // expected-warning@-6{{TRUE}} - // expected-warning@-6{{TRUE}} -#else - // expected-warning@-12{{UNKNOWN}} - // expected-warning@-12{{UNKNOWN}} - // expected-warning@-12{{UNKNOWN}} - // expected-warning@-12{{UNKNOWN}} - // expected-warning@-12{{UNKNOWN}} -#endif + // 0. Construct variable 'c' (all copies/moves elided), + // 1. Destroy variable 'c'. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} } - -class NoDtor { - AddressVector &v; - -public: - NoDtor(AddressVector &v) : v(v) { v.push(this); } -}; - -void f5() { - AddressVector v; - const NoDtor &N = NoDtor(v); - clang_analyzer_eval(v.buf[0] == &N); // expected-warning{{TRUE}} -} - } // end namespace maintain_address_of_copies diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp index 964e7f13c5..de3420e708 100644 --- a/test/Analysis/temporaries.cpp +++ b/test/Analysis/temporaries.cpp @@ -612,107 +612,44 @@ void test() { clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}} C c4 = returnTemporaryWithConstruction(); - clang_analyzer_eval(c4.getX() == 1); - clang_analyzer_eval(c4.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}} C c5 = returnTemporaryWithAnotherFunctionWithConstruction(); - clang_analyzer_eval(c5.getX() == 1); - clang_analyzer_eval(c5.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}} C c6 = returnTemporaryWithCopyConstructionWithConstruction(); - clang_analyzer_eval(c5.getX() == 1); - clang_analyzer_eval(c5.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}} #if __cplusplus >= 201103L C c7 = returnTemporaryWithBraces(); - clang_analyzer_eval(c7.getX() == 1); - clang_analyzer_eval(c7.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}} C c8 = returnTemporaryWithAnotherFunctionWithBraces(); - clang_analyzer_eval(c8.getX() == 1); - clang_analyzer_eval(c8.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}} C c9 = returnTemporaryWithCopyConstructionWithBraces(); - clang_analyzer_eval(c9.getX() == 1); - clang_analyzer_eval(c9.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}} #endif // C++11 D d1 = returnTemporaryWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d1.getX() == 1); - clang_analyzer_eval(d1.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}} D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d2.getX() == 1); - clang_analyzer_eval(d2.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(d2.getY() == 2); // expected-warning{{TRUE}} D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d3.getX() == 1); - clang_analyzer_eval(d3.getY() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(d3.getX() == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(d3.getY() == 2); // expected-warning{{TRUE}} } } // namespace test_return_temporary @@ -767,19 +704,9 @@ void test(int coin) { C c2 = coin ? C(1) : C(2); if (coin) { - clang_analyzer_eval(c2.getX() == 1); -#ifdef TEMPORARY_DTORS - // expected-warning@-2{{TRUE}} -#else - // expected-warning@-4{{UNKNOWN}} -#endif + clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}} } else { - clang_analyzer_eval(c2.getX() == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-2{{TRUE}} -#else - // expected-warning@-4{{UNKNOWN}} -#endif + clang_analyzer_eval(c2.getX() == 2); // expected-warning{{TRUE}} } } @@ -816,16 +743,9 @@ void test_simple_temporary_with_copy() { { C c = C(x, y); } - // Two constructors (temporary object expr and copy) and two destructors. - clang_analyzer_eval(x == 2); - clang_analyzer_eval(y == 2); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + // Only one constructor directly into the variable, and one destructor. + clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(y == 1); // expected-warning{{TRUE}} } void test_ternary_temporary(int coin) { @@ -833,10 +753,10 @@ void test_ternary_temporary(int coin) { { const C &c = coin ? C(x, y) : C(z, w); } - // This time each branch contains an additional elidable copy constructor. + // Only one constructor on every branch, and one automatic destructor. if (coin) { - clang_analyzer_eval(x == 2); - clang_analyzer_eval(y == 2); + clang_analyzer_eval(x == 1); + clang_analyzer_eval(y == 1); #ifdef TEMPORARY_DTORS // expected-warning@-3{{TRUE}} // expected-warning@-3{{TRUE}} @@ -850,8 +770,8 @@ void test_ternary_temporary(int coin) { } else { clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} clang_analyzer_eval(y == 0); // expected-warning{{TRUE}} - clang_analyzer_eval(z == 2); - clang_analyzer_eval(w == 2); + clang_analyzer_eval(z == 1); + clang_analyzer_eval(w == 1); #ifdef TEMPORARY_DTORS // expected-warning@-3{{TRUE}} // expected-warning@-3{{TRUE}} @@ -867,33 +787,18 @@ void test_ternary_temporary_with_copy(int coin) { { C c = coin ? C(x, y) : C(z, w); } - // Temporary expression, elidable copy within branch, - // constructor for variable - 3 total. + // On each branch the variable is constructed directly. if (coin) { - clang_analyzer_eval(x == 3); - clang_analyzer_eval(y == 3); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(y == 1); // expected-warning{{TRUE}} clang_analyzer_eval(z == 0); // expected-warning{{TRUE}} clang_analyzer_eval(w == 0); // expected-warning{{TRUE}} } else { clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} clang_analyzer_eval(y == 0); // expected-warning{{TRUE}} - clang_analyzer_eval(z == 3); - clang_analyzer_eval(w == 3); -#ifdef TEMPORARY_DTORS - // expected-warning@-3{{TRUE}} - // expected-warning@-3{{TRUE}} -#else - // expected-warning@-6{{UNKNOWN}} - // expected-warning@-6{{UNKNOWN}} -#endif + clang_analyzer_eval(z == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(w == 1); // expected-warning{{TRUE}} } } } // namespace test_match_constructors_and_destructors @@ -928,12 +833,13 @@ void testLifetimeExtendedCall() { } void testCopiedCall() { - C c = make(); - // Should have divided by zero in the temporary destructor. - clang_analyzer_warnIfReached(); -#ifndef TEMPORARY_DTORS - // expected-warning@-2{{REACHABLE}} -#endif + { + C c = make(); + // Should have elided the constructor/destructor for the temporary + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} + } + // Should have divided by zero in the destructor. + clang_analyzer_warnIfReached(); // no-warning } } // namespace destructors_for_return_values @@ -1018,20 +924,10 @@ void test() { #endif S s = 20; - clang_analyzer_eval(s.x == 20); -#ifdef TEMPORARY_DTORS - // expected-warning@-2{{TRUE}} -#else - // expected-warning@-4{{UNKNOWN}} -#endif + clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}} C c2 = s; - clang_analyzer_eval(c2.getX() == 20); -#ifdef TEMPORARY_DTORS - // expected-warning@-2{{TRUE}} -#else - // expected-warning@-4{{UNKNOWN}} -#endif + clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}} } } // end namespace implicit_constructor_conversion -- GitLab From e79c5536b0d933df63de745592b7228379841d24 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:42:11 +0000 Subject: [PATCH 0325/1023] [analyzer] Use sufficiently large types for index bounds calculation. The ProgramState::assumeInBound() API is used by checkers to make an assumption that a certain array index is within the array's bounds (i.e. is greater than or equal to 0 and is less than the length of the array). When the type of the index was unspecified by the caller, it assumed that the type is 'int', which caused some indices and sizes to truncate during calculations. Use ArrayIndexTy by default instead, which is used by the analyzer to represent index types and is currently hardcoded to long long. Patch by Bevin Hansson! Differential Revision: https://reviews.llvm.org/D46944 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335803 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ProgramState.cpp | 3 +-- lib/StaticAnalyzer/Core/RegionStore.cpp | 3 ++- test/Analysis/index-type.c | 23 +++++++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 141863d2ac..2b40160729 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -336,9 +336,8 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx, // Get the offset: the minimum value of the array index type. BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); - // FIXME: This should be using ValueManager::ArrayindexTy...somehow. if (indexTy.isNull()) - indexTy = Ctx.IntTy; + indexTy = svalBuilder.getArrayIndexType(); nonloc::ConcreteInt Min(BVF.getMinValue(indexTy)); // Adjust the index. diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index acb6eeab8d..db6449e6d5 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1341,7 +1341,8 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state, // If a variable is reinterpreted as a type that doesn't fit into a larger // type evenly, round it down. // This is a signed value, since it's used in arithmetic with signed indices. - return svalBuilder.makeIntVal(RegionSize / EleSize, false); + return svalBuilder.makeIntVal(RegionSize / EleSize, + svalBuilder.getArrayIndexType()); } //===----------------------------------------------------------------------===// diff --git a/test/Analysis/index-type.c b/test/Analysis/index-type.c index b86913b996..123dcd65bd 100644 --- a/test/Analysis/index-type.c +++ b/test/Analysis/index-type.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -verify %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -DM32 -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -verify %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -DM32 -verify %s // expected-no-diagnostics #define UINT_MAX (~0u) @@ -36,4 +36,23 @@ void testIndexTooBig64() { *ptr = 42; // no-warning } +#define SIZE 4294967296 + +static unsigned size; +static void * addr; +static unsigned buf[SIZE]; + +void testOutOfBounds() { + // Not out of bounds. + buf[SIZE-1] = 1; // no-warning +} + +void testOutOfBoundsCopy1() { + memcpy(buf, addr, size); // no-warning +} + +void testOutOfBoundsCopy2() { + memcpy(addr, buf, size); // no-warning +} + #endif -- GitLab From ad799f218b0f37207ce7100c5c750045abd64357 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 28 Jun 2018 01:07:28 +0000 Subject: [PATCH 0326/1023] [modules] Ensure that an in-class function definition is attached to the declaration of the function that ends up in the primary definition of the class. ... at least for class templates. This is necessary for us to be able to track when an inline friend function has a definition that needs to be (lazily) instantiated. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335805 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReader.cpp | 13 +++++++++++ test/Modules/friend-definition-2.cpp | 34 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 test/Modules/friend-definition-2.cpp diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 982c4cbee8..9287ffd3d6 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9356,6 +9356,19 @@ void ASTReader::finishPendingActions() { PBEnd = PendingBodies.end(); PB != PBEnd; ++PB) { if (FunctionDecl *FD = dyn_cast(PB->first)) { + // For a function defined inline within a class template, force the + // canonical definition to be the one inside the canonical definition of + // the template. This ensures that we instantiate from a correct view + // of the template. + // + // Sadly we can't do this more generally: we can't be sure that all + // copies of an arbitrary class definition will have the same members + // defined (eg, some member functions may not be instantiated, and some + // special members may or may not have been implicitly defined). + if (auto *RD = dyn_cast(FD->getLexicalParent())) + if (RD->isDependentContext() && !RD->isThisDeclarationADefinition()) + continue; + // FIXME: Check for =delete/=default? // FIXME: Complain about ODR violations here? const FunctionDecl *Defn = nullptr; diff --git a/test/Modules/friend-definition-2.cpp b/test/Modules/friend-definition-2.cpp new file mode 100644 index 0000000000..7f876b762a --- /dev/null +++ b/test/Modules/friend-definition-2.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fmodules %s -verify +// expected-no-diagnostics +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template struct ct { friend auto operator-(ct, ct) { struct X {}; return X(); } void x(); }; +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +template struct ct { friend auto operator-(ct, ct) { struct X{}; return X(); } void x(); }; +inline auto f() { return ct() - ct(); } +#pragma clang module end +#pragma clang module endbuild + +// Force the definition of ct in module A to be the primary definition. +#pragma clang module import A +template void ct::x() {} + +// Attempt to cause the definition of operator- in the ct primary template in +// module B to be the primary definition of that function. If that happens, +// we'll be left with a class template ct that appears to not contain a +// definition of the inline friend function. +#pragma clang module import B +auto v = f(); + +ct make(); +void h() { + make() - make(); +} -- GitLab From 4dc3dee0b40da5a342d04142934d6318af523c27 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 28 Jun 2018 01:57:04 +0000 Subject: [PATCH 0327/1023] [modules] Do not serialize / deserialize pending new/delete mismatch checks across module boundaries. This was causing us to load constructor definitions for all consumers of a module with a pending check. (In one case we saw ~7% of total frontend time spent loading constructors for this check.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335807 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.cpp | 17 +++++++---------- lib/Serialization/ASTWriter.cpp | 16 +++++++++------- test/Modules/new-delete.cpp | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 test/Modules/new-delete.cpp diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 7a8cd1ca4e..d6d105c3b0 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1010,11 +1010,6 @@ void Sema::ActOnEndOfTranslationUnit() { // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for // modules when they are built, not every time they are used. emitAndClearUnusedLocalTypedefWarnings(); - - // Modules don't need any of the checking below. - if (!PP.isIncrementalProcessingEnabled()) - TUScope = nullptr; - return; } // C99 6.9.2p2: @@ -1032,8 +1027,7 @@ void Sema::ActOnEndOfTranslationUnit() { for (TentativeDefinitionsType::iterator T = TentativeDefinitions.begin(ExternalSource), TEnd = TentativeDefinitions.end(); - T != TEnd; ++T) - { + T != TEnd; ++T) { VarDecl *VD = (*T)->getActingDefinition(); // If the tentative definition was completed, getActingDefinition() returns @@ -1060,12 +1054,13 @@ void Sema::ActOnEndOfTranslationUnit() { // Notify the consumer that we've completed a tentative definition. if (!VD->isInvalidDecl()) Consumer.CompleteTentativeDefinition(VD); - } // If there were errors, disable 'unused' warnings since they will mostly be - // noise. - if (!Diags.hasErrorOccurred()) { + // noise. Don't warn for a use from a module: either we should warn on all + // file-scope declarations in modules or not at all, but whether the + // declaration is used is immaterial. + if (!Diags.hasErrorOccurred() && TUKind != TU_Module) { // Output warning for unused file scoped decls. for (UnusedFileScopedDeclsType::iterator I = UnusedFileScopedDecls.begin(ExternalSource), @@ -1133,6 +1128,8 @@ void Sema::ActOnEndOfTranslationUnit() { } if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) { + // FIXME: Load additional unused private field candidates from the external + // source. RecordCompleteMap RecordsComplete; RecordCompleteMap MNCComplete; for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(), diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 7d5b521d4d..1c838ae2c0 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4769,13 +4769,15 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, // analyze later in AST. RecordData DeleteExprsToAnalyze; - for (const auto &DeleteExprsInfo : - SemaRef.getMismatchingDeleteExpressions()) { - AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); - for (const auto &DeleteLoc : DeleteExprsInfo.second) { - AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); - DeleteExprsToAnalyze.push_back(DeleteLoc.second); + if (!isModule) { + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) { + AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); + for (const auto &DeleteLoc : DeleteExprsInfo.second) { + AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); + DeleteExprsToAnalyze.push_back(DeleteLoc.second); + } } } diff --git a/test/Modules/new-delete.cpp b/test/Modules/new-delete.cpp new file mode 100644 index 0000000000..585a242b22 --- /dev/null +++ b/test/Modules/new-delete.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fmodules -verify %s +// expected-no-diagnostics + +#pragma clang module build M +module M {} +#pragma clang module contents +#pragma clang module begin M +struct A { + A(); + ~A() { delete p; } // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'}} + int *p; +}; +inline A::A() : p(new int[32]) {} // expected-note {{allocated}} +struct B { + B(); + ~B() { delete p; } + int *p; +}; +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import M +B::B() : p(new int[32]) {} -- GitLab From bd011d17e27bab090b3a5ddf966be495ad8ed639 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 02:33:16 +0000 Subject: [PATCH 0328/1023] [analyzer] Remove redundant ';'. Fixes a compiler warning. No functionan change intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335808 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index c3f5b42a9f..27f7553e7a 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -191,7 +191,7 @@ typedef std::pair typedef llvm::ImmutableSet ElidedDestructorSet; REGISTER_TRAIT_WITH_PROGRAMSTATE(ElidedDestructors, - ElidedDestructorSet); + ElidedDestructorSet) //===----------------------------------------------------------------------===// // Engine construction and deletion. -- GitLab From 7a290f168c98ef77a050254694d3f9f2721ef13d Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 03:11:52 +0000 Subject: [PATCH 0329/1023] Support for multiarch runtimes layout This change adds a support for multiarch style runtimes layout, so in addition to the existing layout where runtimes get installed to: lib/clang/$version/lib/$os Clang now allows runtimes to be installed to: lib/clang/$version/$target/lib This also includes libc++, libc++abi and libunwind; today those are assumed to be in Clang library directory built for host, with the new layout it is possible to install libc++, libc++abi and libunwind into the runtime directory built for different targets. The use of new layout is enabled by setting the LLVM_ENABLE_RUNTIME_TARGET_DIR CMake variable and is supported by both projects and runtimes layouts. The runtimes CMake build has been further modified to use the new layout when building runtimes for multiple targets. Differential Revision: https://reviews.llvm.org/D45604 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335809 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChain.cpp | 17 +++++- lib/Driver/ToolChains/Fuchsia.cpp | 24 +------- lib/Driver/ToolChains/Linux.cpp | 1 + test/CMakeLists.txt | 3 +- .../aarch64-fuchsia/lib/.keep | 0 .../i386-linux-gnu/lib/.keep | 0 .../include/c++/v1/.keep | 0 .../x86_64-fuchsia/lib/.keep | 0 .../x86_64-linux-gnu/lib/.keep | 0 test/Driver/fuchsia.c | 57 +++++++++++-------- test/Driver/fuchsia.cpp | 2 +- test/Driver/linux-header-search.cpp | 5 ++ test/Driver/linux-ld.c | 2 + test/Driver/linux-per-target-runtime-dir.c | 21 +++++++ 14 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep create mode 100644 test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep create mode 100644 test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep create mode 100644 test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep create mode 100644 test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep create mode 100644 test/Driver/linux-per-target-runtime-dir.c diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index a56a038054..d62ba12533 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -74,6 +74,11 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, const ArgList &Args) : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, D.getTargetTriple(), "lib"); + if (getVFS().exists(P)) + getFilePaths().push_back(P.str()); + std::string CandidateLibPath = getArchSpecificLibPath(); if (getVFS().exists(CandidateLibPath)) getFilePaths().push_back(CandidateLibPath); @@ -350,15 +355,23 @@ std::string ToolChain::getCompilerRTPath() const { std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, bool Shared) const { const llvm::Triple &TT = getTriple(); - const char *Env = TT.isAndroid() ? "-android" : ""; bool IsITANMSVCWindows = TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); - StringRef Arch = getArchNameForCompilerRTLib(*this, Args); const char *Prefix = IsITANMSVCWindows ? "" : "lib"; const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so") : (IsITANMSVCWindows ? ".lib" : ".a"); + const Driver &D = getDriver(); + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, D.getTargetTriple(), "lib"); + if (getVFS().exists(P)) { + llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix); + return P.str(); + } + + StringRef Arch = getArchNameForCompilerRTLib(*this, Args); + const char *Env = TT.isAndroid() ? "-android" : ""; SmallString<128> Path(getCompilerRTPath()); llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" + Arch + Env + Suffix); diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index bea59b1ac3..459b68b55a 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -144,21 +144,6 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. -static std::string normalizeTriple(llvm::Triple Triple) { - SmallString<64> T; - T += Triple.getArchName(); - T += "-"; - T += Triple.getOSName(); - return T.str(); -} - -static std::string getTargetDir(const Driver &D, - llvm::Triple Triple) { - SmallString<128> P(llvm::sys::path::parent_path(D.Dir)); - llvm::sys::path::append(P, "lib", normalizeTriple(Triple)); - return P.str(); -} - Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args) { @@ -166,10 +151,6 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, if (getDriver().getInstalledDir() != D.Dir) getProgramPaths().push_back(D.Dir); - SmallString<128> P(getTargetDir(D, getTriple())); - llvm::sys::path::append(P, "lib"); - getFilePaths().push_back(P.str()); - if (!D.SysRoot.empty()) { SmallString<128> P(D.SysRoot); llvm::sys::path::append(P, "lib"); @@ -180,8 +161,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); - Triple.setTriple(normalizeTriple(Triple)); - return Triple.getTriple(); + return (Triple.getArchName() + "-" + Triple.getOSName()).str(); } Tool *Fuchsia::buildLinker() const { @@ -264,7 +244,7 @@ void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { - SmallString<128> P(getTargetDir(getDriver(), getTriple())); + SmallString<128> P(getDriver().ResourceDir); llvm::sys::path::append(P, "include", "c++", "v1"); addSystemInclude(DriverArgs, CC1Args, P.str()); break; diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 675d7b2029..3b99ce581f 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -803,6 +803,7 @@ void Linux::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { const std::string& SysRoot = computeSysRoot(); const std::string LibCXXIncludePathCandidates[] = { + DetectLibcxxIncludePath(getDriver().ResourceDir + "/include/c++"), DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"), // If this is a development, non-installed, clang, libcxx will // not be found at ../include/c++ but it likely to be found at diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d86c60c4fd..4951d86698 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,7 +23,8 @@ llvm_canonicalize_cmake_booleans( CLANG_ENABLE_ARCMT CLANG_ENABLE_STATIC_ANALYZER ENABLE_BACKTRACES - HAVE_LIBZ) + HAVE_LIBZ + LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/i386-linux-gnu/lib/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/include/c++/v1/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep b/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-linux-gnu/lib/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c index c2b02522ab..fa54599623 100644 --- a/test/Driver/fuchsia.c +++ b/test/Driver/fuchsia.c @@ -1,7 +1,9 @@ -// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \ +// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-fuchsia \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-X86_64 %s -// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-unknown-fuchsia \ +// RUN: %clang %s -### -no-canonical-prefixes --target=aarch64-fuchsia \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: --sysroot=%S/platform 2>&1 \ // RUN: | FileCheck -check-prefixes=CHECK,CHECK-AARCH64 %s // CHECK: {{.*}}clang{{.*}}" "-cc1" @@ -23,97 +25,106 @@ // CHECK-NOT: crti.o // CHECK-NOT: crtbegin.o // CHECK: "-L[[SYSROOT]]{{/|\\\\}}lib" -// CHECK-X86_64: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a" -// CHECK-AARCH64: "{{.*[/\\]}}libclang_rt.builtins-aarch64.a" +// CHECK-X86_64: "{{.*[/\\]}}libclang_rt.builtins.a" +// CHECK-AARCH64: "{{.*[/\\]}}libclang_rt.builtins.a" // CHECK: "-lc" // CHECK-NOT: crtend.o // CHECK-NOT: crtn.o -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -rtlib=libgcc 2>&1 \ +// RUN: %clang %s -### --target=x86_64-fuchsia -rtlib=libgcc 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-RTLIB // CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc' -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -static 2>&1 \ +// RUN: %clang %s -### --target=x86_64-fuchsia -static 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-STATIC // CHECK-STATIC: "-Bstatic" // CHECK-STATIC: "-Bdynamic" // CHECK-STATIC: "-lc" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -shared 2>&1 \ +// RUN: %clang %s -### --target=x86_64-fuchsia -shared 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-SHARED // CHECK-SHARED-NOT: "-pie" // CHECK-SHARED: "-shared" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia -r 2>&1 \ +// RUN: %clang %s -### --target=x86_64-fuchsia -r 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE // CHECK-RELOCATABLE-NOT: "-pie" // CHECK-RELOCATABLE-NOT: "--build-id" // CHECK-RELOCATABLE: "-r" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=safe-stack 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-SAFESTACK // CHECK-SAFESTACK: "-fsanitize=safe-stack" -// CHECK-SAFESTACK-NOT: "{{.*[/\\]}}libclang_rt.safestack-x86_64.a" +// CHECK-SAFESTACK-NOT: "{{.*[/\\]}}libclang_rt.safestack.a" // CHECK-SAFESTACK-NOT: "__safestack_init" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=address 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-ASAN-X86 // CHECK-ASAN-X86: "-fsanitize=address" // CHECK-ASAN-X86: "-fsanitize-address-globals-dead-stripping" // CHECK-ASAN-X86: "-dynamic-linker" "asan/ld.so.1" -// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-x86_64.so" -// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-preinit-x86_64.a" +// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan.so" +// CHECK-ASAN-X86: "{{.*[/\\]}}libclang_rt.asan-preinit.a" // RUN: %clang %s -### --target=aarch64-fuchsia \ // RUN: -fsanitize=address 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-ASAN-AARCH64 // CHECK-ASAN-AARCH64: "-fsanitize=address" // CHECK-ASAN-AARCH64: "-fsanitize-address-globals-dead-stripping" // CHECK-ASAN-AARCH64: "-dynamic-linker" "asan/ld.so.1" -// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-aarch64.so" -// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-preinit-aarch64.a" +// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan.so" +// CHECK-ASAN-AARCH64: "{{.*[/\\]}}libclang_rt.asan-preinit.a" -// RUN: %clang %s -### --target=x86_64-unknown-fuchsia \ +// RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=address -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-ASAN-SHARED // CHECK-ASAN-SHARED: "-fsanitize=address" // CHECK-ASAN-SHARED: "-fsanitize-address-globals-dead-stripping" -// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan-x86_64.so" -// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit-x86_64.a" +// CHECK-ASAN-SHARED: "{{.*[/\\]}}libclang_rt.asan.so" +// CHECK-ASAN-SHARED-NOT: "{{.*[/\\]}}libclang_rt.asan-preinit.a" // RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=fuzzer 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-X86 // CHECK-FUZZER-X86: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack" -// CHECK-FUZZER-X86: "{{.*[/\\]}}libclang_rt.fuzzer-x86_64.a" +// CHECK-FUZZER-X86: "{{.*[/\\]}}libclang_rt.fuzzer.a" // RUN: %clang %s -### --target=aarch64-fuchsia \ // RUN: -fsanitize=fuzzer 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-AARCH64 // CHECK-FUZZER-AARCH64: "-fsanitize=fuzzer,fuzzer-no-link,safe-stack" -// CHECK-FUZZER-AARCH64: "{{.*[/\\]}}libclang_rt.fuzzer-aarch64.a" +// CHECK-FUZZER-AARCH64: "{{.*[/\\]}}libclang_rt.fuzzer.a" // RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=scudo 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-X86 // CHECK-SCUDO-X86: "-fsanitize=safe-stack,scudo" // CHECK-SCUDO-X86: "-pie" -// CHECK-SCUDO-X86: "{{.*[/\\]}}libclang_rt.scudo-x86_64.so" +// CHECK-SCUDO-X86: "{{.*[/\\]}}libclang_rt.scudo.so" // RUN: %clang %s -### --target=aarch64-fuchsia \ // RUN: -fsanitize=scudo 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-AARCH64 // CHECK-SCUDO-AARCH64: "-fsanitize=safe-stack,scudo" // CHECK-SCUDO-AARCH64: "-pie" -// CHECK-SCUDO-AARCH64: "{{.*[/\\]}}libclang_rt.scudo-aarch64.so" +// CHECK-SCUDO-AARCH64: "{{.*[/\\]}}libclang_rt.scudo.so" // RUN: %clang %s -### --target=x86_64-fuchsia \ // RUN: -fsanitize=scudo -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED // CHECK-SCUDO-SHARED: "-fsanitize=safe-stack,scudo" -// CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo-x86_64.so" +// CHECK-SCUDO-SHARED: "{{.*[/\\]}}libclang_rt.scudo.so" // RUN: %clang %s -### --target=aarch64-fuchsia \ // RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \ diff --git a/test/Driver/fuchsia.cpp b/test/Driver/fuchsia.cpp index 5b33532d75..83b1875226 100644 --- a/test/Driver/fuchsia.cpp +++ b/test/Driver/fuchsia.cpp @@ -4,7 +4,7 @@ // CHECK: "-triple" "x86_64-fuchsia" // CHECK: "-fuse-init-array" // CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" -// CHECK: "-internal-isystem" "{{.*[/\\]}}x86_64-fuchsia{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1" +// CHECK: "-internal-isystem" "{{.*[/\\]}}include{{/|\\\\}}c++{{/|\\\\}}v1" // CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include" // CHECK: {{.*}}ld.lld{{.*}}" "-z" "rodynamic" // CHECK: "--sysroot=[[SYSROOT]]" diff --git a/test/Driver/linux-header-search.cpp b/test/Driver/linux-header-search.cpp index 9ae57b797c..3f024aa495 100644 --- a/test/Driver/linux-header-search.cpp +++ b/test/Driver/linux-header-search.cpp @@ -7,6 +7,7 @@ // RUN: -target x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s @@ -18,6 +19,7 @@ // RUN: -target x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s @@ -30,6 +32,7 @@ // RUN: -target x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-SYSROOT %s @@ -41,6 +44,7 @@ // RUN: -target x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxxv2_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-INSTALL %s @@ -54,6 +58,7 @@ // RUN: -target x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree \ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT %s diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c index f9f938577b..431bd9ef14 100644 --- a/test/Driver/linux-ld.c +++ b/test/Driver/linux-ld.c @@ -426,6 +426,7 @@ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: --gcc-toolchain="" \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s // CHECK-BASIC-LIBCXX-SYSROOT: "{{[^"]*}}clang{{[^"]*}}" "-cc1" @@ -438,6 +439,7 @@ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ // RUN: --gcc-toolchain="" \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s // CHECK-BASIC-LIBCXX-INSTALL: "{{[^"]*}}clang{{[^"]*}}" "-cc1" diff --git a/test/Driver/linux-per-target-runtime-dir.c b/test/Driver/linux-per-target-runtime-dir.c new file mode 100644 index 0000000000..17a4d6dc6e --- /dev/null +++ b/test/Driver/linux-per-target-runtime-dir.c @@ -0,0 +1,21 @@ +// RUN: %clang -no-canonical-prefixes -x c++ %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-linux-gnu \ +// RUN: -stdlib=libc++ \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ +// RUN: | FileCheck --check-prefix=CHECK-PER-TARGET-RUNTIME %s +// CHECK-PER-TARGET-RUNTIME: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-PER-TARGET-RUNTIME: "-resource-dir" "[[RESDIR:[^"]*]]" +// CHECK-PER-TARGET-RUNTIME: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[RESDIR]]/include/c++/v1" +// CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[SYSROOT]]/usr/local/include" +// CHECK-PER-TARGET-RUNTIME: "--sysroot=[[SYSROOT]]" +// CHECK-PER-TARGET-RUNTIME: "-L[[RESDIR]]/x86_64-linux-gnu/lib" + +// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ +// RUN: --target=x86_64-linux-gnu \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s +// CHECK-CLANGRT-X8664: x86_64-linux-gnu/lib/libclang_rt.builtins.a -- GitLab From cd0dfe191ba850c2df9c39dd69ecaa00f6e2a105 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 03:54:08 +0000 Subject: [PATCH 0330/1023] Handle both Linux and Windows path separator for the resource dir The resource dir path used for the multiarch runtimes support is constructed in a platform independent way and therefore will use native path separators on each platform. We need to make sure that the per target runtime directory test handles both to not fail when the test is being executed on Windows. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335810 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/linux-per-target-runtime-dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Driver/linux-per-target-runtime-dir.c b/test/Driver/linux-per-target-runtime-dir.c index 17a4d6dc6e..89310c11d9 100644 --- a/test/Driver/linux-per-target-runtime-dir.c +++ b/test/Driver/linux-per-target-runtime-dir.c @@ -12,10 +12,10 @@ // CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[RESDIR]]/include/c++/v1" // CHECK-PER-TARGET-RUNTIME: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-PER-TARGET-RUNTIME: "--sysroot=[[SYSROOT]]" -// CHECK-PER-TARGET-RUNTIME: "-L[[RESDIR]]/x86_64-linux-gnu/lib" +// CHECK-PER-TARGET-RUNTIME: "-L[[RESDIR]]{{/|\\\\}}x86_64-linux-gnu{{/|\\\\}}lib" // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=x86_64-linux-gnu \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s -// CHECK-CLANGRT-X8664: x86_64-linux-gnu/lib/libclang_rt.builtins.a +// CHECK-CLANGRT-X8664: x86_64-linux-gnu{{/|\\\\}}lib{{/|\\\\}}libclang_rt.builtins.a -- GitLab From 03d5d6e5e34fb3fe966479393d4cebad2e339e7b Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 05:15:46 +0000 Subject: [PATCH 0331/1023] [CMake] Use explicit targets for building Linux runtimes Previously we were using default logic when building Linux runtimes in Fuchsia toolchain, but that leads to various issues due to how the CMake logic in compiler-rt for determining the platform support is implemented. With this change, we will use explicit target for every provided Linux sysroot. Differential Revision: https://reviews.llvm.org/D48563 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335812 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 131 +++++++++++++++++------------- cmake/caches/Fuchsia.cmake | 3 +- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 07ef48db04..9f28c1770e 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -8,6 +8,7 @@ set(PACKAGE_VENDOR Fuchsia CACHE STRING "") set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") set(LLVM_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "") @@ -27,71 +28,87 @@ set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "") -set(FUCHSIA_BUILTINS_BUILD_TYPE Release CACHE STRING "") -set(FUCHSIA_RUNTIMES_BUILD_TYPE Release CACHE STRING "") -set(FUCHSIA_RUNTIMES_ENABLE_ASSERTIONS ON CACHE BOOL "") +if(APPLE) + list(APPEND BUILTIN_TARGETS "default") + list(APPEND RUNTIME_TARGETS "default") +endif() + +foreach(target i386;x86_64;armhf;aarch64) + if(LINUX_${target}_SYSROOT) + # Set the per-target builtins options. + list(APPEND BUILTIN_TARGETS "${target}-linux-gnu") + set(BUILTINS_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") + set(BUILTINS_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(BUILTINS_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") -set(FUCHSIA_aarch64_NAME arm64) -set(FUCHSIA_x86_64_NAME x64) -foreach(target x86_64;aarch64) - set(FUCHSIA_${target}_COMPILER_FLAGS "-I${FUCHSIA_SDK}/pkg/fdio/include") - set(FUCHSIA_${target}_LINKER_FLAGS "-L${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/lib") - set(FUCHSIA_${target}_SYSROOT "${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/sysroot") + # Set the per-target runtimes options. + list(APPEND RUNTIME_TARGETS "${target}-linux-gnu") + set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + endif() endforeach() -set(LLVM_BUILTIN_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") +if(FUCHSIA_SDK) + set(FUCHSIA_aarch64_NAME arm64) + set(FUCHSIA_x86_64_NAME x64) + foreach(target x86_64;aarch64) + set(FUCHSIA_${target}_COMPILER_FLAGS "-I${FUCHSIA_SDK}/pkg/fdio/include") + set(FUCHSIA_${target}_LINKER_FLAGS "-L${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/lib") + set(FUCHSIA_${target}_SYSROOT "${FUCHSIA_SDK}/arch/${FUCHSIA_${target}_NAME}/sysroot") + endforeach() -# Set the per-target builtins options. -foreach(target x86_64;aarch64) - set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE ${FUCHSIA_BUILTINS_BUILD_TYPE} CACHE STRING "") - set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") -endforeach() + foreach(target x86_64;aarch64) + # Set the per-target builtins options. + list(APPEND BUILTIN_TARGETS "${target}-fuchsia") + set(BUILTINS_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") + set(BUILTINS_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(BUILTINS_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(BUILTINS_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") -set(LLVM_RUNTIME_TARGETS "default;x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") -set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") -set(LLVM_RUNTIME_SANITIZER_Address_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") + # Set the per-target runtimes options. + list(APPEND RUNTIME_TARGETS "${target}-fuchsia") + set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") + set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE STRING "") + set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") + set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "") + endforeach() -# Set the default target runtimes options. -if(NOT APPLE) - set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") - set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") - set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") - set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") - set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") - set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") + set(LLVM_RUNTIME_SANITIZER_Address_TARGETS "x86_64-fuchsia;aarch64-fuchsia" CACHE STRING "") endif() -# Set the per-target runtimes options. -foreach(target x86_64;aarch64) - set(RUNTIMES_${target}-fuchsia_CMAKE_SYSTEM_NAME Fuchsia CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_TYPE ${FUCHSIA_RUNTIMES_BUILD_TYPE} CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE STRING "") - set(RUNTIMES_${target}-fuchsia_CMAKE_ASM_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_C_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_CXX_FLAGS ${FUCHSIA_${target}_COMPILER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_SHARED_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_MODULE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_EXE_LINKER_FLAGS ${FUCHSIA_${target}_LINKER_FLAGS} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") - set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ${FUCHSIA_RUNTIMES_ENABLE_ASSERTIONS} CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "") -endforeach() +set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "") +set(LLVM_RUNTIME_TARGETS "${RUNTIME_TARGETS}" CACHE STRING "") # Setup toolchain. set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index ee7b69bc29..27f304fafb 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -7,10 +7,11 @@ set(PACKAGE_VENDOR Fuchsia CACHE STRING "") set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "") set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "") set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "") -set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "") set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") +set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") +set(CLANG_INCLUDE_TESTS OFF CACHE BOOL "") set(CLANG_PLUGIN_SUPPORT OFF CACHE BOOL "") set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") -- GitLab From e3ba09890ac9769c514f419f80566ee612103b89 Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Thu, 28 Jun 2018 07:35:23 +0000 Subject: [PATCH 0332/1023] [Analyzer] Constraint Manager Negates Difference If range [m .. n] is stored for symbolic expression A - B, then we can deduce the range for B - A which is [-n .. -m]. This is only true for signed types, unless the range is [0 .. 0]. Differential Revision: https://reviews.llvm.org/D35110 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335814 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PathSensitive/RangedConstraintManager.h | 2 + .../Core/RangeConstraintManager.cpp | 69 ++++++++++++- .../constraint_manager_negate_difference.c | 98 +++++++++++++++++++ test/Analysis/ptr-arith.c | 23 ----- 4 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 test/Analysis/constraint_manager_negate_difference.c diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h index 1147466d70..d2ba1f7c95 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -115,6 +115,8 @@ public: RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower, llvm::APSInt Upper) const; + RangeSet Negate(BasicValueFactory &BV, Factory &F) const; + void print(raw_ostream &os) const; bool operator==(const RangeSet &other) const { diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index c081a65002..1d2b94d6f7 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -174,6 +174,38 @@ RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F, return newRanges; } +// Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set +// [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal +// signed values of the type. +RangeSet RangeSet::Negate(BasicValueFactory &BV, Factory &F) const { + PrimRangeSet newRanges = F.getEmptySet(); + + for (iterator i = begin(), e = end(); i != e; ++i) { + const llvm::APSInt &from = i->From(), &to = i->To(); + const llvm::APSInt &newTo = (from.isMinSignedValue() ? + BV.getMaxValue(from) : + BV.getValue(- from)); + if (to.isMaxSignedValue() && !newRanges.isEmpty() && + newRanges.begin()->From().isMinSignedValue()) { + assert(newRanges.begin()->To().isMinSignedValue() && + "Ranges should not overlap"); + assert(!from.isMinSignedValue() && "Ranges should not overlap"); + const llvm::APSInt &newFrom = newRanges.begin()->From(); + newRanges = + F.add(F.remove(newRanges, *newRanges.begin()), Range(newFrom, newTo)); + } else if (!to.isMinSignedValue()) { + const llvm::APSInt &newFrom = BV.getValue(- to); + newRanges = F.add(newRanges, Range(newFrom, newTo)); + } + if (from.isMinSignedValue()) { + newRanges = F.add(newRanges, Range(BV.getMinValue(from), + BV.getMinValue(from))); + } + } + + return newRanges; +} + void RangeSet::print(raw_ostream &os) const { bool isFirst = true; os << "{ "; @@ -252,6 +284,8 @@ private: RangeSet::Factory F; RangeSet getRange(ProgramStateRef State, SymbolRef Sym); + const RangeSet* getRangeForMinusSymbol(ProgramStateRef State, + SymbolRef Sym); RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, @@ -268,6 +302,7 @@ private: RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment); + }; } // end anonymous namespace @@ -423,9 +458,15 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State, if (ConstraintRangeTy::data_type *V = State->get(Sym)) return *V; + BasicValueFactory &BV = getBasicVals(); + + // If Sym is a difference of symbols A - B, then maybe we have range set + // stored for B - A. + if (const RangeSet *R = getRangeForMinusSymbol(State, Sym)) + return R->Negate(BV, F); + // Lazily generate a new RangeSet representing all possible values for the // given symbol type. - BasicValueFactory &BV = getBasicVals(); QualType T = Sym->getType(); RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T)); @@ -441,6 +482,32 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State, return Result; } +// FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to +// obtain the negated symbolic expression instead of constructing the +// symbol manually. This will allow us to support finding ranges of not +// only negated SymSymExpr-type expressions, but also of other, simpler +// expressions which we currently do not know how to negate. +const RangeSet* +RangeConstraintManager::getRangeForMinusSymbol(ProgramStateRef State, + SymbolRef Sym) { + if (const SymSymExpr *SSE = dyn_cast(Sym)) { + if (SSE->getOpcode() == BO_Sub) { + QualType T = Sym->getType(); + SymbolManager &SymMgr = State->getSymbolManager(); + SymbolRef negSym = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, + SSE->getLHS(), T); + if (const RangeSet *negV = State->get(negSym)) { + // Unsigned range set cannot be negated, unless it is [0, 0]. + if ((negV->getConcreteValue() && + (*negV->getConcreteValue() == 0)) || + T->isSignedIntegerOrEnumerationType()) + return negV; + } + } + } + return nullptr; +} + //===------------------------------------------------------------------------=== // assumeSymX methods: protected interface for RangeConstraintManager. //===------------------------------------------------------------------------===/ diff --git a/test/Analysis/constraint_manager_negate_difference.c b/test/Analysis/constraint_manager_negate_difference.c new file mode 100644 index 0000000000..6856f48bb0 --- /dev/null +++ b/test/Analysis/constraint_manager_negate_difference.c @@ -0,0 +1,98 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-relational-comparison-simplification=true -verify %s + +void clang_analyzer_eval(int); + +void exit(int); + +#define UINT_MAX (~0U) +#define INT_MAX (UINT_MAX & (UINT_MAX >> 1)) +#define INT_MIN (UINT_MAX & ~(UINT_MAX >> 1)) + +extern void __assert_fail (__const char *__assertion, __const char *__file, + unsigned int __line, __const char *__function) + __attribute__ ((__noreturn__)); +#define assert(expr) \ + ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) + +void assert_in_range(int x) { + assert(x <= ((int)INT_MAX / 4)); + assert(x >= -(((int)INT_MAX) / 4)); +} + +void assert_in_wide_range(int x) { + assert(x <= ((int)INT_MAX / 2)); + assert(x >= -(((int)INT_MAX) / 2)); +} + +void assert_in_range_2(int m, int n) { + assert_in_range(m); + assert_in_range(n); +} + +void equal(int m, int n) { + assert_in_range_2(m, n); + if (m != n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n == m); // expected-warning{{TRUE}} +} + +void non_equal(int m, int n) { + assert_in_range_2(m, n); + if (m == n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n != m); // expected-warning{{TRUE}} +} + +void less_or_equal(int m, int n) { + assert_in_range_2(m, n); + if (m < n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n <= m); // expected-warning{{TRUE}} +} + +void less(int m, int n) { + assert_in_range_2(m, n); + if (m <= n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n < m); // expected-warning{{TRUE}} +} + +void greater_or_equal(int m, int n) { + assert_in_range_2(m, n); + if (m > n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n >= m); // expected-warning{{TRUE}} +} + +void greater(int m, int n) { + assert_in_range_2(m, n); + if (m >= n) + return; + assert_in_wide_range(m - n); + clang_analyzer_eval(n > m); // expected-warning{{TRUE}} +} + +void negate_positive_range(int m, int n) { + if (m - n <= 0) + return; + clang_analyzer_eval(n - m < 0); // expected-warning{{TRUE}} + clang_analyzer_eval(n - m > INT_MIN); // expected-warning{{TRUE}} + clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{FALSE}} +} + +void negate_int_min(int m, int n) { + if (m - n != INT_MIN) + return; + clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{TRUE}} +} + +void negate_mixed(int m, int n) { + if (m -n > INT_MIN && m - n <= 0) + return; + clang_analyzer_eval(n - m <= 0); // expected-warning{{TRUE}} +} diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c index 804759a32d..c0b20508d8 100644 --- a/test/Analysis/ptr-arith.c +++ b/test/Analysis/ptr-arith.c @@ -265,49 +265,26 @@ void size_implies_comparison(int *lhs, int *rhs) { clang_analyzer_eval((rhs - lhs) > 0); // expected-warning{{TRUE}} } -//------------------------------- -// False positives -//------------------------------- - void zero_implies_reversed_equal(int *lhs, int *rhs) { clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}} if ((rhs - lhs) == 0) { -#ifdef ANALYZER_CM_Z3 clang_analyzer_eval(rhs != lhs); // expected-warning{{FALSE}} clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}} -#else - clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} -#endif return; } clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}} -#ifdef ANALYZER_CM_Z3 clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}} clang_analyzer_eval(rhs != lhs); // expected-warning{{TRUE}} -#else - clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}} -#endif } void canonical_equal(int *lhs, int *rhs) { clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}} if (lhs == rhs) { -#ifdef ANALYZER_CM_Z3 clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}} -#else - clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} -#endif return; } clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}} - -#ifdef ANALYZER_CM_Z3 clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}} -#else - clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}} -#endif } void compare_element_region_and_base(int *p) { -- GitLab From 1107c5c9c8b3927b66e55314e530f3ad769e3b07 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 28 Jun 2018 10:56:40 +0000 Subject: [PATCH 0333/1023] [DebugInfo] Follow-up commit to improve consistency. NFC Follow-up commit for r335757 to address some inconsistencies. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335834 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 218 ++++++++++++++++++------------------ lib/CodeGen/CGDebugInfo.h | 26 ++--- 2 files changed, 117 insertions(+), 127 deletions(-) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 5a527cbde3..08447f895e 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -289,8 +289,7 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { << OC->getIdentifier()->getNameStart() << ')'; } } else if (const auto *OCD = dyn_cast(DC)) { - OS << OCD->getClassInterface()->getName() << '(' - << OCD->getName() << ')'; + OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')'; } else if (isa(DC)) { // We can extract the type of the class from the self pointer. if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) { @@ -385,7 +384,8 @@ CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { return llvm::DIFile::CSK_MD5; } -Optional CGDebugInfo::getSource(const SourceManager &SM, FileID FID) { +Optional CGDebugInfo::getSource(const SourceManager &SM, + FileID FID) { if (!CGM.getCodeGenOpts().EmbedSource) return None; @@ -412,11 +412,11 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { // Cache the results. const char *fname = PLoc.getFilename(); - auto it = DIFileCache.find(fname); + auto It = DIFileCache.find(fname); - if (it != DIFileCache.end()) { + if (It != DIFileCache.end()) { // Verify that the information still exists. - if (llvm::Metadata *V = it->second) + if (llvm::Metadata *V = It->second) return cast(V); } @@ -427,10 +427,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (CSKind) CSInfo.emplace(*CSKind, Checksum); - llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()), - remapDIPath(getCurrentDirname()), - CSInfo, - getSource(SM, SM.getFileID(Loc))); + llvm::DIFile *F = DBuilder.createFile( + remapDIPath(PLoc.getFilename()), remapDIPath(getCurrentDirname()), CSInfo, + getSource(SM, SM.getFileID(Loc))); DIFileCache[fname].reset(F); return F; @@ -438,8 +437,7 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { llvm::DIFile *CGDebugInfo::getOrCreateMainFile() { return DBuilder.createFile( - remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory()), + remapDIPath(TheCU->getFilename()), remapDIPath(TheCU->getDirectory()), TheCU->getFile()->getChecksum(), CGM.getCodeGenOpts().EmbedSource ? TheCU->getSource() : None); } @@ -574,8 +572,7 @@ void CGDebugInfo::CreateCompileUnit() { TheCU = DBuilder.createCompileUnit( LangTag, DBuilder.createFile(remapDIPath(MainFileName), - remapDIPath(getCurrentDirname()), - CSInfo, + remapDIPath(getCurrentDirname()), CSInfo, getSource(SM, SM.getMainFileID())), CGOpts.EmitVersionIdentMetadata ? Producer : "", LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, @@ -640,14 +637,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { return SelTy; } -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t", \ +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + return getOrCreateStructPtrType("opencl_" #ImgType "_" #Suffix "_t", \ SingletonId); #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: - return getOrCreateStructPtrType("opencl_sampler_t", - OCLSamplerDITy); + return getOrCreateStructPtrType("opencl_sampler_t", OCLSamplerDITy); case BuiltinType::OCLEvent: return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy); case BuiltinType::OCLClkEvent: @@ -830,8 +826,7 @@ static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { } // Determines if the tag declaration will require a type identifier. -static bool needsTypeIdentifier(const TagDecl *TD, - CodeGenModule& CGM, +static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM, llvm::DICompileUnit *TheCU) { // We only add a type identifier for types with C++ name mangling. if (!hasCXXMangling(TD, TheCU)) @@ -855,8 +850,7 @@ static bool needsTypeIdentifier(const TagDecl *TD, // When emitting DWARF debug information, we need to produce a type identifier // for all externally visible types with C++ name mangling. This identifier // should be unique across ODR-compliant compilation units. -static SmallString<256> getTypeIdentifier(const TagType *Ty, - CodeGenModule &CGM, +static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM, llvm::DICompileUnit *TheCU) { SmallString<256> Identifier; const TagDecl *TD = Ty->getDecl(); @@ -873,7 +867,7 @@ static SmallString<256> getTypeIdentifier(const TagType *Ty, /// \return the appropriate DWARF tag for a composite type. static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { - llvm::dwarf::Tag Tag; + llvm::dwarf::Tag Tag; if (RD->isStruct() || RD->isInterface()) Tag = llvm::dwarf::DW_TAG_structure_type; else if (RD->isUnion()) @@ -999,9 +993,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, // DW_AT_APPLE_BLOCK attribute and are an implementation detail only // the debugger needs to know about. To allow type uniquing, emit // them without a name or a location. - EltTy = - DBuilder.createStructType(Unit, "", nullptr, LineNo, - FieldOffset, 0, Flags, nullptr, Elements); + EltTy = DBuilder.createStructType(Unit, "", nullptr, LineNo, FieldOffset, 0, + Flags, nullptr, Elements); return DBuilder.createPointerType(EltTy, Size); } @@ -1016,8 +1009,9 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false); printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy()); - auto *AliasDecl = cast( - Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl(); + auto *AliasDecl = + cast(Ty->getTemplateName().getAsTemplateDecl()) + ->getTemplatedDecl(); SourceLocation Loc = AliasDecl->getLocation(); return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc), @@ -1183,8 +1177,8 @@ CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc, } llvm::DINode::DIFlags flags = getAccessFlag(AS, RD); - return DBuilder.createMemberType(scope, name, file, line, SizeInBits, - Align, offsetInBits, flags, debugType); + return DBuilder.createMemberType(scope, name, file, line, SizeInBits, Align, + offsetInBits, flags, debugType); } void CGDebugInfo::CollectRecordLambdaFields( @@ -1602,8 +1596,10 @@ void CGDebugInfo::CollectCXXBasesAux( // vbase offset offset in Itanium. BaseOffset = 4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base); - VBPtrOffset = CGM.getContext().getASTRecordLayout(RD).getVBPtrOffset() - .getQuantity(); + VBPtrOffset = CGM.getContext() + .getASTRecordLayout(RD) + .getVBPtrOffset() + .getQuantity(); } BFlags |= llvm::DINode::FlagVirtual; } else @@ -1612,9 +1608,8 @@ void CGDebugInfo::CollectCXXBasesAux( // BI->isVirtual() and bits when not. BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD); - llvm::DIType *DTy = - DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, VBPtrOffset, - BFlags); + llvm::DIType *DTy = DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, + VBPtrOffset, BFlags); EltTys.push_back(DTy); } } @@ -1688,8 +1683,8 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, V = CGM.getCXXABI().EmitNullMemberPointer(MPT); if (!V) V = llvm::ConstantInt::get(CGM.Int8Ty, 0); - TemplateParams.push_back(DBuilder.createTemplateValueParameter( - TheCU, Name, TTy, V)); + TemplateParams.push_back( + DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V)); } break; case TemplateArgument::Template: TemplateParams.push_back(DBuilder.createTemplateTemplateParameter( @@ -1761,9 +1756,8 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) { Optional DWARFAddressSpace = CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace); - llvm::DIType *vtbl_ptr_type = - DBuilder.createPointerType(SubTy, Size, 0, DWARFAddressSpace, - "__vtbl_ptr_type"); + llvm::DIType *vtbl_ptr_type = DBuilder.createPointerType( + SubTy, Size, 0, DWARFAddressSpace, "__vtbl_ptr_type"); VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size); return VTablePtrType; } @@ -1807,9 +1801,8 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, CGM.getTarget().getDWARFAddressSpace(VtblPtrAddressSpace); // Create a very wide void* type and insert it directly in the element list. - llvm::DIType *VTableType = - DBuilder.createPointerType(nullptr, VTableWidth, 0, DWARFAddressSpace, - "__vtbl_ptr_type"); + llvm::DIType *VTableType = DBuilder.createPointerType( + nullptr, VTableWidth, 0, DWARFAddressSpace, "__vtbl_ptr_type"); EltTys.push_back(VTableType); // The vptr is a pointer to this special vtable type. @@ -1824,9 +1817,9 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, VPtrTy = getOrCreateVTablePtrType(Unit); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType *VPtrMember = DBuilder.createMemberType( - Unit, getVTableName(RD), Unit, 0, Size, 0, 0, - llvm::DINode::FlagArtificial, VPtrTy); + llvm::DIType *VPtrMember = + DBuilder.createMemberType(Unit, getVTableName(RD), Unit, 0, Size, 0, 0, + llvm::DINode::FlagArtificial, VPtrTy); EltTys.push_back(VPtrMember); } @@ -2173,9 +2166,14 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod, OS << "\"-" << (Undef ? 'U' : 'D'); for (char c : Macro) switch (c) { - case '\\' : OS << "\\\\"; break; - case '"' : OS << "\\\""; break; - default: OS << c; + case '\\': + OS << "\\\\"; + break; + case '"': + OS << "\\\""; + break; + default: + OS << c; } OS << '\"'; } @@ -2270,7 +2268,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, EltTys.push_back(PropertyNode); }; { - llvm::SmallPtrSet PropertySet; + llvm::SmallPtrSet PropertySet; for (const ObjCCategoryDecl *ClassExt : ID->known_extensions()) for (auto *PD : ClassExt->properties()) { PropertySet.insert(PD->getIdentifier()); @@ -2351,10 +2349,12 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); PropertyNode = DBuilder.createObjCProperty( PD->getName(), PUnit, PLine, - hasDefaultGetterName(PD, Getter) ? "" : getSelectorName( - PD->getGetterName()), - hasDefaultSetterName(PD, Setter) ? "" : getSelectorName( - PD->getSetterName()), + hasDefaultGetterName(PD, Getter) + ? "" + : getSelectorName(PD->getGetterName()), + hasDefaultSetterName(PD, Setter) + ? "" + : getSelectorName(PD->getSetterName()), PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit)); } @@ -2514,8 +2514,7 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) { return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy); } -llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty, - llvm::DIFile *U) { +llvm::DIType *CGDebugInfo::CreateType(const PipeType *Ty, llvm::DIFile *U) { return getOrCreateType(Ty->getElementType(), U); } @@ -2679,10 +2678,10 @@ llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) { // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); - auto it = TypeCache.find(Ty.getAsOpaquePtr()); - if (it != TypeCache.end()) { + auto It = TypeCache.find(Ty.getAsOpaquePtr()); + if (It != TypeCache.end()) { // Verify that the debug info still exists. - if (llvm::Metadata *V = it->second) + if (llvm::Metadata *V = It->second) return cast(V); } @@ -2717,7 +2716,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { return T; llvm::DIType *Res = CreateTypeNode(Ty, Unit); - void* TyPtr = Ty.getAsOpaquePtr(); + void *TyPtr = Ty.getAsOpaquePtr(); // And update the type cache. TypeCache[TyPtr].reset(Res); @@ -3004,10 +3003,10 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, if (DebugKind >= codegenoptions::LimitedDebugInfo) { if (const NamespaceDecl *NSDecl = - dyn_cast_or_null(FD->getDeclContext())) + dyn_cast_or_null(FD->getDeclContext())) FDContext = getOrCreateNamespace(NSDecl); else if (const RecordDecl *RDecl = - dyn_cast_or_null(FD->getDeclContext())) { + dyn_cast_or_null(FD->getDeclContext())) { llvm::DIScope *Mod = getParentModuleOrNull(RDecl); FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU); } @@ -3034,8 +3033,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, llvm::APInt ConstVal(32, 1); QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); - T = CGM.getContext().getConstantArrayType(ET, ConstVal, - ArrayType::Normal, 0); + T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, + 0); } Name = VD->getName(); @@ -3062,8 +3061,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, if (DC->isRecord()) DC = CGM.getContext().getTranslationUnitDecl(); - llvm::DIScope *Mod = getParentModuleOrNull(VD); - VDContext = getContextDescriptor(cast(DC), Mod ? Mod : TheCU); + llvm::DIScope *Mod = getParentModuleOrNull(VD); + VDContext = getContextDescriptor(cast(DC), Mod ? Mod : TheCU); } llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, @@ -3075,8 +3074,8 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, llvm::DIFile *Unit = getOrCreateFile(Loc); llvm::DIScope *DContext = Unit; unsigned Line = getLineNumber(Loc); - collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, - TParamsArray, Flags); + collectFunctionDeclProps(GD, Unit, Name, LinkageName, DContext, TParamsArray, + Flags); auto *FD = dyn_cast(GD.getDecl()); // Build function type. @@ -3109,13 +3108,11 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, return SP; } -llvm::DISubprogram * -CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) { +llvm::DISubprogram *CGDebugInfo::getFunctionForwardDeclaration(GlobalDecl GD) { return getFunctionFwdDeclOrStub(GD, /* Stub = */ false); } -llvm::DISubprogram * -CGDebugInfo::getFunctionStub(GlobalDecl GD) { +llvm::DISubprogram *CGDebugInfo::getFunctionStub(GlobalDecl GD) { return getFunctionFwdDeclOrStub(GD, /* Stub = */ true); } @@ -3239,7 +3236,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, if (FPT->getNumParams() > 1) SelfDeclTy = FPT->getParamType(0); if (!SelfDeclTy.isNull()) - Elts.push_back(CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F))); + Elts.push_back( + CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F))); // "_cmd" pointer is always second argument. Elts.push_back(DBuilder.createArtificialType( getOrCreateType(CGM.getContext().getObjCSelType(), F))); @@ -3459,8 +3457,7 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { } void CGDebugInfo::AppendAddressSpaceXDeref( - unsigned AddressSpace, - SmallVectorImpl &Expr) const { + unsigned AddressSpace, SmallVectorImpl &Expr) const { Optional DWARFAddressSpace = CGM.getTarget().getDWARFAddressSpace(AddressSpace); if (!DWARFAddressSpace) @@ -3675,8 +3672,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, // // FIXME: Remove this code as soon as GDB supports this. // The debug info verifier in LLVM operates based on the assumption that a - // variable has the same size as its storage and we had to disable the check - // for artificial variables. + // variable has the same size as its storage and we had to disable the + // check for artificial variables. for (const auto *Field : RD->fields()) { llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); StringRef FieldName = Field->getName(); @@ -3701,13 +3698,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, } // Create the descriptor for the variable. - auto *D = ArgNo - ? DBuilder.createParameterVariable( - Scope, Name, *ArgNo, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags) - : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags, - Align); + auto *D = ArgNo ? DBuilder.createParameterVariable( + Scope, Name, *ArgNo, Unit, Line, Ty, + CGM.getLangOpts().Optimize, Flags) + : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, + CGM.getLangOpts().Optimize, + Flags, Align); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), @@ -3818,7 +3814,7 @@ struct BlockLayoutChunk { bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) { return l.OffsetInBits < r.OffsetInBits; } -} +} // namespace void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, StringRef Name, @@ -3857,9 +3853,10 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, blockLayout->getElementOffsetInBits(3), tunit, tunit)); fields.push_back(createFieldType( - "__descriptor", C.getPointerType(block.NeedsCopyDispose - ? C.getBlockDescriptorExtendedType() - : C.getBlockDescriptorType()), + "__descriptor", + C.getPointerType(block.NeedsCopyDispose + ? C.getBlockDescriptorExtendedType() + : C.getBlockDescriptorType()), loc, AS_public, blockLayout->getElementOffsetInBits(4), tunit, tunit)); // We want to sort the captures by offset, not because DWARF @@ -3938,8 +3935,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, } SmallString<36> typeName; - llvm::raw_svector_ostream(typeName) << "__block_literal_" - << CGM.getUniqueBlockCount(); + llvm::raw_svector_ostream(typeName) + << "__block_literal_" << CGM.getUniqueBlockCount(); llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields); @@ -3955,8 +3952,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, // Create the descriptor for the parameter. auto *debugVar = DBuilder.createParameterVariable( - scope, Name, ArgNo, tunit, line, type, - CGM.getLangOpts().Optimize, flags); + scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(), @@ -3995,7 +3991,7 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( if (FieldName.empty()) { if (const auto *RT = dyn_cast(Field->getType())) GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName, - Var, DContext); + Var, DContext); continue; } // Use VarDecl's Tag, Scope and Line number. @@ -4222,7 +4218,6 @@ void CGDebugInfo::setDwoId(uint64_t Signature) { TheCU->setDWOId(Signature); } - void CGDebugInfo::finalize() { // Creating types might create further types - invalidating the current // element and the size(), so don't cache/reference them. @@ -4236,7 +4231,7 @@ void CGDebugInfo::finalize() { if (CGM.getCodeGenOpts().DwarfVersion >= 5) { // Add methods to interface. - for (auto P : ObjCMethodCache) { + for (const auto &P : ObjCMethodCache) { if (P.second.empty()) continue; @@ -4257,32 +4252,32 @@ void CGDebugInfo::finalize() { } } - for (auto p : ReplaceMap) { - assert(p.second); - auto *Ty = cast(p.second); + for (const auto &P : ReplaceMap) { + assert(P.second); + auto *Ty = cast(P.second); assert(Ty->isForwardDecl()); - auto it = TypeCache.find(p.first); - assert(it != TypeCache.end()); - assert(it->second); + auto It = TypeCache.find(P.first); + assert(It != TypeCache.end()); + assert(It->second); DBuilder.replaceTemporary(llvm::TempDIType(Ty), - cast(it->second)); + cast(It->second)); } - for (const auto &p : FwdDeclReplaceMap) { - assert(p.second); - llvm::TempMDNode FwdDecl(cast(p.second)); + for (const auto &P : FwdDeclReplaceMap) { + assert(P.second); + llvm::TempMDNode FwdDecl(cast(P.second)); llvm::Metadata *Repl; - auto it = DeclCache.find(p.first); + auto It = DeclCache.find(P.first); // If there has been no definition for the declaration, call RAUW // with ourselves, that will destroy the temporary MDNode and // replace it with a standard one, avoiding leaking memory. - if (it == DeclCache.end()) - Repl = p.second; + if (It == DeclCache.end()) + Repl = P.second; else - Repl = it->second; + Repl = It->second; if (auto *GVE = dyn_cast_or_null(Repl)) Repl = GVE->getVariable(); @@ -4312,6 +4307,5 @@ llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) { return llvm::DebugLoc(); llvm::MDNode *Scope = LexicalBlockStack.back(); - return llvm::DebugLoc::get( - getLineNumber(Loc), getColumnNumber(Loc), Scope); + return llvm::DebugLoc::get(getLineNumber(Loc), getColumnNumber(Loc), Scope); } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 9f5e639d98..e632806138 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -67,7 +67,7 @@ class CGDebugInfo { llvm::DIType *ClassTy = nullptr; llvm::DICompositeType *ObjTy = nullptr; llvm::DIType *SelTy = nullptr; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ llvm::DIType *SingletonId = nullptr; #include "clang/Basic/OpenCLImageTypes.def" llvm::DIType *OCLSamplerDITy = nullptr; @@ -232,12 +232,12 @@ class CGDebugInfo { /// Helper function for CollectCXXBases. /// Adds debug info entries for types in Bases that are not in SeenTypes. - void CollectCXXBasesAux(const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl &EltTys, - llvm::DIType *RecordTy, - const CXXRecordDecl::base_class_const_range &Bases, - llvm::DenseSet> &SeenTypes, - llvm::DINode::DIFlags StartingFlags); + void CollectCXXBasesAux( + const CXXRecordDecl *RD, llvm::DIFile *Unit, + SmallVectorImpl &EltTys, llvm::DIType *RecordTy, + const CXXRecordDecl::base_class_const_range &Bases, + llvm::DenseSet> &SeenTypes, + llvm::DINode::DIFlags StartingFlags); /// A helper function to collect template parameters. llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList, @@ -256,8 +256,7 @@ class CGDebugInfo { llvm::DIType *createFieldType(StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS, - uint64_t offsetInBits, - uint32_t AlignInBits, + uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit, llvm::DIScope *scope, const RecordDecl *RD = nullptr); @@ -402,11 +401,9 @@ public: /// Emit call to \c llvm.dbg.declare for an imported variable /// declaration in a block. - void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable, - llvm::Value *storage, - CGBuilderTy &Builder, - const CGBlockInfo &blockInfo, - llvm::Instruction *InsertPoint = nullptr); + void EmitDeclareOfBlockDeclRefVariable( + const VarDecl *variable, llvm::Value *storage, CGBuilderTy &Builder, + const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint = nullptr); /// Emit call to \c llvm.dbg.declare for an argument variable /// declaration. @@ -693,7 +690,6 @@ public: static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) { return ApplyDebugLocation(CGF, true, SourceLocation()); } - }; /// A scoped helper to set the current debug location to an inlined location. -- GitLab From 97905d1cb2f4741773dea7e33311446acc3777f8 Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Thu, 28 Jun 2018 10:58:53 +0000 Subject: [PATCH 0334/1023] [Analyzer] Iterator Checker - Part 2: Increment, decrement operators and ahead-of-begin checks Add handling of the begin() funcion of containers to the iterator checkers, together with the pre- and postfix ++ and -- operators of the iterators. This makes possible the checking of iterators dereferenced ahead of the begin of the container. Differential Revision: https://reviews.llvm.org/D32642 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335835 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/IteratorChecker.cpp | 479 ++++++++++++++++-- .../Inputs/system-header-simulator-cxx.h | 24 + .../diagnostics/explicit-suppression.cpp | 2 +- test/Analysis/iterator-range.cpp | 107 +++- 4 files changed, 578 insertions(+), 34 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp index 29d48ef1c5..325e881a74 100644 --- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -46,19 +46,25 @@ // use setter and getters functions which separate the three cases. To store // them we use a pointer union of symbol and memory region. // -// The checker works the following way: We record the past-end iterator for -// all containers whenever their `.end()` is called. Since the Constraint -// Manager cannot handle SVals we need to take over its role. We post-check -// equality and non-equality comparisons and propagate the position of the -// iterator to the other side of the comparison if it is past-end and we are in -// the 'equal' branch (true-branch for `==` and false-branch for `!=`). +// The checker works the following way: We record the begin and the +// past-end iterator for all containers whenever their `.begin()` and `.end()` +// are called. Since the Constraint Manager cannot handle such SVals we need +// to take over its role. We post-check equality and non-equality comparisons +// and record that the two sides are equal if we are in the 'equal' branch +// (true-branch for `==` and false-branch for `!=`). // // In case of type-I or type-II iterators we get a concrete integer as a result // of the comparison (1 or 0) but in case of type-III we only get a Symbol. In // this latter case we record the symbol and reload it in evalAssume() and do // the propagation there. We also handle (maybe double) negated comparisons -// which are represented in the form of (x == 0 or x !=0 ) where x is the +// which are represented in the form of (x == 0 or x != 0) where x is the // comparison itself. +// +// Since `SimpleConstraintManager` cannot handle complex symbolic expressions +// we only use expressions of the format S, S+n or S-n for iterator positions +// where S is a conjured symbol and n is an unsigned concrete integer. When +// making an assumption e.g. `S1 + n == S2 + m` we store `S1 - S2 == m - n` as +// a constraint which we later retrieve when doing an actual comparison. #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -80,7 +86,7 @@ private: const MemRegion *Cont; // Abstract offset - SymbolRef Offset; + const SymbolRef Offset; IteratorPosition(const MemRegion *C, SymbolRef Of) : Cont(C), Offset(Of) {} @@ -113,31 +119,39 @@ public: typedef llvm::PointerUnion RegionOrSymbol; -// Structure to record the symbolic end position of a container +// Structure to record the symbolic begin and end position of a container struct ContainerData { private: - SymbolRef End; + const SymbolRef Begin, End; - ContainerData(SymbolRef E) : End(E) {} + ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {} public: + static ContainerData fromBegin(SymbolRef B) { + return ContainerData(B, nullptr); + } + static ContainerData fromEnd(SymbolRef E) { - return ContainerData(E); + return ContainerData(nullptr, E); } + SymbolRef getBegin() const { return Begin; } SymbolRef getEnd() const { return End; } - ContainerData newEnd(SymbolRef E) const { return ContainerData(E); } + ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); } + + ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); } bool operator==(const ContainerData &X) const { - return End == X.End; + return Begin == X.Begin && End == X.End; } bool operator!=(const ContainerData &X) const { - return End != X.End; + return Begin != X.Begin || End != X.End; } void Profile(llvm::FoldingSetNodeID &ID) const { + ID.Add(Begin); ID.Add(End); } }; @@ -167,8 +181,9 @@ public: class IteratorChecker : public Checker, check::PostStmt, - check::DeadSymbols, + check::LiveSymbols, check::DeadSymbols, eval::Assume> { std::unique_ptr OutOfRangeBugType; @@ -176,10 +191,22 @@ class IteratorChecker void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal, const SVal &RVal, OverloadedOperatorKind Op) const; void verifyDereference(CheckerContext &C, const SVal &Val) const; + void handleIncrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter, + bool Postfix) const; + void handleDecrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter, + bool Postfix) const; + void handleRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op, + const SVal &RetVal, const SVal &LHS, + const SVal &RHS) const; + void handleBegin(CheckerContext &C, const Expr *CE, const SVal &RetVal, + const SVal &Cont) const; void handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal, const SVal &Cont) const; void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal, const MemRegion *Cont) const; + void verifyRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op, + const SVal &RetVal, const SVal &LHS, + const SVal &RHS) const; void reportOutOfRangeBug(const StringRef &Message, const SVal &Val, CheckerContext &C, ExplodedNode *ErrNode) const; @@ -196,8 +223,10 @@ public: void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostCall(const CallEvent &Call, CheckerContext &C) const; + void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const; void checkPostStmt(const MaterializeTemporaryExpr *MTE, CheckerContext &C) const; + void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond, bool Assumption) const; @@ -217,9 +246,13 @@ namespace { bool isIteratorType(const QualType &Type); bool isIterator(const CXXRecordDecl *CRD); +bool isBeginCall(const FunctionDecl *Func); bool isEndCall(const FunctionDecl *Func); bool isSimpleComparisonOperator(OverloadedOperatorKind OK); bool isDereferenceOperator(OverloadedOperatorKind OK); +bool isIncrementOperator(OverloadedOperatorKind OK); +bool isDecrementOperator(OverloadedOperatorKind OK); +bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK); BinaryOperator::Opcode getOpcode(const SymExpr *SE); const RegionOrSymbol getRegionOrSymbol(const SVal &Val); const ProgramStateRef processComparison(ProgramStateRef State, @@ -230,7 +263,11 @@ const ProgramStateRef saveComparison(ProgramStateRef State, const SVal &RVal, bool Eq); const IteratorComparison *loadComparison(ProgramStateRef State, const SymExpr *Condition); +SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont); SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont); +ProgramStateRef createContainerBegin(ProgramStateRef State, + const MemRegion *Cont, + const SymbolRef Sym); ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, const SymbolRef Sym); const IteratorPosition *getIteratorPosition(ProgramStateRef State, @@ -255,6 +292,7 @@ const ContainerData *getContainerData(ProgramStateRef State, ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont, const ContainerData &CData); bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos); +bool isZero(ProgramStateRef State, const NonLoc &Val); } // namespace IteratorChecker::IteratorChecker() { @@ -272,6 +310,22 @@ void IteratorChecker::checkPreCall(const CallEvent &Call, if (Func->isOverloadedOperator()) { if (ChecksEnabled[CK_IteratorRangeChecker] && + isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) { + if (const auto *InstCall = dyn_cast(&Call)) { + // Check for out-of-range incrementions and decrementions + if (Call.getNumArgs() >= 1) { + verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(), + Call.getReturnValue(), + InstCall->getCXXThisVal(), Call.getArgSVal(0)); + } + } else { + if (Call.getNumArgs() >= 2) { + verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(), + Call.getReturnValue(), Call.getArgSVal(0), + Call.getArgSVal(1)); + } + } + } else if (ChecksEnabled[CK_IteratorRangeChecker] && isDereferenceOperator(Func->getOverloadedOperator())) { // Check for dereference of out-of-range iterators if (const auto *InstCall = dyn_cast(&Call)) { @@ -300,6 +354,36 @@ void IteratorChecker::checkPostCall(const CallEvent &Call, handleComparison(C, Call.getReturnValue(), Call.getArgSVal(0), Call.getArgSVal(1), Op); } + } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) { + if (const auto *InstCall = dyn_cast(&Call)) { + if (Call.getNumArgs() >= 1) { + handleRandomIncrOrDecr(C, Func->getOverloadedOperator(), + Call.getReturnValue(), + InstCall->getCXXThisVal(), Call.getArgSVal(0)); + } + } else { + if (Call.getNumArgs() >= 2) { + handleRandomIncrOrDecr(C, Func->getOverloadedOperator(), + Call.getReturnValue(), Call.getArgSVal(0), + Call.getArgSVal(1)); + } + } + } else if (isIncrementOperator(Func->getOverloadedOperator())) { + if (const auto *InstCall = dyn_cast(&Call)) { + handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(), + Call.getNumArgs()); + } else { + handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0), + Call.getNumArgs()); + } + } else if (isDecrementOperator(Func->getOverloadedOperator())) { + if (const auto *InstCall = dyn_cast(&Call)) { + handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(), + Call.getNumArgs()); + } else { + handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0), + Call.getNumArgs()); + } } } else { const auto *OrigExpr = Call.getOriginExpr(); @@ -315,6 +399,11 @@ void IteratorChecker::checkPostCall(const CallEvent &Call, return; if (const auto *InstCall = dyn_cast(&Call)) { + if (isBeginCall(Func)) { + handleBegin(C, OrigExpr, Call.getReturnValue(), + InstCall->getCXXThisVal()); + return; + } if (isEndCall(Func)) { handleEnd(C, OrigExpr, Call.getReturnValue(), InstCall->getCXXThisVal()); @@ -351,6 +440,36 @@ void IteratorChecker::checkPostCall(const CallEvent &Call, } } +void IteratorChecker::checkPreStmt(const CXXOperatorCallExpr *COCE, + CheckerContext &C) const { + const auto *ThisExpr = COCE->getArg(0); + + auto State = C.getState(); + const auto *LCtx = C.getLocationContext(); + + const auto CurrentThis = State->getSVal(ThisExpr, LCtx); + if (const auto *Reg = CurrentThis.getAsRegion()) { + if (!Reg->getAs()) + return; + const auto OldState = C.getPredecessor()->getFirstPred()->getState(); + const auto OldThis = OldState->getSVal(ThisExpr, LCtx); + // FIXME: This solution is unreliable. It may happen that another checker + // subscribes to the pre-statement check of `CXXOperatorCallExpr` + // and adds a transition before us. The proper fix is to make the + // CFG provide a `ConstructionContext` for the `CXXOperatorCallExpr`, + // which would turn the corresponding `CFGStmt` element into a + // `CFGCXXRecordTypedCall` element, which will allow `ExprEngine` to + // foresee that the `begin()`/`end()` call constructs the object + // directly in the temporary region that `CXXOperatorCallExpr` takes + // as its implicit object argument. + const auto *Pos = getIteratorPosition(OldState, OldThis); + if (!Pos) + return; + State = setIteratorPosition(State, CurrentThis, *Pos); + C.addTransition(State); + } +} + void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE, CheckerContext &C) const { /* Transfer iterator state to temporary objects */ @@ -363,6 +482,34 @@ void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE, C.addTransition(State); } +void IteratorChecker::checkLiveSymbols(ProgramStateRef State, + SymbolReaper &SR) const { + // Keep symbolic expressions of iterator positions, container begins and ends + // alive + auto RegionMap = State->get(); + for (const auto Reg : RegionMap) { + const auto Pos = Reg.second; + SR.markLive(Pos.getOffset()); + } + + auto SymbolMap = State->get(); + for (const auto Sym : SymbolMap) { + const auto Pos = Sym.second; + SR.markLive(Pos.getOffset()); + } + + auto ContMap = State->get(); + for (const auto Cont : ContMap) { + const auto CData = Cont.second; + if (CData.getBegin()) { + SR.markLive(CData.getBegin()); + } + if (CData.getEnd()) { + SR.markLive(CData.getEnd()); + } + } +} + void IteratorChecker::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { // Cleanup @@ -470,13 +617,209 @@ void IteratorChecker::verifyDereference(CheckerContext &C, static CheckerProgramPointTag Tag("IteratorRangeChecker", "IteratorOutOfRange"); auto *N = C.generateNonFatalErrorNode(State, &Tag); - if (!N) { + if (!N) return; - } reportOutOfRangeBug("Iterator accessed outside of its range.", Val, C, N); } } +void IteratorChecker::handleIncrement(CheckerContext &C, const SVal &RetVal, + const SVal &Iter, bool Postfix) const { + // Increment the symbolic expressions which represents the position of the + // iterator + auto State = C.getState(); + const auto *Pos = getIteratorPosition(State, Iter); + if (Pos) { + auto &SymMgr = C.getSymbolManager(); + auto &BVF = SymMgr.getBasicVals(); + auto &SVB = C.getSValBuilder(); + const auto OldOffset = Pos->getOffset(); + auto NewOffset = + SVB.evalBinOp(State, BO_Add, + nonloc::SymbolVal(OldOffset), + nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SymMgr.getType(OldOffset)).getAsSymbol(); + auto NewPos = Pos->setTo(NewOffset); + State = setIteratorPosition(State, Iter, NewPos); + State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos); + C.addTransition(State); + } +} + +void IteratorChecker::handleDecrement(CheckerContext &C, const SVal &RetVal, + const SVal &Iter, bool Postfix) const { + // Decrement the symbolic expressions which represents the position of the + // iterator + auto State = C.getState(); + const auto *Pos = getIteratorPosition(State, Iter); + if (Pos) { + auto &SymMgr = C.getSymbolManager(); + auto &BVF = SymMgr.getBasicVals(); + auto &SVB = C.getSValBuilder(); + const auto OldOffset = Pos->getOffset(); + auto NewOffset = + SVB.evalBinOp(State, BO_Sub, + nonloc::SymbolVal(OldOffset), + nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SymMgr.getType(OldOffset)).getAsSymbol(); + auto NewPos = Pos->setTo(NewOffset); + State = setIteratorPosition(State, Iter, NewPos); + State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos); + C.addTransition(State); + } +} + +// This function tells the analyzer's engine that symbols produced by our +// checker, most notably iterator positions, are relatively small. +// A distance between items in the container should not be very large. +// By assuming that it is within around 1/8 of the address space, +// we can help the analyzer perform operations on these symbols +// without being afraid of integer overflows. +// FIXME: Should we provide it as an API, so that all checkers could use it? +static ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, + long Scale) { + SValBuilder &SVB = State->getStateManager().getSValBuilder(); + BasicValueFactory &BV = SVB.getBasicValueFactory(); + + QualType T = Sym->getType(); + assert(T->isSignedIntegerOrEnumerationType()); + APSIntType AT = BV.getAPSIntType(T); + + ProgramStateRef NewState = State; + + llvm::APSInt Max = AT.getMaxValue() / AT.getValue(Scale); + SVal IsCappedFromAbove = + SVB.evalBinOpNN(State, BO_LE, nonloc::SymbolVal(Sym), + nonloc::ConcreteInt(Max), SVB.getConditionType()); + if (auto DV = IsCappedFromAbove.getAs()) { + NewState = NewState->assume(*DV, true); + if (!NewState) + return State; + } + + llvm::APSInt Min = -Max; + SVal IsCappedFromBelow = + SVB.evalBinOpNN(State, BO_GE, nonloc::SymbolVal(Sym), + nonloc::ConcreteInt(Min), SVB.getConditionType()); + if (auto DV = IsCappedFromBelow.getAs()) { + NewState = NewState->assume(*DV, true); + if (!NewState) + return State; + } + + return NewState; +} + +void IteratorChecker::handleRandomIncrOrDecr(CheckerContext &C, + OverloadedOperatorKind Op, + const SVal &RetVal, + const SVal &LHS, + const SVal &RHS) const { + // Increment or decrement the symbolic expressions which represents the + // position of the iterator + auto State = C.getState(); + const auto *Pos = getIteratorPosition(State, LHS); + if (!Pos) + return; + + const auto *value = &RHS; + if (auto loc = RHS.getAs()) { + const auto val = State->getRawSVal(*loc); + value = &val; + } + + auto &SymMgr = C.getSymbolManager(); + auto &SVB = C.getSValBuilder(); + auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub; + const auto OldOffset = Pos->getOffset(); + SymbolRef NewOffset; + if (const auto intValue = value->getAs()) { + // For concrete integers we can calculate the new position + NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset), + *intValue, + SymMgr.getType(OldOffset)).getAsSymbol(); + } else { + // For other symbols create a new symbol to keep expressions simple + const auto &LCtx = C.getLocationContext(); + NewOffset = SymMgr.conjureSymbol(nullptr, LCtx, SymMgr.getType(OldOffset), + C.blockCount()); + State = assumeNoOverflow(State, NewOffset, 4); + } + auto NewPos = Pos->setTo(NewOffset); + auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal; + State = setIteratorPosition(State, TgtVal, NewPos); + C.addTransition(State); +} + +void IteratorChecker::verifyRandomIncrOrDecr(CheckerContext &C, + OverloadedOperatorKind Op, + const SVal &RetVal, + const SVal &LHS, + const SVal &RHS) const { + auto State = C.getState(); + + // If the iterator is initially inside its range, then the operation is valid + const auto *Pos = getIteratorPosition(State, LHS); + if (!Pos || !isOutOfRange(State, *Pos)) + return; + + auto value = RHS; + if (auto loc = RHS.getAs()) { + value = State->getRawSVal(*loc); + } + + // Incremention or decremention by 0 is never bug + if (isZero(State, value.castAs())) + return; + + auto &SymMgr = C.getSymbolManager(); + auto &SVB = C.getSValBuilder(); + auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub; + const auto OldOffset = Pos->getOffset(); + const auto intValue = value.getAs(); + if (!intValue) + return; + + auto NewOffset = SVB.evalBinOp(State, BinOp, nonloc::SymbolVal(OldOffset), + *intValue, + SymMgr.getType(OldOffset)).getAsSymbol(); + auto NewPos = Pos->setTo(NewOffset); + + // If out of range, the only valid operation is to step into the range + if (isOutOfRange(State, NewPos)) { + auto *N = C.generateNonFatalErrorNode(State); + if (!N) + return; + reportOutOfRangeBug("Iterator accessed past its end.", LHS, C, N); + } +} + +void IteratorChecker::handleBegin(CheckerContext &C, const Expr *CE, + const SVal &RetVal, const SVal &Cont) const { + const auto *ContReg = Cont.getAsRegion(); + if (!ContReg) + return; + + while (const auto *CBOR = ContReg->getAs()) { + ContReg = CBOR->getSuperRegion(); + } + + // If the container already has a begin symbol then use it. Otherwise first + // create a new one. + auto State = C.getState(); + auto BeginSym = getContainerBegin(State, ContReg); + if (!BeginSym) { + auto &SymMgr = C.getSymbolManager(); + BeginSym = SymMgr.conjureSymbol(CE, C.getLocationContext(), + C.getASTContext().LongTy, C.blockCount()); + State = assumeNoOverflow(State, BeginSym, 4); + State = createContainerBegin(State, ContReg, BeginSym); + } + State = setIteratorPosition(State, RetVal, + IteratorPosition::getPosition(ContReg, BeginSym)); + C.addTransition(State); +} + void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal, const SVal &Cont) const { const auto *ContReg = Cont.getAsRegion(); @@ -495,6 +838,7 @@ void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE, auto &SymMgr = C.getSymbolManager(); EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(), C.getASTContext().LongTy, C.blockCount()); + State = assumeNoOverflow(State, EndSym, 4); State = createContainerEnd(State, ContReg, EndSym); } State = setIteratorPosition(State, RetVal, @@ -513,6 +857,7 @@ void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE, auto &SymMgr = C.getSymbolManager(); auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(), C.getASTContext().LongTy, C.blockCount()); + State = assumeNoOverflow(State, Sym, 4); State = setIteratorPosition(State, RetVal, IteratorPosition::getPosition(Cont, Sym)); C.addTransition(State); @@ -528,9 +873,12 @@ void IteratorChecker::reportOutOfRangeBug(const StringRef &Message, namespace { +bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2); bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2); bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, BinaryOperator::Opcode Opc); +bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2, + BinaryOperator::Opcode Opc); bool isIteratorType(const QualType &Type) { if (Type->isPointerType()) @@ -584,6 +932,13 @@ bool isIterator(const CXXRecordDecl *CRD) { HasPostIncrOp && HasDerefOp; } +bool isBeginCall(const FunctionDecl *Func) { + const auto *IdInfo = Func->getIdentifier(); + if (!IdInfo) + return false; + return IdInfo->getName().endswith_lower("begin"); +} + bool isEndCall(const FunctionDecl *Func) { const auto *IdInfo = Func->getIdentifier(); if (!IdInfo) @@ -600,6 +955,19 @@ bool isDereferenceOperator(OverloadedOperatorKind OK) { OK == OO_Subscript; } +bool isIncrementOperator(OverloadedOperatorKind OK) { + return OK == OO_PlusPlus; +} + +bool isDecrementOperator(OverloadedOperatorKind OK) { + return OK == OO_MinusMinus; +} + +bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK) { + return OK == OO_Plus || OK == OO_PlusEqual || OK == OO_Minus || + OK == OO_MinusEqual; +} + BinaryOperator::Opcode getOpcode(const SymExpr *SE) { if (const auto *BSE = dyn_cast(SE)) { return BSE->getOpcode(); @@ -659,6 +1027,14 @@ const IteratorComparison *loadComparison(ProgramStateRef State, return State->get(Condition); } +SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont) { + const auto *CDataPtr = getContainerData(State, Cont); + if (!CDataPtr) + return nullptr; + + return CDataPtr->getBegin(); +} + SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) { const auto *CDataPtr = getContainerData(State, Cont); if (!CDataPtr) @@ -667,6 +1043,22 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) { return CDataPtr->getEnd(); } +ProgramStateRef createContainerBegin(ProgramStateRef State, + const MemRegion *Cont, + const SymbolRef Sym) { + // Only create if it does not exist + const auto *CDataPtr = getContainerData(State, Cont); + if (CDataPtr) { + if (CDataPtr->getBegin()) { + return State; + } + const auto CData = CDataPtr->newBegin(Sym); + return setContainerData(State, Cont, CData); + } + const auto CData = ContainerData::fromBegin(Sym); + return setContainerData(State, Cont, CData); +} + ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, const SymbolRef Sym) { // Only create if it does not exist @@ -674,14 +1066,12 @@ ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, if (CDataPtr) { if (CDataPtr->getEnd()) { return State; - } else { - const auto CData = CDataPtr->newEnd(Sym); - return setContainerData(State, Cont, CData); } - } else { - const auto CData = ContainerData::fromEnd(Sym); + const auto CData = CDataPtr->newEnd(Sym); return setContainerData(State, Cont, CData); } + const auto CData = ContainerData::fromEnd(Sym); + return setContainerData(State, Cont, CData); } const ContainerData *getContainerData(ProgramStateRef State, @@ -766,19 +1156,31 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State, const IteratorPosition &Pos1, const IteratorPosition &Pos2, bool Equal) { - // Try to compare them and get a defined value auto &SVB = State->getStateManager().getSValBuilder(); const auto comparison = SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()), nonloc::SymbolVal(Pos2.getOffset()), SVB.getConditionType()) .getAs(); + if (comparison) { - return State->assume(*comparison, Equal); + auto NewState = State->assume(*comparison, Equal); + if (const auto CompSym = comparison->getAsSymbol()) { + return assumeNoOverflow(NewState, cast(CompSym)->getLHS(), 2); + } + + return NewState; } return State; } +bool isZero(ProgramStateRef State, const NonLoc &Val) { + auto &BVF = State->getBasicVals(); + return compare(State, Val, + nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))), + BO_EQ); +} + bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) { const auto *Cont = Pos.getContainer(); const auto *CData = getContainerData(State, Cont); @@ -788,6 +1190,13 @@ bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) { // Out of range means less than the begin symbol or greater or equal to the // end symbol. + const auto Beg = CData->getBegin(); + if (Beg) { + if (isLess(State, Pos.getOffset(), Beg)) { + return true; + } + } + const auto End = CData->getEnd(); if (End) { if (isGreaterOrEqual(State, Pos.getOffset(), End)) { @@ -798,22 +1207,29 @@ bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) { return false; } +bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) { + return compare(State, Sym1, Sym2, BO_LT); +} + bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) { return compare(State, Sym1, Sym2, BO_GE); } bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, BinaryOperator::Opcode Opc) { - auto &SMgr = State->getStateManager(); - auto &SVB = SMgr.getSValBuilder(); + return compare(State, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), Opc); +} + +bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2, + BinaryOperator::Opcode Opc) { + auto &SVB = State->getStateManager().getSValBuilder(); const auto comparison = - SVB.evalBinOp(State, Opc, nonloc::SymbolVal(Sym1), - nonloc::SymbolVal(Sym2), SVB.getConditionType()) + SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType()) .getAs(); - if(comparison) { - return !!State->assume(*comparison, true); + if (comparison) { + return !State->assume(*comparison, false); } return false; @@ -830,3 +1246,4 @@ bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, } REGISTER_CHECKER(IteratorRangeChecker) + diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h index 7702e5196e..5d7e553ed5 100644 --- a/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -252,6 +252,12 @@ namespace std { return size_t(_finish - _start); } + void clear(); + + void push_back(const T &value); + void push_back(T &&value); + void pop_back(); + T &operator[](size_t n) { return _start[n]; } @@ -295,6 +301,8 @@ namespace std { list& operator=(list &&other); list& operator=(std::initializer_list ilist); + void clear(); + iterator begin() { return iterator(_start); } const_iterator begin() const { return const_iterator(_start); } const_iterator cbegin() const { return const_iterator(_start); } @@ -330,6 +338,16 @@ namespace std { return size_t(_finish - _start); } + void clear(); + + void push_back(const T &value); + void push_back(T &&value); + void pop_back(); + + void push_front(const T &value); + void push_front(T &&value); + void pop_front(); + T &operator[](size_t n) { return _start[n]; } @@ -369,6 +387,12 @@ namespace std { forward_list(forward_list &&other); ~forward_list(); + void clear(); + + void push_front(const T &value); + void push_front(T &&value); + void pop_front(); + iterator begin() { return iterator(_start); } const_iterator begin() const { return const_iterator(_start); } const_iterator cbegin() const { return const_iterator(_start); } diff --git a/test/Analysis/diagnostics/explicit-suppression.cpp b/test/Analysis/diagnostics/explicit-suppression.cpp index 96d2b4a7d0..092591836b 100644 --- a/test/Analysis/diagnostics/explicit-suppression.cpp +++ b/test/Analysis/diagnostics/explicit-suppression.cpp @@ -19,6 +19,6 @@ class C { void testCopyNull(C *I, C *E) { std::copy(I, E, (C *)0); #ifndef SUPPRESSED - // expected-warning@../Inputs/system-header-simulator-cxx.h:490 {{Called C++ object pointer is null}} + // expected-warning@../Inputs/system-header-simulator-cxx.h:514 {{Called C++ object pointer is null}} #endif } diff --git a/test/Analysis/iterator-range.cpp b/test/Analysis/iterator-range.cpp index 79b45188ab..45d9f194d4 100644 --- a/test/Analysis/iterator-range.cpp +++ b/test/Analysis/iterator-range.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config c++-container-inlining=false %s -verify -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-relational-comparison-simplification=true -analyzer-config c++-container-inlining=false %s -verify +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-relational-comparison-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify #include "Inputs/system-header-simulator-cxx.h" @@ -13,7 +13,110 @@ void simple_good_end(const std::vector &v) { } } +void simple_good_end_negated(const std::vector &v) { + auto i = v.end(); + if (!(i == v.end())) { + clang_analyzer_warnIfReached(); + *i; // no-warning + } +} + void simple_bad_end(const std::vector &v) { auto i = v.end(); *i; // expected-warning{{Iterator accessed outside of its range}} } + +void simple_good_begin(const std::vector &v) { + auto i = v.begin(); + if (i != v.begin()) { + clang_analyzer_warnIfReached(); + *--i; // no-warning + } +} + +void simple_good_begin_negated(const std::vector &v) { + auto i = v.begin(); + if (!(i == v.begin())) { + clang_analyzer_warnIfReached(); + *--i; // no-warning + } +} + +void simple_bad_begin(const std::vector &v) { + auto i = v.begin(); + *--i; // expected-warning{{Iterator accessed outside of its range}} +} + +void copy(const std::vector &v) { + auto i1 = v.end(); + auto i2 = i1; + *i2; // expected-warning{{Iterator accessed outside of its range}} +} + +void decrease(const std::vector &v) { + auto i = v.end(); + --i; + *i; // no-warning +} + +void copy_and_decrease1(const std::vector &v) { + auto i1 = v.end(); + auto i2 = i1; + --i1; + *i1; // no-warning +} + +void copy_and_decrease2(const std::vector &v) { + auto i1 = v.end(); + auto i2 = i1; + --i1; + *i2; // expected-warning{{Iterator accessed outside of its range}} +} + +void copy_and_increase1(const std::vector &v) { + auto i1 = v.begin(); + auto i2 = i1; + ++i1; + if (i1 == v.end()) + *i2; // no-warning +} + +void copy_and_increase2(const std::vector &v) { + auto i1 = v.begin(); + auto i2 = i1; + ++i1; + if (i2 == v.end()) + *i2; // expected-warning{{Iterator accessed outside of its range}} +} + +void copy_and_increase3(const std::vector &v) { + auto i1 = v.begin(); + auto i2 = i1; + ++i1; + if (v.end() == i2) + *i2; // expected-warning{{Iterator accessed outside of its range}} +} + +void tricky(std::vector &V, int e) { + const auto first = V.begin(); + const auto comp1 = (first != V.end()), comp2 = (first == V.end()); + if (comp1) + *first; +} + +void loop(std::vector &V, int e) { + auto start = V.begin(); + while (true) { + auto item = std::find(start, V.end(), e); + if (item == V.end()) + break; + *item; // no-warning + start = ++item; // no-warning + } +} + +void bad_move(std::list &L1, std::list &L2) { + auto i0 = --L2.cend(); + L1 = std::move(L2); + *++i0; // expected-warning{{Iterator accessed outside of its range}} +} -- GitLab From 5ba30971b95208f233d7fd21f9e9387bebc2ef17 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 28 Jun 2018 12:00:16 +0000 Subject: [PATCH 0335/1023] Fix the indentation in this documentation to remove a Sphinx warning; NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335841 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/AttrDocs.td | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 8210bf0a86..53ae80b0ff 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -2946,11 +2946,10 @@ X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow Enforcement Technology (CET). IBT instruments ENDBR instructions used to specify valid targets of indirect call / jmp. The ``nocf_check`` attribute has two roles: -1. Appertains to a function - do not add ENDBR instruction at the - beginning of the function. -2. Appertains to a function pointer - do not track the target - function of this pointer (by adding nocf_check prefix to the - indirect-call instruction). +1. Appertains to a function - do not add ENDBR instruction at the beginning of +the function. +2. Appertains to a function pointer - do not track the target function of this +pointer (by adding nocf_check prefix to the indirect-call instruction). }]; } -- GitLab From a35288989d952cdc7cb4d19b0f5cdf7f623b18ad Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 28 Jun 2018 12:02:38 +0000 Subject: [PATCH 0336/1023] Correct the code highlighting marker to be Objective-C rather than C++ which fixes a Sphinx build warning; NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335842 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangFormatStyleOptions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 64008b50a0..b6281ecae7 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -1588,7 +1588,7 @@ the configuration (without a prefix: ``Auto``). onto individual lines whenever they go over ``ColumnLimit``. - .. code-block:: c++ + .. code-block:: objc Always (or Auto, if BinPackParameters=true): @interface ccccccccccccc () < -- GitLab From bff556fe3c9d9e8a530ef819fe034ad5ec69ce55 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 28 Jun 2018 12:05:40 +0000 Subject: [PATCH 0337/1023] The :option: syntax was generating Sphinx build warnings; switched to double backticks to silence the warning; NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335843 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ReleaseNotes.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 15ae73e859..c0ce10d6eb 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -103,8 +103,7 @@ Non-comprehensive list of changes in this release New Compiler Flags ------------------ -- :option:`-fstrict-float-cast-overflow` and - :option:`-fno-strict-float-cast-overflow`. +- ``-fstrict-float-cast-overflow`` and ``-fno-strict-float-cast-overflow``. When a floating-point value is not representable in a destination integer type, the code has undefined behavior according to the language standard. By @@ -112,7 +111,7 @@ New Compiler Flags 'no-strict' option, Clang attempts to match the overflowing behavior of the target's native float-to-int conversion instructions. -- :option: `-fforce-emit-vtables` and `-fno-force-emit-vtables`. +- ``-fforce-emit-vtables`` and ``-fno-force-emit-vtables``. In order to improve devirtualization, forces emitting of vtables even in modules where it isn't necessary. It causes more inline virtual functions -- GitLab From 29cdecbf6913d7ddbe26d55e029d96094ae1b0b3 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Thu, 28 Jun 2018 13:28:44 +0000 Subject: [PATCH 0338/1023] [ODRHash] Do not rely on Type* when computing the hash. ODRHash aims to provide Cross-TU stable hashing. Making clang::Type pointer part of the hash connects (remotely) the ODRHash with the TU-specific ::Profile hasher. r332281 exposed the issue by changing the way the ASTContext different elaborated types if there is an owning tag. In that case, ODRHash stores two different types in its TypeMap which yields false ODR violation in modules. The current state of implementation shouldn't need the TypeMap concept anymore. Rip it out. Differential Revision: https://reviews.llvm.org/D48524 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335853 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ODRHash.h | 1 - lib/AST/ODRHash.cpp | 9 --------- .../Modules/Inputs/odr_hash-elaborated-types/first.h | 6 ++++++ .../odr_hash-elaborated-types/module.modulemap | 5 +++++ .../Inputs/odr_hash-elaborated-types/second.h | 6 ++++++ .../Inputs/odr_hash-elaborated-types/textual_stat.h | 11 +++++++++++ .../Inputs/odr_hash-elaborated-types/textual_time.h | 6 ++++++ test/Modules/odr_hash-elaborated-types.cpp | 12 ++++++++++++ 8 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 test/Modules/Inputs/odr_hash-elaborated-types/first.h create mode 100644 test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap create mode 100644 test/Modules/Inputs/odr_hash-elaborated-types/second.h create mode 100644 test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h create mode 100644 test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h create mode 100644 test/Modules/odr_hash-elaborated-types.cpp diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h index c9e80278c7..d4cddb8dfd 100644 --- a/include/clang/AST/ODRHash.h +++ b/include/clang/AST/ODRHash.h @@ -40,7 +40,6 @@ class ODRHash { // Use DenseMaps to convert from DeclarationName and Type pointers // to an index value. llvm::DenseMap DeclNameMap; - llvm::DenseMap TypeMap; // Save space by processing bools at the end. llvm::SmallVector Bools; diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 126b6de25e..ef1235e1d8 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -180,7 +180,6 @@ void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) { void ODRHash::clear() { DeclNameMap.clear(); - TypeMap.clear(); Bools.clear(); ID.clear(); } @@ -770,14 +769,6 @@ public: void ODRHash::AddType(const Type *T) { assert(T && "Expecting non-null pointer."); - auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size())); - ID.AddInteger(Result.first->second); - // On first encounter of a Type pointer, process it. Every time afterwards, - // only the index value is needed. - if (!Result.second) { - return; - } - ODRTypeVisitor(ID, *this).Visit(T); } diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/first.h b/test/Modules/Inputs/odr_hash-elaborated-types/first.h new file mode 100644 index 0000000000..d2c4a033a1 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-elaborated-types/first.h @@ -0,0 +1,6 @@ +#ifndef FIRST +#define FIRST + +#include "textual_time.h" + +#endif diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap b/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap new file mode 100644 index 0000000000..94cb4c1119 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-elaborated-types/module.modulemap @@ -0,0 +1,5 @@ +module M { + module first { header "first.h" export *} + module second { header "second.h" export *} + export * +} diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/second.h b/test/Modules/Inputs/odr_hash-elaborated-types/second.h new file mode 100644 index 0000000000..577cf11345 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-elaborated-types/second.h @@ -0,0 +1,6 @@ +#ifndef SECOND +#define SECOND + +#include "textual_stat.h" + +#endif diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h b/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h new file mode 100644 index 0000000000..5dad510f9e --- /dev/null +++ b/test/Modules/Inputs/odr_hash-elaborated-types/textual_stat.h @@ -0,0 +1,11 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include "textual_time.h" + +struct stat { + struct timespec st_atim; + struct timespec st_mtim; +}; + +#endif diff --git a/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h b/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h new file mode 100644 index 0000000000..2a2a89c5a7 --- /dev/null +++ b/test/Modules/Inputs/odr_hash-elaborated-types/textual_time.h @@ -0,0 +1,6 @@ +#ifndef _TIME_H +#define _TIME_H + +struct timespec { }; + +#endif diff --git a/test/Modules/odr_hash-elaborated-types.cpp b/test/Modules/odr_hash-elaborated-types.cpp new file mode 100644 index 0000000000..7dd11ac6d7 --- /dev/null +++ b/test/Modules/odr_hash-elaborated-types.cpp @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++1z -I%S/Inputs/odr_hash-elaborated-types -verify %s +// RUN: %clang_cc1 -std=c++1z -fmodules -fmodules-local-submodule-visibility -fmodule-map-file=%S/Inputs/odr_hash-elaborated-types/module.modulemap -fmodules-cache-path=%t -x c++ -I%S/Inputs/odr_hash-elaborated-types -verify %s + +#include "textual_stat.h" + +#include "first.h" +#include "second.h" + +void use() { struct stat value; } + +// expected-no-diagnostics -- GitLab From 28e87abe7b2c06bdbe39b267ec671477b982d084 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 28 Jun 2018 13:31:36 +0000 Subject: [PATCH 0339/1023] Fix unittest build with GCC older than 5. Old GCCs have an annoying bug where RVO disables the automatic conversion to base for unique_ptr. Add a pessimizing std::move as a workaround. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335854 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp index 82887a1daf..dcd115e596 100644 --- a/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp +++ b/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp @@ -61,7 +61,7 @@ public: AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("custom.CustomChecker", "Description"); }); - return AnalysisConsumer; + return std::move(AnalysisConsumer); } }; -- GitLab From 4607d74518a90d873ab8752958835f6d37f7ce09 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 28 Jun 2018 13:49:41 +0000 Subject: [PATCH 0340/1023] OpenBSD driver needs ld.lld in sanitizer context Base GNU ld is pretty ancient and does not support --dynamic-list flag. For conveniency, we can it automatically when compile with ubsan sanitizer flag. Reviewers: dberris Reviewed by: dberris Differential Revision: https://reviews.llvm.org/D48574 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335856 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/OpenBSD.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index 3a2a004306..7b98cd62bb 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -230,7 +230,9 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + const char *Exec = Args.MakeArgString( + !NeedsSanitizerDeps ? getToolChain().GetLinkerPath() + : getToolChain().GetProgramPath("ld.lld")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } -- GitLab From aeb727e06401222024a2d001754a9898280ed51f Mon Sep 17 00:00:00 2001 From: Filipe Cabecinhas Date: Thu, 28 Jun 2018 14:16:13 +0000 Subject: [PATCH 0341/1023] Fix test that was failing on Windows due to too many backslashes git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335858 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/linux-per-target-runtime-dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Driver/linux-per-target-runtime-dir.c b/test/Driver/linux-per-target-runtime-dir.c index 89310c11d9..aa9c1017f6 100644 --- a/test/Driver/linux-per-target-runtime-dir.c +++ b/test/Driver/linux-per-target-runtime-dir.c @@ -18,4 +18,4 @@ // RUN: --target=x86_64-linux-gnu \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s -// CHECK-CLANGRT-X8664: x86_64-linux-gnu{{/|\\\\}}lib{{/|\\\\}}libclang_rt.builtins.a +// CHECK-CLANGRT-X8664: x86_64-linux-gnu{{/|\\}}lib{{/|\\}}libclang_rt.builtins.a -- GitLab From 554d9dbbff7d65630d25c41465bd73c30eb8e1ae Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 28 Jun 2018 16:58:24 +0000 Subject: [PATCH 0342/1023] [clang-format] Do not format raw string literals inside a recognized function with a non-recognized delimiter Summary: This stops clang-format from touching raw string contents with unrecognized delimiters inside recognized functions. Unrecognized delimiters signal that the string might be special. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48728 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335876 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 2 +- unittests/Format/FormatTestRawStrings.cpp | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 1a5a6deb04..bb8efd61a3 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -1648,7 +1648,7 @@ ContinuationIndenter::getRawStringStyle(const FormatToken &Current, if (!Delimiter) return None; auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter); - if (!RawStringStyle) + if (!RawStringStyle && Delimiter->empty()) RawStringStyle = RawStringFormats.getEnclosingFunctionStyle( getEnclosingFunctionName(Current)); if (!RawStringStyle) diff --git a/unittests/Format/FormatTestRawStrings.cpp b/unittests/Format/FormatTestRawStrings.cpp index 3ec6bb9cb4..307394341d 100644 --- a/unittests/Format/FormatTestRawStrings.cpp +++ b/unittests/Format/FormatTestRawStrings.cpp @@ -862,6 +862,32 @@ int f() { Style)); } +TEST_F(FormatTestRawStrings, + DoNotFormatUnrecognizedDelimitersInRecognizedFunctions) { + FormatStyle Style = getRawStringPbStyleWithColumns(60); + Style.RawStringFormats[0].EnclosingFunctions.push_back( + "EqualsProto"); + // EqualsProto is a recognized function, but the Raw delimiter is + // unrecognized. Do not touch the string in this case, since it might be + // special. + expect_eq(R"test( +void f() { + aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw( +item { + key: value +} +)Raw")); +})test", + format(R"test( +void f() { + aaaaaaaaa(bbbbbbbbb, EqualsProto(R"Raw( +item { + key: value +} +)Raw")); +})test", + Style)); +} } // end namespace } // end namespace format -- GitLab From 9c9dd21ad722082526b649b2a230ef4ff97d1975 Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Thu, 28 Jun 2018 17:15:52 +0000 Subject: [PATCH 0343/1023] [CUDA] Place all CUDA sections in __NV_CUDA segment on Mac. That's where CUDA binaries appear to put them. Differential Revision: https://reviews.llvm.org/D48615 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335880 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCUDANV.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index f8a7825f0a..b541b1046f 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -389,8 +389,9 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { FatMagic = HIPFatMagic; } else { if (RelocatableDeviceCode) - // TODO: Figure out how this is called on mac OS! - FatbinConstantName = "__nv_relfatbin"; + FatbinConstantName = CGM.getTriple().isMacOSX() + ? "__NV_CUDA,__nv_relfatbin" + : "__nv_relfatbin"; else FatbinConstantName = CGM.getTriple().isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin"; @@ -398,8 +399,9 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { FatbinSectionName = CGM.getTriple().isMacOSX() ? "__NV_CUDA,__fatbin" : ".nvFatBinSegment"; - // TODO: Figure out how this is called on mac OS! - ModuleIDSectionName = "__nv_module_id"; + ModuleIDSectionName = CGM.getTriple().isMacOSX() + ? "__NV_CUDA,__nv_module_id" + : "__nv_module_id"; ModuleIDPrefix = "__nv_"; // For CUDA, create a string literal containing the fat binary loaded from -- GitLab From f176add234ce19907429c79c8a36c00d8b896540 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Thu, 28 Jun 2018 17:53:35 +0000 Subject: [PATCH 0344/1023] [Darwin] Remove _VPMergeHook from the auto-export list Remove _VPMergeHook from Darwin's automatically-exported symbol list for PGO. As of r328987 this symbol is no longer weak. An integration test in compiler-rt will follow. rdar://41470205 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335890 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Darwin.cpp | 1 - test/Driver/darwin-ld.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index cb72903431..d0c633b120 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -1019,7 +1019,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args, // runtime, automatically export symbols necessary to implement some of the // runtime's functionality. if (hasExportSymbolDirective(Args)) { - addExportedSymbol(CmdArgs, "_VPMergeHook"); addExportedSymbol(CmdArgs, "___llvm_profile_filename"); addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); addExportedSymbol(CmdArgs, "_lprofCurFilename"); diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c index 9dd2e2b6ca..14f84bb053 100644 --- a/test/Driver/darwin-ld.c +++ b/test/Driver/darwin-ld.c @@ -366,7 +366,7 @@ // RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log // RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log // RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log -// PROFILE_EXPORT: "-exported_symbol" "_VPMergeHook" "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename" +// PROFILE_EXPORT: "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename" // // RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log // RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log -- GitLab From 9be8d20d728668acd8065f0dc24c81e71002e3c4 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 28 Jun 2018 18:03:00 +0000 Subject: [PATCH 0345/1023] Set the line ending of clang.natvis to CRLF. This corresponds to r335889, which does the same thing for llvm.natvis. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335896 91177308-0d34-0410-b5e6-96231b3b80d8 -- GitLab From 8be0731d31e0934844e0a99812ae08ef505e1c79 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Thu, 28 Jun 2018 18:35:25 +0000 Subject: [PATCH 0346/1023] [CMake] Make bootstrap and compiler-rt depend on cxx-headers. Since r334468, we no longer always copy the libcxx headers by virtue of their presence when cmake runs. This makes some of the later stages (compiler-rt, and the bootstrapped stages) depend on them being copied, via the cxx-headers target. Differential Revision: https://reviews.llvm.org/D48700 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335898 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 11 ++++++++--- runtime/CMakeLists.txt | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae8835d751..52b8819394 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -621,10 +621,15 @@ if (CLANG_ENABLE_BOOTSTRAP) LLVM_ENABLE_PROJECTS LLVM_ENABLE_RUNTIMES) - # We don't need to depend on compiler-rt if we're building instrumented + # We don't need to depend on compiler-rt/libcxx if we're building instrumented # because the next stage will use the same compiler used to build this stage. - if(TARGET compiler-rt AND NOT LLVM_BUILD_INSTRUMENTED) - add_dependencies(clang-bootstrap-deps compiler-rt) + if(NOT LLVM_BUILD_INSTRUMENTED) + if(TARGET compiler-rt) + add_dependencies(clang-bootstrap-deps compiler-rt) + endif() + if(TARGET cxx-headers) + add_dependencies(clang-bootstrap-deps cxx-headers) + endif() endif() set(C_COMPILER "clang") diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index af8ab163c7..9c2f5cd9cf 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -58,8 +58,12 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/) endif() endforeach() + if(TARGET cxx-headers) + set(COMPILER_RT_LIBCXX_DEPENDENCY "cxx-headers") + endif() + ExternalProject_Add(compiler-rt - DEPENDS llvm-config clang + DEPENDS llvm-config clang ${COMPILER_RT_LIBCXX_DEPENDENCY} PREFIX ${COMPILER_RT_PREFIX} SOURCE_DIR ${COMPILER_RT_SRC_ROOT} STAMP_DIR ${STAMP_DIR} -- GitLab From 5026a3c6f0d8ff9d16e1809928264300d9569fb7 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Thu, 28 Jun 2018 19:46:10 +0000 Subject: [PATCH 0347/1023] [OPENMP] Fix incomplete type check for array reductions A reduction for an incomplete array type used to produce an assert fail during codegen. Now it produces a diagnostic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335907 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 2 +- test/OpenMP/parallel_reduction_messages.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/OpenMP/parallel_reduction_messages.c diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 7da9df90ac..6fb0125e6e 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -10335,7 +10335,7 @@ static bool actOnOMPReductionKindClause( // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. - if (S.RequireCompleteType(ELoc, Type, + if (S.RequireCompleteType(ELoc, D->getType(), diag::err_omp_reduction_incomplete_type)) continue; // OpenMP [2.14.3.6, reduction clause, Restrictions] diff --git a/test/OpenMP/parallel_reduction_messages.c b/test/OpenMP/parallel_reduction_messages.c new file mode 100644 index 0000000000..f88f8e0564 --- /dev/null +++ b/test/OpenMP/parallel_reduction_messages.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s + +int incomplete[]; + +void test() { +#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}} + ; +} + +// complete to suppress an additional warning, but it's too late for pragmas +int incomplete[3]; -- GitLab From 7b12778f79ea59978fd63f63088f8b53005c47fd Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Thu, 28 Jun 2018 19:54:27 +0000 Subject: [PATCH 0348/1023] Revert r335907: [OPENMP] Fix incomplete type check for array reductions Sorry, forgot to add commit log attributes again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335910 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 2 +- test/OpenMP/parallel_reduction_messages.c | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 test/OpenMP/parallel_reduction_messages.c diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 6fb0125e6e..7da9df90ac 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -10335,7 +10335,7 @@ static bool actOnOMPReductionKindClause( // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. - if (S.RequireCompleteType(ELoc, D->getType(), + if (S.RequireCompleteType(ELoc, Type, diag::err_omp_reduction_incomplete_type)) continue; // OpenMP [2.14.3.6, reduction clause, Restrictions] diff --git a/test/OpenMP/parallel_reduction_messages.c b/test/OpenMP/parallel_reduction_messages.c deleted file mode 100644 index f88f8e0564..0000000000 --- a/test/OpenMP/parallel_reduction_messages.c +++ /dev/null @@ -1,11 +0,0 @@ -// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s - -int incomplete[]; - -void test() { -#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}} - ; -} - -// complete to suppress an additional warning, but it's too late for pragmas -int incomplete[3]; -- GitLab From c44d5bf82e3194e8db00d33ac64fccb2ac632882 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Thu, 28 Jun 2018 19:54:49 +0000 Subject: [PATCH 0349/1023] [OPENMP] Fix incomplete type check for array reductions A reduction for an incomplete array type used to produce an assert fail during codegen. Now it produces a diagnostic. Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D48735 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335911 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 2 +- test/OpenMP/parallel_reduction_messages.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/OpenMP/parallel_reduction_messages.c diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 7da9df90ac..6fb0125e6e 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -10335,7 +10335,7 @@ static bool actOnOMPReductionKindClause( // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. - if (S.RequireCompleteType(ELoc, Type, + if (S.RequireCompleteType(ELoc, D->getType(), diag::err_omp_reduction_incomplete_type)) continue; // OpenMP [2.14.3.6, reduction clause, Restrictions] diff --git a/test/OpenMP/parallel_reduction_messages.c b/test/OpenMP/parallel_reduction_messages.c new file mode 100644 index 0000000000..f88f8e0564 --- /dev/null +++ b/test/OpenMP/parallel_reduction_messages.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s + +int incomplete[]; + +void test() { +#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}} + ; +} + +// complete to suppress an additional warning, but it's too late for pragmas +int incomplete[3]; -- GitLab From 1f430ab6119b4712a2be5e759fc7455b6231f592 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 20:19:11 +0000 Subject: [PATCH 0350/1023] [CMake] Build static runtimes for host in Fuchsia first stage First stage build is only a minimal build where we don't need a complete multiarch support, but we need enough to build the second stage. Differential Revision: https://reviews.llvm.org/D48707 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335917 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia.cmake | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index 27f304fafb..6535e6be10 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -29,6 +29,18 @@ if(APPLE) set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "") +else() + set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") + set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") + set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") + set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") endif() set(CLANG_BOOTSTRAP_TARGETS -- GitLab From 8d49bfdc6ab7878a204e3d3fec2247b1383fe4ea Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 20:33:18 +0000 Subject: [PATCH 0351/1023] [CMake] Don't build Linux targets on Darwin in Fuchsia toolchain This is currently breaking because Linux target sysroots rely on case sensitive filesystem which is not by default enabled on macOS. Differential Revision: https://reviews.llvm.org/D48710 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335919 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 56 +++++++++++++++---------------- cmake/caches/Fuchsia.cmake | 2 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 9f28c1770e..ae8658debd 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -31,35 +31,35 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRIN if(APPLE) list(APPEND BUILTIN_TARGETS "default") list(APPEND RUNTIME_TARGETS "default") -endif() - -foreach(target i386;x86_64;armhf;aarch64) - if(LINUX_${target}_SYSROOT) - # Set the per-target builtins options. - list(APPEND BUILTIN_TARGETS "${target}-linux-gnu") - set(BUILTINS_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") - set(BUILTINS_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") - set(BUILTINS_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") +elseif(UNIX) + foreach(target i386;x86_64;armhf;aarch64) + if(LINUX_${target}_SYSROOT) + # Set the per-target builtins options. + list(APPEND BUILTIN_TARGETS "${target}-linux-gnu") + set(BUILTINS_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") + set(BUILTINS_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(BUILTINS_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") - # Set the per-target runtimes options. - list(APPEND RUNTIME_TARGETS "${target}-linux-gnu") - set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") - set(RUNTIMES_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") - set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") - set(RUNTIMES_${target}-linux-gnu_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") - set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") - endif() -endforeach() + # Set the per-target runtimes options. + list(APPEND RUNTIME_TARGETS "${target}-linux-gnu") + set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSTEM_NAME Linux CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_CMAKE_BUILD_TYPE Release CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_CMAKE_SYSROOT ${LINUX_${target}_SYSROOT} CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXXABI_INSTALL_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + endif() + endforeach() +endif() if(FUCHSIA_SDK) set(FUCHSIA_aarch64_NAME arm64) diff --git a/cmake/caches/Fuchsia.cmake b/cmake/caches/Fuchsia.cmake index 6535e6be10..fc7dae8499 100644 --- a/cmake/caches/Fuchsia.cmake +++ b/cmake/caches/Fuchsia.cmake @@ -29,7 +29,7 @@ if(APPLE) set(COMPILER_RT_ENABLE_IOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_TVOS OFF CACHE BOOL "") set(COMPILER_RT_ENABLE_WATCHOS OFF CACHE BOOL "") -else() +elseif(UNIX) set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") set(LIBUNWIND_INSTALL_LIBRARY OFF CACHE BOOL "") -- GitLab From ff6b0ecacdfc5a066f35b140db832b02082f9731 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 28 Jun 2018 21:17:55 +0000 Subject: [PATCH 0352/1023] PR37979: integral promotions in C++ treat enum bit-fields like enums, not like bit-fields. We used to get this right "by accident", because conversions for the selected built-in overloaded operator would convert the enum bit-field to its corresponding underlying type early. But after DR1687 that no longer happens. Technically this change should also apply to C, where bit-fields only have special promotion rules if the bit-field's declared type is _Bool, int, signed int, or unsigned int, but for GCC compatibility we only look at the bit-width and not the underlying type when performing bit-field integral promotions in C. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335925 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 10 +++++++++- lib/Sema/SemaOverload.cpp | 13 +++++++++++++ test/CXX/conv/conv.prom/p5.cpp | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/CXX/conv/conv.prom/p5.cpp diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 43577e8640..ca54d8f675 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -5456,6 +5456,12 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) return {}; + // C++ [conv.prom]p5: + // If the bit-field has an enumerated type, it is treated as any other + // value of that type for promotion purposes. + if (getLangOpts().CPlusPlus && E->getType()->isEnumeralType()) + return {}; + // FIXME: We should not do this unless E->refersToBitField() is true. This // matters in C where getSourceBitField() will find bit-fields for various // cases where the source expression is not a bit-field designator. @@ -5482,13 +5488,15 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { // // FIXME: C does not permit promotion of a 'long : 3' bitfield to int. // We perform that promotion here to match GCC and C++. + // FIXME: C does not permit promotion of an enum bit-field whose rank is + // greater than that of 'int'. We perform that promotion to match GCC. if (BitWidth < IntSize) return IntTy; if (BitWidth == IntSize) return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy; - // Types bigger than int are not subject to promotions, and therefore act + // Bit-fields wider than int are not subject to promotions, and therefore act // like the base type. GCC has some weird bugs in this area that we // deliberately do not follow (GCC follows a pre-standard resolution to // C's DR315 which treats bit-width as being part of the type, and this leaks diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e9d2eb6cc5..6f01f19fc5 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2007,6 +2007,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { isCompleteType(From->getLocStart(), FromType)) return Context.hasSameUnqualifiedType( ToType, FromEnumType->getDecl()->getPromotionType()); + + // C++ [conv.prom]p5: + // If the bit-field has an enumerated type, it is treated as any other + // value of that type for promotion purposes. + // + // ... so do not fall through into the bit-field checks below in C++. + if (getLangOpts().CPlusPlus) + return false; } // C++0x [conv.prom]p2: @@ -2054,6 +2062,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // other value of that type for promotion purposes (C++ 4.5p3). // FIXME: We should delay checking of bit-fields until we actually perform the // conversion. + // + // FIXME: In C, only bit-fields of types _Bool, int, or unsigned int may be + // promoted, per C11 6.3.1.1/2. We promote all bit-fields (including enum + // bit-fields and those whose underlying type is larger than int) for GCC + // compatibility. if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { llvm::APSInt BitWidth; diff --git a/test/CXX/conv/conv.prom/p5.cpp b/test/CXX/conv/conv.prom/p5.cpp new file mode 100644 index 0000000000..baf51374c8 --- /dev/null +++ b/test/CXX/conv/conv.prom/p5.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// A prvalue for an integral bit-field can be converted to a prvalue of type +// int if int can represent all the values of the bit-field +struct X { long long e : 1; }; +static_assert(sizeof(+X().e) == sizeof(int), ""); +static_assert(sizeof(X().e + 1) == sizeof(int), ""); +static_assert(sizeof(true ? X().e : 0) == sizeof(int), ""); + +enum E { a = __LONG_LONG_MAX__ }; +static_assert(sizeof(E{}) == sizeof(long long), ""); + +// If the bit-field has an enumerated type, it is treated as any other value of +// that [enumerated] type for promotion purposes. +struct Y { E e : 1; }; +static_assert(sizeof(+Y().e) == sizeof(long long), ""); +static_assert(sizeof(Y().e + 1) == sizeof(long long), ""); +static_assert(sizeof(true ? Y().e : 0) == sizeof(long long), ""); -- GitLab From 8b67bbb0952f6661deea1b2dad51a41519544522 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 28 Jun 2018 21:26:52 +0000 Subject: [PATCH 0353/1023] [analyzer] Fix wrong comparison generation of the ranges generated by the refutation manager The refutation manager is removing a true bug from the test in this patch. The problem is that the following constraint: ``` (conj_$1{struct o *}) - (reg_$3): [-9223372036854775808, 0] ``` is encoded as: ``` (and (bvuge (bvsub $1 $3) #x8000000000000000) (bvule (bvsub $1 $3) #x0000000000000000)) ``` The issue is that unsigned comparisons (bvuge and bvule) are being generated instead of signed comparisons (bvsge and bvsle). When generating the expressions: ``` (conj_$1{p *}) - (reg_$3) >= -9223372036854775808 ``` and ``` (conj_$1{p *}) - (reg_$3) <= 0 ``` both -9223372036854775808 and 0 are casted to pointer type and `LTy->isSignedIntegerOrEnumerationType()` in `Z3ConstraintManager::getZ3BinExpr` only checks if the type is signed, not if it's a pointer. Reviewers: NoQ, george.karpenkov, ddcc Subscribers: rnkovacs, NoQ, george.karpenkov, ddcc, xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D48324 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335926 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/Z3ConstraintManager.cpp | 5 ++-- test/PR37855.c | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 test/PR37855.c diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index a47b7a2e70..9e975676cc 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -1414,9 +1414,8 @@ Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy, // If the two operands are pointers and the operation is a subtraction, the // result is of type ptrdiff_t, which is signed - if (LTy->isAnyPointerType() && LTy == RTy && Op == BO_Sub) { - ASTContext &Ctx = getBasicVals().getContext(); - *RetTy = Ctx.getIntTypeForBitwidth(Ctx.getTypeSize(LTy), true); + if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { + *RetTy = getBasicVals().getContext().getPointerDiffType(); } } diff --git a/test/PR37855.c b/test/PR37855.c new file mode 100644 index 0000000000..24e34c0836 --- /dev/null +++ b/test/PR37855.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -DNO_CROSSCHECK -verify %s +// RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -w -analyzer-config crosscheck-with-z3=true -verify %s +// REQUIRES: z3 + +typedef struct o p; +struct o { + struct { + } s; +}; + +void q(*r, p2) { r < p2; } + +void k(l, node) { + struct { + p *node; + } * n, *nodep, path[sizeof(void)]; + path->node = l; + for (n = path; node != l;) { + q(node, n->node); + nodep = n; + } + if (nodep) // expected-warning {{Branch condition evaluates to a garbage value}} + n[1].node->s; // expected-warning {{Dereference of undefined pointer value}} +} -- GitLab From eed865ada8669f873c9abdcee9c2818cb17ee550 Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Thu, 28 Jun 2018 21:36:00 +0000 Subject: [PATCH 0354/1023] [Parse] Make -Wgcc-compat complain about for loop inits in C89 While clang allows declarations in for loop init statements in c89 and gnu89, gcc does not. So, we should probably warn if users care about gcc compatibility. Differential Revision: https://reviews.llvm.org/D47840 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335927 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticParseKinds.td | 3 +++ lib/Parse/ParseStmt.cpp | 4 +++- test/Parser/gcc-for-loop-init-compatibility.c | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 test/Parser/gcc-for-loop-init-compatibility.c diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index c2a1f095f1..dd4c819225 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -173,6 +173,9 @@ def warn_attribute_on_function_definition : Warning< def warn_gcc_attribute_location : Warning< "GCC does not allow an attribute in this position on a function declaration">, InGroup; +def warn_gcc_variable_decl_in_for_loop : Warning< + "GCC does not allow variable declarations in for loop initializers before " + "C99">, InGroup; def warn_attribute_no_decl : Warning< "attribute %0 ignored, because it is not attached to a declaration">, InGroup; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8c4a3056ec..107fa55637 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1624,8 +1624,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ParenBraceBracketBalancer BalancerRAIIObj(*this); // Parse declaration, which eats the ';'. - if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? + if (!C99orCXXorObjC) { // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); + Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop); + } // In C++0x, "for (T NS:a" might not be a typo for :: bool MightBeForRangeStmt = getLangOpts().CPlusPlus; diff --git a/test/Parser/gcc-for-loop-init-compatibility.c b/test/Parser/gcc-for-loop-init-compatibility.c new file mode 100644 index 0000000000..dc88f08395 --- /dev/null +++ b/test/Parser/gcc-for-loop-init-compatibility.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=gnu89 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify %s -DC99 + +#ifdef C99 +// expected-no-diagnostics +#endif + +void foo() { +#ifndef C99 + // expected-warning@+2{{GCC does not allow variable declarations in for loop initializers before C99}} +#endif + for (int i = 0; i < 10; i++) + ; +} -- GitLab From 264b0f306510ff1e1ef7b2938d5fff3b41ac08e3 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 28 Jun 2018 21:39:41 +0000 Subject: [PATCH 0355/1023] [analyzer] Move test to the correct directory It was accidentaly pushed in r335926 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335929 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/{ => Analysis}/PR37855.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ => Analysis}/PR37855.c (100%) diff --git a/test/PR37855.c b/test/Analysis/PR37855.c similarity index 100% rename from test/PR37855.c rename to test/Analysis/PR37855.c -- GitLab From 1670f60ecbfc01f65c752093196735f29c212dbb Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 28 Jun 2018 22:08:44 +0000 Subject: [PATCH 0356/1023] [analyzer] fix test case expected warning After r335814, the constraint manager is no longer generating a false bug report about the division by zero in the test case. This patch removes the expected false bug report. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335932 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/z3-crosscheck.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/Analysis/z3-crosscheck.c b/test/Analysis/z3-crosscheck.c index 66f778de8a..67d410434f 100644 --- a/test/Analysis/z3-crosscheck.c +++ b/test/Analysis/z3-crosscheck.c @@ -21,22 +21,14 @@ void f(int *a, int *b) { if ((a - b) == 0) c = 0; if (a != b) -#ifdef NO_CROSSCHECK - g(3 / c); // expected-warning {{Division by zero}} -#else g(3 / c); // no-warning -#endif } _Bool nondet_bool(); void h(int d) { int x, y, k, z = 1; -#ifdef NO_CROSSCHECK while (z < k) { // expected-warning {{The right operand of '<' is a garbage value}} -#else - while (z < k) { // expected-warning {{The right operand of '<' is a garbage value}} -#endif z = 2 * z; } } -- GitLab From 5fdc10dc8f915fe3ba480347288af144e7c44f84 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 28 Jun 2018 22:58:04 +0000 Subject: [PATCH 0357/1023] DebugInfo: Add -gno-gnu-pubnames to allow disabling gnu-pubnames later in the command line git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335938 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 1 + lib/Driver/ToolChains/Clang.cpp | 3 ++- test/Driver/debug-options.c | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 089a9b3649..a6b5da209e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1793,6 +1793,7 @@ def gcolumn_info : Flag<["-"], "gcolumn-info">, Group, Flags<[Cor def gno_column_info : Flag<["-"], "gno-column-info">, Group, Flags<[CoreOption]>; def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group; def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group, Flags<[CC1Option]>; +def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group, Flags<[CC1Option]>; def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group; def gmodules : Flag <["-"], "gmodules">, Group, HelpText<"Generate debug info with external references to clang modules" diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 1f08f30345..c5fbd09755 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3046,7 +3046,8 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-debug-info-macro"); // -ggnu-pubnames turns on gnu style pubnames in the backend. - if (Args.hasArg(options::OPT_ggnu_pubnames)) + if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, + false)) CmdArgs.push_back("-ggnu-pubnames"); // -gdwarf-aranges turns on the emission of the aranges section in the diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c index ebbf293760..6d28a7169d 100644 --- a/test/Driver/debug-options.c +++ b/test/Driver/debug-options.c @@ -134,6 +134,8 @@ // RUN: | FileCheck -check-prefix=GIGNORE %s // // RUN: %clang -### -c -ggnu-pubnames %s 2>&1 | FileCheck -check-prefix=GOPT %s +// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOGOPT %s +// RUN: %clang -### -c -ggnu-pubnames -gno-gnu-pubnames %s 2>&1 | FileCheck -check-prefix=NOGOPT %s // // RUN: %clang -### -c -gdwarf-aranges %s 2>&1 | FileCheck -check-prefix=GARANGE %s // @@ -222,6 +224,7 @@ // GIGNORE-NOT: "argument unused during compilation" // // GOPT: -ggnu-pubnames +// NOGOPT-NOT: -ggnu-pubnames // // GARANGE: -generate-arange-section // -- GitLab From 5b2dfe4f4d40e8496413d6c7a5d064dd7026bda3 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 28 Jun 2018 23:23:45 +0000 Subject: [PATCH 0358/1023] [frontend] Don't include the C++ stdlib for -x assembler-with-cpp The new C++ stdlib warning added in r335081 gets triggered when compiling an assembly file with -x assembler-with-cpp. This commit ensures that the C++ stdlib is not included when compiling assembly. In general, it's not really useful to include the C++ stdlib search path when compiling assembly source. rdar://41359632 Differential Revision: https://reviews.llvm.org/D48736 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335940 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Frontend/InitHeaderSearch.cpp | 4 ++-- test/Frontend/nostdlib-for-asmpp.s | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 test/Frontend/nostdlib-for-asmpp.s diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 85aeec461b..8a70404629 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -470,8 +470,8 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, break; } - if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes && - HSOpts.UseStandardSystemIncludes) { + if (Lang.CPlusPlus && !Lang.AsmPreprocessor && + HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) { if (HSOpts.UseLibcxx) { if (triple.isOSDarwin()) { // On Darwin, libc++ may be installed alongside the compiler in diff --git a/test/Frontend/nostdlib-for-asmpp.s b/test/Frontend/nostdlib-for-asmpp.s new file mode 100644 index 0000000000..330fee32a3 --- /dev/null +++ b/test/Frontend/nostdlib-for-asmpp.s @@ -0,0 +1,5 @@ +// RUN: %clang -cc1 -x assembler-with-cpp -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -std=c++11 -v %s 2>&1 | FileCheck %s +// The C++ stdlib path should not be included for an assembly source. + +// CHECK-NOT: usr/include/c++/ +// CHECK-NOT: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead -- GitLab From 0af2982d58db03e4ea1a93bc17112663d83ec078 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 29 Jun 2018 05:43:33 +0000 Subject: [PATCH 0359/1023] [X86] Remove masking from the avx512 packed sqrt builtins. Use select builtins instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335945 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 4 +- lib/CodeGen/CGBuiltin.cpp | 30 +++++----- lib/Headers/avx512fintrin.h | 85 ++++++++++++----------------- lib/Sema/SemaChecking.cpp | 4 +- test/CodeGen/avx512f-builtins.c | 24 ++++---- 5 files changed, 66 insertions(+), 81 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 2128c37139..55be7321ae 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -866,8 +866,8 @@ TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku") TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "n", "pku") // AVX-512 -TARGET_BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtpd512, "V8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtps512, "V16fV16fIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "nc", "avx512f") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 14bf0a78ad..98626dcc1d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9889,24 +9889,22 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_sqrtpd256: case X86::BI__builtin_ia32_sqrtpd: case X86::BI__builtin_ia32_sqrtps256: - case X86::BI__builtin_ia32_sqrtps: { - Function *F = CGM.getIntrinsic(Intrinsic::sqrt, Ops[0]->getType()); - return Builder.CreateCall(F, {Ops[0]}); - } - case X86::BI__builtin_ia32_sqrtps512_mask: - case X86::BI__builtin_ia32_sqrtpd512_mask: { - unsigned CC = cast(Ops[3])->getZExtValue(); - // Support only if the rounding mode is 4 (AKA CUR_DIRECTION), - // otherwise keep the intrinsic. - if (CC != 4) { - Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtps512_mask ? - Intrinsic::x86_avx512_mask_sqrt_ps_512 : - Intrinsic::x86_avx512_mask_sqrt_pd_512; - return Builder.CreateCall(CGM.getIntrinsic(IID), Ops); + case X86::BI__builtin_ia32_sqrtps: + case X86::BI__builtin_ia32_sqrtps512: + case X86::BI__builtin_ia32_sqrtpd512: { + if (Ops.size() == 2) { + unsigned CC = cast(Ops[1])->getZExtValue(); + // Support only if the rounding mode is 4 (AKA CUR_DIRECTION), + // otherwise keep the intrinsic. + if (CC != 4) { + Intrinsic::ID IID = BuiltinID == X86::BI__builtin_ia32_sqrtps512 ? + Intrinsic::x86_avx512_sqrt_ps_512 : + Intrinsic::x86_avx512_sqrt_pd_512; + return Builder.CreateCall(CGM.getIntrinsic(IID), Ops); + } } Function *F = CGM.getIntrinsic(Intrinsic::sqrt, Ops[0]->getType()); - return EmitX86Select(*this, Ops[2], Builder.CreateCall(F, {Ops[0]}), - Ops[1]); + return Builder.CreateCall(F, Ops[0]); } case X86::BI__builtin_ia32_pabsb128: case X86::BI__builtin_ia32_pabsw128: diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 534007b69f..bfb645415e 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -1492,89 +1492,76 @@ _mm512_mask_mullox_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { (__v8di)__W); } +#define _mm512_sqrt_round_pd(A, R) \ + (__m512d)__builtin_ia32_sqrtpd512((__v8df)(__m512d)(A), (int)(R)) + #define _mm512_mask_sqrt_round_pd(W, U, A, R) \ - (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_sqrt_round_pd((A), (R)), \ + (__v8df)(__m512d)(W)) #define _mm512_maskz_sqrt_round_pd(U, A, R) \ - (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) - -#define _mm512_sqrt_round_pd(A, R) \ - (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)_mm512_undefined_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_sqrt_round_pd((A), (R)), \ + (__v8df)_mm512_setzero_pd()) static __inline__ __m512d __DEFAULT_FN_ATTRS -_mm512_sqrt_pd(__m512d __a) +_mm512_sqrt_pd(__m512d __A) { - return (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)__a, - (__v8df) _mm512_setzero_pd (), - (__mmask8) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_sqrtpd512((__v8df)__A, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A) { - return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, - (__v8df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_sqrt_pd(__A), + (__v8df)__W); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A) { - return (__m512d) __builtin_ia32_sqrtpd512_mask ((__v8df) __A, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_sqrt_pd(__A), + (__v8df)_mm512_setzero_pd()); } +#define _mm512_sqrt_round_ps(A, R) \ + (__m512)__builtin_ia32_sqrtps512((__v16sf)(__m512)(A), (int)(R)) + #define _mm512_mask_sqrt_round_ps(W, U, A, R) \ - (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_sqrt_round_ps((A), (R)), \ + (__v16sf)(__m512)(W)) #define _mm512_maskz_sqrt_round_ps(U, A, R) \ - (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) - -#define _mm512_sqrt_round_ps(A, R) \ - (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)_mm512_undefined_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_sqrt_round_ps((A), (R)), \ + (__v16sf)_mm512_setzero_ps()) static __inline__ __m512 __DEFAULT_FN_ATTRS -_mm512_sqrt_ps(__m512 __a) +_mm512_sqrt_ps(__m512 __A) { - return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__a, - (__v16sf) _mm512_setzero_ps (), - (__mmask16) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_sqrtps512((__v16sf)__A, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_sqrt_ps(__m512 __W, __mmask16 __U, __m512 __A) { - return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__A, - (__v16sf) __W, - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_sqrt_ps(__A), + (__v16sf)__W); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A) { - return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__A, - (__v16sf) _mm512_setzero_ps (), - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_sqrt_ps(__A), + (__v16sf)_mm512_setzero_ps()); } static __inline__ __m512d __DEFAULT_FN_ATTRS diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 12a599b4f1..22483f8242 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2373,6 +2373,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vcvtss2si64: case X86::BI__builtin_ia32_vcvtss2usi32: case X86::BI__builtin_ia32_vcvtss2usi64: + case X86::BI__builtin_ia32_sqrtpd512: + case X86::BI__builtin_ia32_sqrtps512: ArgNum = 1; HasRC = true; break; @@ -2404,8 +2406,6 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_cvtqq2ps512_mask: case X86::BI__builtin_ia32_cvtuqq2pd512_mask: case X86::BI__builtin_ia32_cvtuqq2ps512_mask: - case X86::BI__builtin_ia32_sqrtpd512_mask: - case X86::BI__builtin_ia32_sqrtps512_mask: ArgNum = 3; HasRC = true; break; diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 93cbcbe938..cec77dc50c 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -30,26 +30,26 @@ __m512d test_mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A) __m512d test_mm512_mask_sqrt_round_pd(__m512d __W,__mmask8 __U,__m512d __A) { // CHECK-LABEL: @test_mm512_mask_sqrt_round_pd - // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}}) + // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} - return _mm512_mask_sqrt_round_pd(__W,__U,__A,_MM_FROUND_CUR_DIRECTION); + return _mm512_mask_sqrt_round_pd(__W,__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_maskz_sqrt_round_pd(__mmask8 __U,__m512d __A) { // CHECK-LABEL: @test_mm512_maskz_sqrt_round_pd - // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}}) + // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8) // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> {{.*}} - return _mm512_maskz_sqrt_round_pd(__U,__A,_MM_FROUND_CUR_DIRECTION); + return _mm512_maskz_sqrt_round_pd(__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_sqrt_round_pd(__m512d __A) { // CHECK-LABEL: @test_mm512_sqrt_round_pd - // CHECK: call <8 x double> @llvm.sqrt.v8f64(<8 x double> %{{.*}}) - return _mm512_sqrt_round_pd(__A,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <8 x double> @llvm.x86.avx512.sqrt.pd.512(<8 x double> %{{.*}}, i32 8) + return _mm512_sqrt_round_pd(__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_sqrt_ps(__m512 a) @@ -80,26 +80,26 @@ __m512 test_mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A) __m512 test_mm512_mask_sqrt_round_ps(__m512 __W,__mmask16 __U,__m512 __A) { // CHECK-LABEL: @test_mm512_mask_sqrt_round_ps - // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}}) + // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} - return _mm512_mask_sqrt_round_ps(__W,__U,__A,_MM_FROUND_CUR_DIRECTION); + return _mm512_mask_sqrt_round_ps(__W,__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_maskz_sqrt_round_ps(__mmask16 __U,__m512 __A) { // CHECK-LABEL: @test_mm512_maskz_sqrt_round_ps - // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}}) + // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8) // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> {{.*}} - return _mm512_maskz_sqrt_round_ps(__U,__A,_MM_FROUND_CUR_DIRECTION); + return _mm512_maskz_sqrt_round_ps(__U,__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_sqrt_round_ps(__m512 __A) { // CHECK-LABEL: @test_mm512_sqrt_round_ps - // CHECK: call <16 x float> @llvm.sqrt.v16f32(<16 x float> %{{.*}}) - return _mm512_sqrt_round_ps(__A,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <16 x float> @llvm.x86.avx512.sqrt.ps.512(<16 x float> %{{.*}}, i32 8) + return _mm512_sqrt_round_ps(__A,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_rsqrt14_pd(__m512d a) -- GitLab From 622f921fa7a15a20c400b613b05a5a167275f9c5 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Fri, 29 Jun 2018 10:25:19 +0000 Subject: [PATCH 0360/1023] [ASTImporter] Eliminated some unittest warnings. Summary: When running the ASTTests test, warnings produced by the compiler can be distracting when looking for test errors. A part of the warnings is removed by setting extra compiler options. Reviewers: a.sidorin Reviewed By: a.sidorin Subscribers: a_sidorin, martong, cfe-commits Differential Revision: https://reviews.llvm.org/D47459 Patch by Balazs Keri! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335959 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 741 +++++++++++++----------------- 1 file changed, 326 insertions(+), 415 deletions(-) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 69611a4624..622ac9977a 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -472,138 +472,110 @@ TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier Verifier; - testImport("void declToImport() { \"foo\"; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - stringLiteral( - hasType( - asString("const char [4]")))))))); - testImport("void declToImport() { L\"foo\"; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - stringLiteral( - hasType( - asString("const wchar_t [4]")))))))); - testImport("void declToImport() { \"foo\" \"bar\"; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - stringLiteral( - hasType( - asString("const char [7]")))))))); + testImport( + "void declToImport() { (void)\"foo\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + stringLiteral(hasType(asString("const char [4]")))))); + testImport( + "void declToImport() { (void)L\"foo\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + stringLiteral(hasType(asString("const wchar_t [4]")))))); + testImport( + "void declToImport() { (void) \"foo\" \"bar\"; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + stringLiteral(hasType(asString("const char [7]")))))); } TEST_P(ImportExpr, ImportGNUNullExpr) { MatchVerifier Verifier; - testImport("void declToImport() { __null; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - gnuNullExpr( - hasType(isInteger()))))))); + testImport( + "void declToImport() { (void)__null; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger()))))); } TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) { MatchVerifier Verifier; - testImport("void declToImport() { nullptr; }", - Lang_CXX11, "", Lang_CXX11, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - cxxNullPtrLiteralExpr()))))); + testImport( + "void declToImport() { (void)nullptr; }", + Lang_CXX11, "", Lang_CXX11, Verifier, + functionDecl(hasDescendant(cxxNullPtrLiteralExpr()))); } TEST_P(ImportExpr, ImportFloatinglLiteralExpr) { MatchVerifier Verifier; - testImport("void declToImport() { 1.0; }", - Lang_C, "", Lang_C, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - floatLiteral( - equals(1.0), - hasType(asString("double")))))))); - testImport("void declToImport() { 1.0e-5f; }", - Lang_C, "", Lang_C, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - floatLiteral( - equals(1.0e-5f), - hasType(asString("float")))))))); + testImport( + "void declToImport() { (void)1.0; }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant( + floatLiteral(equals(1.0), hasType(asString("double")))))); + testImport( + "void declToImport() { (void)1.0e-5f; }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant( + floatLiteral(equals(1.0e-5f), hasType(asString("float")))))); } TEST_P(ImportExpr, ImportCompoundLiteralExpr) { MatchVerifier Verifier; - testImport("void declToImport() {" - " struct s { int x; long y; unsigned z; }; " - " (struct s){ 42, 0L, 1U }; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - compoundLiteralExpr( - hasType(asString("struct s")), - has(initListExpr( - hasType(asString("struct s")), - has(integerLiteral( - equals(42), hasType(asString("int")))), - has(integerLiteral( - equals(0), hasType(asString("long")))), - has(integerLiteral( - equals(1), - hasType(asString("unsigned int")))) - )))))))); + testImport( + "void declToImport() {" + " struct s { int x; long y; unsigned z; }; " + " (void)(struct s){ 42, 0L, 1U }; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + compoundLiteralExpr( + hasType(asString("struct s")), + has(initListExpr( + hasType(asString("struct s")), + has(integerLiteral( + equals(42), hasType(asString("int")))), + has(integerLiteral( + equals(0), hasType(asString("long")))), + has(integerLiteral( + equals(1), hasType(asString("unsigned int")))))))))); } TEST_P(ImportExpr, ImportCXXThisExpr) { MatchVerifier Verifier; - testImport("class declToImport { void f() { this; } };", - Lang_CXX, "", Lang_CXX, Verifier, - cxxRecordDecl( - hasMethod( - hasBody( - compoundStmt( - has( - cxxThisExpr( - hasType( - asString("class declToImport *"))))))))); + testImport( + "class declToImport { void f() { (void)this; } };", + Lang_CXX, "", Lang_CXX, Verifier, + cxxRecordDecl( + hasMethod( + hasDescendant( + cxxThisExpr( + hasType( + asString("class declToImport *"))))))); } TEST_P(ImportExpr, ImportAtomicExpr) { MatchVerifier Verifier; - testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", - Lang_C, "", Lang_C, Verifier, - functionDecl(hasBody(compoundStmt(has(atomicExpr( - has(ignoringParenImpCasts( - declRefExpr(hasDeclaration(varDecl(hasName("ptr"))), - hasType(asString("int *"))))), - has(integerLiteral(equals(1), hasType(asString("int")))))))))); + testImport( + "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant( + atomicExpr( + has(ignoringParenImpCasts( + declRefExpr(hasDeclaration(varDecl(hasName("ptr"))), + hasType(asString("int *"))))), + has(integerLiteral(equals(1), hasType(asString("int")))))))); } TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { MatchVerifier Verifier; testImport( - "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C, - Verifier, - functionDecl(hasBody(compoundStmt( - has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))), - has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop"))))))))); + "void declToImport() { loop: goto loop; (void)&&loop; }", + Lang_C, "", Lang_C, Verifier, + functionDecl( + hasDescendant( + labelStmt(hasDeclaration(labelDecl(hasName("loop"))))), + hasDescendant( + addrLabelExpr(hasDeclaration(labelDecl(hasName("loop"))))))); } AST_MATCHER_P(TemplateDecl, hasTemplateDecl, @@ -631,10 +603,11 @@ TEST_P(ImportExpr, ImportParenListExpr) { TEST_P(ImportExpr, ImportSwitch) { MatchVerifier Verifier; - testImport("void declToImport() { int b; switch (b) { case 1: break; } }", - Lang_C, "", Lang_C, Verifier, - functionDecl(hasBody(compoundStmt( - has(switchStmt(has(compoundStmt(has(caseStmt()))))))))); + testImport( + "void declToImport() { int b; switch (b) { case 1: break; } }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant( + switchStmt(has(compoundStmt(has(caseStmt()))))))); } TEST_P(ImportExpr, ImportStmtExpr) { @@ -643,164 +616,120 @@ TEST_P(ImportExpr, ImportStmtExpr) { testImport( "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }", Lang_C, "", Lang_C, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - declStmt( - hasSingleDecl( - varDecl( - hasName("C"), - hasType(asString("int")), - hasInitializer( - stmtExpr( - hasAnySubstatement( - declStmt( - hasSingleDecl( - varDecl( - hasName("X"), - hasType(asString("int")), - hasInitializer( + functionDecl(hasDescendant( + varDecl( + hasName("C"), + hasType(asString("int")), + hasInitializer( + stmtExpr( + hasAnySubstatement(declStmt(hasSingleDecl( + varDecl( + hasName("X"), + hasType(asString("int")), + hasInitializer( integerLiteral(equals(4))))))), - hasDescendant( - implicitCastExpr() - ))))))))))); + hasDescendant( + implicitCastExpr()))))))); } TEST_P(ImportExpr, ImportConditionalOperator) { MatchVerifier Verifier; testImport( - "void declToImport() { true ? 1 : -5; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - conditionalOperator( + "void declToImport() { (void)(true ? 1 : -5); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + conditionalOperator( hasCondition(cxxBoolLiteral(equals(true))), hasTrueExpression(integerLiteral(equals(1))), hasFalseExpression( - unaryOperator(hasUnaryOperand(integerLiteral(equals(5)))) - ))))))); + unaryOperator(hasUnaryOperand(integerLiteral(equals(5)))))) + ))); } TEST_P(ImportExpr, ImportBinaryConditionalOperator) { MatchVerifier Verifier; testImport( - "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - binaryConditionalOperator( + "void declToImport() { (void)(1 ?: -5); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + binaryConditionalOperator( hasCondition( - implicitCastExpr( - hasSourceExpression( - opaqueValueExpr( - hasSourceExpression(integerLiteral(equals(1))))), - hasType(booleanType()))), + implicitCastExpr( + hasSourceExpression(opaqueValueExpr( + hasSourceExpression(integerLiteral(equals(1))))), + hasType(booleanType()))), hasTrueExpression( - opaqueValueExpr(hasSourceExpression( - integerLiteral(equals(1))))), + opaqueValueExpr( + hasSourceExpression(integerLiteral(equals(1))))), hasFalseExpression( - unaryOperator(hasOperatorName("-"), - hasUnaryOperand(integerLiteral(equals(5))))) - )))))); + unaryOperator( + hasOperatorName("-"), + hasUnaryOperand(integerLiteral(equals(5))))))))); } TEST_P(ImportExpr, ImportDesignatedInitExpr) { MatchVerifier Verifier; - testImport("void declToImport() {" - " struct point { double x; double y; };" - " struct point ptarray[10] = " - "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }", - Lang_C, "", Lang_C, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - declStmt( - hasSingleDecl( - varDecl( - hasInitializer( - initListExpr( - hasSyntacticForm( - initListExpr( - has( - designatedInitExpr( - designatorCountIs(2), - has(floatLiteral( - equals(1.0))), - has(integerLiteral( - equals(2))))), - has( - designatedInitExpr( - designatorCountIs(2), - has(floatLiteral( - equals(2.0))), - has(integerLiteral( - equals(2))))), - has( - designatedInitExpr( - designatorCountIs(2), - has(floatLiteral( - equals(1.0))), - has(integerLiteral( - equals(0))))) - )))))))))))); + testImport( + "void declToImport() {" + " struct point { double x; double y; };" + " struct point ptarray[10] = " + "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant( + initListExpr( + has(designatedInitExpr( + designatorCountIs(2), + has(floatLiteral(equals(1.0))), + has(integerLiteral(equals(2))))), + has(designatedInitExpr( + designatorCountIs(2), + has(floatLiteral(equals(2.0))), + has(integerLiteral(equals(2))))), + has(designatedInitExpr( + designatorCountIs(2), + has(floatLiteral(equals(1.0))), + has(integerLiteral(equals(0))))))))); } TEST_P(ImportExpr, ImportPredefinedExpr) { MatchVerifier Verifier; // __func__ expands as StringLiteral("declToImport") - testImport("void declToImport() { __func__; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - predefinedExpr( - hasType( - asString("const char [13]")), - has( - stringLiteral( - hasType( - asString("const char [13]")))))))))); + testImport( + "void declToImport() { (void)__func__; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + predefinedExpr( + hasType( + asString("const char [13]")), + has(stringLiteral(hasType( + asString("const char [13]")))))))); } TEST_P(ImportExpr, ImportInitListExpr) { MatchVerifier Verifier; testImport( - "void declToImport() {" - " struct point { double x; double y; };" - " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0," - " [0].x = 1.0 }; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - declStmt( - hasSingleDecl( - varDecl( - hasInitializer( - initListExpr( - has( - cxxConstructExpr( - requiresZeroInitialization())), - has( - initListExpr( - hasType(asString("struct point")), - has(floatLiteral(equals(1.0))), - has(implicitValueInitExpr( - hasType(asString("double")))))), - has( - initListExpr( - hasType(asString("struct point")), - has(floatLiteral(equals(2.0))), - has(floatLiteral(equals(1.0))))) - )))))))))); + "void declToImport() {" + " struct point { double x; double y; };" + " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0," + " [0].x = 1.0 }; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + initListExpr( + has( + cxxConstructExpr( + requiresZeroInitialization())), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(1.0))), + has(implicitValueInitExpr( + hasType(asString("double")))))), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(2.0))), + has(floatLiteral(equals(1.0))))))))); } @@ -808,47 +737,40 @@ const internal::VariadicDynCastAllOfMatcher vaArgExpr; TEST_P(ImportExpr, ImportVAArgExpr) { MatchVerifier Verifier; - testImport("void declToImport(__builtin_va_list list, ...) {" - " (void)__builtin_va_arg(list, int); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - cStyleCastExpr( - hasSourceExpression( - vaArgExpr()))))))); + testImport( + "void declToImport(__builtin_va_list list, ...) {" + " (void)__builtin_va_arg(list, int); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + cStyleCastExpr(hasSourceExpression(vaArgExpr()))))); } TEST_P(ImportExpr, CXXTemporaryObjectExpr) { MatchVerifier Verifier; - testImport("struct C {};" - "void declToImport() { C c = C(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl(hasBody(compoundStmt(has( - declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr( - has(materializeTemporaryExpr(has(implicitCastExpr( - has(cxxTemporaryObjectExpr()))))))))))))))))); + testImport( + "struct C {};" + "void declToImport() { C c = C(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + exprWithCleanups(has(cxxConstructExpr( + has(materializeTemporaryExpr(has(implicitCastExpr( + has(cxxTemporaryObjectExpr()))))))))))); } TEST_P(ImportType, ImportAtomicType) { MatchVerifier Verifier; - testImport("void declToImport() { typedef _Atomic(int) a_int; }", - Lang_CXX11, "", Lang_CXX11, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - declStmt( - has( - typedefDecl( - has(atomicType()))))))))); + testImport( + "void declToImport() { typedef _Atomic(int) a_int; }", + Lang_CXX11, "", Lang_CXX11, Verifier, + functionDecl(hasDescendant(typedefDecl(has(atomicType()))))); } TEST_P(ImportDecl, ImportFunctionTemplateDecl) { MatchVerifier Verifier; - testImport("template void declToImport() { };", Lang_CXX, "", - Lang_CXX, Verifier, functionTemplateDecl()); + testImport( + "template void declToImport() { };", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl()); } const internal::VariadicDynCastAllOfMatcher @@ -856,24 +778,26 @@ const internal::VariadicDynCastAllOfMatcher TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) { MatchVerifier Verifier; - testImport("template struct C { T t; };" - "template void declToImport() {" - " C d;" - " d.t;" - "}" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(has(functionDecl( - has(compoundStmt(has(cxxDependentScopeMemberExpr()))))))); - testImport("template struct C { T t; };" - "template void declToImport() {" - " C d;" - " (&d)->t;" - "}" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(has(functionDecl( - has(compoundStmt(has(cxxDependentScopeMemberExpr()))))))); + testImport( + "template struct C { T t; };" + "template void declToImport() {" + " C d;" + " (void)d.t;" + "}" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasDescendant( + cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); + testImport( + "template struct C { T t; };" + "template void declToImport() {" + " C d;" + " (void)(&d)->t;" + "}" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasDescendant( + cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); } TEST_P(ImportType, ImportTypeAliasTemplate) { @@ -885,8 +809,7 @@ TEST_P(ImportType, ImportTypeAliasTemplate) { "int declToImport() { return dummy2<3>::i; }", Lang_CXX11, "", Lang_CXX11, Verifier, functionDecl( - hasBody(compoundStmt( - has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))), + hasDescendant(implicitCastExpr(has(declRefExpr()))), unless(hasAncestor(translationUnitDecl(has(typeAliasDecl())))))); } @@ -898,32 +821,26 @@ TEST_P(ImportDecl, ImportVarTemplate) { testImport( "template " "T pi = T(3.1415926535897932385L);" - "void declToImport() { pi; }", - Lang_CXX11, "", Lang_CXX11, Verifier, + "void declToImport() { (void)pi; }", + Lang_CXX14, "", Lang_CXX14, Verifier, functionDecl( - hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))), + hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))), unless(hasAncestor(translationUnitDecl(has(varDecl( hasName("pi"), unless(varTemplateSpecializationDecl())))))))); } TEST_P(ImportType, ImportPackExpansion) { MatchVerifier Verifier; - testImport("template " - "struct dummy {" - " dummy(Args... args) {}" - " static const int i = 4;" - "};" - "int declToImport() { return dummy::i; }", - Lang_CXX11, "", Lang_CXX11, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - returnStmt( - has( - implicitCastExpr( - has( - declRefExpr()))))))))); + testImport( + "template " + "struct dummy {" + " dummy(Args... args) {}" + " static const int i = 4;" + "};" + "int declToImport() { return dummy::i; }", + Lang_CXX11, "", Lang_CXX11, Verifier, + functionDecl(hasDescendant( + returnStmt(has(implicitCastExpr(has(declRefExpr()))))))); } const internal::VariadicDynCastAllOfMatcher Verifier; - testImport("template" - "struct A;" - "template" - "struct declToImport {" - " typename A::template B a;" - "};", - Lang_CXX, "", Lang_CXX, Verifier, - classTemplateDecl(has(cxxRecordDecl(has( - fieldDecl(hasType(dependentTemplateSpecializationType()))))))); + testImport( + "template" + "struct A;" + "template" + "struct declToImport {" + " typename A::template B a;" + "};", + Lang_CXX, "", Lang_CXX, Verifier, + classTemplateDecl(has(cxxRecordDecl(has( + fieldDecl(hasType(dependentTemplateSpecializationType()))))))); } const internal::VariadicDynCastAllOfMatcher @@ -948,15 +866,14 @@ const internal::VariadicDynCastAllOfMatcher TEST_P(ImportExpr, ImportSizeOfPackExpr) { MatchVerifier Verifier; - testImport("template " - "void declToImport() {" - " const int i = sizeof...(Ts);" - "};" - "void g() { declToImport(); }", - Lang_CXX11, "", Lang_CXX11, Verifier, - functionTemplateDecl(has(functionDecl( - hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer( - implicitCastExpr(has(sizeOfPackExpr()))))))))))))); + testImport( + "template " + "void declToImport() {" + " const int i = sizeof...(Ts);" + "};" + "void g() { declToImport(); }", + Lang_CXX11, "", Lang_CXX11, Verifier, + functionTemplateDecl(hasDescendant(sizeOfPackExpr()))); testImport( "template " "using X = int[sizeof...(Ts)];" @@ -981,15 +898,12 @@ const internal::VariadicDynCastAllOfMatcher typeTraitExpr; TEST_P(ImportExpr, ImportTypeTraitExpr) { MatchVerifier Verifier; - testImport("void declToImport() { " - " __builtin_types_compatible_p(int, int);" - "}", - Lang_C, "", Lang_C, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - typeTraitExpr(hasType(asString("int")))))))); + testImport( + "void declToImport() { " + " (void)__builtin_types_compatible_p(int, int);" + "}", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int")))))); } const internal::VariadicDynCastAllOfMatcher cxxTypeidExpr; @@ -1012,22 +926,15 @@ TEST_P(ImportExpr, ImportCXXTypeidExpr) { TEST_P(ImportExpr, ImportTypeTraitExprValDep) { MatchVerifier Verifier; - testImport("template struct declToImport {" - " void m() { __is_pod(T); }" - "};" - "void f() { declToImport().m(); }", - Lang_CXX11, "", Lang_CXX11, Verifier, - classTemplateDecl( - has( - cxxRecordDecl( - has( - functionDecl( - hasBody( - compoundStmt( - has( - typeTraitExpr( - hasType(booleanType()) - )))))))))); + testImport( + "template struct declToImport {" + " void m() { (void)__is_pod(T); }" + "};" + "void f() { declToImport().m(); }", + Lang_CXX11, "", Lang_CXX11, Verifier, + classTemplateDecl(has(cxxRecordDecl(has( + functionDecl(hasDescendant( + typeTraitExpr(hasType(booleanType()))))))))); } const internal::VariadicDynCastAllOfMatcher @@ -1035,28 +942,24 @@ const internal::VariadicDynCastAllOfMatcher TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) { MatchVerifier Verifier; - testImport("typedef int T;" - "void declToImport(int *p) {" - " T t;" - " p->T::~T();" - "}", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl(has(compoundStmt(has( - callExpr(has(cxxPseudoDestructorExpr()))))))); + testImport( + "typedef int T;" + "void declToImport(int *p) {" + " T t;" + " p->T::~T();" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant( + callExpr(has(cxxPseudoDestructorExpr()))))); } TEST_P(ImportDecl, ImportUsingDecl) { MatchVerifier Verifier; - testImport("namespace foo { int bar; }" - "void declToImport() { using foo::bar; }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - has( - compoundStmt( - has( - declStmt( - has( - usingDecl()))))))); + testImport( + "namespace foo { int bar; }" + "void declToImport() { using foo::bar; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl(hasDescendant(usingDecl()))); } /// \brief Matches shadow declarations introduced into a scope by a @@ -1074,45 +977,48 @@ const internal::VariadicDynCastAllOfMatcher Verifier; - testImport("namespace foo { int bar; }" - "namespace declToImport { using foo::bar; }", - Lang_CXX, "", Lang_CXX, Verifier, - namespaceDecl(has(usingShadowDecl()))); + testImport( + "namespace foo { int bar; }" + "namespace declToImport { using foo::bar; }", + Lang_CXX, "", Lang_CXX, Verifier, + namespaceDecl(has(usingShadowDecl()))); } TEST_P(ImportExpr, ImportUnresolvedLookupExpr) { MatchVerifier Verifier; - testImport("template int foo();" - "template void declToImport() {" - " ::foo;" - " ::template foo;" - "}" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(has(functionDecl( - has(compoundStmt(has(unresolvedLookupExpr()))))))); + testImport( + "template int foo();" + "template void declToImport() {" + " (void)::foo;" + " (void)::template foo;" + "}" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasDescendant(unresolvedLookupExpr()))); } TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) { MatchVerifier Verifier; - testImport("template struct C { T t; };" - "template void declToImport() {" - " C d;" - " d.t = T();" - "}" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(has(functionDecl(has(compoundStmt(has( - binaryOperator(has(cxxUnresolvedConstructExpr()))))))))); - testImport("template struct C { T t; };" - "template void declToImport() {" - " C d;" - " (&d)->t = T();" - "}" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(has(functionDecl(has(compoundStmt(has( - binaryOperator(has(cxxUnresolvedConstructExpr()))))))))); + testImport( + "template struct C { T t; };" + "template void declToImport() {" + " C d;" + " d.t = T();" + "}" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasDescendant( + binaryOperator(has(cxxUnresolvedConstructExpr()))))); + testImport( + "template struct C { T t; };" + "template void declToImport() {" + " C d;" + " (&d)->t = T();" + "}" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasDescendant( + binaryOperator(has(cxxUnresolvedConstructExpr()))))); } /// Check that function "declToImport()" (which is the templated function @@ -1120,16 +1026,18 @@ TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) { /// Same for class template declarations. TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) { MatchVerifier Verifier; - testImport("template void declToImport() { T a = 1; }" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionTemplateDecl(hasAncestor(translationUnitDecl( - unless(has(functionDecl(hasName("declToImport")))))))); - testImport("template struct declToImport { T t; };" - "void instantiate() { declToImport(); }", - Lang_CXX, "", Lang_CXX, Verifier, - classTemplateDecl(hasAncestor(translationUnitDecl( - unless(has(cxxRecordDecl(hasName("declToImport")))))))); + testImport( + "template void declToImport() { T a = 1; }" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(hasAncestor(translationUnitDecl( + unless(has(functionDecl(hasName("declToImport")))))))); + testImport( + "template struct declToImport { T t; };" + "void instantiate() { declToImport(); }", + Lang_CXX, "", Lang_CXX, Verifier, + classTemplateDecl(hasAncestor(translationUnitDecl( + unless(has(cxxRecordDecl(hasName("declToImport")))))))); } TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) { @@ -1148,22 +1056,24 @@ TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) { TEST_P(ImportExpr, CXXOperatorCallExpr) { MatchVerifier Verifier; - testImport("class declToImport {" - " void f() { *this = declToImport(); }" - "};", - Lang_CXX, "", Lang_CXX, Verifier, - cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt( - has(exprWithCleanups(has(cxxOperatorCallExpr()))))))))); + testImport( + "class declToImport {" + " void f() { *this = declToImport(); }" + "};", + Lang_CXX, "", Lang_CXX, Verifier, + cxxRecordDecl(has(cxxMethodDecl(hasDescendant( + cxxOperatorCallExpr()))))); } TEST_P(ImportExpr, DependentSizedArrayType) { MatchVerifier Verifier; - testImport("template class declToImport {" - " T data[Size];" - "};", - Lang_CXX, "", Lang_CXX, Verifier, - classTemplateDecl(has(cxxRecordDecl( - has(fieldDecl(hasType(dependentSizedArrayType()))))))); + testImport( + "template class declToImport {" + " T data[Size];" + "};", + Lang_CXX, "", Lang_CXX, Verifier, + classTemplateDecl(has(cxxRecordDecl( + has(fieldDecl(hasType(dependentSizedArrayType()))))))); } TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { @@ -2197,7 +2107,8 @@ TEST_P(ImportExpr, DependentScopeDeclRefExpr) { "template void declToImport() {" " (void) S::foo;" "}" - "void instantiate() { declToImport(); }", + "void instantiate() { declToImport(); }" + "template T S::foo;", Lang_CXX11, "", Lang_CXX11, Verifier, functionTemplateDecl(has(functionDecl(has(compoundStmt( has(cStyleCastExpr(has(dependentScopeDeclRefExpr()))))))))); -- GitLab From 41b9b9e380859e739ad6806921c230c12521d1aa Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Fri, 29 Jun 2018 11:25:24 +0000 Subject: [PATCH 0361/1023] [analyzer][UninitializedObjectChecker] Added a NotesAsWarnings flag In order to better support consumers of the plist output that don't parse note entries just yet, a 'NotesAsWarnings' flag was added. If it's set to true, all notes will be converted to warnings. Differential Revision: https://reviews.llvm.org/D48285 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335964 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 74 +++++++++++++------ ...uninitialized-object-notes-as-warnings.cpp | 15 ++++ 2 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index d9168d037e..773fcb2269 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -10,10 +10,19 @@ // This file defines a checker that reports uninitialized fields in objects // created after a constructor call. // -// This checker has an option "Pedantic" (boolean). If its not set or is set to -// false, the checker won't emit warnings for objects that don't have at least -// one initialized field. This may be set with -// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// This checker has two options: +// - "Pedantic" (boolean). If its not set or is set to false, the checker +// won't emit warnings for objects that don't have at least one initialized +// field. This may be set with +// +// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// +// - "NotesAsWarnings" (boolean). If set to true, the checker will emit a +// warning for each uninitalized field, as opposed to emitting one warning +// per constructor call, and listing the uninitialized fields that belongs +// to it in notes. Defaults to false. +// +// `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. // //===----------------------------------------------------------------------===// @@ -32,7 +41,9 @@ class UninitializedObjectChecker : public Checker { std::unique_ptr BT_uninitField; public: - bool IsPedantic; // Will be initialized when registering the checker. + // These fields will be initialized when registering the checker. + bool IsPedantic; + bool ShouldConvertNotesToWarnings; UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} @@ -216,6 +227,9 @@ bool isPrimitiveType(const QualType &T) { return T->isBuiltinType() || T->isEnumeralType(); } +/// Constructs a note message for a given FieldChainInfo object. +void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain); + } // end of anonymous namespace //===----------------------------------------------------------------------===// @@ -264,6 +278,23 @@ void UninitializedObjectChecker::checkEndFunction( LocUsedForUniqueing = PathDiagnosticLocation::createBegin( CallSite, Context.getSourceManager(), Node->getLocationContext()); + // For Plist consumers that don't support notes just yet, we'll convert notes + // to warnings. + if (ShouldConvertNotesToWarnings) { + for (const auto &Chain : UninitFields) { + SmallString<100> WarningBuf; + llvm::raw_svector_ostream WarningOS(WarningBuf); + + printNoteMessage(WarningOS, Chain); + + auto Report = llvm::make_unique( + *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing, + Node->getLocationContext()->getDecl()); + Context.emitReport(std::move(Report)); + } + return; + } + SmallString<100> WarningBuf; llvm::raw_svector_ostream WarningOS(WarningBuf); WarningOS << UninitFields.size() << " uninitialized field" @@ -274,29 +305,16 @@ void UninitializedObjectChecker::checkEndFunction( *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing, Node->getLocationContext()->getDecl()); - // TODO: As of now, one warning is emitted per constructor call, and the - // uninitialized fields are listed in notes. Until there's a better support - // for notes avaible, a note-less version of this checker should be - // implemented. - for (const auto &FieldChain : UninitFields) { + for (const auto &Chain : UninitFields) { SmallString<200> NoteBuf; llvm::raw_svector_ostream NoteOS(NoteBuf); - if (FieldChain.isPointer()) { - if (FieldChain.isDereferenced()) - NoteOS << "uninitialized pointee 'this->"; - else - NoteOS << "uninitialized pointer 'this->"; - } else - NoteOS << "uninitialized field 'this->"; - FieldChain.print(NoteOS); - NoteOS << "'"; + printNoteMessage(NoteOS, Chain); Report->addNote(NoteOS.str(), - PathDiagnosticLocation::create(FieldChain.getEndOfChain(), + PathDiagnosticLocation::create(Chain.getEndOfChain(), Context.getSourceManager())); } - Context.emitReport(std::move(Report)); } @@ -662,10 +680,24 @@ bool isCalledByConstructor(const CheckerContext &Context) { return false; } +void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain) { + if (Chain.isPointer()) { + if (Chain.isDereferenced()) + Out << "uninitialized pointee 'this->"; + else + Out << "uninitialized pointer 'this->"; + } else + Out << "uninitialized field 'this->"; + Chain.print(Out); + Out << "'"; +} + } // end of anonymous namespace void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { auto Chk = Mgr.registerChecker(); Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption( "Pedantic", /*DefaultVal*/ false, Chk); + Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption( + "NotesAsWarnings", /*DefaultVal*/ false, Chk); } diff --git a/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp new file mode 100644 index 0000000000..a49507a1aa --- /dev/null +++ b/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true -std=c++11 -verify %s + +class NotesAsWarningsTest { + int a; + int b; + int dontGetFilteredByNonPedanticMode = 0; + +public: + NotesAsWarningsTest() {} // expected-warning{{uninitialized field 'this->a'}} + // expected-warning@-1{{uninitialized field 'this->b'}} +}; + +void fNotesAsWarningsTest() { + NotesAsWarningsTest(); +} -- GitLab From 776a04d9d7360285a5b89c9f37968496045fce6e Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Fri, 29 Jun 2018 12:17:34 +0000 Subject: [PATCH 0362/1023] [ASTImporter] Added import of CXXStdInitializerListExpr Reviewers: a.sidorin Reviewed By: a.sidorin Subscribers: martong, cfe-commits Differential Revision: https://reviews.llvm.org/D48631 Patch by Balazs Keri! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335968 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 14 ++++++++++++++ test/ASTMerge/std-initializer-list/Inputs/il.cpp | 9 +++++++++ test/ASTMerge/std-initializer-list/test.cpp | 3 +++ 3 files changed, 26 insertions(+) create mode 100644 test/ASTMerge/std-initializer-list/Inputs/il.cpp create mode 100644 test/ASTMerge/std-initializer-list/test.cpp diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 5fa222cf4a..37ddfea7be 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -384,6 +384,7 @@ namespace clang { Expr *VisitCallExpr(CallExpr *E); Expr *VisitLambdaExpr(LambdaExpr *LE); Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); @@ -6622,6 +6623,19 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return To; } +Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr( + CXXStdInitializerListExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SE = Importer.Import(E->getSubExpr()); + if (!SE) + return nullptr; + + return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE); +} + Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { QualType ToType = Importer.Import(E->getType()); if (ToType.isNull()) diff --git a/test/ASTMerge/std-initializer-list/Inputs/il.cpp b/test/ASTMerge/std-initializer-list/Inputs/il.cpp new file mode 100644 index 0000000000..3b2ac187c8 --- /dev/null +++ b/test/ASTMerge/std-initializer-list/Inputs/il.cpp @@ -0,0 +1,9 @@ +namespace std { +template +struct initializer_list { + const T *begin, *end; + initializer_list(); +}; +} // namespace std + +std::initializer_list IL = {1, 2, 3, 4}; diff --git a/test/ASTMerge/std-initializer-list/test.cpp b/test/ASTMerge/std-initializer-list/test.cpp new file mode 100644 index 0000000000..ca7330d308 --- /dev/null +++ b/test/ASTMerge/std-initializer-list/test.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp +// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s +// CHECK-NOT: unsupported AST node -- GitLab From cc3a6212f6b22d9fe27ffb4f2c97a8d324486982 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Fri, 29 Jun 2018 14:25:25 +0000 Subject: [PATCH 0363/1023] [clang-format] Support additional common functions for text proto formatting Summary: This adds a few more common function names expecting a text proto argument. Reviewers: djasper Reviewed By: djasper Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48760 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335978 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 741584d138..59d34308c0 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -775,8 +775,11 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { }, /*EnclosingFunctionNames=*/ { - "PARSE_TEXT_PROTO", "EqualsProto", + "EquivToProto", + "PARSE_TEST_PROTO", + "PARSE_TEXT_PROTO", + "ParseTextOrDie", }, /*CanonicalDelimiter=*/"", /*BasedOnStyle=*/"google", -- GitLab From 4c16104f9413dca35a39162c28f0ce421812f9c9 Mon Sep 17 00:00:00 2001 From: Ben Hamilton Date: Fri, 29 Jun 2018 15:26:37 +0000 Subject: [PATCH 0364/1023] [clang-format/ObjC] Fix NS_SWIFT_NAME(foo(bar:baz:)) after ObjC method decl Summary: In D44638, I partially fixed `NS_SWIFT_NAME(foo(bar:baz:))`-style annotations on C functions, but didn't add a test for Objective-C method declarations. For ObjC method declarations which are annotated with `NS_SWIFT_NAME(...)`, we currently fail to annotate the final component of the selector name as `TT_SelectorName`. Because the token type is left unknown, clang-format will happily cause a compilation error when it changes the following: ``` @interface Foo - (void)doStuffWithFoo:(id)name bar:(id)bar baz:(id)baz NS_SWIFT_NAME(doStuff(withFoo:bar:baz:)); @end ``` to: ``` @interface Foo - (void)doStuffWithFoo:(id)name bar:(id)bar baz:(id)baz NS_SWIFT_NAME(doStuff(withFoo:bar:baz :)); @end ``` (note the linebreak before the final `:`). The logic which decides whether or not to annotate the token before a `:` with `TT_SelectorName` is pretty fragile, and has to handle some pretty odd cases like pair-parameters: ``` [I drawRectOn:surface ofSize:aa:bbb atOrigin:cc:dd]; ``` So, to minimize the effect of this change, I decided to only annotate unknown identifiers before a `:` as `TT_SelectorName` for Objective-C declaration lines. Test Plan: New tests included. Confirmed tests failed before change and passed after change. Ran tests with: % make -j16 FormatTests && ./tools/clang/unittests/Format/FormatTests Reviewers: djasper, krasimir, jolesiak Reviewed By: krasimir Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48679 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335983 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 8 +++++++- unittests/Format/FormatTestObjC.cpp | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 68ea02296b..ec8d351725 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -698,13 +698,19 @@ private: Line.startsWith(TT_ObjCMethodSpecifier)) { Tok->Type = TT_ObjCMethodExpr; const FormatToken *BeforePrevious = Tok->Previous->Previous; + // Ensure we tag all identifiers in method declarations as + // TT_SelectorName. + bool UnknownIdentifierInMethodDeclaration = + Line.startsWith(TT_ObjCMethodSpecifier) && + Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown); if (!BeforePrevious || // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. !(BeforePrevious->is(TT_CastRParen) || (BeforePrevious->is(TT_ObjCMethodExpr) && BeforePrevious->is(tok::colon))) || BeforePrevious->is(tok::r_square) || - Contexts.back().LongestObjCSelectorName == 0) { + Contexts.back().LongestObjCSelectorName == 0 || + UnknownIdentifierInMethodDeclaration) { Tok->Previous->Type = TT_SelectorName; if (!Contexts.back().FirstObjCSelectorName) Contexts.back().FirstObjCSelectorName = Tok->Previous; diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 58559eabe8..9d086551b2 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -923,6 +923,14 @@ TEST_F(FormatTestObjC, ObjCSnippets) { verifyFormat("@property(assign, nonatomic) CGFloat hoverAlpha;"); verifyFormat("@property(assign, getter=isEditable) BOOL editable;"); + Style.ColumnLimit = 50; + verifyFormat("@interface Foo\n" + "- (void)doStuffWithFoo:(id)name\n" + " bar:(id)bar\n" + " baz:(id)baz\n" + " NS_SWIFT_NAME(doStuff(withFoo:bar:baz:));\n" + "@end"); + Style = getMozillaStyle(); verifyFormat("@property (assign, getter=isEditable) BOOL editable;"); verifyFormat("@property BOOL editable;"); -- GitLab From aaf4d11cdd565bd4fe8b99ae5dfaf979491e323a Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Fri, 29 Jun 2018 17:08:19 +0000 Subject: [PATCH 0365/1023] [Fixed Point Arithmetic] Rename `-fsame-fbits` flag - Rename the `-fsame-fbits` flag to `-fpadding-on-unsigned-fixed-point` - Move the flag from a driver option to a cc1 option - Rename the `SameFBits` member in TargetInfo to `PaddingOnUnsignedFixedPoint` - Updated descriptions Differential Revision: https://reviews.llvm.org/D48727 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335993 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/LangOptions.def | 4 +-- include/clang/Basic/TargetInfo.h | 34 +++++++++++++++----------- include/clang/Driver/CC1Options.td | 4 +++ include/clang/Driver/Options.td | 4 --- lib/Basic/TargetInfo.cpp | 4 +-- lib/Driver/ToolChains/Clang.cpp | 5 ---- lib/Frontend/CompilerInvocation.cpp | 5 ++-- lib/Sema/SemaExpr.cpp | 2 +- test/Frontend/fixed_point_same_fbits.c | 2 +- 9 files changed, 33 insertions(+), 31 deletions(-) diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 55f057a0d6..b1ac855715 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -306,8 +306,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions") LANGOPT(FixedPoint, 1, 0, "fixed point types") -LANGOPT(SameFBits, 1, 0, - "unsigned and signed fixed point type having the same number of fractional bits") +LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0, + "unsigned fixed point types having one extra padding bit") #undef LANGOPT #undef COMPATIBLE_LANGOPT diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 9bb4db7205..fd9e2e03fa 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -84,10 +84,11 @@ protected: unsigned char LongFractWidth, LongFractAlign; // If true, unsigned fixed point types have the same number of fractional bits - // as their signed counterparts. Otherwise, unsigned fixed point types have + // as their signed counterparts, forcing the unsigned types to have one extra + // bit of padding. Otherwise, unsigned fixed point types have // one more fractional bit than its corresponding signed type. This is false // by default. - bool SameFBits; + bool PaddingOnUnsignedFixedPoint; // Fixed point integral and fractional bit sizes // Saturated types share the same integral/fractional bits as their @@ -95,7 +96,7 @@ protected: // For simplicity, the fractional bits in a _Fract type will be one less the // width of that _Fract type. This leaves all signed _Fract types having no // padding and unsigned _Fract types will only have 1 bit of padding after the - // sign if SameFBits is set. + // sign if PaddingOnUnsignedFixedPoint is set. unsigned char ShortAccumScale; unsigned char AccumScale; unsigned char LongAccumScale; @@ -436,30 +437,33 @@ public: /// getUnsignedShortAccumScale/IBits - Return the number of /// fractional/integral bits in a 'unsigned short _Accum' type. unsigned getUnsignedShortAccumScale() const { - return SameFBits ? ShortAccumScale : ShortAccumScale + 1; + return PaddingOnUnsignedFixedPoint ? ShortAccumScale : ShortAccumScale + 1; } unsigned getUnsignedShortAccumIBits() const { - return SameFBits ? getShortAccumIBits() - : ShortAccumWidth - getUnsignedShortAccumScale(); + return PaddingOnUnsignedFixedPoint + ? getShortAccumIBits() + : ShortAccumWidth - getUnsignedShortAccumScale(); } /// getUnsignedAccumScale/IBits - Return the number of fractional/integral /// bits in a 'unsigned _Accum' type. unsigned getUnsignedAccumScale() const { - return SameFBits ? AccumScale : AccumScale + 1; + return PaddingOnUnsignedFixedPoint ? AccumScale : AccumScale + 1; } unsigned getUnsignedAccumIBits() const { - return SameFBits ? getAccumIBits() : AccumWidth - getUnsignedAccumScale(); + return PaddingOnUnsignedFixedPoint ? getAccumIBits() + : AccumWidth - getUnsignedAccumScale(); } /// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral /// bits in a 'unsigned long _Accum' type. unsigned getUnsignedLongAccumScale() const { - return SameFBits ? LongAccumScale : LongAccumScale + 1; + return PaddingOnUnsignedFixedPoint ? LongAccumScale : LongAccumScale + 1; } unsigned getUnsignedLongAccumIBits() const { - return SameFBits ? getLongAccumIBits() - : LongAccumWidth - getUnsignedLongAccumScale(); + return PaddingOnUnsignedFixedPoint + ? getLongAccumIBits() + : LongAccumWidth - getUnsignedLongAccumScale(); } /// getShortFractScale - Return the number of fractional bits @@ -477,19 +481,21 @@ public: /// getUnsignedShortFractScale - Return the number of fractional bits /// in a 'unsigned short _Fract' type. unsigned getUnsignedShortFractScale() const { - return SameFBits ? getShortFractScale() : getShortFractScale() + 1; + return PaddingOnUnsignedFixedPoint ? getShortFractScale() + : getShortFractScale() + 1; } /// getUnsignedFractScale - Return the number of fractional bits /// in a 'unsigned _Fract' type. unsigned getUnsignedFractScale() const { - return SameFBits ? getFractScale() : getFractScale() + 1; + return PaddingOnUnsignedFixedPoint ? getFractScale() : getFractScale() + 1; } /// getUnsignedLongFractScale - Return the number of fractional bits /// in a 'unsigned long _Fract' type. unsigned getUnsignedLongFractScale() const { - return SameFBits ? getLongFractScale() : getLongFractScale() + 1; + return PaddingOnUnsignedFixedPoint ? getLongFractScale() + : getLongFractScale() + 1; } /// Determine whether the __int128 type is supported on this target. diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index d500cab92b..72e2697a44 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -36,6 +36,10 @@ def triple_EQ : Joined<["-"], "triple=">, Alias; def mfpmath : Separate<["-"], "mfpmath">, HelpText<"Which unit to use for fp math">; +def fpadding_on_unsigned_fixed_point : Flag<["-"], "fpadding-on-unsigned-fixed-point">, + HelpText<"Force each unsigned fixed point type to have an extra bit of padding to align their scales with those of signed fixed point types">; +def fno_padding_on_unsigned_fixed_point : Flag<["-"], "fno-padding-on-unsigned-fixed-point">; + //===----------------------------------------------------------------------===// // Analyzer Options //===----------------------------------------------------------------------===// diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index a6b5da209e..c228e9e9d2 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -893,10 +893,6 @@ def ffixed_point : Flag<["-"], "ffixed-point">, Group, Flags<[CC1Option]>, HelpText<"Enable fixed point types">; def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group, HelpText<"Disable fixed point types">; -def fsame_fbits : Flag<["-"], "fsame-fbits">, Group, - Flags<[CC1Option]>, - HelpText<"Force each unsigned fixed point type to have the same number of fractional bits as its corresponding signed type">; -def fno_same_fbits : Flag<["-"], "fno-same-fbits">, Group; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 31bc7a44f8..3400c8721f 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -53,7 +53,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { // We give the _Accum 1 fewer fractional bits than their corresponding _Fract // types by default to have the same number of fractional bits between _Accum // and _Fract types. - SameFBits = false; + PaddingOnUnsignedFixedPoint = false; ShortAccumScale = 7; AccumScale = 15; LongAccumScale = 31; @@ -377,7 +377,7 @@ void TargetInfo::adjust(LangOptions &Opts) { // Each unsigned fixed point type has the same number of fractional bits as // its corresponding signed type. - SameFBits |= Opts.SameFBits; + PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint; CheckFixedPointBits(); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index c5fbd09755..790fae4a6c 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3765,11 +3765,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, /*Default=*/false)) Args.AddLastArg(CmdArgs, options::OPT_ffixed_point); - if (Args.hasFlag(options::OPT_fsame_fbits, - options::OPT_fno_same_fbits, - /*Default=*/false)) - Args.AddLastArg(CmdArgs, options::OPT_fsame_fbits); - // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 26414f1a52..3335ccb4fc 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2338,8 +2338,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.FixedPoint = Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) && !Opts.CPlusPlus; - Opts.SameFBits = - Args.hasFlag(OPT_fsame_fbits, OPT_fno_same_fbits, + Opts.PaddingOnUnsignedFixedPoint = + Args.hasFlag(OPT_fpadding_on_unsigned_fixed_point, + OPT_fno_padding_on_unsigned_fixed_point, /*Default=*/false) && Opts.FixedPoint; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a438480a4b..a713136b64 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3358,7 +3358,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { bool Overflowed = Literal.GetFixedPointValue(Val, scale); // Do not use bit_width since some types may have padding like _Fract or - // unsigned _Accums if SameFBits is set. + // unsigned _Accums if PaddingOnUnsignedFixedPoint is set. auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width); if (Literal.isFract && Val == MaxVal + 1) // Clause 6.4.4 - The value of a constant shall be in the range of diff --git a/test/Frontend/fixed_point_same_fbits.c b/test/Frontend/fixed_point_same_fbits.c index 255f7de89f..1d116b7dfa 100644 --- a/test/Frontend/fixed_point_same_fbits.c +++ b/test/Frontend/fixed_point_same_fbits.c @@ -1,5 +1,5 @@ // RUN: %clang -ffixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -ffixed-point -fsame-fbits -S -emit-llvm -o - %s | FileCheck %s -check-prefix=SAME +// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=SAME /* The scale for unsigned fixed point types should be the same as that of signed * fixed point types when -fsame-fbits is enabled. */ -- GitLab From 4497d9c52cf6c9e2f1503d47a5f910c1aaf075fe Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Fri, 29 Jun 2018 18:06:10 +0000 Subject: [PATCH 0366/1023] [MachineOutliner] Make -mno-outline use -enable-machine-outliner=never This updates -mno-outline so that it passes -enable-machine-outliner=never instead of nothing. This puts it in sync with the behaviour in llc and other tools. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336001 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 37 ++++++++++++++++++++------------- test/Driver/aarch64-outliner.c | 2 +- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 790fae4a6c..5999d0b3f9 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4797,23 +4797,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); - if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { - // We only support -moutline in AArch64 right now. If we're not compiling - // for AArch64, emit a warning and ignore the flag. Otherwise, add the - // proper mllvm flags. - if (Triple.getArch() != llvm::Triple::aarch64) { - D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); - } else { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); - - // The outliner shouldn't compete with linkers that dedupe linkonceodr - // functions in LTO. Enable that behaviour by default when compiling with - // LTO. - if (getToolChain().getDriver().isUsingLTO()) { + if (Arg *A = Args.getLastArg(options::OPT_moutline, + options::OPT_mno_outline)) { + if (A->getOption().matches(options::OPT_moutline)) { + // We only support -moutline in AArch64 right now. If we're not compiling + // for AArch64, emit a warning and ignore the flag. Otherwise, add the + // proper mllvm flags. + if (Triple.getArch() != llvm::Triple::aarch64) { + D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); + } else { CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-linkonceodr-outlining"); + CmdArgs.push_back("-enable-machine-outliner"); + + // The outliner shouldn't compete with linkers that dedupe linkonceodr + // functions in LTO. Enable that behaviour by default when compiling with + // LTO. + if (getToolChain().getDriver().isUsingLTO()) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-linkonceodr-outlining"); + } } + } else { + // Disable all outlining behaviour. + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner=never"); } } diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c index a02722df21..82f02ff99f 100644 --- a/test/Driver/aarch64-outliner.c +++ b/test/Driver/aarch64-outliner.c @@ -2,7 +2,7 @@ // RUN: %clang -target aarch64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=ON // ON: "-mllvm" "-enable-machine-outliner" // RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF -// OFF-NOT: "-mllvm" "-enable-machine-outliner" +// OFF: "-mllvm" "-enable-machine-outliner=never" // RUN: %clang -target aarch64 -moutline -flto=thin -S %s -### 2>&1 | FileCheck %s -check-prefix=FLTO // FLTO: "-mllvm" "-enable-linkonceodr-outlining" // RUN: %clang -target aarch64 -moutline -flto=full -S %s -### 2>&1 | FileCheck %s -check-prefix=TLTO -- GitLab From bcf5ad3f2f68dcb6e3839aede4d350c569193640 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Fri, 29 Jun 2018 18:11:43 +0000 Subject: [PATCH 0367/1023] [analyzer] Replace the vector of ConstraintSets by a single ConstraintSet and a function to merge ConstraintSets Now, instead of adding the constraints when they are removed, this patch adds them when they first appear and, since we walk the bug report backward, it should be the last set of ranges generated by the CSA for a given symbol. These are the number before and after the patch: ``` Project | current | patch | tmux | 283.222 | 123.052 | redis | 614.858 | 400.347 | openssl | 308.292 | 307.149 | twin | 274.478 | 245.411 | git | 547.687 | 477.335 | postgresql | 2927.495 | 2002.526 | sqlite3 | 3264.305 | 1028.416 | ``` Major speedups in tmux and sqlite (less than half of the time), redis and postgresql were about 25% faster while the rest are basically the same. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: rnkovacs, xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D48565 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336002 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/BugReporterVisitors.h | 8 ++-- .../Core/BugReporterVisitors.cpp | 46 +++++++++++++------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 031a76c7bd..92118b0fbe 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -336,11 +336,10 @@ public: class FalsePositiveRefutationBRVisitor final : public BugReporterVisitor { private: /// Holds the constraints in a given path - // TODO: should we use a set? - llvm::SmallVector Constraints; + ConstraintRangeTy Constraints; public: - FalsePositiveRefutationBRVisitor() = default; + FalsePositiveRefutationBRVisitor(); void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -348,6 +347,9 @@ public: const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override; + + void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, + BugReport &BR) override; }; namespace bugreporter { diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 468f2184bd..025c2898ee 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -2349,9 +2349,8 @@ TaintBugVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, return std::make_shared(L, "Taint originated here"); } -static bool -areConstraintsUnfeasible(BugReporterContext &BRC, - const llvm::SmallVector &Cs) { +static bool areConstraintsUnfeasible(BugReporterContext &BRC, + const ConstraintRangeTy &Cs) { // Create a refutation manager std::unique_ptr RefutationMgr = CreateZ3ConstraintManager( BRC.getStateManager(), BRC.getStateManager().getOwningEngine()); @@ -2360,28 +2359,45 @@ areConstraintsUnfeasible(BugReporterContext &BRC, static_cast(RefutationMgr.get()); // Add constraints to the solver - for (const auto &C : Cs) - SMTRefutationMgr->addRangeConstraints(C); + SMTRefutationMgr->addRangeConstraints(Cs); // And check for satisfiability return SMTRefutationMgr->isModelFeasible().isConstrainedFalse(); } +static void addNewConstraints(ConstraintRangeTy &Cs, + const ConstraintRangeTy &NewCs, + ConstraintRangeTy::Factory &CF) { + // Add constraints if we don't have them yet + for (auto const &C : NewCs) { + const SymbolRef &Sym = C.first; + if (!Cs.contains(Sym)) { + Cs = CF.add(Cs, Sym, C.second); + } + } +} + +FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor() + : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {} + +void FalsePositiveRefutationBRVisitor::finalizeVisitor( + BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { + // Collect new constraints + VisitNode(EndPathNode, nullptr, BRC, BR); + + // Create a new refutation manager and check feasibility + if (areConstraintsUnfeasible(BRC, Constraints)) + BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext()); +} + std::shared_ptr FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { - // Collect the constraint for the current state - const ConstraintRangeTy &CR = N->getState()->get(); - Constraints.push_back(CR); - - // If there are no predecessor, we reached the root node. In this point, - // a new refutation manager will be created and the path will be checked - // for reachability - if (PrevN->pred_size() == 0 && areConstraintsUnfeasible(BRC, Constraints)) { - BR.markInvalid("Infeasible constraints", N->getLocationContext()); - } + // Collect new constraints + addNewConstraints(Constraints, N->getState()->get(), + N->getState()->get_context()); return nullptr; } -- GitLab From cb739b34669c3214aaa222cb2c8a6b16235f2941 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 29 Jun 2018 19:03:03 +0000 Subject: [PATCH 0368/1023] [mips][ias] Enable IAS by default for OpenBSD / FreeBSD mips64/mips64el. Reviewers: atanasyan Differential Revision: https://reviews.llvm.org/D48515 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336004 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Gnu.cpp | 10 ++++++---- test/Driver/freebsd.c | 7 +++++++ test/Driver/openbsd.c | 7 +++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index deaf51dc77..2f632e2b5a 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -2412,11 +2412,13 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { return true; case llvm::Triple::mips64: case llvm::Triple::mips64el: - // Enabled for Debian and Android mips64/mipsel, as they can precisely - // identify the ABI in use (Debian) or only use N64 for MIPS64 (Android). - // Other targets are unable to distinguish N32 from N64. + // Enabled for Debian, Android, FreeBSD and OpenBSD mips64/mipsel, as they + // can precisely identify the ABI in use (Debian) or only use N64 for MIPS64 + // (Android). Other targets are unable to distinguish N32 from N64. if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 || - getTriple().isAndroid()) + getTriple().isAndroid() || + getTriple().isOSFreeBSD() || + getTriple().isOSOpenBSD()) return true; return false; default: diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c index 48f7c8e7f2..aac4d9d966 100644 --- a/test/Driver/freebsd.c +++ b/test/Driver/freebsd.c @@ -183,3 +183,10 @@ // RUN: %clang -target mips64el-unknown-freebsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s // CHECK-MIPS64-CPU: "-target-cpu" "mips3" + +// Check that the integrated assembler is enabled for MIPS64 +// RUN: %clang -target mips64-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s +// RUN: %clang -target mips64el-unknown-freebsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s +// CHECK-MIPS64-AS-NOT: "-no-integrated-as" diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c index 2bcd703770..098ecc4a27 100644 --- a/test/Driver/openbsd.c +++ b/test/Driver/openbsd.c @@ -74,6 +74,13 @@ // CHECK-MIPS64EL: as{{.*}}" "-mabi" "64" "-EL" // CHECK-MIPS64EL-PIC: as{{.*}}" "-mabi" "64" "-EL" "-KPIC" +// Check that the integrated assembler is enabled for MIPS64 +// RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s +// RUN: %clang -target mips64el-unknown-openbsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s +// CHECK-MIPS64-AS-NOT: "-no-integrated-as" + // Check linking against correct startup code when (not) using PIE // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE %s -- GitLab From 833ad29a88de7d88bd69234b5069bbfaea0235d1 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 29 Jun 2018 19:18:17 +0000 Subject: [PATCH 0369/1023] Request init/fini array on FreeBSD 12 and later Summary: It seems a bad idea to change the default in the middle of a release branch due to possible changes in global ctor / dtor ordering between .ctors and .init_array. With FreeBSD 11.0's release imminent lets change the default now for FreeBSD 12 (the current development stream) and later. FreeBSD rtld has supported .init_array / .fini_array for many years. As of Jan 1 2017 all supported FreeBSD releases and branches will have support. Reviewers: dim, brooks, arichardson Reviewed By: dim, brooks, arichardson Subscribers: bsdjhb, krytarowski, emaste, cfe-commits Differential Revision: https://reviews.llvm.org/D24867 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336008 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Gnu.cpp | 2 ++ test/Driver/constructors.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 2f632e2b5a..1ecf127c4b 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -2543,6 +2543,8 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, bool UseInitArrayDefault = getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::aarch64_be || + (getTriple().getOS() == llvm::Triple::FreeBSD && + getTriple().getOSMajorVersion() >= 12) || (getTriple().getOS() == llvm::Triple::Linux && ((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) || getTriple().isAndroid())) || diff --git a/test/Driver/constructors.c b/test/Driver/constructors.c index 884fbe8466..a3443a3321 100644 --- a/test/Driver/constructors.c +++ b/test/Driver/constructors.c @@ -80,6 +80,14 @@ // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target arm64-none-none-eabi \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-freebsd11 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-INIT-ARRAY %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-freebsd12 \ +// RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target sparc-sun-solaris2.11 \ -- GitLab From dd5dcddd4129abf56d69a0d5b380cc7c31ef07ee Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 29 Jun 2018 20:41:23 +0000 Subject: [PATCH 0370/1023] Specify an explicit underlying type for this enum to fix Windows buildbots. On Windows targets, enums always get an underlying type of 'int', even if they have wider enumerators. (This is non-conforming, but it's effectively part of the target ABI.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336013 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CXX/conv/conv.prom/p5.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CXX/conv/conv.prom/p5.cpp b/test/CXX/conv/conv.prom/p5.cpp index baf51374c8..0c72ebce4a 100644 --- a/test/CXX/conv/conv.prom/p5.cpp +++ b/test/CXX/conv/conv.prom/p5.cpp @@ -8,7 +8,7 @@ static_assert(sizeof(+X().e) == sizeof(int), ""); static_assert(sizeof(X().e + 1) == sizeof(int), ""); static_assert(sizeof(true ? X().e : 0) == sizeof(int), ""); -enum E { a = __LONG_LONG_MAX__ }; +enum E : long long { a = __LONG_LONG_MAX__ }; static_assert(sizeof(E{}) == sizeof(long long), ""); // If the bit-field has an enumerated type, it is treated as any other value of -- GitLab From 013450120264d4ef3d486856a67866a91e4f56f6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 29 Jun 2018 20:46:25 +0000 Subject: [PATCH 0371/1023] [modules] Emit the type of the TypeSourceInfo for a DeclaratorDecl (but not the corresponding location information) earlier. We need the type as written in order to properly merge functions with deduced return types, so we need to load that early. But we don't want to load the location information early, because that contains problematic things such as the function parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336016 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTReader.h | 9 +++++++++ include/clang/Serialization/ASTWriter.h | 2 +- lib/Serialization/ASTReader.cpp | 11 ++++++++--- lib/Serialization/ASTReaderDecl.cpp | 13 ++++++------- lib/Serialization/ASTWriter.cpp | 4 ++-- lib/Serialization/ASTWriterDecl.cpp | 15 ++++++++++----- 6 files changed, 36 insertions(+), 18 deletions(-) diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index d09a9f4023..bf9ed38a15 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1771,6 +1771,10 @@ public: TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F, const RecordData &Record, unsigned &Idx); + /// Raad the type locations for the given TInfo. + void ReadTypeLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx, + TypeLoc TL); + /// Resolve a type ID into a type, potentially building a new /// type. QualType GetType(serialization::TypeID ID); @@ -2460,6 +2464,11 @@ public: return Reader->GetTypeSourceInfo(*F, Record, Idx); } + /// Reads the location information for a type. + void readTypeLoc(TypeLoc TL) { + return Reader->ReadTypeLoc(*F, Record, Idx, TL); + } + /// Map a local type ID within a given AST file to a global type ID. serialization::TypeID getGlobalTypeID(unsigned LocalID) const { return Reader->getGlobalTypeID(*F, LocalID); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 28db00df89..a93579930f 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -886,7 +886,7 @@ public: /// Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo); - /// Emits a type with source-location information. + /// Emits source location information for a type. Does not emit the type. void AddTypeLoc(TypeLoc TL); /// Emits a template argument location info. diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 9287ffd3d6..f56afeb892 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6733,6 +6733,13 @@ void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) { TL.setKWLoc(ReadSourceLocation()); } +void ASTReader::ReadTypeLoc(ModuleFile &F, const ASTReader::RecordData &Record, + unsigned &Idx, TypeLoc TL) { + TypeLocReader TLR(F, *this, Record, Idx); + for (; !TL.isNull(); TL = TL.getNextTypeLoc()) + TLR.Visit(TL); +} + TypeSourceInfo * ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, unsigned &Idx) { @@ -6741,9 +6748,7 @@ ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record, return nullptr; TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy); - TypeLocReader TLR(F, *this, Record, Idx); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLR.Visit(TL); + ReadTypeLoc(F, Record, Idx, TInfo->getTypeLoc()); return TInfo; } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index a1ce26d27c..b0c7bbec20 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -522,13 +522,8 @@ void ASTDeclReader::Visit(Decl *D) { IsDeclMarkedUsed = false; if (auto *DD = dyn_cast(D)) { - if (DD->DeclInfo) { - auto *Info = DD->DeclInfo.get(); - Info->TInfo = GetTypeSourceInfo(); - } - else { - DD->DeclInfo = GetTypeSourceInfo(); - } + if (auto *TInfo = DD->getTypeSourceInfo()) + Record.readTypeLoc(TInfo->getTypeLoc()); } if (auto *TD = dyn_cast(D)) { @@ -815,6 +810,10 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { ReadQualifierInfo(*Info); DD->DeclInfo = Info; } + QualType TSIType = Record.readType(); + DD->setTypeSourceInfo( + TSIType.isNull() ? nullptr + : Reader.getContext().CreateTypeSourceInfo(TSIType)); } void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 1c838ae2c0..279960a129 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5447,12 +5447,11 @@ void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { return; } + AddTypeRef(TInfo->getType()); AddTypeLoc(TInfo->getTypeLoc()); } void ASTRecordWriter::AddTypeLoc(TypeLoc TL) { - AddTypeRef(TL.getType()); - TypeLocWriter TLW(*this); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); @@ -5777,6 +5776,7 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); + AddTypeRef(NNS.getTypeLoc().getType()); AddTypeLoc(NNS.getTypeLoc()); AddSourceLocation(NNS.getLocalSourceRange().getEnd()); break; diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index cf35a2bc1f..1fac13e6ee 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -265,7 +265,8 @@ void ASTDeclWriter::Visit(Decl *D) { // abbreviation infrastructure requires that arrays are encoded last, so // we handle it here in the case of those classes derived from DeclaratorDecl if (DeclaratorDecl *DD = dyn_cast(D)) { - Record.AddTypeSourceInfo(DD->getTypeSourceInfo()); + if (auto *TInfo = DD->getTypeSourceInfo()) + Record.AddTypeLoc(TInfo->getTypeLoc()); } // Handle FunctionDecl's body here and write it after all other Stmts/Exprs @@ -513,6 +514,9 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Record.AddQualifierInfo(*D->getExtInfo()); + // The location information is deferred until the end of the record. + Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() + : QualType()); } void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { @@ -1773,11 +1777,11 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable Abv->Add(BitCodeAbbrevOp(0)); // InitStyle // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -1806,6 +1810,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable Abv->Add(BitCodeAbbrevOp(0)); // InitStyle @@ -1813,7 +1818,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -1949,6 +1953,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // SClass Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec @@ -1965,7 +1970,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2025,6 +2029,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // VarDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec @@ -2045,7 +2050,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // IsInitICE (local) Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum) // Type Source Info - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); @@ -2076,6 +2080,7 @@ void ASTWriter::WriteDeclAbbrevs() { // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType // FunctionDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass -- GitLab From 4f4b04b8c6e771cac18940406830c139f6e7d7cc Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 29 Jun 2018 21:58:24 +0000 Subject: [PATCH 0372/1023] Spurious commit just to help Richard, because git is weird. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336020 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Modules/codegen.test | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Modules/codegen.test b/test/Modules/codegen.test index a919933da2..2d20b078a7 100644 --- a/test/Modules/codegen.test +++ b/test/Modules/codegen.test @@ -6,6 +6,7 @@ RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -fmodules-debuginfo - RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -disable-llvm-passes -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s + For want of any better definition, inline asm goes "everywhere" the same as it if it were in a header (with the disadvantage that the inline asm will be included in the program if the module is used, even if the header containing -- GitLab From fd6e423d4eb805a2cb01a3279b51563e4fbc272f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 29 Jun 2018 21:58:50 +0000 Subject: [PATCH 0373/1023] PR33924: merge local declarations that have linkage of some kind within merged function definitions; also merge functions with deduced return types. This seems like two independent fixes, but unfortunately they are hard to separate because it's challenging to reliably test either one of them without also testing the other. A complication arises with deduced return type support: we need the type of the function in order to know how to merge it, but we can't load the actual type of the function because it might reference an entity declared within the function (and we need to have already merged the function to correctly merge that entity, which we would need to do to determine if the function types match). So we instead compare the declared function type when merging functions, and defer loading the actual type of a function with a deduced type until we've finished loading and merging the function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336021 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTReader.h | 2 +- lib/Serialization/ASTCommon.cpp | 16 +++- lib/Serialization/ASTReaderDecl.cpp | 103 ++++++++++++++++++------ test/Modules/merge-deduced-return.cpp | 33 ++++++++ test/Modules/merge-lambdas.cpp | 48 +++++++++++ test/Modules/merge-static-locals.cpp | 27 +++++++ 6 files changed, 203 insertions(+), 26 deletions(-) create mode 100644 test/Modules/merge-deduced-return.cpp create mode 100644 test/Modules/merge-lambdas.cpp create mode 100644 test/Modules/merge-static-locals.cpp diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index bf9ed38a15..b33f317765 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -546,7 +546,7 @@ private: /// Mergeable declaration contexts that have anonymous declarations /// within them, and those anonymous declarations. - llvm::DenseMap> + llvm::DenseMap> AnonymousDeclarationsForMerging; struct FileDeclsInfo { diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index fcebe5982f..da482717f4 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -419,9 +419,21 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return true; } - // Otherwise, we only care about anonymous class members. + // At block scope, we number everything that we need to deduplicate, since we + // can't just use name matching to keep things lined up. + // FIXME: This is only necessary for an inline function or a template or + // similar. + if (D->getLexicalDeclContext()->isFunctionOrMethod()) { + if (auto *VD = dyn_cast(D)) + return VD->isStaticLocal(); + // FIXME: What about CapturedDecls (and declarations nested within them)? + return isa(D) || isa(D); + } + + // Otherwise, we only care about anonymous class members / block-scope decls. + // FIXME: We need to handle lambdas and blocks within inline / templated + // variables too. if (D->getDeclName() || !isa(D->getLexicalDeclContext())) return false; return isa(D) || isa(D); } - diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index b0c7bbec20..8701d80653 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -87,7 +87,7 @@ namespace clang { using RecordData = ASTReader::RecordData; - TypeID TypeIDForTypeDecl = 0; + TypeID DeferredTypeID = 0; unsigned AnonymousDeclNumber; GlobalDeclID NamedDeclForTagDecl = 0; IdentifierInfo *TypedefNameForLinkage = nullptr; @@ -177,6 +177,8 @@ namespace clang { void MergeDefinitionData(ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD); + static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC); + static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index); @@ -528,7 +530,7 @@ void ASTDeclReader::Visit(Decl *D) { if (auto *TD = dyn_cast(D)) { // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. @@ -537,8 +539,11 @@ void ASTDeclReader::Visit(Decl *D) { cast(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. - ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); + ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); } else if (auto *FD = dyn_cast(D)) { + if (DeferredTypeID) + FD->setType(Reader.GetType(DeferredTypeID)); + // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). @@ -658,7 +663,7 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(ReadSourceLocation()); // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); } ASTDeclReader::RedeclarableResult @@ -791,7 +796,13 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - VD->setType(Record.readType()); + // For function declarations, defer reading the type in case the function has + // a deduced return type that references an entity declared within the + // function. + if (isa(VD)) + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + else + VD->setType(Record.readType()); } void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { @@ -820,6 +831,19 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); VisitDeclaratorDecl(FD); + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && + FD->getTypeSourceInfo()->getType()->castAs() + ->getReturnType()->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + DeferredTypeID = 0; + } + ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); FD->IdentifierNamespace = Record.readInt(); @@ -1084,7 +1108,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); mergeRedeclarable(ID, Redecl); ID->TypeParamList = ReadObjCTypeParamList(); @@ -1890,7 +1914,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // // Beware: we do not yet know our canonical declaration, and may still // get merged once the surrounding class template has got off the ground. - TypeIDForTypeDecl = 0; + DeferredTypeID = 0; } break; } @@ -2843,8 +2867,12 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; // Must be in the same context. - if (!X->getDeclContext()->getRedeclContext()->Equals( - Y->getDeclContext()->getRedeclContext())) + // + // Note that we can't use DeclContext::Equals here, because the DeclContexts + // could be two different declarations of the same function. (We will fix the + // semantic DC to refer to the primary definition after merging.) + if (!declaresSameEntity(cast(X->getDeclContext()->getRedeclContext()), + cast(Y->getDeclContext()->getRedeclContext()))) return false; // Two typedefs refer to the same entity if they have the same underlying @@ -2906,18 +2934,21 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } ASTContext &C = FuncX->getASTContext(); - if (!C.hasSameType(FuncX->getType(), FuncY->getType())) { + auto GetTypeAsWritten = [](const FunctionDecl *FD) { + return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() + : FD->getType(); + }; + QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); + if (!C.hasSameType(XT, YT)) { // We can get functions with different types on the redecl chain in C++17 // if they have differing exception specifications and at least one of // the excpetion specs is unresolved. - // FIXME: Do we need to check for C++14 deduced return types here too? - auto *XFPT = FuncX->getType()->getAs(); - auto *YFPT = FuncY->getType()->getAs(); + auto *XFPT = XT->getAs(); + auto *YFPT = YT->getAs(); if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(), - FuncY->getType())) + C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) return true; return false; } @@ -3109,23 +3140,50 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found, return nullptr; } +/// Find the declaration to use to populate the anonymous declaration table +/// for the given lexical DeclContext. We only care about finding local +/// definitions of the context; we'll merge imported ones as we go. +DeclContext * +ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { + // For classes, we track the definition as we merge. + if (auto *RD = dyn_cast(LexicalDC)) { + auto *DD = RD->getCanonicalDecl()->DefinitionData; + return DD ? DD->Definition : nullptr; + } + + // For anything else, walk its merged redeclarations looking for a definition. + // Note that we can't just call getDefinition here because the redeclaration + // chain isn't wired up. + for (auto *D : merged_redecls(cast(LexicalDC))) { + if (auto *FD = dyn_cast(D)) + if (FD->isThisDeclarationADefinition()) + return FD; + if (auto *MD = dyn_cast(D)) + if (MD->isThisDeclarationADefinition()) + return MD; + } + + // No merged definition yet. + return nullptr; +} + NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index) { // If the lexical context has been merged, look into the now-canonical // definition. - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast(DC)->getCanonicalDecl(); // If we've seen this before, return the canonical declaration. - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index < Previous.size() && Previous[Index]) return Previous[Index]; // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. - if (!cast(DC)->isFromASTFile()) { - numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) { + auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); + if (PrimaryDC && !cast(PrimaryDC)->isFromASTFile()) { + numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { if (Previous.size() == Number) Previous.push_back(cast(ND->getCanonicalDecl())); else @@ -3139,10 +3197,9 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D) { - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast(DC)->getCanonicalDecl(); - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index >= Previous.size()) Previous.resize(Index + 1); if (!Previous[Index]) diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp new file mode 100644 index 0000000000..0a4de7b975 --- /dev/null +++ b/test/Modules/merge-deduced-return.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s +// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s -DLOCAL +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +inline auto f() { struct X {}; return X(); } +inline auto a = f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +inline auto f() { struct X {}; return X(); } +inline auto b = f(); +#pragma clang module end +#pragma clang module endbuild + +#ifdef LOCAL +inline auto f() { struct X {}; return X(); } +inline auto b = f(); +#else +#pragma clang module import B +#endif + +#pragma clang module import A + +using T = decltype(a); +using T = decltype(b); diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp new file mode 100644 index 0000000000..d14483aa3a --- /dev/null +++ b/test/Modules/merge-lambdas.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fmodules -verify %s +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template auto f() { return []{}; } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +#pragma clang module import A +inline auto x1() { return f(); } +inline auto z() { return []{}; } +inline auto x2() { return z(); } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build C +module C {} +#pragma clang module contents +#pragma clang module begin C +#pragma clang module import A +inline auto y1() { return f(); } +inline auto z() { return []{}; } +inline auto y2() { return z(); } +inline auto q() { return []{}; } +inline auto y3() { return q(); } +#pragma clang module end +#pragma clang module endbuild + +inline auto q() { return []{}; } +inline auto x3() { return q(); } + +#pragma clang module import B +#pragma clang module import C +using T = decltype(x1); +using T = decltype(y1); + +using U = decltype(x2); +using U = decltype(y2); + +using V = decltype(x3); +using V = decltype(y3); diff --git a/test/Modules/merge-static-locals.cpp b/test/Modules/merge-static-locals.cpp new file mode 100644 index 0000000000..37ae22ee38 --- /dev/null +++ b/test/Modules/merge-static-locals.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++17 -fmodules -verify %s +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template struct X {}; +auto get() { static int n; return X<&n>(); } +using A = decltype(get()); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +template struct X {}; +auto get() { static int n; return X<&n>(); } +using B = decltype(get()); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import A +#pragma clang module import B +using T = A; +using T = B; -- GitLab From 534c44af2b96e7c066e49de7f4428205a6713d7c Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 29 Jun 2018 22:05:13 +0000 Subject: [PATCH 0374/1023] [analyzer] [tests] Fix 80 column violation in SATestBuild.py git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336022 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/analyzer/SATestBuild.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index 3137b48a78..00f3bd853d 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -274,13 +274,13 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): SBOptions += "-plist-html -o '%s' " % SBOutputDir SBOptions += "-enable-checker " + AllCheckers + " " SBOptions += "--keep-empty " - AnalyzerConfig = { - "stable-report-filename": "true", - "serialize-stats": "true" - } + AnalyzerConfig = [ + ("stable-report-filename", "true"), + ("serialize-stats", "true"), + ] SBOptions += "-analyzer-config '%s' " % ( - ",".join("%s=%s" % (key, value) for key, value in AnalyzerConfig.iteritems())) + ",".join("%s=%s" % (key, value) for (key, value) in AnalyzerConfig)) # Always use ccc-analyze to ensure that we can locate the failures # directory. -- GitLab From b87dc38b6294d3514b0269ec50765d3ab1c0061f Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 29 Jun 2018 22:05:32 +0000 Subject: [PATCH 0375/1023] [analyzer] [tests] Allow the tested project to specify it's own analyzer wrapper git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336023 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/analyzer/SATestBuild.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index 00f3bd853d..882c5ce7fc 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -136,6 +136,9 @@ CleanupScript = "cleanup_run_static_analyzer.sh" # This is a file containing commands for scan-build. BuildScript = "run_static_analyzer.cmd" +# A comment in a build script which disables wrapping. +NoPrefixCmd = "#NOPREFIX" + # The log file name. LogFolderName = "Logs" BuildLogName = "run_static_analyzer.log" @@ -285,6 +288,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): # Always use ccc-analyze to ensure that we can locate the failures # directory. SBOptions += "--override-compiler " + ExtraEnv = {} try: SBCommandFile = open(BuildScriptPath, "r") SBPrefix = "scan-build " + SBOptions + " " @@ -292,6 +296,15 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): Command = Command.strip() if len(Command) == 0: continue + + # Custom analyzer invocation specified by project. + # Communicate required information using environment variables + # instead. + if Command == NoPrefixCmd: + SBPrefix = "" + ExtraEnv['OUTPUT'] = SBOutputDir + continue + # If using 'make', auto imply a -jX argument # to speed up analysis. xcodebuild will # automatically use the maximum number of cores. @@ -305,6 +318,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): check_call(SBCommand, cwd=SBCwd, stderr=PBuildLogFile, stdout=PBuildLogFile, + env=dict(os.environ, **ExtraEnv), shell=True) except CalledProcessError: Local.stderr.write("Error: scan-build failed. Its output was: \n") -- GitLab From 4a70ae36838d67e1bfce5b182ba96a1bd1496756 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 29 Jun 2018 22:27:56 +0000 Subject: [PATCH 0376/1023] [CUDA] Make min/max shims host+device. Summary: Fixes PR37753: min/max can't be called from __host__ __device__ functions in C++14 mode. Testcase in a separate test-suite commit. Reviewers: rsmith Subscribers: sanjoy, lahwaacz, cfe-commits Differential Revision: https://reviews.llvm.org/D48036 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336025 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/cuda_wrappers/algorithm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Headers/cuda_wrappers/algorithm b/lib/Headers/cuda_wrappers/algorithm index 8ee84f7fb0..d8658bf1c7 100644 --- a/lib/Headers/cuda_wrappers/algorithm +++ b/lib/Headers/cuda_wrappers/algorithm @@ -69,28 +69,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template __attribute__((enable_if(true, ""))) -inline __device__ const __T & +inline __host__ __device__ const __T & max(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__a, __b) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __device__ const __T & +inline __host__ __device__ const __T & max(const __T &__a, const __T &__b) { return __a < __b ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __device__ const __T & +inline __host__ __device__ const __T & min(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__b, __a) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __device__ const __T & +inline __host__ __device__ const __T & min(const __T &__a, const __T &__b) { return __a < __b ? __a : __b; } -- GitLab From e5aa4b4257a7bda80ecc229f8f66fddfa17c93b5 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 29 Jun 2018 22:28:09 +0000 Subject: [PATCH 0377/1023] [CUDA] Make __host__/__device__ min/max overloads constexpr in C++14. Summary: Tests in a separate change to the test-suite. Reviewers: rsmith, tra Subscribers: lahwaacz, sanjoy, cfe-commits Differential Revision: https://reviews.llvm.org/D48151 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336026 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/cuda_wrappers/algorithm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/Headers/cuda_wrappers/algorithm b/lib/Headers/cuda_wrappers/algorithm index d8658bf1c7..01af18360d 100644 --- a/lib/Headers/cuda_wrappers/algorithm +++ b/lib/Headers/cuda_wrappers/algorithm @@ -67,34 +67,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #endif +#pragma push_macro("_CPP14_CONSTEXPR") +#if __cplusplus >= 201402L +#define _CPP14_CONSTEXPR constexpr +#else +#define _CPP14_CONSTEXPR +#endif + template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__a, __b) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & max(const __T &__a, const __T &__b) { return __a < __b ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b, __Cmp __cmp) { return __cmp(__b, __a) ? __b : __a; } template __attribute__((enable_if(true, ""))) -inline __host__ __device__ const __T & +inline _CPP14_CONSTEXPR __host__ __device__ const __T & min(const __T &__a, const __T &__b) { return __a < __b ? __a : __b; } +#pragma pop_macro("_CPP14_CONSTEXPR") + #ifdef _LIBCPP_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD #else -- GitLab From 6b9a1ecb46c73d83b14a841351addfcc78775880 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Sat, 30 Jun 2018 00:49:27 +0000 Subject: [PATCH 0378/1023] Add protocol redefinition to the current scope/context Not doing so causes the AST writter to assert since the decl in question never gets emitted. This is fine when modules is not used, but otherwise we need to serialize something other than garbage. rdar://problem/39844933 Differential Revision: https://reviews.llvm.org/D47297 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336031 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclObjC.cpp | 5 +++++ .../protocol-redefinition/Base.framework/Headers/Base.h | 3 +++ .../Base.framework/Modules/module.modulemap | 4 ++++ .../protocol-redefinition/Kit.framework/Headers/Kit.h | 6 ++++++ .../Kit.framework/Modules/module.modulemap | 4 ++++ test/Modules/protocol-redefinition.m | 6 ++++++ 6 files changed, 28 insertions(+) create mode 100644 test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h create mode 100644 test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h create mode 100644 test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap create mode 100644 test/Modules/protocol-redefinition.m diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index d7544ecfaf..6809b48dc8 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1210,6 +1210,11 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, /*PrevDecl=*/nullptr); + + // If we are using modules, add the decl to the context in order to + // serialize something meaningful. + if (getLangOpts().Modules) + PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } else { if (PrevDecl) { diff --git a/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h b/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h new file mode 100644 index 0000000000..e3fe33c1bd --- /dev/null +++ b/test/Modules/Inputs/protocol-redefinition/Base.framework/Headers/Base.h @@ -0,0 +1,3 @@ +@protocol Foo +- (void)someMethodOnFoo; +@end diff --git a/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap b/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap new file mode 100644 index 0000000000..0366bb4f03 --- /dev/null +++ b/test/Modules/Inputs/protocol-redefinition/Base.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module Base { + header "Base.h" + export * +} \ No newline at end of file diff --git a/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h new file mode 100644 index 0000000000..93384c294f --- /dev/null +++ b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Headers/Kit.h @@ -0,0 +1,6 @@ +#import + +// REDECLARATION +@protocol Foo +- (void)someMethodOnFoo; +@end diff --git a/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap new file mode 100644 index 0000000000..2b790f4496 --- /dev/null +++ b/test/Modules/Inputs/protocol-redefinition/Kit.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module Kit { + header "Kit.h" + export * +} \ No newline at end of file diff --git a/test/Modules/protocol-redefinition.m b/test/Modules/protocol-redefinition.m new file mode 100644 index 0000000000..85a957bbfd --- /dev/null +++ b/test/Modules/protocol-redefinition.m @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/protocol-redefinition -fsyntax-only %s -Wno-private-module -verify + +// expected-no-diagnostics + +@import Kit; -- GitLab From 4fed1565d7c760e5bbe0403cedde016ff2b6fff5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 30 Jun 2018 01:32:14 +0000 Subject: [PATCH 0379/1023] [X86] Remove masking from the avx512 rotate builtins. Use a select builtin instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336036 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 48 ++-- lib/Headers/avx512fintrin.h | 147 +++++------- lib/Headers/avx512vlintrin.h | 336 +++++++++++----------------- lib/Sema/SemaChecking.cpp | 24 +- test/CodeGen/avx512f-builtins.c | 64 ++++-- test/CodeGen/avx512vl-builtins.c | 128 +++++++---- 6 files changed, 345 insertions(+), 402 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 55be7321ae..726346dc82 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1352,30 +1352,30 @@ TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "nc", "avx5 TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "nc", "avx512dq") TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "nc", "avx512dq") TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_prold512_mask, "V16iV16iIiV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolq512_mask, "V8LLiV8LLiIiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prold128_mask, "V4iV4iIiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prold256_mask, "V8iV8iIiV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq128_mask, "V2LLiV2LLiIiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq256_mask, "V4LLiV4LLiIiV4LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd512_mask, "V16iV16iV16iV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prord512_mask, "V16iV16iIiV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorq512_mask, "V8LLiV8LLiIiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord128_mask, "V4iV4iIiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord256_mask, "V8iV8iIiV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq128_mask, "V2LLiV2LLiIiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq256_mask, "V4LLiV4LLiIiV4LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd512_mask, "V16iV16iV16iV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prold512, "V16iV16iIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolq512, "V8LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prold128, "V4iV4iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prold256, "V8iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq128, "V2LLiV2LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq256, "V4LLiV4LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd512, "V16iV16iV16i", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prord512, "V16iV16iIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorq512, "V8LLiV8LLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvd128, "V4iV4iV4i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd256, "V8iV8iV8i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord128, "V4iV4iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord256, "V8iV8iIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq128, "V2LLiV2LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq256, "V4LLiV4LLiIi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd512, "V16iV16iV16i", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvd128, "V4iV4iV4i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd256, "V8iV8iV8i", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "nc ", "avx512bw") TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "nc ", "avx512bw") TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "nc", "avx512bw") diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index bfb645415e..b20d48cf15 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -4938,59 +4938,45 @@ _mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_rorv_epi32 (__m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) - _mm512_setzero_si512 (), - (__mmask16) -1); + return (__m512i)__builtin_ia32_prorvd512((__v16si)__A, (__v16si)__B); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_rorv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) __W, - (__mmask16) __U); + return (__m512i)__builtin_ia32_selectd_512(__U, + (__v16si)_mm512_rorv_epi32(__A, __B), + (__v16si)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_rorv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) - _mm512_setzero_si512 (), - (__mmask16) __U); + return (__m512i)__builtin_ia32_selectd_512(__U, + (__v16si)_mm512_rorv_epi32(__A, __B), + (__v16si)_mm512_setzero_si512()); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_rorv_epi64 (__m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) - _mm512_setzero_si512 (), - (__mmask8) -1); + return (__m512i)__builtin_ia32_prorvq512((__v8di)__A, (__v8di)__B); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_rorv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) __W, - (__mmask8) __U); + return (__m512i)__builtin_ia32_selectq_512(__U, + (__v8di)_mm512_rorv_epi64(__A, __B), + (__v8di)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prorvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) - _mm512_setzero_si512 (), - (__mmask8) __U); + return (__m512i)__builtin_ia32_selectq_512(__U, + (__v8di)_mm512_rorv_epi64(__A, __B), + (__v8di)_mm512_setzero_si512()); } @@ -5036,119 +5022,100 @@ _mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) (__mmask8)(m)) #define _mm512_rol_epi32(a, b) \ - (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)-1) + (__m512i)__builtin_ia32_prold512((__v16si)(__m512i)(a), (int)(b)) #define _mm512_mask_rol_epi32(W, U, a, b) \ - (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \ - (__v16si)(__m512i)(W), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_rol_epi32((a), (b)), \ + (__v16si)(__m512i)(W)) #define _mm512_maskz_rol_epi32(U, a, b) \ - (__m512i)__builtin_ia32_prold512_mask((__v16si)(__m512i)(a), (int)(b), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_rol_epi32((a), (b)), \ + (__v16si)_mm512_setzero_si512()) #define _mm512_rol_epi64(a, b) \ - (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)-1) + (__m512i)__builtin_ia32_prolq512((__v8di)(__m512i)(a), (int)(b)) #define _mm512_mask_rol_epi64(W, U, a, b) \ - (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \ - (__v8di)(__m512i)(W), (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_rol_epi64((a), (b)), \ + (__v8di)(__m512i)(W)) #define _mm512_maskz_rol_epi64(U, a, b) \ - (__m512i)__builtin_ia32_prolq512_mask((__v8di)(__m512i)(a), (int)(b), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_rol_epi64((a), (b)), \ + (__v8di)_mm512_setzero_si512()) + static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_rolv_epi32 (__m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) - _mm512_setzero_si512 (), - (__mmask16) -1); + return (__m512i)__builtin_ia32_prolvd512((__v16si)__A, (__v16si)__B); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_rolv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) __W, - (__mmask16) __U); + return (__m512i)__builtin_ia32_selectd_512(__U, + (__v16si)_mm512_rolv_epi32(__A, __B), + (__v16si)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_rolv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvd512_mask ((__v16si) __A, - (__v16si) __B, - (__v16si) - _mm512_setzero_si512 (), - (__mmask16) __U); + return (__m512i)__builtin_ia32_selectd_512(__U, + (__v16si)_mm512_rolv_epi32(__A, __B), + (__v16si)_mm512_setzero_si512()); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_rolv_epi64 (__m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) - _mm512_setzero_si512 (), - (__mmask8) -1); + return (__m512i)__builtin_ia32_prolvq512((__v8di)__A, (__v8di)__B); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_rolv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) __W, - (__mmask8) __U); + return (__m512i)__builtin_ia32_selectq_512(__U, + (__v8di)_mm512_rolv_epi64(__A, __B), + (__v8di)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) { - return (__m512i) __builtin_ia32_prolvq512_mask ((__v8di) __A, - (__v8di) __B, - (__v8di) - _mm512_setzero_si512 (), - (__mmask8) __U); + return (__m512i)__builtin_ia32_selectq_512(__U, + (__v8di)_mm512_rolv_epi64(__A, __B), + (__v8di)_mm512_setzero_si512()); } #define _mm512_ror_epi32(A, B) \ - (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)-1) + (__m512i)__builtin_ia32_prord512((__v16si)(__m512i)(A), (int)(B)) #define _mm512_mask_ror_epi32(W, U, A, B) \ - (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \ - (__v16si)(__m512i)(W), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_ror_epi32((A), (B)), \ + (__v16si)(__m512i)(W)) #define _mm512_maskz_ror_epi32(U, A, B) \ - (__m512i)__builtin_ia32_prord512_mask((__v16si)(__m512i)(A), (int)(B), \ - (__v16si)_mm512_setzero_si512(), \ - (__mmask16)(U)) + (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \ + (__v16si)_mm512_ror_epi32((A), (B)), \ + (__v16si)_mm512_setzero_si512()) #define _mm512_ror_epi64(A, B) \ - (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)-1) + (__m512i)__builtin_ia32_prorq512((__v8di)(__m512i)(A), (int)(B)) #define _mm512_mask_ror_epi64(W, U, A, B) \ - (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \ - (__v8di)(__m512i)(W), (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_ror_epi64((A), (B)), \ + (__v8di)(__m512i)(W)) #define _mm512_maskz_ror_epi64(U, A, B) \ - (__m512i)__builtin_ia32_prorq512_mask((__v8di)(__m512i)(A), (int)(B), \ - (__v8di)_mm512_setzero_si512(), \ - (__mmask8)(U)) + (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \ + (__v8di)_mm512_ror_epi64((A), (B)), \ + (__v8di)_mm512_setzero_si512()) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_slli_epi32(__m512i __A, int __B) diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index fea88e27c8..0638982ca7 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -4212,236 +4212,196 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { #define _mm_rol_epi32(a, b) \ - (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)-1) + (__m128i)__builtin_ia32_prold128((__v4si)(__m128i)(a), (int)(b)) #define _mm_mask_rol_epi32(w, u, a, b) \ - (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \ - (__v4si)(__m128i)(w), (__mmask8)(u)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \ + (__v4si)_mm_rol_epi32((a), (b)), \ + (__v4si)(__m128i)(w)) #define _mm_maskz_rol_epi32(u, a, b) \ - (__m128i)__builtin_ia32_prold128_mask((__v4si)(__m128i)(a), (int)(b), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)(u)) + (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \ + (__v4si)_mm_rol_epi32((a), (b)), \ + (__v4si)_mm_setzero_si128()) #define _mm256_rol_epi32(a, b) \ - (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)-1) + (__m256i)__builtin_ia32_prold256((__v8si)(__m256i)(a), (int)(b)) #define _mm256_mask_rol_epi32(w, u, a, b) \ - (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \ - (__v8si)(__m256i)(w), (__mmask8)(u)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \ + (__v8si)_mm256_rol_epi32((a), (b)), \ + (__v8si)(__m256i)(w)) #define _mm256_maskz_rol_epi32(u, a, b) \ - (__m256i)__builtin_ia32_prold256_mask((__v8si)(__m256i)(a), (int)(b), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)(u)) + (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \ + (__v8si)_mm256_rol_epi32((a), (b)), \ + (__v8si)_mm256_setzero_si256()) #define _mm_rol_epi64(a, b) \ - (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)-1) + (__m128i)__builtin_ia32_prolq128((__v2di)(__m128i)(a), (int)(b)) #define _mm_mask_rol_epi64(w, u, a, b) \ - (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \ - (__v2di)(__m128i)(w), (__mmask8)(u)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \ + (__v2di)_mm_rol_epi64((a), (b)), \ + (__v2di)(__m128i)(w)) #define _mm_maskz_rol_epi64(u, a, b) \ - (__m128i)__builtin_ia32_prolq128_mask((__v2di)(__m128i)(a), (int)(b), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)(u)) + (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \ + (__v2di)_mm_rol_epi64((a), (b)), \ + (__v2di)_mm_setzero_si128()) #define _mm256_rol_epi64(a, b) \ - (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)-1) + (__m256i)__builtin_ia32_prolq256((__v4di)(__m256i)(a), (int)(b)) #define _mm256_mask_rol_epi64(w, u, a, b) \ - (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \ - (__v4di)(__m256i)(w), (__mmask8)(u)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \ + (__v4di)_mm256_rol_epi64((a), (b)), \ + (__v4di)(__m256i)(w)) #define _mm256_maskz_rol_epi64(u, a, b) \ - (__m256i)__builtin_ia32_prolq256_mask((__v4di)(__m256i)(a), (int)(b), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)(u)) + (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \ + (__v4di)_mm256_rol_epi64((a), (b)), \ + (__v4di)_mm256_setzero_si256()) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_rolv_epi32 (__m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) - _mm_setzero_si128 (), - (__mmask8) -1); + return (__m128i)__builtin_ia32_prolvd128((__v4si)__A, (__v4si)__B); } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, - __m128i __B) +_mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) __W, - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectd_128(__U, + (__v4si)_mm_rolv_epi32(__A, __B), + (__v4si)__W); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_maskz_rolv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) - _mm_setzero_si128 (), - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectd_128(__U, + (__v4si)_mm_rolv_epi32(__A, __B), + (__v4si)_mm_setzero_si128()); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_rolv_epi32 (__m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) - _mm256_setzero_si256 (), - (__mmask8) -1); + return (__m256i)__builtin_ia32_prolvd256((__v8si)__A, (__v8si)__B); } static __inline__ __m256i __DEFAULT_FN_ATTRS -_mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, - __m256i __B) +_mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) __W, - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectd_256(__U, + (__v8si)_mm256_rolv_epi32(__A, __B), + (__v8si)__W); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskz_rolv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) - _mm256_setzero_si256 (), - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectd_256(__U, + (__v8si)_mm256_rolv_epi32(__A, __B), + (__v8si)_mm256_setzero_si256()); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_rolv_epi64 (__m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) - _mm_setzero_si128 (), - (__mmask8) -1); + return (__m128i)__builtin_ia32_prolvq128((__v2di)__A, (__v2di)__B); } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, - __m128i __B) +_mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) __W, - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectq_128(__U, + (__v2di)_mm_rolv_epi64(__A, __B), + (__v2di)__W); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_maskz_rolv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prolvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) - _mm_setzero_si128 (), - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectq_128(__U, + (__v2di)_mm_rolv_epi64(__A, __B), + (__v2di)_mm_setzero_si128()); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_rolv_epi64 (__m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) - _mm256_setzero_si256 (), - (__mmask8) -1); + return (__m256i)__builtin_ia32_prolvq256((__v4di)__A, (__v4di)__B); } static __inline__ __m256i __DEFAULT_FN_ATTRS -_mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, - __m256i __B) +_mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) __W, - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectq_256(__U, + (__v4di)_mm256_rolv_epi64(__A, __B), + (__v4di)__W); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prolvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) - _mm256_setzero_si256 (), - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectq_256(__U, + (__v4di)_mm256_rolv_epi64(__A, __B), + (__v4di)_mm256_setzero_si256()); } -#define _mm_ror_epi32(A, B) \ - (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)-1) +#define _mm_ror_epi32(a, b) \ + (__m128i)__builtin_ia32_prord128((__v4si)(__m128i)(a), (int)(b)) -#define _mm_mask_ror_epi32(W, U, A, B) \ - (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \ - (__v4si)(__m128i)(W), (__mmask8)(U)) +#define _mm_mask_ror_epi32(w, u, a, b) \ + (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \ + (__v4si)_mm_ror_epi32((a), (b)), \ + (__v4si)(__m128i)(w)) -#define _mm_maskz_ror_epi32(U, A, B) \ - (__m128i)__builtin_ia32_prord128_mask((__v4si)(__m128i)(A), (int)(B), \ - (__v4si)_mm_setzero_si128(), \ - (__mmask8)(U)) +#define _mm_maskz_ror_epi32(u, a, b) \ + (__m128i)__builtin_ia32_selectd_128((__mmask8)(u), \ + (__v4si)_mm_ror_epi32((a), (b)), \ + (__v4si)_mm_setzero_si128()) -#define _mm256_ror_epi32(A, B) \ - (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)-1) +#define _mm256_ror_epi32(a, b) \ + (__m256i)__builtin_ia32_prord256((__v8si)(__m256i)(a), (int)(b)) -#define _mm256_mask_ror_epi32(W, U, A, B) \ - (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \ - (__v8si)(__m256i)(W), (__mmask8)(U)) +#define _mm256_mask_ror_epi32(w, u, a, b) \ + (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \ + (__v8si)_mm256_ror_epi32((a), (b)), \ + (__v8si)(__m256i)(w)) -#define _mm256_maskz_ror_epi32(U, A, B) \ - (__m256i)__builtin_ia32_prord256_mask((__v8si)(__m256i)(A), (int)(B), \ - (__v8si)_mm256_setzero_si256(), \ - (__mmask8)(U)) +#define _mm256_maskz_ror_epi32(u, a, b) \ + (__m256i)__builtin_ia32_selectd_256((__mmask8)(u), \ + (__v8si)_mm256_ror_epi32((a), (b)), \ + (__v8si)_mm256_setzero_si256()) -#define _mm_ror_epi64(A, B) \ - (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)-1) +#define _mm_ror_epi64(a, b) \ + (__m128i)__builtin_ia32_prorq128((__v2di)(__m128i)(a), (int)(b)) -#define _mm_mask_ror_epi64(W, U, A, B) \ - (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \ - (__v2di)(__m128i)(W), (__mmask8)(U)) +#define _mm_mask_ror_epi64(w, u, a, b) \ + (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \ + (__v2di)_mm_ror_epi64((a), (b)), \ + (__v2di)(__m128i)(w)) -#define _mm_maskz_ror_epi64(U, A, B) \ - (__m128i)__builtin_ia32_prorq128_mask((__v2di)(__m128i)(A), (int)(B), \ - (__v2di)_mm_setzero_si128(), \ - (__mmask8)(U)) +#define _mm_maskz_ror_epi64(u, a, b) \ + (__m128i)__builtin_ia32_selectq_128((__mmask8)(u), \ + (__v2di)_mm_ror_epi64((a), (b)), \ + (__v2di)_mm_setzero_si128()) -#define _mm256_ror_epi64(A, B) \ - (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)-1) +#define _mm256_ror_epi64(a, b) \ + (__m256i)__builtin_ia32_prorq256((__v4di)(__m256i)(a), (int)(b)) -#define _mm256_mask_ror_epi64(W, U, A, B) \ - (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \ - (__v4di)(__m256i)(W), (__mmask8)(U)) +#define _mm256_mask_ror_epi64(w, u, a, b) \ + (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \ + (__v4di)_mm256_ror_epi64((a), (b)), \ + (__v4di)(__m256i)(w)) -#define _mm256_maskz_ror_epi64(U, A, B) \ - (__m256i)__builtin_ia32_prorq256_mask((__v4di)(__m256i)(A), (int)(B), \ - (__v4di)_mm256_setzero_si256(), \ - (__mmask8)(U)) +#define _mm256_maskz_ror_epi64(u, a, b) \ + (__m256i)__builtin_ia32_selectq_256((__mmask8)(u), \ + (__v4di)_mm256_ror_epi64((a), (b)), \ + (__v4di)_mm256_setzero_si256()) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) @@ -4574,121 +4534,89 @@ _mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_rorv_epi32 (__m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) - _mm_setzero_si128 (), - (__mmask8) -1); + return (__m128i)__builtin_ia32_prorvd128((__v4si)__A, (__v4si)__B); } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, - __m128i __B) +_mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) __W, - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectd_128(__U, + (__v4si)_mm_rorv_epi32(__A, __B), + (__v4si)__W); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_maskz_rorv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvd128_mask ((__v4si) __A, - (__v4si) __B, - (__v4si) - _mm_setzero_si128 (), - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectd_128(__U, + (__v4si)_mm_rorv_epi32(__A, __B), + (__v4si)_mm_setzero_si128()); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_rorv_epi32 (__m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) - _mm256_setzero_si256 (), - (__mmask8) -1); + return (__m256i)__builtin_ia32_prorvd256((__v8si)__A, (__v8si)__B); } static __inline__ __m256i __DEFAULT_FN_ATTRS -_mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, - __m256i __B) +_mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) __W, - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectd_256(__U, + (__v8si)_mm256_rorv_epi32(__A, __B), + (__v8si)__W); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskz_rorv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvd256_mask ((__v8si) __A, - (__v8si) __B, - (__v8si) - _mm256_setzero_si256 (), - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectd_256(__U, + (__v8si)_mm256_rorv_epi32(__A, __B), + (__v8si)_mm256_setzero_si256()); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_rorv_epi64 (__m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) - _mm_setzero_si128 (), - (__mmask8) -1); + return (__m128i)__builtin_ia32_prorvq128((__v2di)__A, (__v2di)__B); } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, - __m128i __B) +_mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) __W, - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectq_128(__U, + (__v2di)_mm_rorv_epi64(__A, __B), + (__v2di)__W); } static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_maskz_rorv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { - return (__m128i) __builtin_ia32_prorvq128_mask ((__v2di) __A, - (__v2di) __B, - (__v2di) - _mm_setzero_si128 (), - (__mmask8) __U); + return (__m128i)__builtin_ia32_selectq_128(__U, + (__v2di)_mm_rorv_epi64(__A, __B), + (__v2di)_mm_setzero_si128()); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_rorv_epi64 (__m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) - _mm256_setzero_si256 (), - (__mmask8) -1); + return (__m256i)__builtin_ia32_prorvq256((__v4di)__A, (__v4di)__B); } static __inline__ __m256i __DEFAULT_FN_ATTRS -_mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, - __m256i __B) +_mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) __W, - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectq_256(__U, + (__v4di)_mm256_rorv_epi64(__A, __B), + (__v4di)__W); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) { - return (__m256i) __builtin_ia32_prorvq256_mask ((__v4di) __A, - (__v4di) __B, - (__v4di) - _mm256_setzero_si256 (), - (__mmask8) __U); + return (__m256i)__builtin_ia32_selectq_256(__U, + (__v4di)_mm256_rorv_epi64(__A, __B), + (__v4di)_mm256_setzero_si256()); } static __inline__ __m128i __DEFAULT_FN_ATTRS diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 22483f8242..19acb32113 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2814,18 +2814,18 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_reduceps128_mask: case X86::BI__builtin_ia32_reduceps256_mask: case X86::BI__builtin_ia32_reduceps512_mask: - case X86::BI__builtin_ia32_prold512_mask: - case X86::BI__builtin_ia32_prolq512_mask: - case X86::BI__builtin_ia32_prold128_mask: - case X86::BI__builtin_ia32_prold256_mask: - case X86::BI__builtin_ia32_prolq128_mask: - case X86::BI__builtin_ia32_prolq256_mask: - case X86::BI__builtin_ia32_prord512_mask: - case X86::BI__builtin_ia32_prorq512_mask: - case X86::BI__builtin_ia32_prord128_mask: - case X86::BI__builtin_ia32_prord256_mask: - case X86::BI__builtin_ia32_prorq128_mask: - case X86::BI__builtin_ia32_prorq256_mask: + case X86::BI__builtin_ia32_prold512: + case X86::BI__builtin_ia32_prolq512: + case X86::BI__builtin_ia32_prold128: + case X86::BI__builtin_ia32_prold256: + case X86::BI__builtin_ia32_prolq128: + case X86::BI__builtin_ia32_prolq256: + case X86::BI__builtin_ia32_prord512: + case X86::BI__builtin_ia32_prorq512: + case X86::BI__builtin_ia32_prord128: + case X86::BI__builtin_ia32_prord256: + case X86::BI__builtin_ia32_prorq128: + case X86::BI__builtin_ia32_prorq256: case X86::BI__builtin_ia32_fpclasspd128_mask: case X86::BI__builtin_ia32_fpclasspd256_mask: case X86::BI__builtin_ia32_fpclassps128_mask: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index cec77dc50c..e6d7f1c99a 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -3217,146 +3217,162 @@ __m512i test_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) { __m512i test_mm512_rol_epi32(__m512i __A) { // CHECK-LABEL: @test_mm512_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.512 + // CHECK: @llvm.x86.avx512.prol.d.512 return _mm512_rol_epi32(__A, 5); } __m512i test_mm512_mask_rol_epi32(__m512i __W, __mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.512 + // CHECK: @llvm.x86.avx512.prol.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_rol_epi32(__W, __U, __A, 5); } __m512i test_mm512_maskz_rol_epi32(__mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.512 + // CHECK: @llvm.x86.avx512.prol.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_rol_epi32(__U, __A, 5); } __m512i test_mm512_rol_epi64(__m512i __A) { // CHECK-LABEL: @test_mm512_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.512 + // CHECK: @llvm.x86.avx512.prol.q.512 return _mm512_rol_epi64(__A, 5); } __m512i test_mm512_mask_rol_epi64(__m512i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.512 + // CHECK: @llvm.x86.avx512.prol.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_rol_epi64(__W, __U, __A, 5); } __m512i test_mm512_maskz_rol_epi64(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.512 + // CHECK: @llvm.x86.avx512.prol.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_rol_epi64(__U, __A, 5); } __m512i test_mm512_rolv_epi32(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.512 + // CHECK: @llvm.x86.avx512.prolv.d.512 return _mm512_rolv_epi32(__A, __B); } __m512i test_mm512_mask_rolv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.512 + // CHECK: @llvm.x86.avx512.prolv.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_rolv_epi32(__W, __U, __A, __B); } __m512i test_mm512_maskz_rolv_epi32(__mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.512 + // CHECK: @llvm.x86.avx512.prolv.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_rolv_epi32(__U, __A, __B); } __m512i test_mm512_rolv_epi64(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.512 + // CHECK: @llvm.x86.avx512.prolv.q.512 return _mm512_rolv_epi64(__A, __B); } __m512i test_mm512_mask_rolv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.512 + // CHECK: @llvm.x86.avx512.prolv.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_rolv_epi64(__W, __U, __A, __B); } __m512i test_mm512_maskz_rolv_epi64(__mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.512 + // CHECK: @llvm.x86.avx512.prolv.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_rolv_epi64(__U, __A, __B); } __m512i test_mm512_ror_epi32(__m512i __A) { // CHECK-LABEL: @test_mm512_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.512 + // CHECK: @llvm.x86.avx512.pror.d.512 return _mm512_ror_epi32(__A, 5); } __m512i test_mm512_mask_ror_epi32(__m512i __W, __mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.512 + // CHECK: @llvm.x86.avx512.pror.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_ror_epi32(__W, __U, __A, 5); } __m512i test_mm512_maskz_ror_epi32(__mmask16 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.512 + // CHECK: @llvm.x86.avx512.pror.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_ror_epi32(__U, __A, 5); } __m512i test_mm512_ror_epi64(__m512i __A) { // CHECK-LABEL: @test_mm512_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.512 + // CHECK: @llvm.x86.avx512.pror.q.512 return _mm512_ror_epi64(__A, 5); } __m512i test_mm512_mask_ror_epi64(__m512i __W, __mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_mask_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.512 + // CHECK: @llvm.x86.avx512.pror.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_ror_epi64(__W, __U, __A, 5); } __m512i test_mm512_maskz_ror_epi64(__mmask8 __U, __m512i __A) { // CHECK-LABEL: @test_mm512_maskz_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.512 + // CHECK: @llvm.x86.avx512.pror.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_ror_epi64(__U, __A, 5); } __m512i test_mm512_rorv_epi32(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.512 + // CHECK: @llvm.x86.avx512.prorv.d.512 return _mm512_rorv_epi32(__A, __B); } __m512i test_mm512_mask_rorv_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.512 + // CHECK: @llvm.x86.avx512.prorv.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_mask_rorv_epi32(__W, __U, __A, __B); } __m512i test_mm512_maskz_rorv_epi32(__mmask16 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.512 + // CHECK: @llvm.x86.avx512.prorv.d.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} return _mm512_maskz_rorv_epi32(__U, __A, __B); } __m512i test_mm512_rorv_epi64(__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.512 + // CHECK: @llvm.x86.avx512.prorv.q.512 return _mm512_rorv_epi64(__A, __B); } __m512i test_mm512_mask_rorv_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mask_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.512 + // CHECK: @llvm.x86.avx512.prorv.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_mask_rorv_epi64(__W, __U, __A, __B); } __m512i test_mm512_maskz_rorv_epi64(__mmask8 __U, __m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_maskz_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.512 + // CHECK: @llvm.x86.avx512.prorv.q.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} return _mm512_maskz_rorv_epi64(__U, __A, __B); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 3e68d7091f..efaa524b9b 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -4182,290 +4182,322 @@ __m256i test_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) { __m128i test_mm_rol_epi32(__m128i __A) { // CHECK-LABEL: @test_mm_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.128 + // CHECK: @llvm.x86.avx512.prol.d.128 return _mm_rol_epi32(__A, 5); } __m128i test_mm_mask_rol_epi32(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.128 + // CHECK: @llvm.x86.avx512.prol.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_rol_epi32(__W, __U, __A, 5); } __m128i test_mm_maskz_rol_epi32(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.128 + // CHECK: @llvm.x86.avx512.prol.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_rol_epi32(__U, __A, 5); } __m256i test_mm256_rol_epi32(__m256i __A) { // CHECK-LABEL: @test_mm256_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.256 + // CHECK: @llvm.x86.avx512.prol.d.256 return _mm256_rol_epi32(__A, 5); } __m256i test_mm256_mask_rol_epi32(__m256i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.256 + // CHECK: @llvm.x86.avx512.prol.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_rol_epi32(__W, __U, __A, 5); } __m256i test_mm256_maskz_rol_epi32(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_rol_epi32 - // CHECK: @llvm.x86.avx512.mask.prol.d.256 + // CHECK: @llvm.x86.avx512.prol.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_rol_epi32(__U, __A, 5); } __m128i test_mm_rol_epi64(__m128i __A) { // CHECK-LABEL: @test_mm_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.128 + // CHECK: @llvm.x86.avx512.prol.q.128 return _mm_rol_epi64(__A, 5); } __m128i test_mm_mask_rol_epi64(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.128 + // CHECK: @llvm.x86.avx512.prol.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_rol_epi64(__W, __U, __A, 5); } __m128i test_mm_maskz_rol_epi64(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.128 + // CHECK: @llvm.x86.avx512.prol.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_rol_epi64(__U, __A, 5); } __m256i test_mm256_rol_epi64(__m256i __A) { // CHECK-LABEL: @test_mm256_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.256 + // CHECK: @llvm.x86.avx512.prol.q.256 return _mm256_rol_epi64(__A, 5); } __m256i test_mm256_mask_rol_epi64(__m256i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.256 + // CHECK: @llvm.x86.avx512.prol.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_rol_epi64(__W, __U, __A, 5); } __m256i test_mm256_maskz_rol_epi64(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_rol_epi64 - // CHECK: @llvm.x86.avx512.mask.prol.q.256 + // CHECK: @llvm.x86.avx512.prol.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_rol_epi64(__U, __A, 5); } __m128i test_mm_rolv_epi32(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.128 + // CHECK: @llvm.x86.avx512.prolv.d.128 return _mm_rolv_epi32(__A, __B); } __m128i test_mm_mask_rolv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.128 + // CHECK: @llvm.x86.avx512.prolv.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_rolv_epi32(__W, __U, __A, __B); } __m128i test_mm_maskz_rolv_epi32(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.128 + // CHECK: @llvm.x86.avx512.prolv.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_rolv_epi32(__U, __A, __B); } __m256i test_mm256_rolv_epi32(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.256 + // CHECK: @llvm.x86.avx512.prolv.d.256 return _mm256_rolv_epi32(__A, __B); } __m256i test_mm256_mask_rolv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.256 + // CHECK: @llvm.x86.avx512.prolv.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_rolv_epi32(__W, __U, __A, __B); } __m256i test_mm256_maskz_rolv_epi32(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_rolv_epi32 - // CHECK: @llvm.x86.avx512.mask.prolv.d.256 + // CHECK: @llvm.x86.avx512.prolv.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_rolv_epi32(__U, __A, __B); } __m128i test_mm_rolv_epi64(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.128 + // CHECK: @llvm.x86.avx512.prolv.q.128 return _mm_rolv_epi64(__A, __B); } __m128i test_mm_mask_rolv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.128 + // CHECK: @llvm.x86.avx512.prolv.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_rolv_epi64(__W, __U, __A, __B); } __m128i test_mm_maskz_rolv_epi64(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.128 + // CHECK: @llvm.x86.avx512.prolv.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_rolv_epi64(__U, __A, __B); } __m256i test_mm256_rolv_epi64(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.256 + // CHECK: @llvm.x86.avx512.prolv.q.256 return _mm256_rolv_epi64(__A, __B); } __m256i test_mm256_mask_rolv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.256 + // CHECK: @llvm.x86.avx512.prolv.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_rolv_epi64(__W, __U, __A, __B); } __m256i test_mm256_maskz_rolv_epi64(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_rolv_epi64 - // CHECK: @llvm.x86.avx512.mask.prolv.q.256 + // CHECK: @llvm.x86.avx512.prolv.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_rolv_epi64(__U, __A, __B); } __m128i test_mm_ror_epi32(__m128i __A) { // CHECK-LABEL: @test_mm_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.128 + // CHECK: @llvm.x86.avx512.pror.d.128 return _mm_ror_epi32(__A, 5); } __m128i test_mm_mask_ror_epi32(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.128 + // CHECK: @llvm.x86.avx512.pror.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_ror_epi32(__W, __U, __A, 5); } __m128i test_mm_maskz_ror_epi32(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.128 + // CHECK: @llvm.x86.avx512.pror.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_ror_epi32(__U, __A, 5); } __m256i test_mm256_ror_epi32(__m256i __A) { // CHECK-LABEL: @test_mm256_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.256 + // CHECK: @llvm.x86.avx512.pror.d.256 return _mm256_ror_epi32(__A, 5); } __m256i test_mm256_mask_ror_epi32(__m256i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.256 + // CHECK: @llvm.x86.avx512.pror.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_ror_epi32(__W, __U, __A, 5); } __m256i test_mm256_maskz_ror_epi32(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_ror_epi32 - // CHECK: @llvm.x86.avx512.mask.pror.d.256 + // CHECK: @llvm.x86.avx512.pror.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_ror_epi32(__U, __A, 5); } __m128i test_mm_ror_epi64(__m128i __A) { // CHECK-LABEL: @test_mm_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.128 + // CHECK: @llvm.x86.avx512.pror.q.128 return _mm_ror_epi64(__A, 5); } __m128i test_mm_mask_ror_epi64(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.128 + // CHECK: @llvm.x86.avx512.pror.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_ror_epi64(__W, __U, __A, 5); } __m128i test_mm_maskz_ror_epi64(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.128 + // CHECK: @llvm.x86.avx512.pror.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_ror_epi64(__U, __A, 5); } __m256i test_mm256_ror_epi64(__m256i __A) { // CHECK-LABEL: @test_mm256_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.256 + // CHECK: @llvm.x86.avx512.pror.q.256 return _mm256_ror_epi64(__A, 5); } __m256i test_mm256_mask_ror_epi64(__m256i __W, __mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.256 + // CHECK: @llvm.x86.avx512.pror.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_ror_epi64(__W, __U, __A,5); } __m256i test_mm256_maskz_ror_epi64(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_ror_epi64 - // CHECK: @llvm.x86.avx512.mask.pror.q.256 + // CHECK: @llvm.x86.avx512.pror.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_ror_epi64(__U, __A, 5); } __m128i test_mm_rorv_epi32(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.128 + // CHECK: @llvm.x86.avx512.prorv.d.128 return _mm_rorv_epi32(__A, __B); } __m128i test_mm_mask_rorv_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.128 + // CHECK: @llvm.x86.avx512.prorv.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_mask_rorv_epi32(__W, __U, __A, __B); } __m128i test_mm_maskz_rorv_epi32(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.128 + // CHECK: @llvm.x86.avx512.prorv.d.128 + // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} return _mm_maskz_rorv_epi32(__U, __A, __B); } __m256i test_mm256_rorv_epi32(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.256 + // CHECK: @llvm.x86.avx512.prorv.d.256 return _mm256_rorv_epi32(__A, __B); } __m256i test_mm256_mask_rorv_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.256 + // CHECK: @llvm.x86.avx512.prorv.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_mask_rorv_epi32(__W, __U, __A, __B); } __m256i test_mm256_maskz_rorv_epi32(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_rorv_epi32 - // CHECK: @llvm.x86.avx512.mask.prorv.d.256 + // CHECK: @llvm.x86.avx512.prorv.d.256 + // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} return _mm256_maskz_rorv_epi32(__U, __A, __B); } __m128i test_mm_rorv_epi64(__m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.128 + // CHECK: @llvm.x86.avx512.prorv.q.128 return _mm_rorv_epi64(__A, __B); } __m128i test_mm_mask_rorv_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.128 + // CHECK: @llvm.x86.avx512.prorv.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_mask_rorv_epi64(__W, __U, __A, __B); } __m128i test_mm_maskz_rorv_epi64(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.128 + // CHECK: @llvm.x86.avx512.prorv.q.128 + // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}} return _mm_maskz_rorv_epi64(__U, __A, __B); } __m256i test_mm256_rorv_epi64(__m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.256 + // CHECK: @llvm.x86.avx512.prorv.q.256 return _mm256_rorv_epi64(__A, __B); } __m256i test_mm256_mask_rorv_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.256 + // CHECK: @llvm.x86.avx512.prorv.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_mask_rorv_epi64(__W, __U, __A, __B); } __m256i test_mm256_maskz_rorv_epi64(__mmask8 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_rorv_epi64 - // CHECK: @llvm.x86.avx512.mask.prorv.q.256 + // CHECK: @llvm.x86.avx512.prorv.q.256 + // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}} return _mm256_maskz_rorv_epi64(__U, __A, __B); } -- GitLab From 2d905745130852cf4fa35dddd0500763394d2b28 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Sat, 30 Jun 2018 02:55:54 +0000 Subject: [PATCH 0380/1023] Driver: Don't mix system tools with devtoolset tools on RHEL Summary: On RHEL, devtoolset provides a more up-to-date toolchain than the base install, and we want to make sure all the tools use are from the same toolchain. Reviewers: rsmith, bruno Reviewed By: bruno Subscribers: bruno, cfe-commits Differential Revision: https://reviews.llvm.org/D34848 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336037 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Linux.cpp | 9 +++++++++ test/Driver/linux-ld.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 3b99ce581f..9a477556cf 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -238,6 +238,15 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("relro"); } + if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") != + StringRef::npos) + // With devtoolset on RHEL, we want to add a bin directory that is relative + // to the detected gcc install, because if we are using devtoolset gcc then + // we want to use other tools from devtoolset (e.g. ld) instead of the + // standard system tools. + PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + + "/../bin").str()); + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c index 431bd9ef14..7c61cf7b04 100644 --- a/test/Driver/linux-ld.c +++ b/test/Driver/linux-ld.c @@ -1782,3 +1782,12 @@ // CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // CHECK-LD-GENTOO-X32: "-lc" // CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --gcc-toolchain="%S/Inputs/rhel_7_tree/opt/rh/devtoolset-7/root/usr" \ +// RUN: --sysroot=%S/Inputs/rhel_7_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD-RHEL7-DTS %s +// CHECK-LD-RHEL7-DTS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-LD-RHLE7-DTS: Selected GCC installation: [[GCC_INSTALL:[[SYSROOT]]/lib/gcc/x86_64-redhat-linux/7]] +// CHECK-LD-RHEL7-DTS-NOT: /usr/bin/ld +// CHECK-LD-RHLE7-DTS: [[GCC_INSTALL]/../../../bin/ld -- GitLab From c70199d74c5776c222abeeba360bc58d659ff6b8 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Sat, 30 Jun 2018 03:50:10 +0000 Subject: [PATCH 0381/1023] Driver: Add an explicit target to testcase from r336037 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336039 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/linux-ld.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c index 7c61cf7b04..02bb88266c 100644 --- a/test/Driver/linux-ld.c +++ b/test/Driver/linux-ld.c @@ -1784,6 +1784,7 @@ // CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux-gnu \ // RUN: --gcc-toolchain="%S/Inputs/rhel_7_tree/opt/rh/devtoolset-7/root/usr" \ // RUN: --sysroot=%S/Inputs/rhel_7_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-RHEL7-DTS %s -- GitLab From ea8ce112b30b6c9d197006eb79a374de9648d46d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 30 Jun 2018 06:05:17 +0000 Subject: [PATCH 0382/1023] [X86] Correct the width of mask arguments in intrinsic headers and tests. All of these found by grepping through IR from the builtin tests for extra trunc and zext/sext instructions that shouldn't have been there. Some of these were real bugs where we lost bits from the user input: _mm512_mask_broadcast_f32x8 _mm512_maskz_broadcast_f32x8 _mm512_mask_broadcast_i32x8 _mm512_maskz_broadcast_i32x8 _mm256_mask_cvtusepi16_storeu_epi8 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336042 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512dqintrin.h | 8 +- lib/Headers/avx512vlbwintrin.h | 6 +- lib/Headers/avx512vlintrin.h | 8 +- test/CodeGen/avx512f-builtins.c | 44 +++++----- test/CodeGen/avx512vl-builtins.c | 8 +- test/CodeGen/avx512vlbw-builtins.c | 128 ++++++++++++++--------------- 6 files changed, 100 insertions(+), 102 deletions(-) diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h index 76ce32f086..6181c15d02 100644 --- a/lib/Headers/avx512dqintrin.h +++ b/lib/Headers/avx512dqintrin.h @@ -995,7 +995,7 @@ _mm512_broadcast_f32x8(__m256 __A) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A) { - return (__m512)__builtin_ia32_selectps_512((__mmask8)__M, + return (__m512)__builtin_ia32_selectps_512((__mmask16)__M, (__v16sf)_mm512_broadcast_f32x8(__A), (__v16sf)__O); } @@ -1003,7 +1003,7 @@ _mm512_mask_broadcast_f32x8(__m512 __O, __mmask16 __M, __m256 __A) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_broadcast_f32x8(__mmask16 __M, __m256 __A) { - return (__m512)__builtin_ia32_selectps_512((__mmask8)__M, + return (__m512)__builtin_ia32_selectps_512((__mmask16)__M, (__v16sf)_mm512_broadcast_f32x8(__A), (__v16sf)_mm512_setzero_ps()); } @@ -1066,7 +1066,7 @@ _mm512_broadcast_i32x8(__m256i __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A) { - return (__m512i)__builtin_ia32_selectd_512((__mmask8)__M, + return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, (__v16si)_mm512_broadcast_i32x8(__A), (__v16si)__O); } @@ -1074,7 +1074,7 @@ _mm512_mask_broadcast_i32x8(__m512i __O, __mmask16 __M, __m256i __A) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_broadcast_i32x8(__mmask16 __M, __m256i __A) { - return (__m512i)__builtin_ia32_selectd_512((__mmask8)__M, + return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, (__v16si)_mm512_broadcast_i32x8(__A), (__v16si)_mm512_setzero_si512()); } diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h index f2dfb567dd..1c0cb49a57 100644 --- a/lib/Headers/avx512vlbwintrin.h +++ b/lib/Headers/avx512vlbwintrin.h @@ -557,7 +557,7 @@ _mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) { } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_packs_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) +_mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, (__v8hi)_mm_packs_epi32(__A, __B), @@ -621,7 +621,7 @@ _mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B) } static __inline__ __m128i __DEFAULT_FN_ATTRS -_mm_mask_packus_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) +_mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, (__v8hi)_mm_packus_epi32(__A, __B), @@ -1566,7 +1566,7 @@ _mm256_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A) } static __inline__ void __DEFAULT_FN_ATTRS -_mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) +_mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A) { __builtin_ia32_pmovuswb256mem_mask ((__v16qi*) __P, (__v16hi) __A, __M); } diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index 0638982ca7..a3bb589864 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -1849,7 +1849,7 @@ _mm_mask_cvtepi32_ps (__m128 __W, __mmask8 __U, __m128i __A) { } static __inline__ __m128 __DEFAULT_FN_ATTRS -_mm_maskz_cvtepi32_ps (__mmask16 __U, __m128i __A) { +_mm_maskz_cvtepi32_ps (__mmask8 __U, __m128i __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_cvtepi32_ps(__A), (__v4sf)_mm_setzero_ps()); @@ -1863,7 +1863,7 @@ _mm256_mask_cvtepi32_ps (__m256 __W, __mmask8 __U, __m256i __A) { } static __inline__ __m256 __DEFAULT_FN_ATTRS -_mm256_maskz_cvtepi32_ps (__mmask16 __U, __m256i __A) { +_mm256_maskz_cvtepi32_ps (__mmask8 __U, __m256i __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_cvtepi32_ps(__A), (__v8sf)_mm256_setzero_ps()); @@ -2888,14 +2888,14 @@ _mm_maskz_abs_epi32(__mmask8 __U, __m128i __A) { static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_mask_abs_epi32(__m256i __W, __mmask8 __U, __m256i __A) { - return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U, + return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_abs_epi32(__A), (__v8si)__W); } static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_maskz_abs_epi32(__mmask8 __U, __m256i __A) { - return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U, + return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_abs_epi32(__A), (__v8si)_mm256_setzero_si256()); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index e6d7f1c99a..8d6e01af2f 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1391,7 +1391,7 @@ __mmask8 test_mm512_cmpeq_pd_mask(__m512d a, __m512d b) { return _mm512_cmpeq_pd_mask(a, b); } -__mmask8 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpeq_ps_mask // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpeq_ps_mask(a, b); @@ -1404,7 +1404,7 @@ __mmask8 test_mm512_mask_cmpeq_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpeq_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpeq_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpeq_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpeq_ps_mask // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1417,7 +1417,7 @@ __mmask8 test_mm512_cmple_pd_mask(__m512d a, __m512d b) { return _mm512_cmple_pd_mask(a, b); } -__mmask8 test_mm512_cmple_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmple_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmple_ps_mask // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}} return _mm512_cmple_ps_mask(a, b); @@ -1430,7 +1430,7 @@ __mmask8 test_mm512_mask_cmple_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmple_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmple_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmple_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmple_ps_mask // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1443,7 +1443,7 @@ __mmask8 test_mm512_cmplt_pd_mask(__m512d a, __m512d b) { return _mm512_cmplt_pd_mask(a, b); } -__mmask8 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmplt_ps_mask // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}} return _mm512_cmplt_ps_mask(a, b); @@ -1456,7 +1456,7 @@ __mmask8 test_mm512_mask_cmplt_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmplt_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmplt_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmplt_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmplt_ps_mask // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1469,7 +1469,7 @@ __mmask8 test_mm512_cmpneq_pd_mask(__m512d a, __m512d b) { return _mm512_cmpneq_pd_mask(a, b); } -__mmask8 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpneq_ps_mask // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpneq_ps_mask(a, b); @@ -1482,7 +1482,7 @@ __mmask8 test_mm512_mask_cmpneq_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpneq_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpneq_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpneq_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpneq_ps_mask // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1495,7 +1495,7 @@ __mmask8 test_mm512_cmpnle_pd_mask(__m512d a, __m512d b) { return _mm512_cmpnle_pd_mask(a, b); } -__mmask8 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpnle_ps_mask // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpnle_ps_mask(a, b); @@ -1508,7 +1508,7 @@ __mmask8 test_mm512_mask_cmpnle_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpnle_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpnle_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpnle_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpnle_ps_mask // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1521,7 +1521,7 @@ __mmask8 test_mm512_cmpnlt_pd_mask(__m512d a, __m512d b) { return _mm512_cmpnlt_pd_mask(a, b); } -__mmask8 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpnlt_ps_mask // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpnlt_ps_mask(a, b); @@ -1534,7 +1534,7 @@ __mmask8 test_mm512_mask_cmpnlt_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpnlt_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpnlt_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpnlt_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpnlt_ps_mask // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1547,7 +1547,7 @@ __mmask8 test_mm512_cmpord_pd_mask(__m512d a, __m512d b) { return _mm512_cmpord_pd_mask(a, b); } -__mmask8 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpord_ps_mask // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpord_ps_mask(a, b); @@ -1560,7 +1560,7 @@ __mmask8 test_mm512_mask_cmpord_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpord_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpord_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpord_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpord_ps_mask // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -1573,7 +1573,7 @@ __mmask8 test_mm512_cmpunord_pd_mask(__m512d a, __m512d b) { return _mm512_cmpunord_pd_mask(a, b); } -__mmask8 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) { +__mmask16 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_cmpunord_ps_mask // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}} return _mm512_cmpunord_ps_mask(a, b); @@ -1586,7 +1586,7 @@ __mmask8 test_mm512_mask_cmpunord_pd_mask(__mmask8 k, __m512d a, __m512d b) { return _mm512_mask_cmpunord_pd_mask(k, a, b); } -__mmask8 test_mm512_mask_cmpunord_ps_mask(__mmask8 k, __m512 a, __m512 b) { +__mmask16 test_mm512_mask_cmpunord_ps_mask(__mmask16 k, __m512 a, __m512 b) { // CHECK-LABEL: @test_mm512_mask_cmpunord_ps_mask // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} @@ -2232,7 +2232,7 @@ __m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) { return _mm512_mul_epi32(__A,__B); } -__m512i test_mm512_maskz_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B) { +__m512i test_mm512_maskz_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B) { //CHECK-LABEL: @test_mm512_maskz_mul_epi32 //CHECK: shl <8 x i64> %{{.*}}, //CHECK: ashr <8 x i64> %{{.*}}, @@ -2243,8 +2243,7 @@ __m512i test_mm512_maskz_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B) { return _mm512_maskz_mul_epi32(__k,__A,__B); } -__m512i test_mm512_mask_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B, - __m512i __src) { +__m512i test_mm512_mask_mul_epi32 (__mmask8 __k,__m512i __A, __m512i __B, __m512i __src) { //CHECK-LABEL: @test_mm512_mask_mul_epi32 //CHECK: shl <8 x i64> %{{.*}}, //CHECK: ashr <8 x i64> %{{.*}}, @@ -2263,7 +2262,7 @@ __m512i test_mm512_mul_epu32 (__m512i __A, __m512i __B) { return _mm512_mul_epu32(__A,__B); } -__m512i test_mm512_maskz_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B) { +__m512i test_mm512_maskz_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B) { //CHECK-LABEL: @test_mm512_maskz_mul_epu32 //CHECK: and <8 x i64> %{{.*}}, //CHECK: and <8 x i64> %{{.*}}, @@ -2272,8 +2271,7 @@ __m512i test_mm512_maskz_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B) { return _mm512_maskz_mul_epu32(__k,__A,__B); } -__m512i test_mm512_mask_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B, - __m512i __src) { +__m512i test_mm512_mask_mul_epu32 (__mmask8 __k,__m512i __A, __m512i __B, __m512i __src) { //CHECK-LABEL: @test_mm512_mask_mul_epu32 //CHECK: and <8 x i64> %{{.*}}, //CHECK: and <8 x i64> %{{.*}}, @@ -3888,7 +3886,7 @@ int test_mm_cvt_roundss_i32(__m128 __A) { } #ifdef __x86_64__ -int test_mm_cvt_roundss_si64(__m128 __A) { +long long test_mm_cvt_roundss_si64(__m128 __A) { // CHECK-LABEL: @test_mm_cvt_roundss_si64 // CHECK: @llvm.x86.avx512.vcvtss2si64 return _mm_cvt_roundss_si64(__A, _MM_FROUND_CUR_DIRECTION); diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index efaa524b9b..1b153cdc68 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -2018,7 +2018,7 @@ __m128 test_mm_mask_add_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm_mask_add_ps(__W,__U,__A,__B); } -__m128 test_mm_maskz_add_ps(__mmask16 __U, __m128 __A, __m128 __B) { +__m128 test_mm_maskz_add_ps(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_maskz_add_ps // CHECK: fadd <4 x float> %{{.*}}, %{{.*}} // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -2228,7 +2228,7 @@ __m128 test_mm_mask_cvtepi32_ps(__m128 __W, __mmask8 __U, __m128i __A) { // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}} return _mm_mask_cvtepi32_ps(__W,__U,__A); } -__m128 test_mm_maskz_cvtepi32_ps(__mmask16 __U, __m128i __A) { +__m128 test_mm_maskz_cvtepi32_ps(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_cvtepi32_ps // CHECK: sitofp <4 x i32> %{{.*}} to <4 x float> // CHECK: select <4 x i1> {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}} @@ -2240,7 +2240,7 @@ __m256 test_mm256_mask_cvtepi32_ps(__m256 __W, __mmask8 __U, __m256i __A) { // CHECK: select <8 x i1> {{.*}}, <8 x float> {{.*}}, <8 x float> {{.*}} return _mm256_mask_cvtepi32_ps(__W,__U,__A); } -__m256 test_mm256_maskz_cvtepi32_ps(__mmask16 __U, __m256i __A) { +__m256 test_mm256_maskz_cvtepi32_ps(__mmask8 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_cvtepi32_ps // CHECK: sitofp <8 x i32> %{{.*}} to <8 x float> // CHECK: select <8 x i1> {{.*}}, <8 x float> {{.*}}, <8 x float> {{.*}} @@ -2605,7 +2605,7 @@ __m128 test_mm_mask_div_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm_mask_div_ps(__W,__U,__A,__B); } -__m128 test_mm_maskz_div_ps(__mmask16 __U, __m128 __A, __m128 __B) { +__m128 test_mm_maskz_div_ps(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_maskz_div_ps // CHECK: fdiv <4 x float> %{{.*}}, %{{.*}} // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c index 427037cafb..607b011794 100644 --- a/test/CodeGen/avx512vlbw-builtins.c +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -974,7 +974,7 @@ __m128i test_mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_packs_epi32(__M,__A,__B); } -__m128i test_mm_mask_packs_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_packs_epi32 // CHECK: @llvm.x86.sse2.packssdw // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -986,7 +986,7 @@ __m256i test_mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_packs_epi32(__M,__A,__B); } -__m256i test_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_packs_epi32 // CHECK: @llvm.x86.avx2.packssdw // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -998,7 +998,7 @@ __m128i test_mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_packs_epi16(__M,__A,__B); } -__m128i test_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_packs_epi16 // CHECK: @llvm.x86.sse2.packsswb // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1010,14 +1010,14 @@ __m256i test_mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_packs_epi16(__M,__A,__B); } -__m256i test_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_packs_epi16 // CHECK: @llvm.x86.avx2.packsswb // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_packs_epi16(__W,__M,__A,__B); } -__m128i test_mm_mask_packus_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_packus_epi32 // CHECK: @llvm.x86.sse41.packusdw // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1038,7 +1038,7 @@ __m256i test_mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B) { return _mm256_maskz_packus_epi32(__M,__A,__B); } -__m256i test_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_packus_epi32 // CHECK: @llvm.x86.avx2.packusdw // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1052,7 +1052,7 @@ __m128i test_mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B) { return _mm_maskz_packus_epi16(__M,__A,__B); } -__m128i test_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_packus_epi16 // CHECK: @llvm.x86.sse2.packuswb // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1066,14 +1066,14 @@ __m256i test_mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B) { return _mm256_maskz_packus_epi16(__M,__A,__B); } -__m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_packus_epi16 // CHECK: @llvm.x86.avx2.packuswb // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_mask_packus_epi16(__W,__M,__A,__B); } -__m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epi8 // CHECK: @llvm.x86.sse2.padds.b // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1085,7 +1085,7 @@ __m128i test_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_adds_epi8(__U,__A,__B); } -__m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epi8 // CHECK: @llvm.x86.avx2.padds.b // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} @@ -1097,7 +1097,7 @@ __m256i test_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_adds_epi8(__U,__A,__B); } -__m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epi16 // CHECK: @llvm.x86.sse2.padds.w // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1109,7 +1109,7 @@ __m128i test_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_adds_epi16(__U,__A,__B); } -__m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epi16 // CHECK: @llvm.x86.avx2.padds.w // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1121,7 +1121,7 @@ __m256i test_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_adds_epi16(__U,__A,__B); } -__m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epu8 // CHECK: @llvm.x86.sse2.paddus.b // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1133,7 +1133,7 @@ __m128i test_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_adds_epu8(__U,__A,__B); } -__m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epu8 // CHECK: @llvm.x86.avx2.paddus.b // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} @@ -1145,7 +1145,7 @@ __m256i test_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_adds_epu8(__U,__A,__B); } -__m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_adds_epu16 // CHECK: @llvm.x86.sse2.paddus.w // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1157,7 +1157,7 @@ __m128i test_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_adds_epu16(__U,__A,__B); } -__m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_adds_epu16 // CHECK: @llvm.x86.avx2.paddus.w // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1169,7 +1169,7 @@ __m256i test_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_adds_epu16(__U,__A,__B); } -__m128i test_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_avg_epu8 // CHECK-NOT: @llvm.x86.sse2.pavg.b // CHECK: zext <16 x i8> %{{.*}} to <16 x i16> @@ -1194,7 +1194,7 @@ __m128i test_mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_avg_epu8(__U,__A,__B); } -__m256i test_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_avg_epu8 // CHECK-NOT: @llvm.x86.avx2.pavg.b // CHECK: zext <32 x i8> %{{.*}} to <32 x i16> @@ -1219,7 +1219,7 @@ __m256i test_mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_avg_epu8(__U,__A,__B); } -__m128i test_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_avg_epu16 // CHECK-NOT: @llvm.x86.sse2.pavg.w // CHECK: zext <8 x i16> %{{.*}} to <8 x i32> @@ -1244,7 +1244,7 @@ __m128i test_mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_avg_epu16(__U,__A,__B); } -__m256i test_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_avg_epu16 // CHECK-NOT: @llvm.x86.avx2.pavg.w // CHECK: zext <16 x i16> %{{.*}} to <16 x i32> @@ -1276,7 +1276,7 @@ __m128i test_mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}} return _mm_maskz_max_epi8(__M,__A,__B); } -__m128i test_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_max_epi8 // CHECK: [[CMP:%.*]] = icmp sgt <16 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]] @@ -1290,7 +1290,7 @@ __m256i test_mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}} return _mm256_maskz_max_epi8(__M,__A,__B); } -__m256i test_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_max_epi8 // CHECK: [[CMP:%.*]] = icmp sgt <32 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]] @@ -1304,7 +1304,7 @@ __m128i test_mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}} return _mm_maskz_max_epi16(__M,__A,__B); } -__m128i test_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_max_epi16 // CHECK: [[CMP:%.*]] = icmp sgt <8 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]] @@ -1318,7 +1318,7 @@ __m256i test_mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}} return _mm256_maskz_max_epi16(__M,__A,__B); } -__m256i test_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_max_epi16 // CHECK: [[CMP:%.*]] = icmp sgt <16 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]] @@ -1332,7 +1332,7 @@ __m128i test_mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}} return _mm_maskz_max_epu8(__M,__A,__B); } -__m128i test_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_max_epu8 // CHECK: [[CMP:%.*]] = icmp ugt <16 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]] @@ -1346,7 +1346,7 @@ __m256i test_mm256_maskz_max_epu8(__mmask32 __M, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}} return _mm256_maskz_max_epu8(__M,__A,__B); } -__m256i test_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_max_epu8 // CHECK: [[CMP:%.*]] = icmp ugt <32 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]] @@ -1360,7 +1360,7 @@ __m128i test_mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}} return _mm_maskz_max_epu16(__M,__A,__B); } -__m128i test_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_max_epu16 // CHECK: [[CMP:%.*]] = icmp ugt <8 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]] @@ -1374,7 +1374,7 @@ __m256i test_mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}} return _mm256_maskz_max_epu16(__M,__A,__B); } -__m256i test_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_max_epu16 // CHECK: [[CMP:%.*]] = icmp ugt <16 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]] @@ -1388,7 +1388,7 @@ __m128i test_mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}} return _mm_maskz_min_epi8(__M,__A,__B); } -__m128i test_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_min_epi8 // CHECK: [[CMP:%.*]] = icmp slt <16 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]] @@ -1402,7 +1402,7 @@ __m256i test_mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}} return _mm256_maskz_min_epi8(__M,__A,__B); } -__m256i test_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_min_epi8 // CHECK: [[CMP:%.*]] = icmp slt <32 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]] @@ -1416,7 +1416,7 @@ __m128i test_mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}} return _mm_maskz_min_epi16(__M,__A,__B); } -__m128i test_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_min_epi16 // CHECK: [[CMP:%.*]] = icmp slt <8 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]] @@ -1430,7 +1430,7 @@ __m256i test_mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}} return _mm256_maskz_min_epi16(__M,__A,__B); } -__m256i test_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_min_epi16 // CHECK: [[CMP:%.*]] = icmp slt <16 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]] @@ -1444,7 +1444,7 @@ __m128i test_mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}} return _mm_maskz_min_epu8(__M,__A,__B); } -__m128i test_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_min_epu8 // CHECK: [[CMP:%.*]] = icmp ult <16 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i8> [[X]], <16 x i8> [[Y]] @@ -1458,7 +1458,7 @@ __m256i test_mm256_maskz_min_epu8(__mmask32 __M, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}} return _mm256_maskz_min_epu8(__M,__A,__B); } -__m256i test_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_min_epu8 // CHECK: [[CMP:%.*]] = icmp ult <32 x i8> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i8> [[X]], <32 x i8> [[Y]] @@ -1472,7 +1472,7 @@ __m128i test_mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}} return _mm_maskz_min_epu16(__M,__A,__B); } -__m128i test_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { +__m128i test_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_min_epu16 // CHECK: [[CMP:%.*]] = icmp ult <8 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i16> [[X]], <8 x i16> [[Y]] @@ -1486,14 +1486,14 @@ __m256i test_mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}} return _mm256_maskz_min_epu16(__M,__A,__B); } -__m256i test_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_min_epu16 // CHECK: [[CMP:%.*]] = icmp ult <16 x i16> [[X:%.*]], [[Y:%.*]] // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i16> [[X]], <16 x i16> [[Y]] // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}} return _mm256_mask_min_epu16(__W,__M,__A,__B); } -__m128i test_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_shuffle_epi8 // CHECK: @llvm.x86.ssse3.pshuf.b // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1505,7 +1505,7 @@ __m128i test_mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_shuffle_epi8(__U,__A,__B); } -__m256i test_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_shuffle_epi8 // CHECK: @llvm.x86.avx2.pshuf.b // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} @@ -1517,7 +1517,7 @@ __m256i test_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_shuffle_epi8(__U,__A,__B); } -__m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epi8 // CHECK: @llvm.x86.sse2.psubs.b // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1529,7 +1529,7 @@ __m128i test_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_subs_epi8(__U,__A,__B); } -__m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epi8 // CHECK: @llvm.x86.avx2.psubs.b // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} @@ -1541,7 +1541,7 @@ __m256i test_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_subs_epi8(__U,__A,__B); } -__m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epi16 // CHECK: @llvm.x86.sse2.psubs.w // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1553,7 +1553,7 @@ __m128i test_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_subs_epi16(__U,__A,__B); } -__m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epi16 // CHECK: @llvm.x86.avx2.psubs.w // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1565,7 +1565,7 @@ __m256i test_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_subs_epi16(__U,__A,__B); } -__m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epu8 // CHECK: @llvm.x86.sse2.psubus.b // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} @@ -1577,7 +1577,7 @@ __m128i test_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) { // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}} return _mm_maskz_subs_epu8(__U,__A,__B); } -__m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epu8 // CHECK: @llvm.x86.avx2.psubus.b // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} @@ -1589,7 +1589,7 @@ __m256i test_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) { // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}} return _mm256_maskz_subs_epu8(__U,__A,__B); } -__m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { +__m128i test_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { // CHECK-LABEL: @test_mm_mask_subs_epu16 // CHECK: @llvm.x86.sse2.psubus.w // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1601,7 +1601,7 @@ __m128i test_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) { // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_subs_epu16(__U,__A,__B); } -__m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { +__m256i test_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_subs_epu16 // CHECK: @llvm.x86.avx2.psubus.w // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1615,13 +1615,13 @@ __m256i test_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) { } -__m128i test_mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) { +__m128i test_mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) { // CHECK-LABEL: @test_mm_mask2_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.128 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask2_permutex2var_epi16(__A,__I,__U,__B); } -__m256i test_mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, __m256i __B) { +__m256i test_mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, __m256i __B) { // CHECK-LABEL: @test_mm256_mask2_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.256 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -1632,13 +1632,13 @@ __m128i test_mm_permutex2var_epi16(__m128i __A, __m128i __I, __m128i __B) { // CHECK: @llvm.x86.avx512.vpermi2var.hi.128 return _mm_permutex2var_epi16(__A,__I,__B); } -__m128i test_mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) { +__m128i test_mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) { // CHECK-LABEL: @test_mm_mask_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.128 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_permutex2var_epi16(__A,__U,__I,__B); } -__m128i test_mm_maskz_permutex2var_epi16(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) { +__m128i test_mm_maskz_permutex2var_epi16(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) { // CHECK-LABEL: @test_mm_maskz_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.128 // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -1650,13 +1650,13 @@ __m256i test_mm256_permutex2var_epi16(__m256i __A, __m256i __I, __m256i __B) { // CHECK: @llvm.x86.avx512.vpermi2var.hi.256 return _mm256_permutex2var_epi16(__A,__I,__B); } -__m256i test_mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, __m256i __B) { +__m256i test_mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, __m256i __B) { // CHECK-LABEL: @test_mm256_mask_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.256 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_permutex2var_epi16(__A,__U,__I,__B); } -__m256i test_mm256_maskz_permutex2var_epi16(__mmask16 __U, __m256i __A, __m256i __I, __m256i __B) { +__m256i test_mm256_maskz_permutex2var_epi16(__mmask16 __U, __m256i __A, __m256i __I, __m256i __B) { // CHECK-LABEL: @test_mm256_maskz_permutex2var_epi16 // CHECK: @llvm.x86.avx512.vpermi2var.hi.256 // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -2024,7 +2024,7 @@ __m256i test_mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B) return _mm256_maskz_unpacklo_epi16(__U, __A, __B); } -__m128i test_mm_mask_cvtepi8_epi16(__m128i __W, __mmask32 __U, __m128i __A) { +__m128i test_mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_cvtepi8_epi16 // CHECK: sext <8 x i8> %{{.*}} to <8 x i16> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -2038,7 +2038,7 @@ __m128i test_mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A) { return _mm_maskz_cvtepi8_epi16(__U, __A); } -__m256i test_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask32 __U, __m128i __A) { +__m256i test_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A) { // CHECK-LABEL: @test_mm256_mask_cvtepi8_epi16 // CHECK: sext <16 x i8> %{{.*}} to <16 x i16> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -2052,7 +2052,7 @@ __m256i test_mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A) { return _mm256_maskz_cvtepi8_epi16(__U, __A); } -__m128i test_mm_mask_cvtepu8_epi16(__m128i __W, __mmask32 __U, __m128i __A) { +__m128i test_mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_cvtepu8_epi16 // CHECK: zext <8 x i8> %{{.*}} to <8 x i16> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} @@ -2066,7 +2066,7 @@ __m128i test_mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A) { return _mm_maskz_cvtepu8_epi16(__U, __A); } -__m256i test_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask32 __U, __m128i __A) { +__m256i test_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A) { // CHECK-LABEL: @test_mm256_mask_cvtepu8_epi16 // CHECK: zext <16 x i8> %{{.*}} to <16 x i16> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} @@ -3015,56 +3015,56 @@ __mmask16 test_mm256_movepi16_mask(__m256i __A) { return _mm256_movepi16_mask(__A); } -__m128i test_mm_mask_shufflehi_epi16(__m128i __W, __mmask32 __U, __m128i __A) { +__m128i test_mm_mask_shufflehi_epi16(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_shufflehi_epi16 // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shufflehi_epi16(__W, __U, __A, 5); } -__m128i test_mm_maskz_shufflehi_epi16(__mmask32 __U, __m128i __A) { +__m128i test_mm_maskz_shufflehi_epi16(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_shufflehi_epi16 // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shufflehi_epi16(__U, __A, 5); } -__m128i test_mm_mask_shufflelo_epi16(__m128i __W, __mmask32 __U, __m128i __A) { +__m128i test_mm_mask_shufflelo_epi16(__m128i __W, __mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_mask_shufflelo_epi16 // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_mask_shufflelo_epi16(__W, __U, __A, 5); } -__m128i test_mm_maskz_shufflelo_epi16(__mmask32 __U, __m128i __A) { +__m128i test_mm_maskz_shufflelo_epi16(__mmask8 __U, __m128i __A) { // CHECK-LABEL: @test_mm_maskz_shufflelo_epi16 // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> undef, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}} return _mm_maskz_shufflelo_epi16(__U, __A, 5); } -__m256i test_mm256_mask_shufflehi_epi16(__m256i __W, __mmask32 __U, __m256i __A) { +__m256i test_mm256_mask_shufflehi_epi16(__m256i __W, __mmask16 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_shufflehi_epi16 // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shufflehi_epi16(__W, __U, __A, 5); } -__m256i test_mm256_maskz_shufflehi_epi16(__mmask32 __U, __m256i __A) { +__m256i test_mm256_maskz_shufflehi_epi16(__mmask16 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_shufflehi_epi16 // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_maskz_shufflehi_epi16(__U, __A, 5); } -__m256i test_mm256_mask_shufflelo_epi16(__m256i __W, __mmask32 __U, __m256i __A) { +__m256i test_mm256_mask_shufflelo_epi16(__m256i __W, __mmask16 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_mask_shufflelo_epi16 // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} return _mm256_mask_shufflelo_epi16(__W, __U, __A, 5); } -__m256i test_mm256_maskz_shufflelo_epi16(__mmask32 __U, __m256i __A) { +__m256i test_mm256_maskz_shufflelo_epi16(__mmask16 __U, __m256i __A) { // CHECK-LABEL: @test_mm256_maskz_shufflelo_epi16 // CHECK: shufflevector <16 x i16> %{{.*}}, <16 x i16> undef, <16 x i32> // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}} -- GitLab From 4446de2c5a3f327eb1780dead5970ad4fa4bc5f0 Mon Sep 17 00:00:00 2001 From: Yaron Keren Date: Sat, 30 Jun 2018 11:18:44 +0000 Subject: [PATCH 0383/1023] Add expected fail triple x86_64-pc-windows-gnu to test as x86_64-w64-mingw32 is already there git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336047 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/2007-06-18-SextAttrAggregate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/2007-06-18-SextAttrAggregate.c b/test/CodeGen/2007-06-18-SextAttrAggregate.c index 23c211d3ba..e781bd5673 100644 --- a/test/CodeGen/2007-06-18-SextAttrAggregate.c +++ b/test/CodeGen/2007-06-18-SextAttrAggregate.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s -// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32 +// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32, x86_64-pc-windows-gnu // PR1513 -- GitLab From bd0a790826076840e27115582dad5d493bc57073 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 2 Jul 2018 12:31:20 +0000 Subject: [PATCH 0384/1023] [ms] Fix mangling of char16_t and char32_t to be compatible with MSVC. MSVC limits char16_t and char32_t string literal names to 32 bytes of character data, not to 32 characters. wchar_t string literal names on the other hand can get up to 64 bytes of character data. https://reviews.llvm.org/D48781 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336097 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 20 +++++++------- test/CodeGenCXX/mangle-ms-string-literals.cpp | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 6ffd7e3183..e6235cc625 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -3164,9 +3164,9 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) { - // ::= 0 # char - // ::= 1 # wchar_t - // ::= ??? # char16_t/char32_t will need a mangling too... + // ::= 0 # char, char16_t, char32_t + // # (little endian char data in mangling) + // ::= 1 # wchar_t (big endian char data in mangling) // // ::= # the length of the literal // @@ -3228,8 +3228,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // scheme. Mangler.mangleNumber(JC.getCRC()); - // : The mangled name also contains the first 32 _characters_ - // (including null-terminator bytes) of the StringLiteral. + // : The mangled name also contains the first 32 bytes + // (including null-terminator bytes) of the encoded StringLiteral. // Each character is encoded by splitting them into bytes and then encoding // the constituent bytes. auto MangleByte = [&Mangler](char Byte) { @@ -3258,17 +3258,17 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, } }; - // Enforce our 32 character max. - unsigned NumCharsToMangle = std::min(32U, SL->getLength()); - for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E; - ++I) + // Enforce our 32 bytes max, except wchar_t which gets 32 chars instead. + unsigned MaxBytesToMangle = SL->isWide() ? 64U : 32U; + unsigned NumBytesToMangle = std::min(MaxBytesToMangle, SL->getByteLength()); + for (unsigned I = 0; I != NumBytesToMangle; ++I) if (SL->isWide()) MangleByte(GetBigEndianByte(I)); else MangleByte(GetLittleEndianByte(I)); // Encode the NUL terminator if there is room. - if (NumCharsToMangle < 32) + if (NumBytesToMangle < MaxBytesToMangle) for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); ++NullTerminator) MangleByte(0); diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp index ee9994b0c9..214586d732 100644 --- a/test/CodeGenCXX/mangle-ms-string-literals.cpp +++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp @@ -719,9 +719,35 @@ const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF"; // CHECK: @"??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@" const wchar_t *UnicodeLiteral = L"\ud7ff"; // CHECK: @"??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@" + const char *U8Literal = u8"hi"; // CHECK: @"??_C@_02PCEFGMJL@hi?$AA@" +const char *LongU8Literal = u8"012345678901234567890123456789ABCDEF"; +// CHECK: @"??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@" + const char16_t *U16Literal = u"hi"; // CHECK: @"??_C@_05OMLEGLOC@h?$AAi?$AA?$AA?$AA@" +// Note this starts with o instead of 0. Else LongWideString would have +// the same initializer and CodeGenModule::ConstantStringMap would map them +// to the same global with a shared mangling. +// FIXME: ConstantStringMap probably shouldn't map things with the same data +// but different manglings to the same variable. +const char16_t *LongU16Literal = u"o12345678901234567890123456789ABCDEF"; +// CHECK: @"??_C@_0EK@FEAOBHPP@o?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA@" + const char32_t *U32Literal = U"hi"; // CHECK: @"??_C@_0M@GFNAJIPG@h?$AA?$AA?$AAi?$AA?$AA?$AA?$AA?$AA?$AA?$AA@" +const char32_t *LongU32Literal = U"012345678901234567890123456789ABCDEF"; +// CHECK: @"??_C@_0JE@IMHFEDAA@0?$AA?$AA?$AA1?$AA?$AA?$AA2?$AA?$AA?$AA3?$AA?$AA?$AA4?$AA?$AA?$AA5?$AA?$AA?$AA6?$AA?$AA?$AA7?$AA?$AA?$AA@" + +// These all have just the right length that the trailing 0 just fits. +const char *MaxASCIIString = "012345678901234567890123456789A"; +// CHECK: @"??_C@_0CA@NMANGEKF@012345678901234567890123456789A?$AA@" +const wchar_t *MaxWideString = L"012345678901234567890123456789A"; +// CHECK: @"??_C@_1EA@LJAFPILO@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AA?$AA@" +const char *MaxU8String = u8"012345678901234567890123456789A"; +// CHECK: @"??_C@_0CA@NMANGEKF@012345678901234567890123456789A?$AA@" +const char16_t *MaxU16String = u"012345678901234"; +// CHECK: @"??_C@_0CA@NFEFHIFO@0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA?$AA?$AA@" +const char32_t *MaxU32String = U"0123456"; +// CHECK: @"??_C@_0CA@KFPHPCC@0?$AA?$AA?$AA1?$AA?$AA?$AA2?$AA?$AA?$AA3?$AA?$AA?$AA4?$AA?$AA?$AA5?$AA?$AA?$AA6?$AA?$AA?$AA?$AA?$AA?$AA?$AA@" -- GitLab From 629b0132f03ea8404eb324a06b5c53660e8ae450 Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Mon, 2 Jul 2018 14:14:07 +0000 Subject: [PATCH 0385/1023] Test commit access git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336108 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 622ac9977a..b1e6e42b5a 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -274,7 +274,7 @@ public: }; // This class provides generic methods to write tests which can check internal -// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also, +// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also, // this fixture makes it possible to import from several "From" contexts. class ASTImporterTestBase : public ParameterizedTestsFixture { -- GitLab From 4084c9e30339676a7bea9cca1496101f0b191a3f Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 2 Jul 2018 17:10:40 +0000 Subject: [PATCH 0386/1023] [analyzer] [tests] Pass clang executable path to prefix-less executor scripts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336124 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/analyzer/SATestBuild.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py index 882c5ce7fc..4da025aa53 100755 --- a/utils/analyzer/SATestBuild.py +++ b/utils/analyzer/SATestBuild.py @@ -303,6 +303,7 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile): if Command == NoPrefixCmd: SBPrefix = "" ExtraEnv['OUTPUT'] = SBOutputDir + ExtraEnv['CC'] = Clang continue # If using 'make', auto imply a -jX argument -- GitLab From ddb77a4e35a61b758922bc15fb68c8ca224655e5 Mon Sep 17 00:00:00 2001 From: Piotr Padlewski Date: Mon, 2 Jul 2018 19:21:36 +0000 Subject: [PATCH 0387/1023] [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers Summary: Emmiting new intrinsic that strips invariant.groups to make devirtulization sound, as described in RFC: Devirtualization v2. Reviewers: rjmccall, rsmith, amharc, kuhar Subscribers: llvm-commits, cfe-commits Differential Revision: https://reviews.llvm.org/D47299 Co-authored-by: Krzysztof Pszeniczny git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336137 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 12 + include/clang/AST/Type.h | 7 + lib/AST/Type.cpp | 10 + lib/CodeGen/CGExpr.cpp | 12 + lib/CodeGen/CGExprScalar.cpp | 60 ++++- test/CodeGenCXX/strict-vtable-pointers.cpp | 295 +++++++++++++++++++-- 6 files changed, 376 insertions(+), 20 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index a64593c79d..1d0489912c 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -790,6 +790,18 @@ public: return data().Polymorphic || data().NumVBases != 0; } + /// @returns true if class is dynamic or might be dynamic because the + /// definition is incomplete of dependent. + bool mayBeDynamicClass() const { + return !hasDefinition() || isDynamicClass() || hasAnyDependentBases(); + } + + /// @returns true if class is non dynamic or might be non dynamic because the + /// definition is incomplete of dependent. + bool mayBeNonDynamicClass() const { + return !hasDefinition() || !isDynamicClass() || hasAnyDependentBases(); + } + void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; } bool isParsingBaseSpecifiers() const { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 5e1fc372a0..3de86041c8 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -810,6 +810,13 @@ public: /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + + /// Returns true if it is a class and it might be dynamic. + bool mayBeDynamicClass() const; + + /// Returns true if it is not a class or if the class might not be dynamic. + bool mayBeNotDynamicClass() const; + // Don't promise in the API that anything besides 'const' can be // easily added. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index eb65220bc1..ddb45868ec 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -88,6 +88,16 @@ const IdentifierInfo* QualType::getBaseTypeIdentifier() const { return nullptr; } +bool QualType::mayBeDynamicClass() const { + const auto *ClassDecl = getTypePtr()->getPointeeCXXRecordDecl(); + return ClassDecl && ClassDecl->mayBeDynamicClass(); +} + +bool QualType::mayBeNotDynamicClass() const { + const auto *ClassDecl = getTypePtr()->getPointeeCXXRecordDecl(); + return !ClassDecl || ClassDecl->mayBeNonDynamicClass(); +} + bool QualType::isConstant(QualType T, const ASTContext &Ctx) { if (T.isConstQualified()) return true; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 12b30936dc..3097caacb3 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -3870,6 +3870,18 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, } Address addr = base.getAddress(); + if (auto *ClassDef = dyn_cast(rec)) { + if (CGM.getCodeGenOpts().StrictVTablePointers && + ClassDef->isDynamicClass()) { + // Getting to any field of dynamic object requires stripping dynamic + // information provided by invariant.group. This is because accessing + // fields may leak the real address of dynamic object, which could result + // in miscompilation when leaked pointer would be compared. + auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); + addr = Address(stripped, addr.getAlignment()); + } + } + unsigned RecordCVR = base.getVRQualifiers(); if (rec->isUnion()) { // For unions, there is no pointer adjustment. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 10c59a2cb8..783f74c502 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1621,6 +1621,24 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CE->getLocStart()); } + if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { + const QualType SrcType = E->getType(); + + if (SrcType.mayBeNotDynamicClass() && DestTy.mayBeDynamicClass()) { + // Casting to pointer that could carry dynamic information (provided by + // invariant.group) requires launder. + Src = Builder.CreateLaunderInvariantGroup(Src); + } else if (SrcType.mayBeDynamicClass() && DestTy.mayBeNotDynamicClass()) { + // Casting to pointer that does not carry dynamic information (provided + // by invariant.group) requires stripping it. Note that we don't do it + // if the source could not be dynamic type and destination could be + // dynamic because dynamic information is already laundered. It is + // because launder(strip(src)) == launder(src), so there is no need to + // add extra strip before launder. + Src = Builder.CreateStripInvariantGroup(Src); + } + } + return Builder.CreateBitCast(Src, DstTy); } case CK_AddressSpaceConversion: { @@ -1757,12 +1775,31 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { llvm::Value* IntResult = Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); - return Builder.CreateIntToPtr(IntResult, DestLLVMTy); + auto *IntToPtr = Builder.CreateIntToPtr(IntResult, DestLLVMTy); + + if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { + // Going from integer to pointer that could be dynamic requires reloading + // dynamic information from invariant.group. + if (DestTy.mayBeDynamicClass()) + IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr); + } + return IntToPtr; } - case CK_PointerToIntegral: + case CK_PointerToIntegral: { assert(!DestTy->isBooleanType() && "bool should use PointerToBool"); - return Builder.CreatePtrToInt(Visit(E), ConvertType(DestTy)); + auto *PtrExpr = Visit(E); + + if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) { + const QualType SrcType = E->getType(); + // Casting to integer requires stripping dynamic information as it does + // not carries it. + if (SrcType.mayBeDynamicClass()) + PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr); + } + + return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy)); + } case CK_ToVoid: { CGF.EmitIgnoredExpr(E); return nullptr; @@ -3241,6 +3278,23 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp"); } else { // Unsigned integers and pointers. + + if (CGF.CGM.getCodeGenOpts().StrictVTablePointers && + !isa(LHS) && + !isa(RHS)) { + + // Dynamic information is required to be stripped for comparisons, + // because it could leak the dynamic information. Based on comparisons + // of pointers to dynamic objects, the optimizer can replace one pointer + // with another, which might be incorrect in presence of invariant + // groups. Comparison with null is safe because null does not carry any + // dynamic information. + if (LHSTy.mayBeDynamicClass()) + LHS = Builder.CreateStripInvariantGroup(LHS); + if (RHSTy.mayBeDynamicClass()) + RHS = Builder.CreateStripInvariantGroup(RHS); + } + Result = Builder.CreateICmp(UICmpOpc, LHS, RHS, "cmp"); } diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp index f92cd05a55..098c779895 100644 --- a/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -5,7 +5,8 @@ // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll typedef __typeof__(sizeof(0)) size_t; -void *operator new(size_t, void*) throw(); +void *operator new(size_t, void *) throw(); +using uintptr_t = unsigned long long; struct NotTrivialDtor { ~NotTrivialDtor(); @@ -17,7 +18,7 @@ struct DynamicBase1 { }; struct DynamicDerived : DynamicBase1 { - void foo(); + void foo() override; }; struct DynamicBase2 { @@ -28,8 +29,8 @@ struct DynamicBase2 { }; struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 { - virtual void foo(); - virtual void bar(); + void foo() override; + void bar() override; }; struct StaticBase { @@ -47,9 +48,8 @@ struct DynamicFromVirtualStatic1 : virtual StaticBase { struct DynamicFromVirtualStatic2 : virtual StaticBase { }; -struct DynamicFrom2Virtuals : - DynamicFromVirtualStatic1, - DynamicFromVirtualStatic2 { +struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1, + DynamicFromVirtualStatic2 { }; // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv() @@ -89,7 +89,6 @@ struct DynamicFrom2Virtuals; // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8( // CHECK-CTORS-LABEL: {{^}}} - // CHECK-NEW-LABEL: define void @_Z9Pointers1v() // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8( // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev( @@ -134,7 +133,6 @@ struct DynamicBase1; // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8( // CHECK-CTORS-LABEL: {{^}}} - struct DynamicDerived; // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev( @@ -164,14 +162,12 @@ struct DynamicDerivedMultiple; // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev( // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8 - // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)*** // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]] // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8* // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16 // CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)*** - // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]] // CHECK-CTORS-LABEL: {{^}}} @@ -182,9 +178,10 @@ struct DynamicFromStatic; struct A { virtual void foo(); + int m; }; struct B : A { - virtual void foo(); + void foo() override; }; union U { @@ -209,7 +206,7 @@ void UnionsBarriers(U *u) { // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8* // CHECK-NEW: call void @_Z2g2P1A(%struct.A* g2(&u->b); - // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* + // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* changeToA(u); // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8* // call void @_Z2g2P1A(%struct.A* %a) @@ -294,12 +291,279 @@ void UnionsBarrier3(U3 &u) { take(u.v3); } +// CHECK-NEW-LABEL: define void @_Z7comparev() +void compare() { + A *a = new A; + a->foo(); + // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8* + A *b = new (a) B; + + // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A* + // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A* + // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]] + if (a == b) + b->foo(); +} + +// CHECK-NEW-LABEL: compare2 +bool compare2(A *a, A *a2) { + // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A* + // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A* + // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]] + return a < a2; +} +// CHECK-NEW-LABEL: compareIntPointers +bool compareIntPointers(int *a, int *b) { + // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group + return a == b; +} + +struct HoldingOtherVirtuals { + B b; +}; + +// There is no need to add barriers for comparision of pointer to classes +// that are not dynamic. +// CHECK-NEW-LABEL: compare5 +bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) { + // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group + return a == b; +} +// CHECK-NEW-LABEL: compareNull +bool compareNull(A *a) { + // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group + + if (a != nullptr) + return false; + if (!a) + return false; + return a == nullptr; +} + +struct X; +// We have to also introduce the barriers if comparing pointers to incomplete +// objects +// CHECK-NEW-LABEL: define zeroext i1 @_Z8compare4P1XS0_ +bool compare4(X *x, X *x2) { + // CHECK-NEW: %[[x:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[xp:.*]] = bitcast i8* %[[x]] to %struct.X* + // CHECK-NEW: %[[x2:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* + // CHECK-NEW: %[[x2p:.*]] = bitcast i8* %[[x2]] to %struct.X* + // CHECK-NEW: %cmp = icmp eq %struct.X* %[[xp]], %[[x2p]] + return x == x2; +} + +// CHECK-NEW-LABEL: define void @_Z7member1P20HoldingOtherVirtuals( +void member1(HoldingOtherVirtuals *p) { + + // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group.p0i8( + (void)p->b; +} + +// CHECK-NEW-LABEL: member2 +void member2(A *a) { + // CHECK-NEW: call i8* @llvm.strip.invariant.group.p0i8 + (void)a->m; +} + +// Check if from comparison of addresses of member we can't infer the equality +// of ap and bp. +// CHECK-NEW-LABEL: @_Z18testCompareMembersv( +void testCompareMembers() { + // CHECK-NEW: [[AP:%.*]] = alloca %struct.A* + // CHECK-NEW: [[APM:%.*]] = alloca i32* + // CHECK-NEW: [[BP:%.*]] = alloca %struct.B* + // CHECK-NEW: [[BPM:%.*]] = alloca i32* + + A *ap = new A; + // CHECK-NEW: call void %{{.*}}(%struct.A* %{{.*}}) + ap->foo(); + // CHECK-NEW: [[TMP7:%.*]] = load %struct.A*, %struct.A** [[AP]] + // CHECK-NEW: [[TMP8:%.*]] = bitcast %struct.A* [[TMP7]] to i8* + // CHECK-NEW: [[TMP9:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP8]]) + // CHECK-NEW: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to %struct.A* + // CHECK-NEW: [[M:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP10]], i32 0, i32 1 + // CHECK-NEW: store i32* [[M]], i32** [[APM]] + int *const apm = &ap->m; + + B *bp = new (ap) B; + + // CHECK-NEW: [[TMP20:%.*]] = load %struct.B*, %struct.B** [[BP]] + // CHECK-NEW: [[TMP21:%.*]] = bitcast %struct.B* [[TMP20]] to %struct.A* + // CHECK-NEW: [[TMP22:%.*]] = bitcast %struct.A* [[TMP21]] to i8* + // CHECK-NEW: [[TMP23:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP22]]) + // CHECK-NEW: [[TMP24:%.*]] = bitcast i8* [[TMP23]] to %struct.A* + // CHECK-NEW: [[M4:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP24]], i32 0, i32 1 + // CHECK-NEW: store i32* [[M4]], i32** [[BPM]] + int *const bpm = &bp->m; + + // CHECK-NEW: [[TMP25:%.*]] = load i32*, i32** [[APM]] + // CHECK-NEW: [[TMP26:%.*]] = load i32*, i32** [[BPM]] + // CHECK-NEW-NOT: strip.invariant.group + // CHECK-NEW-NOT: launder.invariant.group + // CHECK-NEW: [[CMP:%.*]] = icmp eq i32* [[TMP25]], [[TMP26]] + if (apm == bpm) { + bp->foo(); + } +} + +// CHECK-NEW-LABEL: define void @_Z9testCast1P1A(%struct.A* +void testCast1(A *a) { + // Here we get rid of dynamic info + // CHECK-NEW: call i8* @llvm.strip.invariant.group + auto *v = (void *)a; + + // CHECK-NEW: call i8* @llvm.strip.invariant.group + auto i2 = (uintptr_t)a; + (void)i2; + + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW-NOT: @llvm.launder.invariant.group + + // The information is already stripped + auto i = (uintptr_t)v; +} + +struct Incomplete; +// CHECK-NEW-LABEL: define void @_Z9testCast2P10Incomplete(%struct.Incomplete* +void testCast2(Incomplete *I) { + // Here we get rid of potential dynamic info + // CHECK-NEW: call i8* @llvm.strip.invariant.group + auto *v = (void *)I; + + // CHECK-NEW: call i8* @llvm.strip.invariant.group + auto i2 = (uintptr_t)I; + (void)i2; + + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW-NOT: @llvm.launder.invariant.group + + // The information is already stripped + auto i = (uintptr_t)v; +} + +// CHECK-NEW-LABEL: define void @_Z9testCast3y( +void testCast3(uintptr_t i) { + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW: @llvm.launder.invariant.group + A *a3 = (A *)i; + (void)a3; + + auto *v2 = (void *)i; + + // CHECK-NEW: @llvm.launder.invariant.group + A *a2 = (A *)v2; + (void)a2; + + // CHECK-NEW-NOT: @llvm.launder.invariant.group + auto *v3 = (void *)i; + (void)v3; +} + +// CHECK-NEW-LABEL: define void @_Z9testCast4y( +void testCast4(uintptr_t i) { + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW: @llvm.launder.invariant.group + auto *a3 = (Incomplete *)i; + (void)a3; + + // CHECK-NEW: @llvm.launder.invariant.group + auto *v2 = (void *)i; + // CHECK-NEW-NOT: @llvm.launder.invariant.group + auto *a2 = (Incomplete *)v2; + (void)a2; +} + +// CHECK-NEW-LABEL: define void @_Z9testCast5P1B( +void testCast5(B *b) { + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW-NOT: @llvm.launder.invariant.group + A *a = b; + (void)a; + + auto *b2 = (B *)a; + (void)b2; +} + +// CHECK-NEW-LABEL: define void @_Z9testCast6P1A( +void testCast6(A *a) { + + // CHECK-NEW: @llvm.strip.invariant.group + auto *I = (Incomplete *)a; + (void)I; + // CHECK-NEW: @llvm.launder.invariant.group + auto *a2 = (A *)I; + (void)a2; + + // CHECK-NEW: @llvm.strip.invariant.group + auto *E = (Empty *)a; + (void)E; + + // CHECK-NEW: @llvm.launder.invariant.group + auto *a3 = (A *)E; + (void)a3; + + // CHECK-NEW-NOT: @llvm.strip.invariant.group + auto i = (uintptr_t)E; + (void)i; +} + +class Incomplete2; +// CHECK-NEW-LABEL: define void @_Z9testCast7P10Incomplete( +void testCast7(Incomplete *I) { + // CHECK-NEW-NOT: @llvm.strip.invariant.group + + // Incomplete2 could be dynamic where Incomplete may not be dynamic, thus + // launder is needed. We don't strip firstly because launder is sufficient. + + // CHECK-NEW: @llvm.launder.invariant.group + auto *I2 = (Incomplete2 *)I; + (void)I2; + // CHECK-NEW-LABEL: ret void +} + +template +struct PossiblyDerivingFromDynamicBase : Base { +}; + +// CHECK-NEW-LABEL: define void @_Z9testCast8P10Incomplete( +void testCast8(Incomplete *I) { + // CHECK-NEW-NOT: @llvm.strip.invariant.group + // CHECK-NEW: @llvm.launder.invariant.group + auto *P = (PossiblyDerivingFromDynamicBase *)I; + (void)P; + + // CHECK-NEW: @llvm.launder.invariant.group + auto *P2 = (PossiblyDerivingFromDynamicBase *)I; + (void)P2; + + // CHECK-NEW: @llvm.launder.invariant.group + auto *P3 = (PossiblyDerivingFromDynamicBase *)I; + (void)P3; + + // CHECK-NEW-NOT: @llvm.launder.invariant.group + auto *a3 = (A *)P3; + + // CHECK-NEW-LABEL: ret void +} + +// CHECK-NEW-LABEL: define void @_Z9testCast9 +void testCast9(PossiblyDerivingFromDynamicBase *P) { + // CHECK-NEW: @llvm.strip.invariant.group + auto *V = (void *)P; + + // CHECK-NEW-LABEL: ret void +} + /** DTORS **/ // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev( // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8( // CHECK-DTORS-LABEL: {{^}}} - // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev( // CHECK-DTORS-NOT: invariant.barrier // CHECK-DTORS-LABEL: {{^}}} @@ -308,7 +572,6 @@ void UnionsBarrier3(U3 &u) { // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8( // CHECK-DTORS-LABEL: {{^}}} - // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev( // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev( @@ -323,10 +586,8 @@ void UnionsBarrier3(U3 &u) { // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8( // CHECK-DTORS-LABEL: {{^}}} - // CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}} // CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1} // CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]} // CHECK-LINK-REQ: ![[META]] = !{!"StrictVTablePointers", i32 1} - -- GitLab From 2a670227465c2be203f30650676da8b51715c44f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 2 Jul 2018 23:25:22 +0000 Subject: [PATCH 0388/1023] Per C++ [over.match.copy]p1, direct-initialization of a reference can only invoke converting constructors of the reference's underlying type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336153 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 10 ++++++---- test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp | 9 +++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index b3f401e63a..6e695ff6ee 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4224,9 +4224,11 @@ static OverloadingResult TryRefInitWithConversionFunction( OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); - // Determine whether we are allowed to call explicit constructors or - // explicit conversion operators. - bool AllowExplicit = Kind.AllowExplicit(); + // Determine whether we are allowed to call explicit conversion operators. + // Note that none of [over.match.copy], [over.match.conv], nor + // [over.match.ref] permit an explicit constructor to be chosen when + // initializing a reference, not even for direct-initialization. + bool AllowExplicitCtors = false; bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding(); const RecordType *T1RecordType = nullptr; @@ -4242,7 +4244,7 @@ static OverloadingResult TryRefInitWithConversionFunction( continue; if (!Info.Constructor->isInvalidDecl() && - Info.Constructor->isConvertingConstructor(AllowExplicit)) { + Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp index e775e8f0e3..869fc4f014 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -61,3 +61,12 @@ namespace test3 { unsigned &t9 = (a->bitY += 3); // expected-error {{non-const reference cannot bind to bit-field 'bitY'}} } } + +namespace explicit_ctor { + struct A {}; + struct B { // expected-note 2{{candidate}} + explicit B(const A&); + }; + A a; + const B &b(a); // expected-error {{no viable conversion}} +} -- GitLab From aa3be4e3c06473db5996695a3ab9755aee5f9f9d Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 3 Jul 2018 04:15:49 +0000 Subject: [PATCH 0389/1023] [Driver][Darwin] Use Host Triple to infer target os version Summary: When clang required to infer target os version from --target option and the os version is not specified in targets, check the host triple. If the host and target are both macOS, use host triple to infer target os version. rdar://problem/41651999 Reviewers: arphaman, dexonsmith Reviewed By: arphaman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48849 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336168 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Darwin.cpp | 8 +++++++- test/Driver/clang-g-opts.c | 4 ++-- test/Driver/target-triple-deployment.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index d0c633b120..11f77096ae 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -1472,10 +1472,16 @@ Optional inferDeploymentTargetFromSDK(DerivedArgList &Args) { std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple, const Driver &TheDriver) { unsigned Major, Minor, Micro; + llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); switch (OS) { case llvm::Triple::Darwin: case llvm::Triple::MacOSX: - if (!Triple.getMacOSXVersion(Major, Minor, Micro)) + // If there is no version specified on triple, and both host and target are + // macos, use the host triple to infer OS version. + if (Triple.isMacOSX() && SystemTriple.isMacOSX() && + !Triple.getOSMajorVersion()) + SystemTriple.getMacOSXVersion(Major, Minor, Micro); + else if (!Triple.getMacOSXVersion(Major, Minor, Micro)) TheDriver.Diag(diag::err_drv_invalid_darwin_version) << Triple.getOSName(); break; diff --git a/test/Driver/clang-g-opts.c b/test/Driver/clang-g-opts.c index a26fb29652..bc714b6c93 100644 --- a/test/Driver/clang-g-opts.c +++ b/test/Driver/clang-g-opts.c @@ -3,7 +3,7 @@ // RUN: | FileCheck --check-prefix=CHECK-WITH-G %s // Assert that the toolchains which should default to a lower Dwarf version do so. -// RUN: %clang -### -S %s -g -target x86_64-apple-darwin 2>&1 \ +// RUN: %clang -### -S %s -g -target x86_64-apple-darwin8 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s // RUN: %clang -### -S %s -g -target i686-pc-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s @@ -21,7 +21,7 @@ // // RUN: %clang -### -S %s -g0 -g -target x86_64-linux-gnu 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WITH-G %s -// RUN: %clang -### -S %s -g0 -g -target x86_64-apple-darwin 2>&1 \ +// RUN: %clang -### -S %s -g0 -g -target x86_64-apple-darwin8 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WITH-G-STANDALONE %s // RUN: %clang -### -S %s -g0 -g -target i686-pc-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s diff --git a/test/Driver/target-triple-deployment.c b/test/Driver/target-triple-deployment.c index 4f5de59e73..b59f81a010 100644 --- a/test/Driver/target-triple-deployment.c +++ b/test/Driver/target-triple-deployment.c @@ -1,5 +1,5 @@ // RUN: touch %t.o -// RUN: %clang -target x86_64-apple-macosx -### %t.o 2> %t.log +// RUN: %clang -target x86_64-apple-macosx10.4 -### %t.o 2> %t.log // RUN: %clang -target x86_64-apple-darwin9 -### %t.o 2>> %t.log // RUN: %clang -target x86_64-apple-macosx10.7 -### %t.o 2>> %t.log // -- GitLab From cfd5890f82db858d610ec28a9fbb44e0e853c8c0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 3 Jul 2018 07:51:41 +0000 Subject: [PATCH 0390/1023] Revert r336021 "PR33924: merge local declarations that have linkage of some kind within" This caused test failures in 32-bit builds (PR38015). > merged function definitions; also merge functions with deduced return > types. > > This seems like two independent fixes, but unfortunately they are hard > to separate because it's challenging to reliably test either one of them > without also testing the other. > > A complication arises with deduced return type support: we need the type > of the function in order to know how to merge it, but we can't load the > actual type of the function because it might reference an entity > declared within the function (and we need to have already merged the > function to correctly merge that entity, which we would need to do to > determine if the function types match). So we instead compare the > declared function type when merging functions, and defer loading the > actual type of a function with a deduced type until we've finished > loading and merging the function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336175 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTReader.h | 2 +- lib/Serialization/ASTCommon.cpp | 16 +--- lib/Serialization/ASTReaderDecl.cpp | 103 ++++++------------------ test/Modules/merge-deduced-return.cpp | 33 -------- test/Modules/merge-lambdas.cpp | 48 ----------- test/Modules/merge-static-locals.cpp | 27 ------- 6 files changed, 26 insertions(+), 203 deletions(-) delete mode 100644 test/Modules/merge-deduced-return.cpp delete mode 100644 test/Modules/merge-lambdas.cpp delete mode 100644 test/Modules/merge-static-locals.cpp diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index b33f317765..bf9ed38a15 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -546,7 +546,7 @@ private: /// Mergeable declaration contexts that have anonymous declarations /// within them, and those anonymous declarations. - llvm::DenseMap> + llvm::DenseMap> AnonymousDeclarationsForMerging; struct FileDeclsInfo { diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index da482717f4..fcebe5982f 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -419,21 +419,9 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return true; } - // At block scope, we number everything that we need to deduplicate, since we - // can't just use name matching to keep things lined up. - // FIXME: This is only necessary for an inline function or a template or - // similar. - if (D->getLexicalDeclContext()->isFunctionOrMethod()) { - if (auto *VD = dyn_cast(D)) - return VD->isStaticLocal(); - // FIXME: What about CapturedDecls (and declarations nested within them)? - return isa(D) || isa(D); - } - - // Otherwise, we only care about anonymous class members / block-scope decls. - // FIXME: We need to handle lambdas and blocks within inline / templated - // variables too. + // Otherwise, we only care about anonymous class members. if (D->getDeclName() || !isa(D->getLexicalDeclContext())) return false; return isa(D) || isa(D); } + diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 8701d80653..b0c7bbec20 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -87,7 +87,7 @@ namespace clang { using RecordData = ASTReader::RecordData; - TypeID DeferredTypeID = 0; + TypeID TypeIDForTypeDecl = 0; unsigned AnonymousDeclNumber; GlobalDeclID NamedDeclForTagDecl = 0; IdentifierInfo *TypedefNameForLinkage = nullptr; @@ -177,8 +177,6 @@ namespace clang { void MergeDefinitionData(ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD); - static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC); - static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index); @@ -530,7 +528,7 @@ void ASTDeclReader::Visit(Decl *D) { if (auto *TD = dyn_cast(D)) { // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); + TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. @@ -539,11 +537,8 @@ void ASTDeclReader::Visit(Decl *D) { cast(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. - ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); + ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); } else if (auto *FD = dyn_cast(D)) { - if (DeferredTypeID) - FD->setType(Reader.GetType(DeferredTypeID)); - // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). @@ -663,7 +658,7 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(ReadSourceLocation()); // Delay type reading until after we have fully initialized the decl. - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); } ASTDeclReader::RedeclarableResult @@ -796,13 +791,7 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - // For function declarations, defer reading the type in case the function has - // a deduced return type that references an entity declared within the - // function. - if (isa(VD)) - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); - else - VD->setType(Record.readType()); + VD->setType(Record.readType()); } void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { @@ -831,19 +820,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); VisitDeclaratorDecl(FD); - // Attach a type to this function. Use the real type if possible, but fall - // back to the type as written if it involves a deduced return type. - if (FD->getTypeSourceInfo() && - FD->getTypeSourceInfo()->getType()->castAs() - ->getReturnType()->getContainedAutoType()) { - // We'll set up the real type in Visit, once we've finished loading the - // function. - FD->setType(FD->getTypeSourceInfo()->getType()); - } else { - FD->setType(Reader.GetType(DeferredTypeID)); - DeferredTypeID = 0; - } - ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); FD->IdentifierNamespace = Record.readInt(); @@ -1108,7 +1084,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); mergeRedeclarable(ID, Redecl); ID->TypeParamList = ReadObjCTypeParamList(); @@ -1914,7 +1890,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // // Beware: we do not yet know our canonical declaration, and may still // get merged once the surrounding class template has got off the ground. - DeferredTypeID = 0; + TypeIDForTypeDecl = 0; } break; } @@ -2867,12 +2843,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; // Must be in the same context. - // - // Note that we can't use DeclContext::Equals here, because the DeclContexts - // could be two different declarations of the same function. (We will fix the - // semantic DC to refer to the primary definition after merging.) - if (!declaresSameEntity(cast(X->getDeclContext()->getRedeclContext()), - cast(Y->getDeclContext()->getRedeclContext()))) + if (!X->getDeclContext()->getRedeclContext()->Equals( + Y->getDeclContext()->getRedeclContext())) return false; // Two typedefs refer to the same entity if they have the same underlying @@ -2934,21 +2906,18 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } ASTContext &C = FuncX->getASTContext(); - auto GetTypeAsWritten = [](const FunctionDecl *FD) { - return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() - : FD->getType(); - }; - QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); - if (!C.hasSameType(XT, YT)) { + if (!C.hasSameType(FuncX->getType(), FuncY->getType())) { // We can get functions with different types on the redecl chain in C++17 // if they have differing exception specifications and at least one of // the excpetion specs is unresolved. - auto *XFPT = XT->getAs(); - auto *YFPT = YT->getAs(); + // FIXME: Do we need to check for C++14 deduced return types here too? + auto *XFPT = FuncX->getType()->getAs(); + auto *YFPT = FuncY->getType()->getAs(); if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) + C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(), + FuncY->getType())) return true; return false; } @@ -3140,50 +3109,23 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found, return nullptr; } -/// Find the declaration to use to populate the anonymous declaration table -/// for the given lexical DeclContext. We only care about finding local -/// definitions of the context; we'll merge imported ones as we go. -DeclContext * -ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { - // For classes, we track the definition as we merge. - if (auto *RD = dyn_cast(LexicalDC)) { - auto *DD = RD->getCanonicalDecl()->DefinitionData; - return DD ? DD->Definition : nullptr; - } - - // For anything else, walk its merged redeclarations looking for a definition. - // Note that we can't just call getDefinition here because the redeclaration - // chain isn't wired up. - for (auto *D : merged_redecls(cast(LexicalDC))) { - if (auto *FD = dyn_cast(D)) - if (FD->isThisDeclarationADefinition()) - return FD; - if (auto *MD = dyn_cast(D)) - if (MD->isThisDeclarationADefinition()) - return MD; - } - - // No merged definition yet. - return nullptr; -} - NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index) { // If the lexical context has been merged, look into the now-canonical // definition. - auto *CanonDC = cast(DC)->getCanonicalDecl(); + if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) + DC = Merged; // If we've seen this before, return the canonical declaration. - auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; if (Index < Previous.size() && Previous[Index]) return Previous[Index]; // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. - auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); - if (PrimaryDC && !cast(PrimaryDC)->isFromASTFile()) { - numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { + if (!cast(DC)->isFromASTFile()) { + numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) { if (Previous.size() == Number) Previous.push_back(cast(ND->getCanonicalDecl())); else @@ -3197,9 +3139,10 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D) { - auto *CanonDC = cast(DC)->getCanonicalDecl(); + if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) + DC = Merged; - auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; if (Index >= Previous.size()) Previous.resize(Index + 1); if (!Previous[Index]) diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp deleted file mode 100644 index 0a4de7b975..0000000000 --- a/test/Modules/merge-deduced-return.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s -// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s -DLOCAL -// expected-no-diagnostics - -#pragma clang module build A -module A {} -#pragma clang module contents -#pragma clang module begin A -inline auto f() { struct X {}; return X(); } -inline auto a = f(); -#pragma clang module end -#pragma clang module endbuild - -#pragma clang module build B -module B {} -#pragma clang module contents -#pragma clang module begin B -inline auto f() { struct X {}; return X(); } -inline auto b = f(); -#pragma clang module end -#pragma clang module endbuild - -#ifdef LOCAL -inline auto f() { struct X {}; return X(); } -inline auto b = f(); -#else -#pragma clang module import B -#endif - -#pragma clang module import A - -using T = decltype(a); -using T = decltype(b); diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp deleted file mode 100644 index d14483aa3a..0000000000 --- a/test/Modules/merge-lambdas.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// RUN: %clang_cc1 -fmodules -verify %s -// expected-no-diagnostics - -#pragma clang module build A -module A {} -#pragma clang module contents -#pragma clang module begin A -template auto f() { return []{}; } -#pragma clang module end -#pragma clang module endbuild - -#pragma clang module build B -module B {} -#pragma clang module contents -#pragma clang module begin B -#pragma clang module import A -inline auto x1() { return f(); } -inline auto z() { return []{}; } -inline auto x2() { return z(); } -#pragma clang module end -#pragma clang module endbuild - -#pragma clang module build C -module C {} -#pragma clang module contents -#pragma clang module begin C -#pragma clang module import A -inline auto y1() { return f(); } -inline auto z() { return []{}; } -inline auto y2() { return z(); } -inline auto q() { return []{}; } -inline auto y3() { return q(); } -#pragma clang module end -#pragma clang module endbuild - -inline auto q() { return []{}; } -inline auto x3() { return q(); } - -#pragma clang module import B -#pragma clang module import C -using T = decltype(x1); -using T = decltype(y1); - -using U = decltype(x2); -using U = decltype(y2); - -using V = decltype(x3); -using V = decltype(y3); diff --git a/test/Modules/merge-static-locals.cpp b/test/Modules/merge-static-locals.cpp deleted file mode 100644 index 37ae22ee38..0000000000 --- a/test/Modules/merge-static-locals.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// RUN: %clang_cc1 -std=c++17 -fmodules -verify %s -// expected-no-diagnostics - -#pragma clang module build A -module A {} -#pragma clang module contents -#pragma clang module begin A -template struct X {}; -auto get() { static int n; return X<&n>(); } -using A = decltype(get()); -#pragma clang module end -#pragma clang module endbuild - -#pragma clang module build B -module B {} -#pragma clang module contents -#pragma clang module begin B -template struct X {}; -auto get() { static int n; return X<&n>(); } -using B = decltype(get()); -#pragma clang module end -#pragma clang module endbuild - -#pragma clang module import A -#pragma clang module import B -using T = A; -using T = B; -- GitLab From 82cfb485f0e0e3174b95881c5a6e5d080e91b916 Mon Sep 17 00:00:00 2001 From: Kostya Kortchinsky Date: Tue, 3 Jul 2018 14:39:29 +0000 Subject: [PATCH 0391/1023] [Driver] Add PPC64 as supported for Scudo Summary: Scudo works on PPC64 as is, so mark the architecture as supported for it. This will also require a change to config-ix.cmake on the compiler-rt side. Update the tests accordingly. Reviewers: eugenis, alekseyshl Reviewed By: alekseyshl Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48833 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336202 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Linux.cpp | 3 ++- test/Driver/fsanitize.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 9a477556cf..d27f994d32 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -931,7 +931,8 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Efficiency; if (IsX86 || IsX86_64) Res |= SanitizerKind::Function; - if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch) + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch || + IsPowerPC64) Res |= SanitizerKind::Scudo; if (IsX86_64 || IsAArch64) { Res |= SanitizerKind::HWAddress; diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 98fd1636b7..354e7c0296 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -670,6 +670,8 @@ // RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO // RUN: %clang -target mips-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO // RUN: %clang -target mipsel-unknown-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// RUN: %clang -target powerpc64-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// RUN: %clang -target powerpc64le-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO // CHECK-SCUDO: "-fsanitize=scudo" // RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE -- GitLab From a0c03f2df39aa547e4182dcf632ba1c1d533da4e Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 3 Jul 2018 18:12:39 +0000 Subject: [PATCH 0392/1023] Fix crash in clang. This happened during a recent refactor. toStringRefArray() returns a vector, which was being implicitly converted to an ArrayRef, and then the vector was immediately being destroyed, so the ArrayRef<> was losing its backing storage. Fix this by making sure the vector gets permanent storage. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336219 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Job.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index 74af597ad3..bd1a9bd8e3 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -318,10 +318,12 @@ int Command::Execute(ArrayRef> Redirects, SmallVector Argv; Optional> Env; + std::vector ArgvVectorStorage; if (!Environment.empty()) { assert(Environment.back() == nullptr && "Environment vector should be null-terminated by now"); - Env = llvm::toStringRefArray(Environment.data()); + ArgvVectorStorage = llvm::toStringRefArray(Environment.data()); + Env = makeArrayRef(ArgvVectorStorage); } if (ResponseFile == nullptr) { -- GitLab From 83dc9e5eeb282d9fea92251023c292c24d94fec7 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 3 Jul 2018 20:30:34 +0000 Subject: [PATCH 0393/1023] Fix allocation of Nullability attribute. Existing code always allocates for on the declarator's attribute pool, but sometimes adds it to the declspec. This patch ensures that the correct pool is used. Discovered while testing: https://reviews.llvm.org/D48788 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336225 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseObjc.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ff33d5fb96..81b930a228 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -381,25 +381,23 @@ static void addContextSensitiveTypeNullability(Parser &P, SourceLocation nullabilityLoc, bool &addedToDeclSpec) { // Create the attribute. - auto getNullabilityAttr = [&]() -> AttributeList * { - return D.getAttributePool().create( - P.getNullabilityKeyword(nullability), - SourceRange(nullabilityLoc), - nullptr, SourceLocation(), - nullptr, 0, - AttributeList::AS_ContextSensitiveKeyword); + auto getNullabilityAttr = [&](AttributePool &Pool) -> AttributeList * { + return Pool.create(P.getNullabilityKeyword(nullability), + SourceRange(nullabilityLoc), nullptr, SourceLocation(), + nullptr, 0, AttributeList::AS_ContextSensitiveKeyword); }; if (D.getNumTypeObjects() > 0) { // Add the attribute to the declarator chunk nearest the declarator. - auto nullabilityAttr = getNullabilityAttr(); + auto nullabilityAttr = getNullabilityAttr(D.getAttributePool()); DeclaratorChunk &chunk = D.getTypeObject(0); nullabilityAttr->setNext(chunk.getAttrListRef()); chunk.getAttrListRef() = nullabilityAttr; } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().addAttributes(getNullabilityAttr()); + D.getMutableDeclSpec().addAttributes( + getNullabilityAttr(D.getDeclSpec().getAttributePool())); addedToDeclSpec = true; } } -- GitLab From 1faea10f9051a30ea0441599659f9798d835dbf1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 3 Jul 2018 21:34:13 +0000 Subject: [PATCH 0394/1023] Factor out Clang's desired 8MB stack size constant from the various places we hardcode it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336231 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Stack.h | 25 +++++++++++++++++++ lib/Frontend/CompilerInstance.cpp | 4 +-- lib/StaticAnalyzer/Frontend/ModelInjector.cpp | 4 +-- tools/driver/cc1_main.cpp | 22 ++++++---------- tools/libclang/CIndex.cpp | 5 ++-- 5 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 include/clang/Basic/Stack.h diff --git a/include/clang/Basic/Stack.h b/include/clang/Basic/Stack.h new file mode 100644 index 0000000000..9ed38a7991 --- /dev/null +++ b/include/clang/Basic/Stack.h @@ -0,0 +1,25 @@ +//===--- Stack.h - Utilities for dealing with stack space -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines utilities for dealing with stack allocation and stack space. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_STACK_H +#define LLVM_CLANG_BASIC_STACK_H + +namespace clang { + /// The amount of stack space that Clang would like to be provided with. + /// If less than this much is available, we may be unable to reach our + /// template instantiation depth limit and other similar limits. + constexpr size_t DesiredStackSize = 8 << 20; +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_STACK_H diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index d9900867d8..c4863d6c03 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" @@ -1164,14 +1165,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. - const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; CRC.RunSafelyOnThread( [&]() { GenerateModuleFromModuleMapAction Action; Instance.ExecuteAction(Action); }, - ThreadStackSize); + DesiredStackSize); PostBuildStep(Instance); diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index 853aec2ea6..c43d30440c 100644 --- a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -10,6 +10,7 @@ #include "ModelInjector.h" #include "clang/AST/Decl.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" @@ -95,11 +96,10 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { ParseModelFileAction parseModelFile(Bodies); - const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(parseModelFile); }, - ThreadStackSize); + DesiredStackSize); Instance.getPreprocessor().FinalizeForModelFile(); diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 4d200bfada..952b1c1c0d 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -16,6 +16,7 @@ #include "llvm/Option/Arg.h" #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" #include "clang/Config/config.h" +#include "clang/Basic/Stack.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" @@ -73,13 +74,6 @@ void initializePollyPasses(llvm::PassRegistry &Registry); #endif #ifdef CLANG_HAVE_RLIMITS -// The amount of stack we think is "sufficient". If less than this much is -// available, we may be unable to reach our template instantiation depth -// limit and other similar limits. -// FIXME: Unify this with the stack we request when spawning a thread to build -// a module. -static const int kSufficientStack = 8 << 20; - #if defined(__linux__) && defined(__PIE__) static size_t getCurrentStackAllocation() { // If we can't compute the current stack usage, allow for 512K of command @@ -117,7 +111,7 @@ static size_t getCurrentStackAllocation() { #include LLVM_ATTRIBUTE_NOINLINE -static void ensureStackAddressSpace(int ExtraChunks = 0) { +static void ensureStackAddressSpace() { // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary // relatively close to the stack (they are only guaranteed to be 128MiB // apart). This results in crashes if we happen to heap-allocate more than @@ -126,7 +120,7 @@ static void ensureStackAddressSpace(int ExtraChunks = 0) { // To avoid these crashes, ensure that we have sufficient virtual memory // pages allocated before we start running. size_t Curr = getCurrentStackAllocation(); - const int kTargetStack = kSufficientStack - 256 * 1024; + const int kTargetStack = DesiredStackSize - 256 * 1024; if (Curr < kTargetStack) { volatile char *volatile Alloc = static_cast(alloca(kTargetStack - Curr)); @@ -146,21 +140,21 @@ static void ensureSufficientStack() { // Increase the soft stack limit to our desired level, if necessary and // possible. - if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) { + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < DesiredStackSize) { // Try to allocate sufficient stack. - if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack) - rlim.rlim_cur = kSufficientStack; + if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= DesiredStackSize) + rlim.rlim_cur = DesiredStackSize; else if (rlim.rlim_cur == rlim.rlim_max) return; else rlim.rlim_cur = rlim.rlim_max; if (setrlimit(RLIMIT_STACK, &rlim) != 0 || - rlim.rlim_cur != kSufficientStack) + rlim.rlim_cur != DesiredStackSize) return; } - // We should now have a stack of size at least kSufficientStack. Ensure + // We should now have a stack of size at least DesiredStackSize. Ensure // that we can actually use that much, if necessary. ensureStackAddressSpace(); } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index c2aac1f102..b61dff3238 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -26,6 +26,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticCategories.h" #include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Frontend/ASTUnit.h" @@ -8474,8 +8475,8 @@ void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) { // Misc. utility functions. //===----------------------------------------------------------------------===// -/// Default to using an 8 MB stack size on "safety" threads. -static unsigned SafetyStackThreadSize = 8 << 20; +/// Default to using our desired 8 MB stack size on "safety" threads. +static unsigned SafetyStackThreadSize = DesiredStackSize; namespace clang { -- GitLab From 7cb94b0502fe0fbf58c5c6f213f1da9386c08034 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Tue, 3 Jul 2018 22:15:36 +0000 Subject: [PATCH 0395/1023] [Sema] Discarded statment should be an evaluatable context. The constexpr evaluator was erroring out because these templates weren't defined. Despite being used in a discarded statement, we still need to constexpr evaluate them, which means that we need to instantiate them. Fixes PR37585. Differential revision: https://reviews.llvm.org/D48322 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336233 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 2 +- test/SemaCXX/constant-expression-cxx1z.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a713136b64..820e5a9553 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14237,13 +14237,13 @@ static bool isEvaluatableContext(Sema &SemaRef) { switch (SemaRef.ExprEvalContexts.back().Context) { case Sema::ExpressionEvaluationContext::Unevaluated: case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: - case Sema::ExpressionEvaluationContext::DiscardedStatement: // Expressions in this context are never evaluated. return false; case Sema::ExpressionEvaluationContext::UnevaluatedList: case Sema::ExpressionEvaluationContext::ConstantEvaluated: case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: + case Sema::ExpressionEvaluationContext::DiscardedStatement: // Expressions in this context could be evaluated. return true; diff --git a/test/SemaCXX/constant-expression-cxx1z.cpp b/test/SemaCXX/constant-expression-cxx1z.cpp index a48c9b11b8..2b366adf2e 100644 --- a/test/SemaCXX/constant-expression-cxx1z.cpp +++ b/test/SemaCXX/constant-expression-cxx1z.cpp @@ -46,3 +46,16 @@ namespace Cxx17CD_NB_GB19 { const int &r = 0; constexpr int n = r; } + +namespace PR37585 { +template struct S { static constexpr bool value = true; }; +template constexpr bool f() { return true; } +template constexpr bool v = true; + +void test() { + if constexpr (true) {} + else if constexpr (f()) {} + else if constexpr (S::value) {} + else if constexpr (v) {} +} +} -- GitLab From 2926189c9bf4982cd6a0e9cc00d785837112d457 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Wed, 4 Jul 2018 01:37:11 +0000 Subject: [PATCH 0396/1023] [Sema] Consider all format_arg attributes. If a function has multiple format_arg attributes, clang only considers the first it finds (because AttributeLists are in reverse order, not necessarily the textually first) and ignores all others. Loop over all FormatArgAttr to print warnings for all declared format_arg attributes. For instance, libintl's ngettext (select plural or singular version of format string) has two __format_arg__ attributes. Differential Revision: https://reviews.llvm.org/D48734 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336239 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 21 +++++++++++++++------ test/Sema/attr-format_arg.c | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 19acb32113..98aeb61fa7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -5518,13 +5518,22 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args, case Stmt::CXXMemberCallExprClass: { const CallExpr *CE = cast(E); if (const NamedDecl *ND = dyn_cast_or_null(CE->getCalleeDecl())) { - if (const FormatArgAttr *FA = ND->getAttr()) { + bool IsFirst = true; + StringLiteralCheckType CommonResult; + for (const auto *FA : ND->specific_attrs()) { const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex()); - return checkFormatStringExpr(S, Arg, Args, - HasVAListArg, format_idx, firstDataArg, - Type, CallType, InFunctionCall, - CheckedVarArgs, UncoveredArg, Offset); - } else if (const FunctionDecl *FD = dyn_cast(ND)) { + StringLiteralCheckType Result = checkFormatStringExpr( + S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, + CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset); + if (IsFirst) { + CommonResult = Result; + IsFirst = false; + } + } + if (!IsFirst) + return CommonResult; + + if (const auto *FD = dyn_cast(ND)) { unsigned BuiltinID = FD->getBuiltinID(); if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString || BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) { diff --git a/test/Sema/attr-format_arg.c b/test/Sema/attr-format_arg.c index 64a2387831..e041c5acbf 100644 --- a/test/Sema/attr-format_arg.c +++ b/test/Sema/attr-format_arg.c @@ -4,10 +4,27 @@ int printf(const char *, ...); const char* f(const char *s) __attribute__((format_arg(1))); +const char *h(const char *msg1, const char *msg2) + __attribute__((__format_arg__(1))) __attribute__((__format_arg__(2))); + void g(const char *s) { printf("%d", 123); printf("%d %d", 123); // expected-warning{{more '%' conversions than data arguments}} printf(f("%d"), 123); printf(f("%d %d"), 123); // expected-warning{{more '%' conversions than data arguments}} + + printf(h( + "", // expected-warning {{format string is empty}} + "" // expected-warning {{format string is empty}} + ), 123); + printf(h( + "%d", + "" // expected-warning {{format string is empty}} + ), 123); + printf(h( + "", // expected-warning {{format string is empty}} + "%d" + ), 123); + printf(h("%d", "%d"), 123); } -- GitLab From ef356db5c03a0f052c09ebd0a964b9eda3852847 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 4 Jul 2018 02:25:38 +0000 Subject: [PATCH 0397/1023] PR33924: merge local declarations that have linkage of some kind within merged function definitions; also merge functions with deduced return types. This seems like two independent fixes, but unfortunately they are hard to separate because it's challenging to reliably test either one of them without also testing the other. A complication arises with deduced return type support: we need the type of the function in order to know how to merge it, but we can't load the actual type of the function because it might reference an entity declared within the function (and we need to have already merged the function to correctly merge that entity, which we would need to do to determine if the function types match). So we instead compare the declared function type when merging functions, and defer loading the actual type of a function with a deduced type until we've finished loading and merging the function. This reverts r336175, reinstating r336021, with one change (for PR38015): we look at the TypeSourceInfo of the first-so-far declaration of each function when considering whether to merge two functions. This works around a problem where the calling convention in the TypeSourceInfo for subsequent redeclarations may not match if it was implicitly adjusted. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336240 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTReader.h | 2 +- lib/Serialization/ASTCommon.cpp | 16 +++- lib/Serialization/ASTReaderDecl.cpp | 108 +++++++++++++++++++----- test/Modules/cxx-dtor.cpp | 1 + test/Modules/friend-definition-2.cpp | 1 + test/Modules/merge-deduced-return.cpp | 33 ++++++++ test/Modules/merge-lambdas.cpp | 48 +++++++++++ test/Modules/merge-static-locals.cpp | 27 ++++++ test/Modules/pr27401.cpp | 1 + 9 files changed, 211 insertions(+), 26 deletions(-) create mode 100644 test/Modules/merge-deduced-return.cpp create mode 100644 test/Modules/merge-lambdas.cpp create mode 100644 test/Modules/merge-static-locals.cpp diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index bf9ed38a15..b33f317765 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -546,7 +546,7 @@ private: /// Mergeable declaration contexts that have anonymous declarations /// within them, and those anonymous declarations. - llvm::DenseMap> + llvm::DenseMap> AnonymousDeclarationsForMerging; struct FileDeclsInfo { diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index fcebe5982f..da482717f4 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -419,9 +419,21 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return true; } - // Otherwise, we only care about anonymous class members. + // At block scope, we number everything that we need to deduplicate, since we + // can't just use name matching to keep things lined up. + // FIXME: This is only necessary for an inline function or a template or + // similar. + if (D->getLexicalDeclContext()->isFunctionOrMethod()) { + if (auto *VD = dyn_cast(D)) + return VD->isStaticLocal(); + // FIXME: What about CapturedDecls (and declarations nested within them)? + return isa(D) || isa(D); + } + + // Otherwise, we only care about anonymous class members / block-scope decls. + // FIXME: We need to handle lambdas and blocks within inline / templated + // variables too. if (D->getDeclName() || !isa(D->getLexicalDeclContext())) return false; return isa(D) || isa(D); } - diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index b0c7bbec20..b33b88c271 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -87,7 +87,7 @@ namespace clang { using RecordData = ASTReader::RecordData; - TypeID TypeIDForTypeDecl = 0; + TypeID DeferredTypeID = 0; unsigned AnonymousDeclNumber; GlobalDeclID NamedDeclForTagDecl = 0; IdentifierInfo *TypedefNameForLinkage = nullptr; @@ -177,6 +177,8 @@ namespace clang { void MergeDefinitionData(ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD); + static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC); + static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index); @@ -528,7 +530,7 @@ void ASTDeclReader::Visit(Decl *D) { if (auto *TD = dyn_cast(D)) { // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. @@ -537,8 +539,11 @@ void ASTDeclReader::Visit(Decl *D) { cast(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. - ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); + ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); } else if (auto *FD = dyn_cast(D)) { + if (DeferredTypeID) + FD->setType(Reader.GetType(DeferredTypeID)); + // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). @@ -658,7 +663,7 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(ReadSourceLocation()); // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); } ASTDeclReader::RedeclarableResult @@ -791,7 +796,13 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - VD->setType(Record.readType()); + // For function declarations, defer reading the type in case the function has + // a deduced return type that references an entity declared within the + // function. + if (isa(VD)) + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + else + VD->setType(Record.readType()); } void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { @@ -820,6 +831,19 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); VisitDeclaratorDecl(FD); + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && + FD->getTypeSourceInfo()->getType()->castAs() + ->getReturnType()->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + DeferredTypeID = 0; + } + ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); FD->IdentifierNamespace = Record.readInt(); @@ -1084,7 +1108,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt()); + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); mergeRedeclarable(ID, Redecl); ID->TypeParamList = ReadObjCTypeParamList(); @@ -1890,7 +1914,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // // Beware: we do not yet know our canonical declaration, and may still // get merged once the surrounding class template has got off the ground. - TypeIDForTypeDecl = 0; + DeferredTypeID = 0; } break; } @@ -2843,8 +2867,12 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { return true; // Must be in the same context. - if (!X->getDeclContext()->getRedeclContext()->Equals( - Y->getDeclContext()->getRedeclContext())) + // + // Note that we can't use DeclContext::Equals here, because the DeclContexts + // could be two different declarations of the same function. (We will fix the + // semantic DC to refer to the primary definition after merging.) + if (!declaresSameEntity(cast(X->getDeclContext()->getRedeclContext()), + cast(Y->getDeclContext()->getRedeclContext()))) return false; // Two typedefs refer to the same entity if they have the same underlying @@ -2906,18 +2934,26 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { } ASTContext &C = FuncX->getASTContext(); - if (!C.hasSameType(FuncX->getType(), FuncY->getType())) { + auto GetTypeAsWritten = [](const FunctionDecl *FD) { + // Map to the first declaration that we've already merged into this one. + // The TSI of redeclarations might not match (due to calling conventions + // being inherited onto the type but not the TSI), but the TSI type of + // the first declaration of the function should match across modules. + FD = FD->getCanonicalDecl(); + return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() + : FD->getType(); + }; + QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); + if (!C.hasSameType(XT, YT)) { // We can get functions with different types on the redecl chain in C++17 // if they have differing exception specifications and at least one of // the excpetion specs is unresolved. - // FIXME: Do we need to check for C++14 deduced return types here too? - auto *XFPT = FuncX->getType()->getAs(); - auto *YFPT = FuncY->getType()->getAs(); + auto *XFPT = XT->getAs(); + auto *YFPT = YT->getAs(); if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(), - FuncY->getType())) + C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) return true; return false; } @@ -3109,23 +3145,50 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found, return nullptr; } +/// Find the declaration to use to populate the anonymous declaration table +/// for the given lexical DeclContext. We only care about finding local +/// definitions of the context; we'll merge imported ones as we go. +DeclContext * +ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { + // For classes, we track the definition as we merge. + if (auto *RD = dyn_cast(LexicalDC)) { + auto *DD = RD->getCanonicalDecl()->DefinitionData; + return DD ? DD->Definition : nullptr; + } + + // For anything else, walk its merged redeclarations looking for a definition. + // Note that we can't just call getDefinition here because the redeclaration + // chain isn't wired up. + for (auto *D : merged_redecls(cast(LexicalDC))) { + if (auto *FD = dyn_cast(D)) + if (FD->isThisDeclarationADefinition()) + return FD; + if (auto *MD = dyn_cast(D)) + if (MD->isThisDeclarationADefinition()) + return MD; + } + + // No merged definition yet. + return nullptr; +} + NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index) { // If the lexical context has been merged, look into the now-canonical // definition. - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast(DC)->getCanonicalDecl(); // If we've seen this before, return the canonical declaration. - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index < Previous.size() && Previous[Index]) return Previous[Index]; // If this is the first time, but we have parsed a declaration of the context, // build the anonymous declaration list from the parsed declaration. - if (!cast(DC)->isFromASTFile()) { - numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) { + auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC); + if (PrimaryDC && !cast(PrimaryDC)->isFromASTFile()) { + numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) { if (Previous.size() == Number) Previous.push_back(cast(ND->getCanonicalDecl())); else @@ -3139,10 +3202,9 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader, void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D) { - if (auto *Merged = Reader.MergedDeclContexts.lookup(DC)) - DC = Merged; + auto *CanonDC = cast(DC)->getCanonicalDecl(); - auto &Previous = Reader.AnonymousDeclarationsForMerging[DC]; + auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC]; if (Index >= Previous.size()) Previous.resize(Index + 1); if (!Previous[Index]) diff --git a/test/Modules/cxx-dtor.cpp b/test/Modules/cxx-dtor.cpp index 63427ee0af..d685b69d51 100644 --- a/test/Modules/cxx-dtor.cpp +++ b/test/Modules/cxx-dtor.cpp @@ -1,3 +1,4 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs/cxx-dtor -emit-llvm-only %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs/cxx-dtor -emit-llvm-only %s -triple i686-windows #include "b.h" diff --git a/test/Modules/friend-definition-2.cpp b/test/Modules/friend-definition-2.cpp index 7f876b762a..b226b5c0d1 100644 --- a/test/Modules/friend-definition-2.cpp +++ b/test/Modules/friend-definition-2.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fmodules %s -verify +// RUN: %clang_cc1 -fmodules %s -verify -triple i686-windows // expected-no-diagnostics #pragma clang module build A module A {} diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp new file mode 100644 index 0000000000..0a4de7b975 --- /dev/null +++ b/test/Modules/merge-deduced-return.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s +// RUN: %clang_cc1 -fmodules -std=c++17 -verify %s -DLOCAL +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +inline auto f() { struct X {}; return X(); } +inline auto a = f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +inline auto f() { struct X {}; return X(); } +inline auto b = f(); +#pragma clang module end +#pragma clang module endbuild + +#ifdef LOCAL +inline auto f() { struct X {}; return X(); } +inline auto b = f(); +#else +#pragma clang module import B +#endif + +#pragma clang module import A + +using T = decltype(a); +using T = decltype(b); diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp new file mode 100644 index 0000000000..d14483aa3a --- /dev/null +++ b/test/Modules/merge-lambdas.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fmodules -verify %s +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template auto f() { return []{}; } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +#pragma clang module import A +inline auto x1() { return f(); } +inline auto z() { return []{}; } +inline auto x2() { return z(); } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build C +module C {} +#pragma clang module contents +#pragma clang module begin C +#pragma clang module import A +inline auto y1() { return f(); } +inline auto z() { return []{}; } +inline auto y2() { return z(); } +inline auto q() { return []{}; } +inline auto y3() { return q(); } +#pragma clang module end +#pragma clang module endbuild + +inline auto q() { return []{}; } +inline auto x3() { return q(); } + +#pragma clang module import B +#pragma clang module import C +using T = decltype(x1); +using T = decltype(y1); + +using U = decltype(x2); +using U = decltype(y2); + +using V = decltype(x3); +using V = decltype(y3); diff --git a/test/Modules/merge-static-locals.cpp b/test/Modules/merge-static-locals.cpp new file mode 100644 index 0000000000..37ae22ee38 --- /dev/null +++ b/test/Modules/merge-static-locals.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++17 -fmodules -verify %s +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template struct X {}; +auto get() { static int n; return X<&n>(); } +using A = decltype(get()); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +template struct X {}; +auto get() { static int n; return X<&n>(); } +using B = decltype(get()); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import A +#pragma clang module import B +using T = A; +using T = B; diff --git a/test/Modules/pr27401.cpp b/test/Modules/pr27401.cpp index 7d5479cb92..8db3bbb009 100644 --- a/test/Modules/pr27401.cpp +++ b/test/Modules/pr27401.cpp @@ -1,6 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR27401 -verify %s // RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27401/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR27401 -verify %s +// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27401/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR27401 -verify %s -triple i686-windows #include "a.h" #define _LIBCPP_VECTOR -- GitLab From 4f874f4052f3375bfbd0d3a7655ee049d3cccdd8 Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Wed, 4 Jul 2018 08:32:02 +0000 Subject: [PATCH 0398/1023] NFC - typo fix in test/CodeGen/avx512f-builtins.c git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336243 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/avx512f-builtins.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 8d6e01af2f..0f35a56f22 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -2757,12 +2757,12 @@ __m512d test_mm512_maskz_div_round_pd(__mmask8 __U, __m512d __A, __m512d __B) { return _mm512_maskz_div_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_div_pd(__m512d __a, __m512d __b) { - // CHECK-LABLE: @test_mm512_div_pd + // CHECK-LABEL: @test_mm512_div_pd // CHECK: fdiv <8 x double> return _mm512_div_pd(__a,__b); } __m512d test_mm512_mask_div_pd(__m512d __w, __mmask8 __u, __m512d __a, __m512d __b) { - // CHECK-LABLE: @test_mm512_mask_div_pd + // CHECK-LABEL: @test_mm512_mask_div_pd // CHECK: fdiv <8 x double> %{{.*}}, %{{.*}} // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_div_pd(__w,__u,__a,__b); -- GitLab From c8c9b4da91fdf2e1bd938704f419763a969b56ed Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 4 Jul 2018 08:50:12 +0000 Subject: [PATCH 0399/1023] [Sema] Fix crash in getConstructorName. Summary: Can happen when getConstructorName is called on invalid decls, specifically the ones that do not have the injected class name. Reviewers: bkramer, rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48880 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336244 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 2 ++ test/SemaCXX/injected-class-name-crash.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 test/SemaCXX/injected-class-name-crash.cpp diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index db47931348..8dd9c19bd3 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -113,6 +113,8 @@ ParsedType Sema::getConstructorName(IdentifierInfo &II, break; } } + if (!InjectedClassName && CurClass->isInvalidDecl()) + return ParsedType(); assert(InjectedClassName && "couldn't find injected class name"); QualType T = Context.getTypeDeclType(InjectedClassName); diff --git a/test/SemaCXX/injected-class-name-crash.cpp b/test/SemaCXX/injected-class-name-crash.cpp new file mode 100644 index 0000000000..2996a7cdb4 --- /dev/null +++ b/test/SemaCXX/injected-class-name-crash.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X : public Foo +X::X() { +} -- GitLab From 6c9c407460d1ae31a35fb223d179f83ab5ff515c Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Wed, 4 Jul 2018 10:01:18 +0000 Subject: [PATCH 0400/1023] [SemaCodeComplete] Make sure visited contexts are passed to completion results handler. Reviewers: ilya-biryukov Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48917 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336255 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCodeComplete.cpp | 182 ++++++++++++---------------- unittests/Sema/CodeCompleteTest.cpp | 11 ++ 2 files changed, 86 insertions(+), 107 deletions(-) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 5bc428a04a..c56df52eeb 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3700,9 +3700,11 @@ struct Sema::CodeCompleteExpressionData { /// type we're looking for. void Sema::CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data) { - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_Expression); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_Expression, + Data.PreferredType)); if (Data.ObjCCollection) Results.setFilter(&ResultBuilder::IsObjCCollection); else if (Data.IntegralConstantExpression) @@ -3741,10 +3743,8 @@ void Sema::CodeCompleteExpression(Scope *S, if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false, PreferredTypeIsPointer); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext(CodeCompletionContext::CCC_Expression, - Data.PreferredType), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { @@ -4360,17 +4360,11 @@ void Sema::CodeCompleteCase(Scope *S) { } Results.ExitScope(); - //We need to make sure we're setting the right context, - //so only say we include macros if the code completer says we do - enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other; if (CodeCompleter->includeMacros()) { AddMacroResults(PP, Results, false); - kind = CodeCompletionContext::CCC_OtherWithMacros; } - - HandleCodeCompleteResults(this, CodeCompleter, - kind, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } static bool anyNullArguments(ArrayRef Args) { @@ -4773,10 +4767,9 @@ void Sema::CodeCompleteUsing(Scope *S) { CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_PotentiallyQualifiedName, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteUsingDirective(Scope *S) { @@ -4795,9 +4788,8 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Namespace, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteNamespaceDecl(Scope *S) { @@ -4893,10 +4885,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) { // Add any type specifiers AddTypeSpecifierResults(getLangOpts(), Results); Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Type, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteConstructorInitializer( @@ -5177,9 +5168,8 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S) { else AddObjCTopLevelResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { @@ -5311,9 +5301,8 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) { Results.EnterNewScope(); AddObjCVisibilityResults(getLangOpts(), Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCAtStatement(Scope *S) { @@ -5324,9 +5313,8 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) { AddObjCStatementResults(Results, false); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCAtExpression(Scope *S) { @@ -5336,9 +5324,8 @@ void Sema::CodeCompleteObjCAtExpression(Scope *S) { Results.EnterNewScope(); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } /// Determine whether the addition of the given flag to an Objective-C @@ -5432,9 +5419,8 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { Results.AddResult(CodeCompletionResult("null_resettable")); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } /// Describes the kind of Objective-C method that we want to find @@ -5616,9 +5602,8 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCPropertySetter(Scope *S) { @@ -5645,9 +5630,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { Selectors, /*AllowSameLength=*/true, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, @@ -5723,8 +5707,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Type, + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -6396,9 +6379,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Results.AddResult(Builder.TakeString()); } Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_SelectorName, + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -6441,10 +6423,9 @@ void Sema::CodeCompleteObjCProtocolReferences( Results.ExitScope(); } - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCProtocolName, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCProtocolDecl(Scope *) { @@ -6461,10 +6442,9 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) { Results.ExitScope(); } - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCProtocolName, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } /// Add all of the Objective-C interface declarations that we find in @@ -6485,12 +6465,12 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, } } -void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { +void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_Other); + CodeCompletionContext::CCC_ObjCInterfaceName); Results.EnterNewScope(); - + if (CodeCompleter->includeGlobals()) { // Add all classes. AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, @@ -6499,9 +6479,8 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCInterfaceName, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, @@ -6525,15 +6504,14 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCInterfaceName, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } -void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { +void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_Other); + CodeCompletionContext::CCC_ObjCImplementation); Results.EnterNewScope(); if (CodeCompleter->includeGlobals()) { @@ -6544,9 +6522,8 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCInterfaceName, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, @@ -6578,10 +6555,9 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, nullptr), CurContext, nullptr, false); Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCCategoryName, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCImplementationCategory(Scope *S, @@ -6620,10 +6596,9 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, IgnoreImplemented = false; } Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_ObjCCategoryName, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { @@ -6660,10 +6635,9 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { false, /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, @@ -6753,10 +6727,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, } Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } // Mapping from selectors to the methods that implement that selector, along @@ -7686,10 +7659,9 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, } Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, @@ -7776,9 +7748,8 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, } } - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompletePreprocessorDirective(bool InConditional) { @@ -7934,9 +7905,8 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { // FIXME: we don't support #assert or #unassert, so don't suggest them. Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_PreprocessorDirective, + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -7993,10 +7963,9 @@ void Sema::CodeCompletePreprocessorExpression() { Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Builder.TakeString()); Results.ExitScope(); - - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_PreprocessorExpression, - Results.data(), Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, @@ -8028,9 +7997,8 @@ void Sema::CodeCompleteAvailabilityPlatformName() { Twine(Platform) + "ApplicationExtension"))); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, Results.data(), - Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, diff --git a/unittests/Sema/CodeCompleteTest.cpp b/unittests/Sema/CodeCompleteTest.cpp index 8e888cbe52..04cb14b971 100644 --- a/unittests/Sema/CodeCompleteTest.cpp +++ b/unittests/Sema/CodeCompleteTest.cpp @@ -131,4 +131,15 @@ TEST(SemaCodeCompleteTest, VisitedNSForInvalideQualifiedId) { EXPECT_TRUE(VisitedNS.empty()); } +TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) { + auto VisitedNS = runCodeCompleteOnCode(R"cpp( + namespace n1 { + namespace n2 { + void f(^) {} + } + } + )cpp"); + EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2")); +} + } // namespace -- GitLab From c09b7287e3768a54a51dd1d64bf949ba7e2e24e4 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 4 Jul 2018 11:14:18 +0000 Subject: [PATCH 0401/1023] Add missing include for size_t git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336261 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Stack.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/clang/Basic/Stack.h b/include/clang/Basic/Stack.h index 9ed38a7991..15a37c6d59 100644 --- a/include/clang/Basic/Stack.h +++ b/include/clang/Basic/Stack.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_BASIC_STACK_H #define LLVM_CLANG_BASIC_STACK_H +#include + namespace clang { /// The amount of stack space that Clang would like to be provided with. /// If less than this much is available, we may be unable to reach our -- GitLab From 4239cbe33e357c0230913abaf9792f9c07b80dfe Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Wed, 4 Jul 2018 11:21:44 +0000 Subject: [PATCH 0402/1023] NFC - Fix typo in test/Layout/itanium-pack-and-align.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336262 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Layout/itanium-pack-and-align.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Layout/itanium-pack-and-align.cpp b/test/Layout/itanium-pack-and-align.cpp index 64569168e4..ac64979af3 100644 --- a/test/Layout/itanium-pack-and-align.cpp +++ b/test/Layout/itanium-pack-and-align.cpp @@ -23,4 +23,4 @@ T t; // CHECK-NEXT: 0 | char x // CHECK-NEXT: 1 | int y // CHECK-NEXT: | [sizeof=8, dsize=8, align=8, -// CHECK-NETX: | nvsize=8, nvalign=8] +// CHECK-NEXT: | nvsize=8, nvalign=8] -- GitLab From dd6f2c1d2e5a70e68609eeecc96a23c13b05a226 Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Wed, 4 Jul 2018 11:26:09 +0000 Subject: [PATCH 0403/1023] NFC - Fix typo in test/CodeGenObjC/gnustep2-class.m git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336263 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGenObjC/gnustep2-class.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGenObjC/gnustep2-class.m b/test/CodeGenObjC/gnustep2-class.m index eaa4f0e8c7..0103a6fcee 100644 --- a/test/CodeGenObjC/gnustep2-class.m +++ b/test/CodeGenObjC/gnustep2-class.m @@ -51,5 +51,5 @@ // And check that we get a pointer to it in the right place // CHECK: @._OBJC_REF_CLASS_X = global // CHECK-SAME: @._OBJC_CLASS_X -// CHECK-SAMEsection "__objc_class_refs" +// CHECK-SAME: section "__objc_class_refs" -- GitLab From 1d7006dc77d3ac7d4b6a2392bc8436f69a7244de Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Wed, 4 Jul 2018 11:29:21 +0000 Subject: [PATCH 0404/1023] NFC - Fix type in builtins-ppc-p9vector.c test git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336264 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/builtins-ppc-p9vector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/builtins-ppc-p9vector.c b/test/CodeGen/builtins-ppc-p9vector.c index f92df86561..bfbb815854 100644 --- a/test/CodeGen/builtins-ppc-p9vector.c +++ b/test/CodeGen/builtins-ppc-p9vector.c @@ -983,7 +983,7 @@ vector bool int test86(void) { } vector bool long long test87(void) { // CHECK-BE: @llvm.ppc.vsx.xvtstdcdp(<2 x double> {{.+}}, i32 127) -// CHECK-BE_NEXT: ret <2 x i64 +// CHECK-BE-NEXT: ret <2 x i64> // CHECK: @llvm.ppc.vsx.xvtstdcdp(<2 x double> {{.+}}, i32 127) // CHECK-NEXT: ret <2 x i64> return vec_test_data_class(vda, __VEC_CLASS_FP_NOT_NORMAL); -- GitLab From 06787e3d57b9ee0cc5e3bf5003b2f95f4c357c9a Mon Sep 17 00:00:00 2001 From: Rafael Stahl Date: Wed, 4 Jul 2018 13:34:05 +0000 Subject: [PATCH 0405/1023] [ASTImporter] import macro source locations Summary: Implement full import of macro expansion info with spelling and expansion locations. Reviewers: a.sidorin, klimek, martong, balazske, xazax.hun Reviewed By: martong Subscribers: thakis, xazax.hun, balazske, rnkovacs, cfe-commits Differential Revision: https://reviews.llvm.org/D47698 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336269 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 83 +++++++++++++++++-------------- unittests/AST/ASTImporterTest.cpp | 60 ++++++++++++++++++++++ 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 37ddfea7be..bc75d80a55 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -7164,19 +7164,13 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) { return {}; SourceManager &FromSM = FromContext.getSourceManager(); - - // For now, map everything down to its file location, so that we - // don't have to import macro expansions. - // FIXME: Import macro expansions! - FromLoc = FromSM.getFileLoc(FromLoc); + std::pair Decomposed = FromSM.getDecomposedLoc(FromLoc); - SourceManager &ToSM = ToContext.getSourceManager(); FileID ToFileID = Import(Decomposed.first); if (ToFileID.isInvalid()) return {}; - SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID) - .getLocWithOffset(Decomposed.second); - return ret; + SourceManager &ToSM = ToContext.getSourceManager(); + return ToSM.getComposedLoc(ToFileID, Decomposed.second); } SourceRange ASTImporter::Import(SourceRange FromRange) { @@ -7184,41 +7178,56 @@ SourceRange ASTImporter::Import(SourceRange FromRange) { } FileID ASTImporter::Import(FileID FromID) { - llvm::DenseMap::iterator Pos - = ImportedFileIDs.find(FromID); + llvm::DenseMap::iterator Pos = ImportedFileIDs.find(FromID); if (Pos != ImportedFileIDs.end()) return Pos->second; - + SourceManager &FromSM = FromContext.getSourceManager(); SourceManager &ToSM = ToContext.getSourceManager(); const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID); - assert(FromSLoc.isFile() && "Cannot handle macro expansions yet"); - - // Include location of this file. - SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); - - // Map the FileID for to the "to" source manager. + + // Map the FromID to the "to" source manager. FileID ToID; - const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); - if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { - // FIXME: We probably want to use getVirtualFile(), so we don't hit the - // disk again - // FIXME: We definitely want to re-use the existing MemoryBuffer, rather - // than mmap the files several times. - const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName()); - if (!Entry) - return {}; - ToID = ToSM.createFileID(Entry, ToIncludeLoc, - FromSLoc.getFile().getFileCharacteristic()); + if (FromSLoc.isExpansion()) { + const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion(); + SourceLocation ToSpLoc = Import(FromEx.getSpellingLoc()); + SourceLocation ToExLocS = Import(FromEx.getExpansionLocStart()); + unsigned TokenLen = FromSM.getFileIDSize(FromID); + SourceLocation MLoc; + if (FromEx.isMacroArgExpansion()) { + MLoc = ToSM.createMacroArgExpansionLoc(ToSpLoc, ToExLocS, TokenLen); + } else { + SourceLocation ToExLocE = Import(FromEx.getExpansionLocEnd()); + MLoc = ToSM.createExpansionLoc(ToSpLoc, ToExLocS, ToExLocE, TokenLen, + FromEx.isExpansionTokenRange()); + } + ToID = ToSM.getFileID(MLoc); } else { - // FIXME: We want to re-use the existing MemoryBuffer! - const llvm::MemoryBuffer * - FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM); - std::unique_ptr ToBuf - = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), - FromBuf->getBufferIdentifier()); - ToID = ToSM.createFileID(std::move(ToBuf), - FromSLoc.getFile().getFileCharacteristic()); + // Include location of this file. + SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); + + const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); + if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { + // FIXME: We probably want to use getVirtualFile(), so we don't hit the + // disk again + // FIXME: We definitely want to re-use the existing MemoryBuffer, rather + // than mmap the files several times. + const FileEntry *Entry = + ToFileManager.getFile(Cache->OrigEntry->getName()); + if (!Entry) + return {}; + ToID = ToSM.createFileID(Entry, ToIncludeLoc, + FromSLoc.getFile().getFileCharacteristic()); + } else { + // FIXME: We want to re-use the existing MemoryBuffer! + const llvm::MemoryBuffer *FromBuf = + Cache->getBuffer(FromContext.getDiagnostics(), FromSM); + std::unique_ptr ToBuf = + llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), + FromBuf->getBufferIdentifier()); + ToID = ToSM.createFileID(std::move(ToBuf), + FromSLoc.getFile().getFileCharacteristic()); + } } ImportedFileIDs[FromID] = ToID; diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index b1e6e42b5a..dfcb6c1893 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -1577,6 +1577,66 @@ TEST_P(ASTImporterTestBase, ToTU, cxxRecordDecl(unless(isImplicit())))); } +static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) { + EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber()); + EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber()); + EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber()); + EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber()); +} +static void CompareSourceRanges(SourceRange Range1, SourceRange Range2, + SourceManager &SM1, SourceManager &SM2) { + CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 }, + FullSourceLoc{ Range2.getBegin(), SM2 }); + CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 }, + FullSourceLoc{ Range2.getEnd(), SM2 }); +} +TEST_P(ASTImporterTestBase, ImportSourceLocs) { + Decl *FromTU = getTuDecl( + R"( + #define MFOO(arg) arg = arg + 1 + + void foo() { + int a = 5; + MFOO(a); + } + )", + Lang_CXX); + auto FromD = FirstDeclMatcher().match(FromTU, functionDecl()); + auto ToD = Import(FromD, Lang_CXX); + + auto ToLHS = LastDeclMatcher().match(ToD, declRefExpr()); + auto FromLHS = LastDeclMatcher().match(FromTU, declRefExpr()); + auto ToRHS = LastDeclMatcher().match(ToD, integerLiteral()); + auto FromRHS = + LastDeclMatcher().match(FromTU, integerLiteral()); + + SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); + SourceManager &FromSM = FromD->getASTContext().getSourceManager(); + CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, + FromSM); + CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM, + FromSM); + CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM, + FromSM); +} + +TEST_P(ASTImporterTestBase, DISABLED_ImportNestedMacro) { + Decl *FromTU = getTuDecl( + R"( + #define FUNC_INT void declToImport + #define FUNC FUNC_INT + FUNC(int a); + )", + Lang_CXX); + auto FromD = FirstDeclMatcher().match(FromTU, functionDecl()); + auto ToD = Import(FromD, Lang_CXX); + + SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); + SourceManager &FromSM = FromD->getASTContext().getSourceManager(); + CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, + FromSM); +} + TEST_P( ASTImporterTestBase, ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) -- GitLab From d29eb3a6ffe17e9da5dcaa4fb50c5738e0a57d1e Mon Sep 17 00:00:00 2001 From: Rafael Stahl Date: Wed, 4 Jul 2018 14:12:58 +0000 Subject: [PATCH 0406/1023] [analyzer][ctu] fix unsortable diagnostics Summary: In the provided test case the PathDiagnostic compare function was not able to find a difference. Reviewers: xazax.hun, NoQ, dcoughlin, george.karpenkov Reviewed By: george.karpenkov Subscribers: a_sidorin, szepet, rnkovacs, a.sidorin, mikhail.ramalho, cfe-commits Differential Revision: https://reviews.llvm.org/D48474 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336275 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 10 +++++++--- test/Analysis/Inputs/ctu-other.cpp | 7 +++++++ test/Analysis/Inputs/externalFnMap.txt | 1 + test/Analysis/ctu-hdr.h | 3 +++ test/Analysis/ctu-main.cpp | 7 +++++++ 5 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 test/Analysis/ctu-hdr.h diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 95a7f33ce8..1b698ec5c0 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -406,11 +406,15 @@ static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) { std::pair InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs); if (InSameTU.first) return XL.isBeforeInTranslationUnitThan(YL); - const FileEntry *XFE = SM.getFileEntryForID(XL.getFileID()); - const FileEntry *YFE = SM.getFileEntryForID(YL.getFileID()); + const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID()); + const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID()); if (!XFE || !YFE) return XFE && !YFE; - return XFE->getName() < YFE->getName(); + int NameCmp = XFE->getName().compare(YFE->getName()); + if (NameCmp != 0) + return NameCmp == -1; + // Last resort: Compare raw file IDs that are possibly expansions. + return XL.getFileID() < YL.getFileID(); } static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) { diff --git a/test/Analysis/Inputs/ctu-other.cpp b/test/Analysis/Inputs/ctu-other.cpp index eceac5af3c..8cad861578 100644 --- a/test/Analysis/Inputs/ctu-other.cpp +++ b/test/Analysis/Inputs/ctu-other.cpp @@ -1,3 +1,5 @@ +#include "../ctu-hdr.h" + int callback_to_main(int x); int f(int x) { return x - 1; @@ -68,3 +70,8 @@ int chf1(int x) { typedef struct { int n; } Anonymous; int fun_using_anon_struct(int n) { Anonymous anon; anon.n = n; return anon.n; } + +int other_macro_diag(int x) { + MACRODIAG(); + return x; +} diff --git a/test/Analysis/Inputs/externalFnMap.txt b/test/Analysis/Inputs/externalFnMap.txt index 805990f25c..5461685dc6 100644 --- a/test/Analysis/Inputs/externalFnMap.txt +++ b/test/Analysis/Inputs/externalFnMap.txt @@ -12,3 +12,4 @@ c:@F@h_chain#I# ctu-chain.cpp.ast c:@N@chns@S@chcls@F@chf4#I# ctu-chain.cpp.ast c:@N@chns@F@chf2#I# ctu-chain.cpp.ast c:@F@fun_using_anon_struct#I# ctu-other.cpp.ast +c:@F@other_macro_diag#I# ctu-other.cpp.ast diff --git a/test/Analysis/ctu-hdr.h b/test/Analysis/ctu-hdr.h new file mode 100644 index 0000000000..5a1e694d06 --- /dev/null +++ b/test/Analysis/ctu-hdr.h @@ -0,0 +1,3 @@ +#define MACRODIAG() clang_analyzer_warnIfReached() + +void clang_analyzer_warnIfReached(); diff --git a/test/Analysis/ctu-main.cpp b/test/Analysis/ctu-main.cpp index 3e9db816f2..33da84962c 100644 --- a/test/Analysis/ctu-main.cpp +++ b/test/Analysis/ctu-main.cpp @@ -4,6 +4,8 @@ // RUN: cp %S/Inputs/externalFnMap.txt %T/ctudir/ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config experimental-enable-naive-ctu-analysis=true -analyzer-config ctu-dir=%T/ctudir -verify %s +#include "ctu-hdr.h" + void clang_analyzer_eval(int); int f(int); @@ -41,6 +43,7 @@ int chf1(int x); } int fun_using_anon_struct(int); +int other_macro_diag(int); int main() { clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}} @@ -58,4 +61,8 @@ int main() { clang_analyzer_eval(chns::chf1(4) == 12); // expected-warning{{TRUE}} clang_analyzer_eval(fun_using_anon_struct(8) == 8); // expected-warning{{TRUE}} + + clang_analyzer_eval(other_macro_diag(1) == 1); // expected-warning{{TRUE}} + // expected-warning@Inputs/ctu-other.cpp:75{{REACHABLE}} + MACRODIAG(); // expected-warning{{REACHABLE}} } -- GitLab From 90dccc4bb943ae29d4d0b146ad2adfdaed1da475 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 5 Jul 2018 00:33:03 +0000 Subject: [PATCH 0407/1023] [Index] Remove unused index::IndexDataConsumer::_anchor() It was supposed to serve as a key function, but it was invalid as it was not the first out-of-line non-pure virtual function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336300 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/IndexDataConsumer.h | 3 --- lib/Index/IndexingAction.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h index 53cdea9183..8115b04af6 100644 --- a/include/clang/Index/IndexDataConsumer.h +++ b/include/clang/Index/IndexDataConsumer.h @@ -54,9 +54,6 @@ public: SymbolRoleSet Roles, SourceLocation Loc); virtual void finish() {} - -private: - virtual void _anchor(); }; } // namespace index diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp index c8f65804b0..e378a092be 100644 --- a/lib/Index/IndexingAction.cpp +++ b/lib/Index/IndexingAction.cpp @@ -19,8 +19,6 @@ using namespace clang; using namespace clang::index; -void IndexDataConsumer::_anchor() {} - bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, SourceLocation Loc, -- GitLab From bbe9af000db62ee0cc5f741df7e772c3dca64d99 Mon Sep 17 00:00:00 2001 From: Lei Huang Date: Thu, 5 Jul 2018 04:32:01 +0000 Subject: [PATCH 0408/1023] [Power9] Update fp128 as a valid homogenous aggregate base type Update clang to treat fp128 as a valid base type for homogeneous aggregate passing and returning. Differential Revision: https://reviews.llvm.org/D48044 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336308 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 7 ++ lib/CodeGen/TargetInfo.cpp | 13 ++- test/CodeGen/ppc64le-f128Aggregates.c | 124 ++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/ppc64le-f128Aggregates.c diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 3de86041c8..dbe96a00f5 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1807,6 +1807,7 @@ public: bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isFloat128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) bool isVoidType() const; // C99 6.2.5p19 @@ -6299,6 +6300,12 @@ inline bool Type::isFloat16Type() const { return false; } +inline bool Type::isFloat128Type() const { + if (const auto *BT = dyn_cast(CanonicalType)) + return BT->getKind() == BuiltinType::Float128; + return false; +} + inline bool Type::isNullPtrType() const { if (const auto *BT = getAs()) return BT->getKind() == BuiltinType::NullPtr; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 3fcafbbfd3..2078ea1fea 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -4619,7 +4619,9 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { if (const BuiltinType *BT = Ty->getAs()) { if (BT->getKind() == BuiltinType::Float || BT->getKind() == BuiltinType::Double || - BT->getKind() == BuiltinType::LongDouble) { + BT->getKind() == BuiltinType::LongDouble || + (getContext().getTargetInfo().hasFloat128Type() && + (BT->getKind() == BuiltinType::Float128))) { if (IsSoftFloatABI) return false; return true; @@ -4634,10 +4636,13 @@ bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { bool PPC64_SVR4_ABIInfo::isHomogeneousAggregateSmallEnough( const Type *Base, uint64_t Members) const { - // Vector types require one register, floating point types require one - // or two registers depending on their size. + // Vector and fp128 types require one register, other floating point types + // require one or two registers depending on their size. uint32_t NumRegs = - Base->isVectorType() ? 1 : (getContext().getTypeSize(Base) + 63) / 64; + ((getContext().getTargetInfo().hasFloat128Type() && + Base->isFloat128Type()) || + Base->isVectorType()) ? 1 + : (getContext().getTypeSize(Base) + 63) / 64; // Homogeneous Aggregates may occupy at most 8 registers. return Members * NumRegs <= 8; diff --git a/test/CodeGen/ppc64le-f128Aggregates.c b/test/CodeGen/ppc64le-f128Aggregates.c new file mode 100644 index 0000000000..a51b6d5e70 --- /dev/null +++ b/test/CodeGen/ppc64le-f128Aggregates.c @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm \ +// RUN: -target-cpu pwr9 -target-feature +float128 -o - %s | FileCheck %s + +// Test homogeneous fp128 aggregate passing and returning. + +struct fp1 { __float128 f[1]; }; +struct fp2 { __float128 f[2]; }; +struct fp3 { __float128 f[3]; }; +struct fp4 { __float128 f[4]; }; +struct fp5 { __float128 f[5]; }; +struct fp6 { __float128 f[6]; }; +struct fp7 { __float128 f[7]; }; +struct fp8 { __float128 f[8]; }; +struct fp9 { __float128 f[9]; }; + +struct fpab { __float128 a; __float128 b; }; +struct fpabc { __float128 a; __float128 b; __float128 c; }; + +struct fp2a2b { __float128 a[2]; __float128 b[2]; }; + +// CHECK: define [1 x fp128] @func_f1(fp128 inreg %x.coerce) +struct fp1 func_f1(struct fp1 x) { return x; } + +// CHECK: define [2 x fp128] @func_f2([2 x fp128] %x.coerce) +struct fp2 func_f2(struct fp2 x) { return x; } + +// CHECK: define [3 x fp128] @func_f3([3 x fp128] %x.coerce) +struct fp3 func_f3(struct fp3 x) { return x; } + +// CHECK: define [4 x fp128] @func_f4([4 x fp128] %x.coerce) +struct fp4 func_f4(struct fp4 x) { return x; } + +// CHECK: define [5 x fp128] @func_f5([5 x fp128] %x.coerce) +struct fp5 func_f5(struct fp5 x) { return x; } + +// CHECK: define [6 x fp128] @func_f6([6 x fp128] %x.coerce) +struct fp6 func_f6(struct fp6 x) { return x; } + +// CHECK: define [7 x fp128] @func_f7([7 x fp128] %x.coerce) +struct fp7 func_f7(struct fp7 x) { return x; } + +// CHECK: define [8 x fp128] @func_f8([8 x fp128] %x.coerce) +struct fp8 func_f8(struct fp8 x) { return x; } + +// CHECK: define void @func_f9(%struct.fp9* noalias sret %agg.result, %struct.fp9* byval align 16 %x) +struct fp9 func_f9(struct fp9 x) { return x; } + +// CHECK: define [2 x fp128] @func_fab([2 x fp128] %x.coerce) +struct fpab func_fab(struct fpab x) { return x; } + +// CHECK: define [3 x fp128] @func_fabc([3 x fp128] %x.coerce) +struct fpabc func_fabc(struct fpabc x) { return x; } + +// CHECK: define [4 x fp128] @func_f2a2b([4 x fp128] %x.coerce) +struct fp2a2b func_f2a2b(struct fp2a2b x) { return x; } + +// CHECK-LABEL: @call_fp1 +// CHECK: %[[TMP:[^ ]+]] = load fp128, fp128* getelementptr inbounds (%struct.fp1, %struct.fp1* @global_f1, i32 0, i32 0, i32 0), align 16 +// CHECK: call [1 x fp128] @func_f1(fp128 inreg %[[TMP]]) +struct fp1 global_f1; +void call_fp1(void) { global_f1 = func_f1(global_f1); } + +// CHECK-LABEL: @call_fp2 +// CHECK: %[[TMP:[^ ]+]] = load [2 x fp128], [2 x fp128]* getelementptr inbounds (%struct.fp2, %struct.fp2* @global_f2, i32 0, i32 0), align 16 +// CHECK: call [2 x fp128] @func_f2([2 x fp128] %[[TMP]]) +struct fp2 global_f2; +void call_fp2(void) { global_f2 = func_f2(global_f2); } + +// CHECK-LABEL: @call_fp3 +// CHECK: %[[TMP:[^ ]+]] = load [3 x fp128], [3 x fp128]* getelementptr inbounds (%struct.fp3, %struct.fp3* @global_f3, i32 0, i32 0), align 16 +// CHECK: call [3 x fp128] @func_f3([3 x fp128] %[[TMP]]) +struct fp3 global_f3; +void call_fp3(void) { global_f3 = func_f3(global_f3); } + +// CHECK-LABEL: @call_fp4 +// CHECK: %[[TMP:[^ ]+]] = load [4 x fp128], [4 x fp128]* getelementptr inbounds (%struct.fp4, %struct.fp4* @global_f4, i32 0, i32 0), align 16 +// CHECK: call [4 x fp128] @func_f4([4 x fp128] %[[TMP]]) +struct fp4 global_f4; +void call_fp4(void) { global_f4 = func_f4(global_f4); } + +// CHECK-LABEL: @call_fp5 +// CHECK: %[[TMP:[^ ]+]] = load [5 x fp128], [5 x fp128]* getelementptr inbounds (%struct.fp5, %struct.fp5* @global_f5, i32 0, i32 0), align 16 +// CHECK: call [5 x fp128] @func_f5([5 x fp128] %[[TMP]]) +struct fp5 global_f5; +void call_fp5(void) { global_f5 = func_f5(global_f5); } + +// CHECK-LABEL: @call_fp6 +// CHECK: %[[TMP:[^ ]+]] = load [6 x fp128], [6 x fp128]* getelementptr inbounds (%struct.fp6, %struct.fp6* @global_f6, i32 0, i32 0), align 16 +// CHECK: call [6 x fp128] @func_f6([6 x fp128] %[[TMP]]) +struct fp6 global_f6; +void call_fp6(void) { global_f6 = func_f6(global_f6); } + +// CHECK-LABEL: @call_fp7 +// CHECK: %[[TMP:[^ ]+]] = load [7 x fp128], [7 x fp128]* getelementptr inbounds (%struct.fp7, %struct.fp7* @global_f7, i32 0, i32 0), align 16 +// CHECK: call [7 x fp128] @func_f7([7 x fp128] %[[TMP]]) +struct fp7 global_f7; +void call_fp7(void) { global_f7 = func_f7(global_f7); } + +// CHECK-LABEL: @call_fp8 +// CHECK: %[[TMP:[^ ]+]] = load [8 x fp128], [8 x fp128]* getelementptr inbounds (%struct.fp8, %struct.fp8* @global_f8, i32 0, i32 0), align 16 +// CHECK: call [8 x fp128] @func_f8([8 x fp128] %[[TMP]]) +struct fp8 global_f8; +void call_fp8(void) { global_f8 = func_f8(global_f8); } + +// CHECK-LABEL: @call_fp9 +// CHECK: %[[TMP1:[^ ]+]] = alloca %struct.fp9, align 16 +// CHECK: call void @func_f9(%struct.fp9* sret %[[TMP2:[^ ]+]], %struct.fp9* byval align 16 @global_f9 +// CHECK: %[[TMP3:[^ ]+]] = bitcast %struct.fp9* %[[TMP2]] to i8* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 bitcast (%struct.fp9* @global_f9 to i8*), i8* align 16 %[[TMP3]], i64 144, i1 false +// CHECK: ret void +struct fp9 global_f9; +void call_fp9(void) { global_f9 = func_f9(global_f9); } + +// CHECK-LABEL: @call_fpab +// CHECK: %[[TMP:[^ ]+]] = load [2 x fp128], [2 x fp128]* bitcast (%struct.fpab* @global_fab to [2 x fp128]*) +// CHECK: call [2 x fp128] @func_fab([2 x fp128] %[[TMP]]) +struct fpab global_fab; +void call_fpab(void) { global_fab = func_fab(global_fab); } + +// CHECK-LABEL: @call_fpabc +// CHECK: %[[TMP:[^ ]+]] = load [3 x fp128], [3 x fp128]* bitcast (%struct.fpabc* @global_fabc to [3 x fp128]*) +// CHECK: call [3 x fp128] @func_fabc([3 x fp128] %[[TMP]]) +struct fpabc global_fabc; +void call_fpabc(void) { global_fabc = func_fabc(global_fabc); } -- GitLab From d2b3d463c20a6c951a18a65297b17ddef894bb18 Mon Sep 17 00:00:00 2001 From: Kirill Bobyrev Date: Thu, 5 Jul 2018 09:37:26 +0000 Subject: [PATCH 0409/1023] [NFS] Wipe trailing whitespaces This patch is a preparation for another one containing meaningful changes. This patch simply removes trailing whitespaces in few files affected by the upcoming patch and reformats git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336330 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/CodeCompleteConsumer.h | 16 +- lib/Sema/SemaCodeComplete.cpp | 1480 ++++++++++----------- 2 files changed, 748 insertions(+), 748 deletions(-) diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 86e52f404c..d3f6b651b7 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -554,14 +554,14 @@ private: /// The availability of this code-completion result. unsigned Availability : 2; - + /// The name of the parent context. StringRef ParentName; /// A brief documentation comment attached to the declaration of /// entity being completed by this result. const char *BriefComment; - + CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, unsigned NumAnnotations, @@ -599,7 +599,7 @@ public: /// Retrieve the annotation string specified by \c AnnotationNr. const char *getAnnotation(unsigned AnnotationNr) const; - + /// Retrieve the name of the parent context. StringRef getParentContextName() const { return ParentName; @@ -608,7 +608,7 @@ public: const char *getBriefComment() const { return BriefComment; } - + /// Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. std::string getAsString() const; @@ -669,7 +669,7 @@ private: CXAvailabilityKind Availability = CXAvailability_Available; StringRef ParentName; const char *BriefComment = nullptr; - + /// The chunks stored in this string. SmallVector Chunks; @@ -728,7 +728,7 @@ public: const char *getBriefComment() const { return BriefComment; } void addBriefComment(StringRef Comment); - + StringRef getParentName() const { return ParentName; } }; @@ -886,8 +886,8 @@ public: StartsNestedNameSpecifier(false), AllParametersAreInformative(false), DeclaringEntity(false) { computeCursorKindAndAvailability(); - } - + } + /// Retrieve the declaration stored in this result. const NamedDecl *getDeclaration() const { assert(Kind == RK_Declaration && "Not a declaration result"); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index c56df52eeb..a2252f2ace 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -50,16 +50,16 @@ namespace { typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; typedef CodeCompletionResult Result; - + private: /// The actual results we have found. std::vector Results; - + /// A record of all of the declarations we have found and placed /// into the result set, used to ensure that no declaration ever gets into /// the result set twice. llvm::SmallPtrSet AllDeclsFound; - + typedef std::pair DeclIndexPair; /// An entry in the shadow map, which is optimized to store @@ -119,8 +119,8 @@ namespace { /// this name within a particular scope and their index within the list of /// results. typedef llvm::DenseMap ShadowMap; - - /// The semantic analysis object for which results are being + + /// The semantic analysis object for which results are being /// produced. Sema &SemaRef; @@ -128,7 +128,7 @@ namespace { CodeCompletionAllocator &Allocator; CodeCompletionTUInfo &CCTUInfo; - + /// If non-NULL, a filter function used to remove any code-completion /// results that are not desirable. LookupFilter Filter; @@ -140,27 +140,27 @@ namespace { /// If set, the type that we would prefer our resulting value /// declarations to have. /// - /// Closely matching the preferred type gives a boost to a result's + /// Closely matching the preferred type gives a boost to a result's /// priority. CanQualType PreferredType; - + /// A list of shadow maps, which is used to model name hiding at /// different levels of, e.g., the inheritance hierarchy. std::list ShadowMaps; - + /// If we're potentially referring to a C++ member function, the set /// of qualifiers applied to the object type. Qualifiers ObjectTypeQualifiers; - + /// Whether the \p ObjectTypeQualifiers field is active. bool HasObjectTypeQualifiers; - + /// The selector that we prefer. Selector PreferredSelector; - + /// The completion context in which we are gathering results. CodeCompletionContext CompletionContext; - + /// If we are in an instance method definition, the \@implementation /// object. ObjCImplementationDecl *ObjCImplementation; @@ -168,19 +168,19 @@ namespace { void AdjustResultPriorityForDecl(Result &R); void MaybeAddConstructorResults(Result R); - + public: explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, const CodeCompletionContext &CompletionContext, LookupFilter Filter = nullptr) : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), - Filter(Filter), - AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), + Filter(Filter), + AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), ObjCImplementation(nullptr) - { - // If this is an Objective-C instance method definition, dig out the + { + // If this is an Objective-C instance method definition, dig out the // corresponding implementation. switch (CompletionContext.getKind()) { case CodeCompletionContext::CCC_Expression: @@ -193,7 +193,7 @@ namespace { if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) ObjCImplementation = Interface->getImplementation(); break; - + default: break; } @@ -205,10 +205,10 @@ namespace { /// Whether we should include code patterns in the completion /// results. bool includeCodePatterns() const { - return SemaRef.CodeCompleter && + return SemaRef.CodeCompleter && SemaRef.CodeCompleter->includeCodePatterns(); } - + /// Set the filter used for code-completion results. void setFilter(LookupFilter Filter) { this->Filter = Filter; @@ -217,24 +217,24 @@ namespace { Result *data() { return Results.empty()? nullptr : &Results.front(); } unsigned size() const { return Results.size(); } bool empty() const { return Results.empty(); } - + /// Specify the preferred type. - void setPreferredType(QualType T) { - PreferredType = SemaRef.Context.getCanonicalType(T); + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); } - + /// Set the cv-qualifiers on the object type, for us in filtering /// calls to member functions. /// /// When there are qualifiers in this set, they will be used to filter - /// out member functions that aren't available (because there will be a + /// out member functions that aren't available (because there will be a /// cv-qualifier mismatch) or prefer functions with an exact qualifier /// match. void setObjectTypeQualifiers(Qualifiers Quals) { ObjectTypeQualifiers = Quals; HasObjectTypeQualifiers = true; } - + /// Set the preferred selector. /// /// When an Objective-C method declaration result is added, and that @@ -243,13 +243,13 @@ namespace { void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; } - + /// Retrieve the code-completion context for which results are /// being collected. - const CodeCompletionContext &getCompletionContext() const { - return CompletionContext; + const CodeCompletionContext &getCompletionContext() const { + return CompletionContext; } - + /// Specify whether nested-name-specifiers are allowed. void allowNestedNameSpecifiers(bool Allow = true) { AllowNestedNameSpecifiers = Allow; @@ -258,12 +258,12 @@ namespace { /// Return the semantic analysis object for which we are collecting /// code completion results. Sema &getSema() const { return SemaRef; } - + /// Retrieve the allocator used to allocate code completion strings. CodeCompletionAllocator &getAllocator() const { return Allocator; } CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } - + /// Determine whether the given declaration is at all interesting /// as a code-completion result. /// @@ -273,7 +273,7 @@ namespace { /// only interesting when it is a nested-name-specifier. bool isInterestingDecl(const NamedDecl *ND, bool &AsNestedNameSpecifier) const; - + /// Check whether the result is hidden by the Hiding declaration. /// /// \returns true if the result is hidden and cannot be found, false if @@ -282,9 +282,9 @@ namespace { /// qualification). bool CheckHiddenResult(Result &R, DeclContext *CurContext, const NamedDecl *Hiding); - + /// Add a new result to this result set (if it isn't already in one - /// of the shadow maps), or replace an existing result (for, e.g., a + /// of the shadow maps), or replace an existing result (for, e.g., a /// redeclaration). /// /// \param R the result to add (if it is unique). @@ -305,16 +305,16 @@ namespace { /// class of the searched context. void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, bool InBaseClass); - + /// Add a new non-declaration result to this result set. void AddResult(Result R); /// Enter into a new scope. void EnterNewScope(); - + /// Exit from the current scope. void ExitScope(); - + /// Ignore this declaration, if it is seen again. void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } @@ -327,7 +327,7 @@ namespace { /// /// These predicates can be passed to the name lookup functions to filter the /// results of name lookup. All of the predicates have the same type, so that - /// + /// //@{ bool IsOrdinaryName(const NamedDecl *ND) const; bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; @@ -346,8 +346,8 @@ namespace { bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; bool IsObjCCollection(const NamedDecl *ND) const; bool IsImpossibleToSatisfy(const NamedDecl *ND) const; - //@} - }; + //@} + }; } class ResultBuilder::ShadowMapEntry::iterator { @@ -359,7 +359,7 @@ public: typedef value_type reference; typedef std::ptrdiff_t difference_type; typedef std::input_iterator_tag iterator_category; - + class pointer { DeclIndexPair Value; @@ -420,7 +420,7 @@ public: } }; -ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::iterator ResultBuilder::ShadowMapEntry::begin() const { if (DeclOrVector.isNull()) return iterator(); @@ -431,7 +431,7 @@ ResultBuilder::ShadowMapEntry::begin() const { return iterator(DeclOrVector.get()->begin()); } -ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::iterator ResultBuilder::ShadowMapEntry::end() const { if (DeclOrVector.is() || DeclOrVector.isNull()) return iterator(); @@ -447,7 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const { /// \param CurContext the context where an entity is being named, which is /// typically based on the current scope. /// -/// \param TargetContext the context in which the named entity actually +/// \param TargetContext the context in which the named entity actually /// resides. /// /// \returns a nested name specifier that refers into the target context, or @@ -457,14 +457,14 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, const DeclContext *TargetContext) { SmallVector TargetParents; - + for (const DeclContext *CommonAncestor = TargetContext; CommonAncestor && !CommonAncestor->Encloses(CurContext); CommonAncestor = CommonAncestor->getLookupParent()) { if (CommonAncestor->isTransparentContext() || CommonAncestor->isFunctionOrMethod()) continue; - + TargetParents.push_back(CommonAncestor); } @@ -482,7 +482,7 @@ getRequiredQualification(ASTContext &Context, Result = NestedNameSpecifier::Create(Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); - } + } return Result; } @@ -531,17 +531,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, // Skip unnamed entities. if (!ND->getDeclName()) return false; - + // Friend declarations and declarations introduced due to friends are never // added as results. if (ND->getFriendObjectKind() == Decl::FOK_Undeclared) return false; - + // Class template (partial) specializations are never added as results. if (isa(ND) || isa(ND)) return false; - + // Using declarations themselves are never added as results. if (isa(ND)) return false; @@ -559,17 +559,17 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, // Filter out any unwanted results. if (Filter && !(this->*Filter)(Named)) { // Check whether it is interesting as a nested-name-specifier. - if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && + if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && IsNestedNameSpecifier(ND) && (Filter != &ResultBuilder::IsMember || - (isa(ND) && + (isa(ND) && cast(ND)->isInjectedClassName()))) { AsNestedNameSpecifier = true; return true; } return false; - } + } // ... then it must be interesting! return true; } @@ -581,24 +581,24 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, // name if we introduce the tag type. if (!SemaRef.getLangOpts().CPlusPlus) return true; - + const DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext(); - + // There is no way to qualify a name declared in a function or method. if (HiddenCtx->isFunctionOrMethod()) return true; - + if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) return true; - + // We can refer to the result with the appropriate qualification. Do it. R.Hidden = true; R.QualifierIsInformative = false; - + if (!R.Qualifier) - R.Qualifier = getRequiredQualification(SemaRef.Context, - CurContext, + R.Qualifier = getRequiredQualification(SemaRef.Context, + CurContext, R.Declaration->getDeclContext()); return false; } @@ -611,62 +611,62 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { switch (cast(T)->getKind()) { case BuiltinType::Void: return STC_Void; - + case BuiltinType::NullPtr: return STC_Pointer; - + case BuiltinType::Overload: case BuiltinType::Dependent: return STC_Other; - + case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: return STC_ObjectiveC; - + default: return STC_Arithmetic; } case Type::Complex: return STC_Arithmetic; - + case Type::Pointer: return STC_Pointer; - + case Type::BlockPointer: return STC_Block; - + case Type::LValueReference: case Type::RValueReference: return getSimplifiedTypeClass(T->getAs()->getPointeeType()); - + case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: return STC_Array; - + case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: return STC_Arithmetic; - + case Type::FunctionProto: case Type::FunctionNoProto: return STC_Function; - + case Type::Record: return STC_Record; - + case Type::Enum: return STC_Arithmetic; - + case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: return STC_ObjectiveC; - + default: return STC_Other; } @@ -676,12 +676,12 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { /// is used as an expression in its "typical" code-completion form. QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { ND = ND->getUnderlyingDecl(); - + if (const TypeDecl *Type = dyn_cast(ND)) return C.getTypeDeclType(Type); if (const ObjCInterfaceDecl *Iface = dyn_cast(ND)) return C.getObjCInterfaceType(Iface); - + QualType T; if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getCallResultType(); @@ -726,7 +726,7 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { break; } while (true); - + return T; } @@ -786,7 +786,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { if (const ObjCMethodDecl *Method = dyn_cast(R.Declaration)) if (PreferredSelector == Method->getSelector()) R.Priority += CCD_SelectorMatch; - + // If we have a preferred type, adjust the priority for results with exactly- // matching or nearly-matching types. if (!PreferredType.isNull()) { @@ -800,16 +800,16 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { else if ((getSimplifiedTypeClass(PreferredType) == getSimplifiedTypeClass(TC)) && !(PreferredType->isEnumeralType() && TC->isEnumeralType())) - R.Priority /= CCF_SimilarTypeMatch; + R.Priority /= CCF_SimilarTypeMatch; } - } + } } void ResultBuilder::MaybeAddConstructorResults(Result R) { if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || !CompletionContext.wantConstructorResults()) return; - + ASTContext &Context = SemaRef.Context; const NamedDecl *D = R.Declaration; const CXXRecordDecl *Record = nullptr; @@ -823,12 +823,12 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { // There are no constructors here. return; } - + Record = Record->getDefinition(); if (!Record) return; - + QualType RecordTy = Context.getTypeDeclType(Record); DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( @@ -851,7 +851,7 @@ static bool isConstructor(const Decl *ND) { void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { assert(!ShadowMaps.empty() && "Must enter into a results scope"); - + if (R.Kind != Result::RK_Declaration) { // For non-declaration results, just add the result. Results.push_back(R); @@ -867,14 +867,14 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { CurContext); return; } - + const Decl *CanonDecl = R.Declaration->getCanonicalDecl(); unsigned IDNS = CanonDecl->getIdentifierNamespace(); bool AsNestedNameSpecifier = false; if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) return; - + // C++ constructors are never found by name lookup. if (isConstructor(R.Declaration)) return; @@ -893,12 +893,12 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { if (ND->getCanonicalDecl() == CanonDecl) { // This is a redeclaration. Always pick the newer declaration. Results[Index].Declaration = R.Declaration; - + // We're done. return; } } - + // This is a new declaration in this scope. However, check whether this // declaration name is hidden by a similarly-named declaration in an outer // scope. @@ -917,21 +917,21 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol))) continue; - + // Protocols are in distinct namespaces from everything else. if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || (IDNS & Decl::IDNS_ObjCProtocol)) && I->first->getIdentifierNamespace() != IDNS) continue; - + // The newly-added result is hidden by an entry in the shadow map. if (CheckHiddenResult(R, CurContext, I->first)) return; - + break; } } - + // Make sure that any given declaration only shows up in the result set once. if (!AllDeclsFound.insert(CanonDecl).second) return; @@ -941,9 +941,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { if (AsNestedNameSpecifier) { R.StartsNestedNameSpecifier = true; R.Priority = CCP_NestedNameSpecifier; - } else + } else AdjustResultPriorityForDecl(R); - + // If this result is supposed to have an informative qualifier, add one. if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { @@ -957,17 +957,17 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { else R.QualifierIsInformative = false; } - + // Insert this result into the set of results and into the current shadow // map. SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); Results.push_back(R); - + if (!AsNestedNameSpecifier) MaybeAddConstructorResults(R); } -void ResultBuilder::AddResult(Result R, DeclContext *CurContext, +void ResultBuilder::AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, bool InBaseClass = false) { if (R.Kind != Result::RK_Declaration) { // For non-declaration results, just add the result. @@ -983,11 +983,11 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, CurContext, Hiding); return; } - + bool AsNestedNameSpecifier = false; if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) return; - + // C++ constructors are never found by name lookup. if (isConstructor(R.Declaration)) return; @@ -998,7 +998,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, // Make sure that any given declaration only shows up in the result set once. if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second) return; - + // If the filter is for nested-name-specifiers, then this result starts a // nested-name-specifier. if (AsNestedNameSpecifier) { @@ -1023,13 +1023,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, else R.QualifierIsInformative = false; } - + // Adjust the priority if this result comes from a base class. if (InBaseClass) R.Priority += CCD_InBaseClass; - + AdjustResultPriorityForDecl(R); - + if (HasObjectTypeQualifiers) if (const CXXMethodDecl *Method = dyn_cast(R.Declaration)) if (Method->isInstance()) { @@ -1038,21 +1038,21 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (ObjectTypeQualifiers == MethodQuals) R.Priority += CCD_ObjectQualifierMatch; else if (ObjectTypeQualifiers - MethodQuals) { - // The method cannot be invoked, because doing so would drop + // The method cannot be invoked, because doing so would drop // qualifiers. return; } } - + // Insert this result into the set of results. Results.push_back(R); - + if (!AsNestedNameSpecifier) MaybeAddConstructorResults(R); } void ResultBuilder::AddResult(Result R) { - assert(R.Kind != Result::RK_Declaration && + assert(R.Kind != Result::RK_Declaration && "Declaration results need more context"); Results.push_back(R); } @@ -1067,7 +1067,7 @@ void ResultBuilder::ExitScope() { E != EEnd; ++E) E->second.Destroy(); - + ShadowMaps.pop_back(); } @@ -1085,7 +1085,7 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { if (isa(ND)) return true; } - + return ND->getIdentifierNamespace() & IDNS; } @@ -1110,18 +1110,18 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { if (isa(ND)) return true; } - + return ND->getIdentifierNamespace() & IDNS; } bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { if (!IsOrdinaryNonTypeName(ND)) return 0; - + if (const ValueDecl *VD = dyn_cast(ND->getUnderlyingDecl())) if (VD->getType()->isIntegralOrEnumerationType()) return true; - + return false; } @@ -1133,19 +1133,19 @@ bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; - - return (ND->getIdentifierNamespace() & IDNS) && - !isa(ND) && !isa(ND) && + + return (ND->getIdentifierNamespace() & IDNS) && + !isa(ND) && !isa(ND) && !isa(ND); } -/// Determines whether the given declaration is suitable as the +/// Determines whether the given declaration is suitable as the /// start of a C++ nested-name-specifier, e.g., a class or namespace. bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { // Allow us to find class templates, too. if (const ClassTemplateDecl *ClassTemplate = dyn_cast(ND)) ND = ClassTemplate->getTemplatedDecl(); - + return SemaRef.isAcceptableNestedNameSpecifier(ND); } @@ -1165,7 +1165,7 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || RD->getTagKind() == TTK_Interface; - + return false; } @@ -1174,10 +1174,10 @@ bool ResultBuilder::IsUnion(const NamedDecl *ND) const { // Allow us to find class templates, too. if (const ClassTemplateDecl *ClassTemplate = dyn_cast(ND)) ND = ClassTemplate->getTemplatedDecl(); - + if (const RecordDecl *RD = dyn_cast(ND)) return RD->getTagKind() == TTK_Union; - + return false; } @@ -1186,7 +1186,7 @@ bool ResultBuilder::IsNamespace(const NamedDecl *ND) const { return isa(ND); } -/// Determines whether the given declaration is a namespace or +/// Determines whether the given declaration is a namespace or /// namespace alias. bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const { return isa(ND->getUnderlyingDecl()); @@ -1210,31 +1210,31 @@ bool ResultBuilder::IsMember(const NamedDecl *ND) const { static bool isObjCReceiverType(ASTContext &C, QualType T) { T = C.getCanonicalType(T); switch (T->getTypeClass()) { - case Type::ObjCObject: + case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: return true; - + case Type::Builtin: switch (cast(T)->getKind()) { case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: return true; - + default: break; } return false; - + default: break; } - + if (!C.getLangOpts().CPlusPlus) return false; - // FIXME: We could perform more analysis here to determine whether a + // FIXME: We could perform more analysis here to determine whether a // particular class type has any conversions to Objective-C types. For now, // just accept all class types. return T->isDependentType() || T->isRecordType(); @@ -1244,7 +1244,7 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { QualType T = getDeclUsageType(SemaRef.Context, ND); if (T.isNull()) return false; - + T = SemaRef.Context.getBaseElementType(T); return isObjCReceiverType(SemaRef.Context, T); } @@ -1252,11 +1252,11 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const { if (IsObjCMessageReceiver(ND)) return true; - + const VarDecl *Var = dyn_cast(ND); if (!Var) return false; - + return Var->hasLocalStorage() && !Var->hasAttr(); } @@ -1264,14 +1264,14 @@ bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) return false; - + QualType T = getDeclUsageType(SemaRef.Context, ND); if (T.isNull()) return false; - + T = SemaRef.Context.getBaseElementType(T); return T->isObjCObjectType() || T->isObjCObjectPointerType() || - T->isObjCIdType() || + T->isObjCIdType() || (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); } @@ -1342,16 +1342,16 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.AddResult(Result("_Bool", CCP_Type)); Results.AddResult(Result("restrict", CCP_Type)); } - + CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); if (LangOpts.CPlusPlus) { // C++-specific - Results.AddResult(Result("bool", CCP_Type + + Results.AddResult(Result("bool", CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); Results.AddResult(Result("class", CCP_Type)); Results.AddResult(Result("wchar_t", CCP_Type)); - + // typename qualified-id Builder.AddTypedTextChunk("typename"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1359,12 +1359,12 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Builder.AddTextChunk("::"); Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); - + if (LangOpts.CPlusPlus11) { Results.AddResult(Result("auto", CCP_Type)); Results.AddResult(Result("char16_t", CCP_Type)); Results.AddResult(Result("char32_t", CCP_Type)); - + Builder.AddTypedTextChunk("decltype"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); @@ -1380,7 +1380,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, // Results.AddResult(Result("_Decimal32")); // Results.AddResult(Result("_Decimal64")); // Results.AddResult(Result("_Decimal128")); - + Builder.AddTypedTextChunk("typeof"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); @@ -1400,7 +1400,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, } static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, - const LangOptions &LangOpts, + const LangOptions &LangOpts, ResultBuilder &Results) { typedef CodeCompletionResult Result; // Note: we don't suggest either "auto" or "register", because both @@ -1426,7 +1426,7 @@ static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, } static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, - const LangOptions &LangOpts, + const LangOptions &LangOpts, ResultBuilder &Results) { typedef CodeCompletionResult Result; switch (CCC) { @@ -1437,7 +1437,7 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, Results.AddResult(Result("friend")); Results.AddResult(Result("mutable")); Results.AddResult(Result("virtual")); - } + } LLVM_FALLTHROUGH; case Sema::PCC_ObjCInterface: @@ -1465,7 +1465,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); static void AddObjCVisibilityResults(const LangOptions &LangOpts, ResultBuilder &Results, - bool NeedAt); + bool NeedAt); static void AddObjCImplementationResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt); @@ -1482,7 +1482,7 @@ static void AddTypedefResult(ResultBuilder &Results) { Builder.AddPlaceholderChunk("type"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("name"); - Results.AddResult(CodeCompletionResult(Builder.TakeString())); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); } static bool WantTypesInContext(Sema::ParserCompletionContext CCC, @@ -1499,15 +1499,15 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC, case Sema::PCC_ParenthesizedExpression: case Sema::PCC_LocalDeclarationSpecifiers: return true; - + case Sema::PCC_Expression: case Sema::PCC_Condition: return LangOpts.CPlusPlus; - + case Sema::PCC_ObjCInterface: case Sema::PCC_ObjCImplementation: return false; - + case Sema::PCC_ForInit: return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; } @@ -1543,7 +1543,7 @@ static const char *GetCompletionTypeString(QualType T, // Built-in type names are constant strings. if (const BuiltinType *BT = dyn_cast(T)) return BT->getNameAsCString(Policy); - + // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast(T)) if (TagDecl *Tag = TagT->getDecl()) @@ -1557,7 +1557,7 @@ static const char *GetCompletionTypeString(QualType T, } } } - + // Slow path: format the type as a string. std::string Result; T.getAsStringInternal(Result, Policy); @@ -1569,12 +1569,12 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { QualType ThisTy = S.getCurrentThisType(); if (ThisTy.isNull()) return; - + CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); PrintingPolicy Policy = getCompletionPrintingPolicy(S); - Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, - S.Context, + Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, + S.Context, Policy, Allocator)); Builder.AddTypedTextChunk("this"); @@ -1603,7 +1603,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); - + typedef CodeCompletionResult Result; switch (CCC) { case Sema::PCC_Namespace: @@ -1619,7 +1619,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - + // namespace identifier = identifier ; Builder.AddTypedTextChunk("namespace"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1636,7 +1636,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("identifier"); Results.AddResult(Result(Builder.TakeString())); - // asm(string-literal) + // asm(string-literal) Builder.AddTypedTextChunk("asm"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("string-literal"); @@ -1651,10 +1651,10 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); } } - + if (SemaRef.getLangOpts().ObjC1) AddObjCTopLevelResults(Results, true); - + AddTypedefResult(Results); LLVM_FALLTHROUGH; @@ -1667,7 +1667,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddTextChunk("::"); Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); - + // using typename qualifier::name (only in a dependent context) if (SemaRef.CurContext->isDependentContext()) { Builder.AddTypedTextChunk("using"); @@ -1728,17 +1728,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; - + case Sema::PCC_ObjCImplementation: AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); break; - + case Sema::PCC_ObjCInstanceVariableList: AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); break; - + case Sema::PCC_RecoveryInFunction: case Sema::PCC_Statement: { AddTypedefResult(Results); @@ -1762,7 +1762,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } if (SemaRef.getLangOpts().ObjC1) AddObjCStatementResults(Results, true); - + if (Results.includeCodePatterns()) { // if (condition) { statements } Builder.AddTypedTextChunk("if"); @@ -1791,7 +1791,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - + // Switch-specific statements. if (!SemaRef.getCurFunction()->SwitchStack.empty()) { // case expression: @@ -1853,7 +1853,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - + if (S->getContinueParent()) { // continue ; Builder.AddTypedTextChunk("continue"); @@ -1874,7 +1874,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, else if (ObjCMethodDecl *Method = dyn_cast(SemaRef.CurContext)) isVoid = Method->getReturnType()->isVoidType(); - else if (SemaRef.getCurBlock() && + else if (SemaRef.getCurBlock() && !SemaRef.getCurBlock()->ReturnType.isNull()) isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType(); Builder.AddTypedTextChunk("return"); @@ -1888,7 +1888,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddTypedTextChunk("goto"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("label"); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // Using directives Builder.AddTypedTextChunk("using"); @@ -1918,7 +1918,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("type"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // (__bridge_transfer ) Builder.AddTypedTextChunk("__bridge_transfer"); @@ -1926,7 +1926,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("Objective-C type"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // (__bridge_retained ) Builder.AddTypedTextChunk("__bridge_retained"); @@ -1934,7 +1934,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("CF type"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); } // Fall through LLVM_FALLTHROUGH; @@ -1943,12 +1943,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, if (SemaRef.getLangOpts().CPlusPlus) { // 'this', if we're in a non-static member function. addThisCompletion(SemaRef, Results); - + // true Builder.AddResultTypeChunk("bool"); Builder.AddTypedTextChunk("true"); Results.AddResult(Result(Builder.TakeString())); - + // false Builder.AddResultTypeChunk("bool"); Builder.AddTypedTextChunk("false"); @@ -1963,9 +1963,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); } - + // static_cast < type-id > ( expression ) Builder.AddTypedTextChunk("static_cast"); Builder.AddChunk(CodeCompletionString::CK_LeftAngle); @@ -1974,7 +1974,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // reinterpret_cast < type-id > ( expression ) Builder.AddTypedTextChunk("reinterpret_cast"); @@ -1984,7 +1984,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // const_cast < type-id > ( expression ) Builder.AddTypedTextChunk("const_cast"); @@ -1994,7 +1994,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); if (SemaRef.getLangOpts().RTTI) { // typeid ( expression-or-type ) @@ -2003,9 +2003,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression-or-type"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); } - + // new T ( ... ) Builder.AddTypedTextChunk("new"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -2013,7 +2013,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expressions"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // new T [ ] ( ... ) Builder.AddTypedTextChunk("new"); @@ -2025,14 +2025,14 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expressions"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // delete expression Builder.AddResultTypeChunk("void"); Builder.AddTypedTextChunk("delete"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + Results.AddResult(Result(Builder.TakeString())); // delete [] expression Builder.AddResultTypeChunk("void"); @@ -2052,7 +2052,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); } - + // FIXME: Rethrow? if (SemaRef.getLangOpts().CPlusPlus11) { @@ -2097,7 +2097,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, SuperType = ID->getSuperClass()->getNameAsString(); if (Method->isInstanceMethod()) SuperType += " *"; - + Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); Builder.AddTypedTextChunk("super"); Results.AddResult(Result(Builder.TakeString())); @@ -2129,7 +2129,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result(Builder.TakeString())); break; } - + case Sema::PCC_Type: case Sema::PCC_LocalDeclarationSpecifiers: break; @@ -2142,7 +2142,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result("operator")); } -/// If the given declaration has an associated type, add it as a result +/// If the given declaration has an associated type, add it as a result /// type chunk. static void AddResultTypeChunk(ASTContext &Context, const PrintingPolicy &Policy, @@ -2184,10 +2184,10 @@ static void AddResultTypeChunk(ASTContext &Context, else T = Property->getType(); } - + if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) return; - + Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy, Result.getAllocator())); } @@ -2206,7 +2206,7 @@ static void MaybeAddSentinel(Preprocessor &PP, } } -static std::string formatObjCParamQualifiers(unsigned ObjCQuals, +static std::string formatObjCParamQualifiers(unsigned ObjCQuals, QualType &Type) { std::string Result; if (ObjCQuals & Decl::OBJC_TQ_In) @@ -2303,13 +2303,13 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, bool ObjCMethodParam = isa(Param->getDeclContext()); if (Param->getType()->isDependentType() || !Param->getType()->isBlockPointerType()) { - // The argument for a dependent or non-block parameter is a placeholder + // The argument for a dependent or non-block parameter is a placeholder // containing that parameter's type. std::string Result; - + if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) Result = Param->getIdentifier()->getName(); - + QualType Type = Param->getType(); if (ObjCSubsts) Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts, @@ -2350,7 +2350,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, Result = Param->getIdentifier()->getName(); QualType Type = Param->getType().getUnqualifiedType(); - + if (ObjCMethodParam) { Result = Type.getAsString(Policy); std::string Quals = @@ -2364,7 +2364,7 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, } else { Type.getAsStringInternal(Result, Policy); } - + return Result; } @@ -2475,10 +2475,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP, unsigned Start = 0, bool InOptional = false) { bool FirstParameter = true; - + for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { const ParmVarDecl *Param = Function->getParamDecl(P); - + if (Param->hasDefaultArg() && !InOptional) { // When we see an optional default argument, put that argument and // the remaining default arguments into a new, optional string. @@ -2490,14 +2490,14 @@ static void AddFunctionParameterChunks(Preprocessor &PP, Result.AddOptionalChunk(Opt.TakeString()); break; } - + if (FirstParameter) FirstParameter = false; else Result.AddChunk(CodeCompletionString::CK_Comma); - + InOptional = false; - + // Format the placeholder string. std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) @@ -2510,8 +2510,8 @@ static void AddFunctionParameterChunks(Preprocessor &PP, Result.AddPlaceholderChunk( Result.getAllocator().CopyString(PlaceholderStr)); } - - if (const FunctionProtoType *Proto + + if (const FunctionProtoType *Proto = Function->getType()->getAs()) if (Proto->isVariadic()) { if (Proto->getNumParams() == 0) @@ -2539,7 +2539,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, TemplateParameterList::iterator PEnd = Params->end(); if (MaxParameters) PEnd = Params->begin() + MaxParameters; - for (TemplateParameterList::iterator P = Params->begin() + Start; + for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd; ++P) { bool HasDefaultArg = false; std::string PlaceholderStr; @@ -2548,14 +2548,14 @@ static void AddTemplateParameterChunks(ASTContext &Context, PlaceholderStr = "typename"; else PlaceholderStr = "class"; - + if (TTP->getIdentifier()) { PlaceholderStr += ' '; PlaceholderStr += TTP->getIdentifier()->getName(); } - + HasDefaultArg = TTP->hasDefaultArgument(); - } else if (NonTypeTemplateParmDecl *NTTP + } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*P)) { if (NTTP->getIdentifier()) PlaceholderStr = NTTP->getIdentifier()->getName(); @@ -2564,7 +2564,7 @@ static void AddTemplateParameterChunks(ASTContext &Context, } else { assert(isa(*P)); TemplateTemplateParmDecl *TTP = cast(*P); - + // Since putting the template argument list into the placeholder would // be very, very long, we just use an abbreviation. PlaceholderStr = "template<...> class"; @@ -2572,10 +2572,10 @@ static void AddTemplateParameterChunks(ASTContext &Context, PlaceholderStr += ' '; PlaceholderStr += TTP->getIdentifier()->getName(); } - + HasDefaultArg = TTP->hasDefaultArgument(); } - + if (HasDefaultArg && !InDefaultArg) { // When we see an optional default argument, put that argument and // the remaining default arguments into a new, optional string. @@ -2588,31 +2588,31 @@ static void AddTemplateParameterChunks(ASTContext &Context, Result.AddOptionalChunk(Opt.TakeString()); break; } - + InDefaultArg = false; - + if (FirstParameter) FirstParameter = false; else Result.AddChunk(CodeCompletionString::CK_Comma); - + // Add the placeholder string. Result.AddPlaceholderChunk( Result.getAllocator().CopyString(PlaceholderStr)); - } + } } /// Add a qualifier to the given code-completion string, if the /// provided nested-name-specifier is non-NULL. -static void -AddQualifierToCompletionString(CodeCompletionBuilder &Result, - NestedNameSpecifier *Qualifier, +static void +AddQualifierToCompletionString(CodeCompletionBuilder &Result, + NestedNameSpecifier *Qualifier, bool QualifierIsInformative, ASTContext &Context, const PrintingPolicy &Policy) { if (!Qualifier) return; - + std::string PrintedNNS; { llvm::raw_string_ostream OS(PrintedNNS); @@ -2624,7 +2624,7 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result, Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); } -static void +static void AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, const FunctionDecl *Function) { const FunctionProtoType *Proto @@ -2633,7 +2633,7 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, return; // FIXME: Add ref-qualifier! - + // Handle single qualifiers without copying if (Proto->getTypeQuals() == Qualifiers::Const) { Result.AddInformativeChunk(" const"); @@ -2661,29 +2661,29 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); } -/// Add the name of the given declaration +/// Add the name of the given declaration static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, const NamedDecl *ND, CodeCompletionBuilder &Result) { DeclarationName Name = ND->getDeclName(); if (!Name) return; - + switch (Name.getNameKind()) { case DeclarationName::CXXOperatorName: { const char *OperatorName = nullptr; switch (Name.getCXXOverloadedOperator()) { - case OO_None: + case OO_None: case OO_Conditional: case NUM_OVERLOADED_OPERATORS: - OperatorName = "operator"; + OperatorName = "operator"; break; - + #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ case OO_##Name: OperatorName = "operator" Spelling; break; #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) #include "clang/Basic/OperatorKinds.def" - + case OO_New: OperatorName = "operator new"; break; case OO_Delete: OperatorName = "operator delete"; break; case OO_Array_New: OperatorName = "operator new[]"; break; @@ -2694,7 +2694,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.AddTypedTextChunk(OperatorName); break; } - + case DeclarationName::Identifier: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXDestructorName: @@ -2702,14 +2702,14 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.AddTypedTextChunk( Result.getAllocator().CopyString(ND->getNameAsString())); break; - + case DeclarationName::CXXDeductionGuideName: case DeclarationName::CXXUsingDirective: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: break; - + case DeclarationName::CXXConstructorName: { CXXRecordDecl *Record = nullptr; QualType Ty = Name.getCXXNameType(); @@ -2723,7 +2723,7 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, Result.getAllocator().CopyString(ND->getNameAsString())); break; } - + Result.AddTypedTextChunk( Result.getAllocator().CopyString(Record->getNameAsString())); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { @@ -2759,12 +2759,12 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) { CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); - + PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); if (Kind == RK_Pattern) { Pattern->Priority = Priority; Pattern->Availability = Availability; - + if (Declaration) { Result.addParentContext(Declaration->getDeclContext()); Pattern->ParentName = Result.getParentName(); @@ -2774,15 +2774,15 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Pattern->BriefComment = Result.getBriefComment(); } } - + return Pattern; } - + if (Kind == RK_Keyword) { Result.AddTypedTextChunk(Keyword); return Result.TakeString(); } - + if (Kind == RK_Macro) { const MacroInfo *MI = PP.getMacroInfo(Macro); Result.AddTypedTextChunk( @@ -2790,20 +2790,20 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (!MI || !MI->isFunctionLike()) return Result.TakeString(); - + // Format a function-like macro with placeholders for the arguments. Result.AddChunk(CodeCompletionString::CK_LeftParen); MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); - + // C99 variadic macros add __VA_ARGS__ at the end. Skip it. if (MI->isC99Varargs()) { --AEnd; - + if (A == AEnd) { Result.AddPlaceholderChunk("..."); } } - + for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { if (A != MI->param_begin()) Result.AddChunk(CodeCompletionString::CK_Comma); @@ -2825,7 +2825,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } - + assert(Kind == RK_Declaration && "Missed a result kind?"); const NamedDecl *ND = Declaration; Result.addParentContext(ND->getDeclContext()); @@ -2834,7 +2834,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // Add documentation comment, if it exists. if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) { Result.addBriefComment(RC->getBriefText(Ctx)); - } + } } if (StartsNestedNameSpecifier) { @@ -2848,9 +2848,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation())); AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); - + if (const FunctionDecl *Function = dyn_cast(ND)) { - AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); Result.AddChunk(CodeCompletionString::CK_LeftParen); @@ -2859,9 +2859,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); } - + if (const FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) { - AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); AddTypedNameChunk(Ctx, Policy, Function, Result); @@ -2882,30 +2882,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, LastDeducibleArgument - 1); if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) HasDefaultArg = TTP->hasDefaultArgument(); - else if (NonTypeTemplateParmDecl *NTTP + else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(Param)) HasDefaultArg = NTTP->hasDefaultArgument(); else { assert(isa(Param)); - HasDefaultArg + HasDefaultArg = cast(Param)->hasDefaultArgument(); } - + if (!HasDefaultArg) break; } } - + if (LastDeducibleArgument) { // Some of the function template arguments cannot be deduced from a // function call, so we introduce an explicit template argument list // containing all of the arguments up to the first deducible argument. Result.AddChunk(CodeCompletionString::CK_LeftAngle); - AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, + AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, LastDeducibleArgument); Result.AddChunk(CodeCompletionString::CK_RightAngle); } - + // Add the function parameters Result.AddChunk(CodeCompletionString::CK_LeftParen); AddFunctionParameterChunks(PP, Policy, Function, Result); @@ -2913,9 +2913,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); } - + if (const TemplateDecl *Template = dyn_cast(ND)) { - AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Template->getNameAsString())); @@ -2924,7 +2924,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddChunk(CodeCompletionString::CK_RightAngle); return Result.TakeString(); } - + if (const ObjCMethodDecl *Method = dyn_cast(ND)) { Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { @@ -2939,7 +2939,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); else { Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); - + // If there is only one parameter, and we're past it, add an empty // typed-text chunk since there is nothing to type. if (Method->param_size() == 1) @@ -2958,10 +2958,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Keyword += ":"; if (Idx < StartParameter || AllParametersAreInformative) Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); - else + else Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); } - + // If we're before the starting parameter, skip the placeholder. if (Idx < StartParameter) continue; @@ -2987,10 +2987,10 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (DeclaringEntity || AllParametersAreInformative) Arg += II->getName(); } - + if (Method->isVariadic() && (P + 1) == PEnd) Arg += ", ..."; - + if (DeclaringEntity) Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); else if (AllParametersAreInformative) @@ -3008,15 +3008,15 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, else Result.AddPlaceholderChunk(", ..."); } - + MaybeAddSentinel(PP, Method, Result); } - + return Result.TakeString(); } if (Qualifier) - AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); Result.AddTypedTextChunk( @@ -3160,7 +3160,7 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( const FunctionProtoType *Proto = dyn_cast(getFunctionType()); if (!FDecl && !Proto) { - // Function without a prototype. Just give the return type and a + // Function without a prototype. Just give the return type and a // highlighted ellipsis. const FunctionType *FT = getFunctionType(); Result.AddResultTypeChunk(Result.getAllocator().CopyString( @@ -3193,18 +3193,18 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( return Result.TakeString(); } -unsigned clang::getMacroUsagePriority(StringRef MacroName, +unsigned clang::getMacroUsagePriority(StringRef MacroName, const LangOptions &LangOpts, bool PreferredTypeIsPointer) { unsigned Priority = CCP_Macro; - + // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. - if (MacroName.equals("nil") || MacroName.equals("NULL") || + if (MacroName.equals("nil") || MacroName.equals("NULL") || MacroName.equals("Nil")) { Priority = CCP_Constant; if (PreferredTypeIsPointer) Priority = Priority / CCF_SimilarTypeMatch; - } + } // Treat "YES", "NO", "true", and "false" as constants. else if (MacroName.equals("YES") || MacroName.equals("NO") || MacroName.equals("true") || MacroName.equals("false")) @@ -3212,27 +3212,27 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName, // Treat "bool" as a type. else if (MacroName.equals("bool")) Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); - - + + return Priority; } CXCursorKind clang::getCursorKindForDecl(const Decl *D) { if (!D) return CXCursor_UnexposedDecl; - + switch (D->getKind()) { case Decl::Enum: return CXCursor_EnumDecl; case Decl::EnumConstant: return CXCursor_EnumConstantDecl; case Decl::Field: return CXCursor_FieldDecl; - case Decl::Function: + case Decl::Function: return CXCursor_FunctionDecl; case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; - case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; + case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; case Decl::ObjCMethod: return cast(D)->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; @@ -3261,17 +3261,17 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { case Decl::StaticAssert: return CXCursor_StaticAssert; case Decl::Friend: return CXCursor_FriendDecl; case Decl::TranslationUnit: return CXCursor_TranslationUnit; - + case Decl::Using: case Decl::UnresolvedUsingValue: - case Decl::UnresolvedUsingTypename: + case Decl::UnresolvedUsingTypename: return CXCursor_UsingDeclaration; - + case Decl::ObjCPropertyImpl: switch (cast(D)->getPropertyImplementation()) { case ObjCPropertyImplDecl::Dynamic: return CXCursor_ObjCDynamicDecl; - + case ObjCPropertyImplDecl::Synthesize: return CXCursor_ObjCSynthesizeDecl; } @@ -3292,7 +3292,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { } } } - + return CXCursor_UnexposedDecl; } @@ -3300,10 +3300,10 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, bool IncludeUndefined, bool TargetTypeIsPointer = false) { typedef CodeCompletionResult Result; - + Results.EnterNewScope(); - - for (Preprocessor::macro_iterator M = PP.macro_begin(), + + for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { auto MD = PP.getMacroDefinition(M->first); @@ -3318,17 +3318,17 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, TargetTypeIsPointer))); } } - + Results.ExitScope(); - + } -static void AddPrettyFunctionResults(const LangOptions &LangOpts, +static void AddPrettyFunctionResults(const LangOptions &LangOpts, ResultBuilder &Results) { typedef CodeCompletionResult Result; - + Results.EnterNewScope(); - + Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); Results.AddResult(Result("__FUNCTION__", CCP_Constant)); if (LangOpts.C99 || LangOpts.CPlusPlus11) @@ -3345,24 +3345,24 @@ static void HandleCodeCompleteResults(Sema *S, CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); } -static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, +static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { switch (PCC) { case Sema::PCC_Namespace: return CodeCompletionContext::CCC_TopLevel; - + case Sema::PCC_Class: return CodeCompletionContext::CCC_ClassStructUnion; case Sema::PCC_ObjCInterface: return CodeCompletionContext::CCC_ObjCInterface; - + case Sema::PCC_ObjCImplementation: return CodeCompletionContext::CCC_ObjCImplementation; case Sema::PCC_ObjCInstanceVariableList: return CodeCompletionContext::CCC_ObjCIvarList; - + case Sema::PCC_Template: case Sema::PCC_MemberTemplate: if (S.CurContext->isFileContext()) @@ -3370,7 +3370,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, if (S.CurContext->isRecord()) return CodeCompletionContext::CCC_ClassStructUnion; return CodeCompletionContext::CCC_Other; - + case Sema::PCC_RecoveryInFunction: return CodeCompletionContext::CCC_Recovery; @@ -3384,7 +3384,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_Expression: case Sema::PCC_Condition: return CodeCompletionContext::CCC_Expression; - + case Sema::PCC_Statement: return CodeCompletionContext::CCC_Statement; @@ -3393,7 +3393,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_ParenthesizedExpression: return CodeCompletionContext::CCC_ParenthesizedExpression; - + case Sema::PCC_LocalDeclarationSpecifiers: return CodeCompletionContext::CCC_Type; } @@ -3402,26 +3402,26 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, } /// If we're in a C++ virtual member function, add completion results -/// that invoke the functions we override, since it's common to invoke the +/// that invoke the functions we override, since it's common to invoke the /// overridden function as well as adding new functionality. /// /// \param S The semantic analysis object for which we are generating results. /// /// \param InContext This context in which the nested-name-specifier preceding -/// the code-completion point +/// the code-completion point static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, ResultBuilder &Results) { // Look through blocks. DeclContext *CurContext = S.CurContext; while (isa(CurContext)) CurContext = CurContext->getParent(); - - + + CXXMethodDecl *Method = dyn_cast(CurContext); if (!Method || !Method->isVirtual()) return; - - // We need to have names for all of the parameters, if we're going to + + // We need to have names for all of the parameters, if we're going to // generate a forwarding call. for (auto P : Method->parameters()) if (!P->getDeclName()) @@ -3433,7 +3433,7 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, Results.getCodeCompletionTUInfo()); if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) continue; - + // If we need a nested-name-specifier, add one now. if (!InContext) { NestedNameSpecifier *NNS @@ -3447,8 +3447,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, } } else if (!InContext->Equals(Overridden->getDeclContext())) continue; - - Builder.AddTypedTextChunk(Results.getAllocator().CopyString( + + Builder.AddTypedTextChunk(Results.getAllocator().CopyString( Overridden->getNameAsString())); Builder.AddChunk(CodeCompletionString::CK_LeftParen); bool FirstParam = true; @@ -3471,14 +3471,14 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, } } -void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, +void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); Results.EnterNewScope(); - + CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); typedef CodeCompletionResult Result; @@ -3490,7 +3490,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, Builder.AddTypedTextChunk( Builder.getAllocator().CopyString(Modules[I]->Name)); Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, + CCP_Declaration, CXCursor_ModuleImportDecl, Modules[I]->isAvailable() ? CXAvailability_Available @@ -3503,14 +3503,14 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, /*IsInclusionDirective=*/false); // Enumerate submodules. if (Mod) { - for (Module::submodule_iterator Sub = Mod->submodule_begin(), + for (Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { - + Builder.AddTypedTextChunk( Builder.getAllocator().CopyString((*Sub)->Name)); Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, + CCP_Declaration, CXCursor_ModuleImportDecl, (*Sub)->isAvailable() ? CXAvailability_Available @@ -3518,18 +3518,18 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, } } } - Results.ExitScope(); + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } -void Sema::CodeCompleteOrdinaryName(Scope *S, +void Sema::CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), mapCodeCompletionContext(*this, CompletionContext)); Results.EnterNewScope(); - + // Determine how to filter results, e.g., so that the names of // values (functions, enumerators, function templates, etc.) are // only allowed where we can have an expression. @@ -3555,11 +3555,11 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, Results.setFilter(&ResultBuilder::IsOrdinaryName); else Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); - + if (getLangOpts().CPlusPlus) MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results); break; - + case PCC_RecoveryInFunction: // Unfiltered break; @@ -3571,7 +3571,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, if (CurMethod->isInstance()) Results.setObjectTypeQualifiers( Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); - + CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), @@ -3588,7 +3588,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, if (S->getFnParent()) AddPrettyFunctionResults(getLangOpts(), Results); break; - + case PCC_Namespace: case PCC_Class: case PCC_ObjCInterface: @@ -3602,15 +3602,15 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case PCC_LocalDeclarationSpecifiers: break; } - + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } -static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef SelIdents, bool AtArgumentExpression, @@ -3627,7 +3627,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, ? CodeCompletionContext::CCC_PotentiallyQualifiedName : CodeCompletionContext::CCC_Name); Results.EnterNewScope(); - + // Type qualifiers can come after names. Results.AddResult(Result("const")); Results.AddResult(Result("volatile")); @@ -3641,9 +3641,9 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, Results.AddResult("final"); if (AllowNonIdentifiers) { - Results.AddResult(Result("operator")); + Results.AddResult(Result("operator")); } - + // Add nested-name-specifiers. if (AllowNestedNameSpecifiers) { Results.allowNestedNameSpecifiers(); @@ -3670,7 +3670,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, S && (S->getFlags() & Scope::DeclScope) != 0 && (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | - Scope::FunctionPrototypeScope | + Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == 0) { ParsedType T = DS.getRepAsType(); if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) @@ -3680,16 +3680,16 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, // Note that we intentionally suppress macro results here, since we do not // encourage using macros to produce the names of entities. - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } struct Sema::CodeCompleteExpressionData { - CodeCompleteExpressionData(QualType PreferredType = QualType()) + CodeCompleteExpressionData(QualType PreferredType = QualType()) : PreferredType(PreferredType), IntegralConstantExpression(false), ObjCCollection(false) { } - + QualType PreferredType; bool IntegralConstantExpression; bool ObjCCollection; @@ -3698,7 +3698,7 @@ struct Sema::CodeCompleteExpressionData { /// Perform code-completion in an expression context when we know what /// type we're looking for. -void Sema::CodeCompleteExpression(Scope *S, +void Sema::CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data) { ResultBuilder Results( *this, CodeCompleter->getAllocator(), @@ -3716,11 +3716,11 @@ void Sema::CodeCompleteExpression(Scope *S, if (!Data.PreferredType.isNull()) Results.setPreferredType(Data.PreferredType.getNonReferenceType()); - + // Ignore any declarations that we were told that we don't care about. for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) Results.Ignore(Data.IgnoreDecls[I]); - + CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), @@ -3729,15 +3729,15 @@ void Sema::CodeCompleteExpression(Scope *S, Results.EnterNewScope(); AddOrdinaryNameResults(PCC_Expression, S, *this, Results); Results.ExitScope(); - + bool PreferredTypeIsPointer = false; if (!Data.PreferredType.isNull()) PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() - || Data.PreferredType->isMemberPointerType() + || Data.PreferredType->isMemberPointerType() || Data.PreferredType->isBlockPointerType(); - - if (S->getFnParent() && - !Data.ObjCCollection && + + if (S->getFnParent() && + !Data.ObjCCollection && !Data.IntegralConstantExpression) AddPrettyFunctionResults(getLangOpts(), Results); @@ -3763,14 +3763,14 @@ static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { if (ObjCInterfaceDecl *Interface = dyn_cast(Container)) { if (Interface->hasDefinition()) return Interface->getDefinition(); - + return Interface; } - + if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { if (Protocol->hasDefinition()) return Protocol->getDefinition(); - + return Protocol; } return Container; @@ -3823,7 +3823,7 @@ static void AddObjCProperties( // Retrieve the definition. Container = getContainerDef(Container); - + // Add properties in this container. const auto AddProperty = [&](const ObjCPropertyDecl *P) { if (!AddedProperties.insert(P->getIdentifier()).second) @@ -3942,7 +3942,7 @@ static void AddObjCProperties( } } } - + // Add properties in referenced protocols. if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { for (auto *P : Protocol->protocols()) @@ -4190,23 +4190,23 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { Filter = &ResultBuilder::IsEnum; ContextKind = CodeCompletionContext::CCC_EnumTag; break; - + case DeclSpec::TST_union: Filter = &ResultBuilder::IsUnion; ContextKind = CodeCompletionContext::CCC_UnionTag; break; - + case DeclSpec::TST_struct: case DeclSpec::TST_class: case DeclSpec::TST_interface: Filter = &ResultBuilder::IsClassOrStruct; ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; - + default: llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); } - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), ContextKind); CodeCompletionDeclConsumer Consumer(Results, CurContext); @@ -4224,7 +4224,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); } - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } @@ -4250,7 +4250,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { Results.EnterNewScope(); AddTypeQualifierResults(DS, Results, LangOpts); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -4293,20 +4293,20 @@ void Sema::CodeCompleteCase(Scope *S) { CodeCompleteExpression(S, Data); return; } - + // Code-complete the cases of a switch statement over an enumeration type - // by providing the list of + // by providing the list of EnumDecl *Enum = type->castAs()->getDecl(); if (EnumDecl *Def = Enum->getDefinition()) Enum = Def; - + // Determine which enumerators we have already seen in the switch statement. // FIXME: Ideally, we would also be able to look *past* the code-completion // token, in case we are code-completing in the middle of the switch and not // at the end. However, we aren't able to do so at the moment. llvm::SmallPtrSet EnumeratorsSeen; NestedNameSpecifier *Qualifier = nullptr; - for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; + for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { CaseStmt *Case = dyn_cast(SC); if (!Case) @@ -4314,16 +4314,16 @@ void Sema::CodeCompleteCase(Scope *S) { Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); if (DeclRefExpr *DRE = dyn_cast(CaseVal)) - if (EnumConstantDecl *Enumerator + if (EnumConstantDecl *Enumerator = dyn_cast(DRE->getDecl())) { - // We look into the AST of the case statement to determine which - // enumerator was named. Alternatively, we could compute the value of + // We look into the AST of the case statement to determine which + // enumerator was named. Alternatively, we could compute the value of // the integral constant expression, then compare it against the - // values of each enumerator. However, value-based approach would not - // work as well with C++ templates where enumerators declared within a + // values of each enumerator. However, value-based approach would not + // work as well with C++ templates where enumerators declared within a // template are type- and value-dependent. EnumeratorsSeen.insert(Enumerator); - + // If this is a qualified-id, keep track of the nested-name-specifier // so that we can reproduce it as part of code completion, e.g., // @@ -4338,14 +4338,14 @@ void Sema::CodeCompleteCase(Scope *S) { Qualifier = DRE->getQualifier(); } } - + if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { - // If there are no prior enumerators in C++, check whether we have to + // If there are no prior enumerators in C++, check whether we have to // qualify the names of the enumerators that we suggest, because they // may not be visible in this scope. Qualifier = getRequiredQualification(Context, CurContext, Enum); } - + // Add any enumerators that have not yet been mentioned. ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), @@ -4354,7 +4354,7 @@ void Sema::CodeCompleteCase(Scope *S) { for (auto *E : Enum->enumerators()) { if (EnumeratorsSeen.count(E)) continue; - + CodeCompletionResult R(E, CCP_EnumInCase, Qualifier); Results.AddResult(R, CurContext, nullptr, false); } @@ -4596,7 +4596,7 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { CodeCompleteOrdinaryName(S, PCC_Expression); return; } - + CodeCompleteExpression(S, VD->getType()); } @@ -4622,14 +4622,14 @@ void Sema::CodeCompleteAfterIf(Scope *S) { mapCodeCompletionContext(*this, PCC_Statement)); Results.setFilter(&ResultBuilder::IsOrdinaryName); Results.EnterNewScope(); - + CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); AddOrdinaryNameResults(PCC_Statement, S, *this, Results); - + // "else" block CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -4666,13 +4666,13 @@ void Sema::CodeCompleteAfterIf(Scope *S) { Results.AddResult(Builder.TakeString()); Results.ExitScope(); - + if (S->getFnParent()) AddPrettyFunctionResults(getLangOpts(), Results); - + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } @@ -4749,18 +4749,18 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, void Sema::CodeCompleteUsing(Scope *S) { if (!CodeCompleter) return; - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PotentiallyQualifiedName, &ResultBuilder::IsNestedNameSpecifier); Results.EnterNewScope(); - + // If we aren't in class scope, we could see the "namespace" keyword. if (!S->isClassScope()) Results.AddResult(CodeCompletionResult("namespace")); - - // After "using", we can see anything that would start a + + // After "using", we can see anything that would start a // nested-name-specifier. CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, @@ -4775,7 +4775,7 @@ void Sema::CodeCompleteUsing(Scope *S) { void Sema::CodeCompleteUsingDirective(Scope *S) { if (!CodeCompleter) return; - + // After "using namespace", we expect to see a namespace name or namespace // alias. ResultBuilder Results(*this, CodeCompleter->getAllocator(), @@ -4795,36 +4795,36 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!CodeCompleter) return; - + DeclContext *Ctx = S->getEntity(); if (!S->getParent()) Ctx = Context.getTranslationUnitDecl(); - + bool SuppressedGlobalResults = Ctx && !CodeCompleter->includeGlobals() && isa(Ctx); - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), SuppressedGlobalResults ? CodeCompletionContext::CCC_Namespace : CodeCompletionContext::CCC_Other, &ResultBuilder::IsNamespace); - + if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { // We only want to see those namespaces that have already been defined // within this scope, because its likely that the user is creating an - // extended namespace declaration. Keep track of the most recent + // extended namespace declaration. Keep track of the most recent // definition of each namespace. std::map OrigToLatest; - for (DeclContext::specific_decl_iterator + for (DeclContext::specific_decl_iterator NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); NS != NSEnd; ++NS) OrigToLatest[NS->getOriginalNamespace()] = *NS; - - // Add the most recent definition (or extended definition) of each + + // Add the most recent definition (or extended definition) of each // namespace to the list of results. Results.EnterNewScope(); - for (std::map::iterator + for (std::map::iterator NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) @@ -4834,8 +4834,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { CurContext, nullptr, false); Results.ExitScope(); } - - HandleCodeCompleteResults(this, CodeCompleter, + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } @@ -4843,7 +4843,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { if (!CodeCompleter) return; - + // After "namespace", we expect to see a namespace or alias. ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), @@ -4853,7 +4853,7 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } @@ -4868,13 +4868,13 @@ void Sema::CodeCompleteOperatorName(Scope *S) { CodeCompletionContext::CCC_Type, &ResultBuilder::IsType); Results.EnterNewScope(); - + // Add the names of overloadable operators. #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ if (std::strcmp(Spelling, "?")) \ Results.AddResult(Result(Spelling)); #include "clang/Basic/OperatorKinds.def" - + // Add any type names visible from the current scope Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); @@ -4901,12 +4901,12 @@ void Sema::CodeCompleteConstructorInitializer( CXXConstructorDecl *Constructor = dyn_cast(ConstructorD); if (!Constructor) return; - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PotentiallyQualifiedName); Results.EnterNewScope(); - + // Fill in any already-initialized fields or base classes. llvm::SmallPtrSet InitializedFields; llvm::SmallPtrSet InitializedBases; @@ -4918,7 +4918,7 @@ void Sema::CodeCompleteConstructorInitializer( InitializedFields.insert(cast( Initializers[I]->getAnyMember())); } - + // Add completions for base classes. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -4929,69 +4929,69 @@ void Sema::CodeCompleteConstructorInitializer( if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { SawLastInitializer - = !Initializers.empty() && + = !Initializers.empty() && Initializers.back()->isBaseInitializer() && Context.hasSameUnqualifiedType(Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - + Builder.AddTypedTextChunk( Results.getAllocator().CopyString( Base.getType().getAsString(Policy))); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("args"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SawLastInitializer? CCP_NextInitializer : CCP_MemberDeclaration)); SawLastInitializer = false; } - + // Add completions for virtual base classes. for (const auto &Base : ClassDecl->vbases()) { if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { SawLastInitializer - = !Initializers.empty() && + = !Initializers.empty() && Initializers.back()->isBaseInitializer() && Context.hasSameUnqualifiedType(Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - + Builder.AddTypedTextChunk( Builder.getAllocator().CopyString( Base.getType().getAsString(Policy))); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("args"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SawLastInitializer? CCP_NextInitializer : CCP_MemberDeclaration)); SawLastInitializer = false; } - + // Add completions for members. for (auto *Field : ClassDecl->fields()) { if (!InitializedFields.insert(cast(Field->getCanonicalDecl())) .second) { SawLastInitializer - = !Initializers.empty() && + = !Initializers.empty() && Initializers.back()->isAnyMemberInitializer() && Initializers.back()->getAnyMember() == Field; continue; } - + if (!Field->getDeclName()) continue; - + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Field->getIdentifier()->getName())); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("args"); Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SawLastInitializer? CCP_NextInitializer : CCP_MemberDeclaration, CXCursor_MemberRef, @@ -5000,7 +5000,7 @@ void Sema::CodeCompleteConstructorInitializer( SawLastInitializer = false; } Results.ExitScope(); - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -5029,10 +5029,10 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, IncludedThis = true; continue; } - + Known.insert(C.Id); } - + // Look for other capturable variables. for (; S && !isNamespaceScope(S); S = S->getParent()) { for (const auto *D : S->decls()) { @@ -5041,7 +5041,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, !Var->hasLocalStorage() || Var->hasAttr()) continue; - + if (Known.insert(Var->getIdentifier()).second) Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), CurContext, nullptr, false); @@ -5051,9 +5051,9 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, // Add 'this', if it would be valid. if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) addThisCompletion(*this, Results); - + Results.ExitScope(); - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -5068,7 +5068,7 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, typedef CodeCompletionResult Result; // Since we have an implementation, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); - + CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); if (LangOpts.ObjC2) { @@ -5077,30 +5077,30 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); - + // @synthesize Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); - } + } } static void AddObjCInterfaceResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - + // Since we have an interface or protocol, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); - + if (LangOpts.ObjC2) { // @property Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property"))); - + // @required Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required"))); - + // @optional Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional"))); } @@ -5110,35 +5110,35 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - + // @class name ; Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); - + if (Results.includeCodePatterns()) { - // @interface name - // FIXME: Could introduce the whole pattern, including superclasses and + // @interface name + // FIXME: Could introduce the whole pattern, including superclasses and // such. Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); - + // @protocol name Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("protocol"); Results.AddResult(Result(Builder.TakeString())); - + // @implementation name Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); } - + // @compatibility_alias name Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -5188,7 +5188,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { Builder.AddPlaceholderChunk("type-name"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); - + // @protocol ( protocol-name ) Builder.AddResultTypeChunk("Protocol *"); Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); @@ -5241,7 +5241,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - + if (Results.includeCodePatterns()) { // @try { statements } @catch ( declaration ) { statements } @finally // { statements } @@ -5262,13 +5262,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - + // @throw Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); - + if (Results.includeCodePatterns()) { // @synchronized ( expression ) { statements } Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized")); @@ -5334,14 +5334,14 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { // Check if we've already added this flag. if (Attributes & NewFlag) return true; - + Attributes |= NewFlag; - + // Check for collisions with "readonly". if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) return true; - + // Check for more than one of { assign, copy, retain, strong, weak }. unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | @@ -5357,16 +5357,16 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak) return true; - + return false; } -void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { +void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { if (!CodeCompleter) return; - + unsigned Attributes = ODS.getPropertyAttributes(); - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); @@ -5438,20 +5438,20 @@ static bool isAcceptableObjCSelector(Selector Sel, unsigned NumSelIdents = SelIdents.size(); if (NumSelIdents > Sel.getNumArgs()) return false; - + switch (WantKind) { case MK_Any: break; case MK_ZeroArgSelector: return Sel.isUnarySelector(); case MK_OneArgSelector: return Sel.getNumArgs() == 1; } - + if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) return false; - + for (unsigned I = 0; I != NumSelIdents; ++I) if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) return false; - + return true; } @@ -5464,16 +5464,16 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, } namespace { - /// A set of selectors, which is used to avoid introducing multiple + /// A set of selectors, which is used to avoid introducing multiple /// completions with the same selector into the result set. typedef llvm::SmallPtrSet VisitedSelectorSet; } -/// Add all of the Objective-C methods in the given Objective-C +/// Add all of the Objective-C methods in the given Objective-C /// container to the set of results. /// -/// The container will be a class, protocol, category, or implementation of -/// any of the above. This mether will recurse to include methods from +/// The container will be a class, protocol, category, or implementation of +/// any of the above. This mether will recurse to include methods from /// the superclasses of classes along with their categories, protocols, and /// implementations. /// @@ -5505,7 +5505,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, // metaclass. if (M->isInstanceMethod() == WantInstanceMethods || (IsRootClass && !WantInstanceMethods)) { - // Check whether the selector identifiers we've been given are a + // Check whether the selector identifiers we've been given are a // subset of the identifiers for this particular method. if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength)) continue; @@ -5521,23 +5521,23 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Results.MaybeAddResult(R, CurContext); } } - + // Visit the protocols of protocols. if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { if (Protocol->hasDefinition()) { const ObjCList &Protocols = Protocol->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, false, IsRootClass); } } - + if (!IFace || !IFace->hasDefinition()) return; - + // Add methods in protocols. for (auto *I : IFace->protocols()) AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext, @@ -5550,7 +5550,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, InOriginalClass, IsRootClass); // Add a categories protocol methods. - const ObjCList &Protocols + const ObjCList &Protocols = CatDecl->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), E = Protocols.end(); @@ -5564,7 +5564,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Selectors, AllowSameLength, Results, InOriginalClass, IsRootClass); } - + // Add methods in superclass. // Avoid passing in IsRootClass since root classes won't have super classes. if (IFace->getSuperClass()) @@ -5640,22 +5640,22 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type); Results.EnterNewScope(); - + // Add context-sensitive, Objective-C parameter-passing keywords. bool AddedInOut = false; - if ((DS.getObjCDeclQualifier() & + if ((DS.getObjCDeclQualifier() & (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) { Results.AddResult("in"); Results.AddResult("inout"); AddedInOut = true; } - if ((DS.getObjCDeclQualifier() & + if ((DS.getObjCDeclQualifier() & (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) { Results.AddResult("out"); if (!AddedInOut) Results.AddResult("inout"); } - if ((DS.getObjCDeclQualifier() & + if ((DS.getObjCDeclQualifier() & (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | ObjCDeclSpec::DQ_Oneway)) == 0) { Results.AddResult("bycopy"); @@ -5667,8 +5667,8 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, Results.AddResult("nullable"); Results.AddResult("null_unspecified"); } - - // If we're completing the return type of an Objective-C method and the + + // If we're completing the return type of an Objective-C method and the // identifier IBAction refers to a macro, provide a completion item for // an action, e.g., // IBAction)<#selector#>:(id)sender @@ -5692,11 +5692,11 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, if (!IsParameter) { Results.AddResult(CodeCompletionResult("instancetype")); } - + // Add various builtin type names and specifiers. AddOrdinaryNameResults(PCC_Type, S, *this, Results); Results.ExitScope(); - + // Add the various type names Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); CodeCompletionDeclConsumer Consumer(Results, CurContext); @@ -5783,7 +5783,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { } // Add a special completion for a message send to "super", which fills in the -// most likely case of forwarding all of our arguments to the superclass +// most likely case of forwarding all of our arguments to the superclass // function. /// /// \param S The semantic analysis object. @@ -5796,7 +5796,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { /// /// \param Results The set of results to augment. /// -/// \returns the Objective-C method declaration that would be invoked by +/// \returns the Objective-C method declaration that would be invoked by /// this "super" completion. If NULL, no completion was added. static ObjCMethodDecl *AddSuperSendCompletion( Sema &S, bool NeedSuperKeyword, @@ -5814,7 +5814,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( ObjCMethodDecl *SuperMethod = nullptr; while ((Class = Class->getSuperClass()) && !SuperMethod) { // Check in the class - SuperMethod = Class->getMethod(CurMethod->getSelector(), + SuperMethod = Class->getMethod(CurMethod->getSelector(), CurMethod->isInstanceMethod()); // Check in categories or class extensions. @@ -5840,7 +5840,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( SuperP = SuperMethod->param_begin(); CurP != CurPEnd; ++CurP, ++SuperP) { // Make sure the parameter types are compatible. - if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), + if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), (*SuperP)->getType())) return nullptr; @@ -5848,11 +5848,11 @@ static ObjCMethodDecl *AddSuperSendCompletion( if (!(*CurP)->getIdentifier()) return nullptr; } - + // We have a superclass method. Now, form the send-to-super completion. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - + // Give this completion a return type. AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, Results.getCompletionContext().getBaseType(), @@ -5863,7 +5863,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( Builder.AddTypedTextChunk("super"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); } - + Selector Sel = CurMethod->getSelector(); if (Sel.isUnarySelector()) { if (NeedSuperKeyword) @@ -5877,7 +5877,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { if (I > SelIdents.size()) Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - + if (I < SelIdents.size()) Builder.AddInformativeChunk( Builder.getAllocator().CopyString( @@ -5893,16 +5893,16 @@ static ObjCMethodDecl *AddSuperSendCompletion( Builder.getAllocator().CopyString( Sel.getNameForSlot(I) + ":")); Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( - (*CurP)->getIdentifier()->getName())); + (*CurP)->getIdentifier()->getName())); } } } - + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, CCP_SuperCompletion)); return SuperMethod; } - + void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), @@ -5911,7 +5911,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { getLangOpts().CPlusPlus11 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture : &ResultBuilder::IsObjCMessageReceiver); - + CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, @@ -5924,20 +5924,20 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) if (Iface->getSuperClass()) { Results.AddResult(Result("super")); - + AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results); } - + if (getLangOpts().CPlusPlus11) addThisCompletion(*this, Results); - + Results.ExitScope(); - + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); - + } void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, @@ -5949,7 +5949,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, CDecl = CurMethod->getClassInterface(); if (!CDecl) return; - + // Find the superclass of this class. CDecl = CDecl->getSuperClass(); if (!CDecl) @@ -5969,7 +5969,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // "super" may be the name of a type or variable. Figure out which // it is. IdentifierInfo *Super = getSuperIdentifier(); - NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); if ((CDecl = dyn_cast_or_null(ND))) { // "super" names an interface. Use it. @@ -5998,7 +5998,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, ParsedType Receiver; if (CDecl) Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); - return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, + return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, AtArgumentExpression, /*IsSuper=*/true); } @@ -6007,15 +6007,15 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, /// send, determine the preferred type (if any) for that argument expression. static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, unsigned NumSelIdents) { - typedef CodeCompletionResult Result; + typedef CodeCompletionResult Result; ASTContext &Context = Results.getSema().Context; - + QualType PreferredType; unsigned BestPriority = CCP_Unlikely * 2; Result *ResultsData = Results.data(); for (unsigned I = 0, N = Results.size(); I != N; ++I) { Result &R = ResultsData[I]; - if (R.Kind == Result::RK_Declaration && + if (R.Kind == Result::RK_Declaration && isa(R.Declaration)) { if (R.Priority <= BestPriority) { const ObjCMethodDecl *Method = cast(R.Declaration); @@ -6037,7 +6037,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, return PreferredType; } -static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef SelIdents, bool AtArgumentExpression, @@ -6050,55 +6050,55 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, // corresponding declaration. if (Receiver) { QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr); - if (!T.isNull()) + if (!T.isNull()) if (const ObjCObjectType *Interface = T->getAs()) CDecl = Interface->getInterface(); } - + // Add all of the factory methods in this Objective-C class, its protocols, // superclasses, categories, implementation, etc. Results.EnterNewScope(); - - // If this is a send-to-super, try to add the special "super" send + + // If this is a send-to-super, try to add the special "super" send // completion. if (IsSuper) { if (ObjCMethodDecl *SuperMethod = AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) Results.Ignore(SuperMethod); } - + // If we're inside an Objective-C method definition, prefer its selector to // others. if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) Results.setPreferredSelector(CurMethod->getSelector()); - + VisitedSelectorSet Selectors; - if (CDecl) + if (CDecl) AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext, Selectors, AtArgumentExpression, - Results); + Results); else { // We're messaging "id" as a type; provide all class/factory methods. - + // If we have an external source, load the entire class method // pool from the AST file. if (SemaRef.getExternalSource()) { - for (uint32_t I = 0, + for (uint32_t I = 0, N = SemaRef.getExternalSource()->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I); if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) continue; - + SemaRef.ReadMethodPool(Sel); } } - + for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), MEnd = SemaRef.MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.second; - MethList && MethList->getMethod(); + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -6111,32 +6111,32 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, } } } - - Results.ExitScope(); + + Results.ExitScope(); } void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, ArrayRef SelIdents, bool AtArgumentExpression, bool IsSuper) { - + QualType T = this->GetTypeFromParser(Receiver); - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, SelIdents)); - + AddClassMessageCompletions(*this, S, Receiver, SelIdents, AtArgumentExpression, IsSuper, Results); - - // If we're actually at the argument expression (rather than prior to the + + // If we're actually at the argument expression (rather than prior to the // selector), we're actually performing code completion for an expression. - // Determine whether we have a single, best method. If so, we can + // Determine whether we have a single, best method. If so, we can // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); @@ -6145,7 +6145,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, return; } - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -6155,9 +6155,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, bool AtArgumentExpression, ObjCInterfaceDecl *Super) { typedef CodeCompletionResult Result; - + Expr *RecExpr = static_cast(Receiver); - + // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. if (RecExpr) { @@ -6166,18 +6166,18 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; RecExpr = Conv.get(); } - QualType ReceiverType = RecExpr? RecExpr->getType() + QualType ReceiverType = RecExpr? RecExpr->getType() : Super? Context.getObjCObjectPointerType( Context.getObjCInterfaceType(Super)) : Context.getObjCIdType(); - + // If we're messaging an expression with type "id" or "Class", check // whether we know something special about the receiver that allows // us to assume a more-specific receiver type. if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) { if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { if (ReceiverType->isObjCClassType()) - return CodeCompleteObjCClassMessage(S, + return CodeCompleteObjCClassMessage(S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents, AtArgumentExpression, Super); @@ -6198,36 +6198,36 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, ReceiverType, SelIdents)); - + Results.EnterNewScope(); - // If this is a send-to-super, try to add the special "super" send + // If this is a send-to-super, try to add the special "super" send // completion. if (Super) { if (ObjCMethodDecl *SuperMethod = AddSuperSendCompletion(*this, false, SelIdents, Results)) Results.Ignore(SuperMethod); } - + // If we're inside an Objective-C method definition, prefer its selector to // others. if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) Results.setPreferredSelector(CurMethod->getSelector()); - + // Keep track of the selectors we've already added. VisitedSelectorSet Selectors; - + // Handle messages to Class. This really isn't a message to an instance // method, so we treat it the same way we would treat a message send to a // class method. - if (ReceiverType->isObjCClassType() || + if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, Selectors, AtArgumentExpression, Results); } - } + } // Handle messages to a qualified ID ("id"). else if (const ObjCObjectPointerType *QualID = ReceiverType->getAsObjCQualifiedIdType()) { @@ -6243,7 +6243,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, CurContext, Selectors, AtArgumentExpression, Results); - + // Search protocols for instance methods. for (auto *I : IFacePtr->quals()) AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, @@ -6271,11 +6271,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, MEnd = MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.first; - MethList && MethList->getMethod(); + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; - + if (!Selectors.insert(MethList->getMethod()->getSelector()).second) continue; @@ -6288,15 +6288,15 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, } } Results.ExitScope(); - - - // If we're actually at the argument expression (rather than prior to the + + + // If we're actually at the argument expression (rather than prior to the // selector), we're actually performing code completion for an expression. - // Determine whether we have a single, best method. If so, we can + // Determine whether we have a single, best method. If so, we can // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); @@ -6304,17 +6304,17 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, CodeCompleteExpression(S, PreferredType); return; } - - HandleCodeCompleteResults(this, CodeCompleter, + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); } -void Sema::CodeCompleteObjCForCollection(Scope *S, +void Sema::CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar) { CodeCompleteExpressionData Data; Data.ObjCCollection = true; - + if (IterationVar.getAsOpaquePtr()) { DeclGroupRef DG = IterationVar.get(); for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { @@ -6322,7 +6322,7 @@ void Sema::CodeCompleteObjCForCollection(Scope *S, Data.IgnoreDecls.push_back(*I); } } - + CodeCompleteExpression(S, Data); } @@ -6336,11 +6336,11 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || MethodPool.count(Sel)) continue; - + ReadMethodPool(Sel); } } - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_SelectorName); @@ -6348,7 +6348,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, for (GlobalMethodPool::iterator M = MethodPool.begin(), MEnd = MethodPool.end(); M != MEnd; ++M) { - + Selector Sel = M->first; if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents)) continue; @@ -6361,7 +6361,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Results.AddResult(Builder.TakeString()); continue; } - + std::string Accumulator; for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { if (I == SelIdents.size()) { @@ -6371,7 +6371,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Accumulator.clear(); } } - + Accumulator += Sel.getNameForSlot(I); Accumulator += ':'; } @@ -6390,7 +6390,7 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, bool OnlyForwardDeclarations, ResultBuilder &Results) { typedef CodeCompletionResult Result; - + for (const auto *D : Ctx->decls()) { // Record any protocols we find. if (const auto *Proto = dyn_cast(D)) @@ -6405,10 +6405,10 @@ void Sema::CodeCompleteObjCProtocolReferences( ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); - + if (CodeCompleter->includeGlobals()) { Results.EnterNewScope(); - + // Tell the result set to ignore all of the protocols we have // already seen. // FIXME: This doesn't work when caching code-completion results. @@ -6432,10 +6432,10 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); - + if (CodeCompleter->includeGlobals()) { Results.EnterNewScope(); - + // Add all protocols. AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, Results); @@ -6454,7 +6454,7 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, bool OnlyUnimplemented, ResultBuilder &Results) { typedef CodeCompletionResult Result; - + for (const auto *D : Ctx->decls()) { // Record any interfaces we find. if (const auto *Class = dyn_cast(D)) @@ -6476,7 +6476,7 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, false, Results); } - + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -6484,12 +6484,12 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { } void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc) { + SourceLocation ClassNameLoc) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCInterfaceName); Results.EnterNewScope(); - + // Make sure that we ignore the class we're currently defining. NamedDecl *CurClass = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); @@ -6501,7 +6501,7 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, false, Results); } - + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -6519,22 +6519,22 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, true, Results); } - + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } -void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, +void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { typedef CodeCompletionResult Result; - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); - + // Ignore any categories we find that have already been implemented by this // interface. llvm::SmallPtrSet CategoryNames; @@ -6548,7 +6548,7 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, // Add all of the categories we know about. Results.EnterNewScope(); TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - for (const auto *D : TU->decls()) + for (const auto *D : TU->decls()) if (const auto *Category = dyn_cast(D)) if (CategoryNames.insert(Category->getIdentifier()).second) Results.AddResult(Result(Category, Results.getBasePriority(Category), @@ -6560,11 +6560,11 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, Results.data(), Results.size()); } -void Sema::CodeCompleteObjCImplementationCategory(Scope *S, +void Sema::CodeCompleteObjCImplementationCategory(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { typedef CodeCompletionResult Result; - + // Find the corresponding interface. If we couldn't find the interface, the // program itself is ill-formed. However, we'll try to be helpful still by // providing the list of all of the categories we know about. @@ -6573,12 +6573,12 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, ObjCInterfaceDecl *Class = dyn_cast_or_null(CurClass); if (!Class) return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); - + ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCCategoryName); - - // Add all of the categories that have have corresponding interface + + // Add all of the categories that have have corresponding interface // declarations in this class and any of its superclasses, except for // already-implemented categories in the class itself. llvm::SmallPtrSet CategoryNames; @@ -6591,7 +6591,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr), CurContext, nullptr, false); } - + Class = Class->getSuperClass(); IgnoreImplemented = false; } @@ -6610,29 +6610,29 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { // Figure out where this @synthesize lives. ObjCContainerDecl *Container = dyn_cast_or_null(CurContext); - if (!Container || - (!isa(Container) && + if (!Container || + (!isa(Container) && !isa(Container))) - return; + return; // Ignore any properties that have already been implemented. Container = getContainerDef(Container); for (const auto *D : Container->decls()) if (const auto *PropertyImpl = dyn_cast(D)) Results.Ignore(PropertyImpl->getPropertyDecl()); - + // Add any properties that we find. AddedPropertiesSet AddedProperties; Results.EnterNewScope(); if (ObjCImplementationDecl *ClassImpl = dyn_cast(Container)) AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false, - /*AllowNullaryMethods=*/false, CurContext, + /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); else AddObjCProperties(CCContext, cast(Container)->getCategoryDecl(), - false, /*AllowNullaryMethods=*/false, CurContext, + false, /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); Results.ExitScope(); @@ -6640,7 +6640,7 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { Results.data(), Results.size()); } -void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, +void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, IdentifierInfo *PropertyName) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), @@ -6650,11 +6650,11 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Figure out where this @synthesize lives. ObjCContainerDecl *Container = dyn_cast_or_null(CurContext); - if (!Container || - (!isa(Container) && + if (!Container || + (!isa(Container) && !isa(Container))) - return; - + return; + // Figure out which interface we're looking into. ObjCInterfaceDecl *Class = nullptr; if (ObjCImplementationDecl *ClassImpl @@ -6669,10 +6669,10 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, if (Class) { if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { - PropertyType + PropertyType = Property->getType().getNonReferenceType().getUnqualifiedType(); - - // Give preference to ivars + + // Give preference to ivars Results.setPreferredType(PropertyType); } } @@ -6686,32 +6686,32 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, std::string NameWithSuffix = PropertyName->getName().str(); NameWithSuffix += '_'; for(; Class; Class = Class->getSuperClass()) { - for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; + for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; Ivar = Ivar->getNextIvar()) { Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), CurContext, nullptr, false); - // Determine whether we've seen an ivar with a name similar to the + // Determine whether we've seen an ivar with a name similar to the // property. if ((PropertyName == Ivar->getIdentifier() || NameWithPrefix == Ivar->getName() || NameWithSuffix == Ivar->getName())) { SawSimilarlyNamedIvar = true; - + // Reduce the priority of this result by one, to give it a slight // advantage over other results whose names don't match so closely. - if (Results.size() && - Results.data()[Results.size() - 1].Kind + if (Results.size() && + Results.data()[Results.size() - 1].Kind == CodeCompletionResult::RK_Declaration && Results.data()[Results.size() - 1].Declaration == Ivar) Results.data()[Results.size() - 1].Priority--; } } } - + if (!SawSimilarlyNamedIvar) { // Create ivar result _propName, that the user can use to synthesize - // an ivar of the appropriate type. + // an ivar of the appropriate type. unsigned Priority = CCP_MemberDeclaration + 1; typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); @@ -6722,10 +6722,10 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, Policy, Allocator)); Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); - Results.AddResult(Result(Builder.TakeString(), Priority, + Results.AddResult(Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl)); } - + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -6754,11 +6754,11 @@ static void FindImplementableMethods(ASTContext &Context, IFace = IFace->getDefinition(); Container = IFace; - + const ObjCList &Protocols = IFace->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, KnownMethods, InOriginalClass); @@ -6766,12 +6766,12 @@ static void FindImplementableMethods(ASTContext &Context, // Add methods from any class extensions and categories. for (auto *Cat : IFace->visible_categories()) { FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType, - KnownMethods, false); + KnownMethods, false); } // Visit the superclass. if (IFace->getSuperClass()) - FindImplementableMethods(Context, IFace->getSuperClass(), + FindImplementableMethods(Context, IFace->getSuperClass(), WantInstanceMethods, ReturnType, KnownMethods, false); } @@ -6781,14 +6781,14 @@ static void FindImplementableMethods(ASTContext &Context, const ObjCList &Protocols = Category->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, KnownMethods, InOriginalClass); - + // If this category is the original class, jump to the interface. if (InOriginalClass && Category->getClassInterface()) - FindImplementableMethods(Context, Category->getClassInterface(), + FindImplementableMethods(Context, Category->getClassInterface(), WantInstanceMethods, ReturnType, KnownMethods, false); } @@ -6799,12 +6799,12 @@ static void FindImplementableMethods(ASTContext &Context, return; Protocol = Protocol->getDefinition(); Container = Protocol; - + // Recurse into protocols. const ObjCList &Protocols = Protocol->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, KnownMethods, false); @@ -6825,7 +6825,7 @@ static void FindImplementableMethods(ASTContext &Context, } } -/// Add the parenthesized return or parameter type chunk to a code +/// Add the parenthesized return or parameter type chunk to a code /// completion string. static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals, @@ -6843,17 +6843,17 @@ static void AddObjCPassingTypeChunk(QualType Type, /// Determine whether the given class is or inherits from a class by /// the given name. -static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, +static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) { if (!Class) return false; - + if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name) return true; - + return InheritsFromClassNamed(Class->getSuperClass(), Name); } - + /// Add code completions for Objective-C Key-Value Coding (KVC) and /// Key-Value Observing (KVO). static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, @@ -6865,17 +6865,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, IdentifierInfo *PropName = Property->getIdentifier(); if (!PropName || PropName->getLength() == 0) return; - + PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); // Builder that will create each code completion. typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); - + // The selector table. SelectorTable &Selectors = Context.Selectors; - + // The property name, copied into the code completion allocation region // on demand. struct KeyHolder { @@ -6889,22 +6889,22 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, operator const char *() { if (CopiedKey) return CopiedKey; - + return CopiedKey = Allocator.CopyString(Key); } } Key(Allocator, PropName->getName()); - + // The uppercased name of the property name. std::string UpperKey = PropName->getName(); if (!UpperKey.empty()) UpperKey[0] = toUppercase(UpperKey[0]); - + bool ReturnTypeMatchesProperty = ReturnType.isNull() || - Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), + Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), Property->getType()); - bool ReturnTypeMatchesVoid + bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType(); - + // Add the normal accessor -(type)key. if (IsInstanceMethod && KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second && @@ -6912,19 +6912,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, if (ReturnType.isNull()) AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, Builder); - + Builder.AddTypedTextChunk(Key); - Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); } - + // If we have an integral or boolean property (or the user has provided // an integral or boolean return type), add the accessor -(type)isKey. if (IsInstanceMethod && - ((!ReturnType.isNull() && + ((!ReturnType.isNull() && (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || - (ReturnType.isNull() && - (Property->getType()->isIntegerType() || + (ReturnType.isNull() && + (Property->getType()->isIntegerType() || Property->getType()->isBooleanType())))) { std::string SelectorName = (Twine("is") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); @@ -6935,16 +6935,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("BOOL"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk( Allocator.CopyString(SelectorId->getName())); - Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); } } - + // Add the normal mutator. - if (IsInstanceMethod && ReturnTypeMatchesVoid && + if (IsInstanceMethod && ReturnTypeMatchesVoid && !Property->getSetterMethodDecl()) { std::string SelectorName = (Twine("set") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); @@ -6954,36 +6954,36 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk( Allocator.CopyString(SelectorId->getName())); Builder.AddTypedTextChunk(":"); AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, Builder); Builder.AddTextChunk(Key); - Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); } } - + // Indexed and unordered accessors unsigned IndexedGetterPriority = CCP_CodePattern; unsigned IndexedSetterPriority = CCP_CodePattern; unsigned UnorderedGetterPriority = CCP_CodePattern; unsigned UnorderedSetterPriority = CCP_CodePattern; - if (const ObjCObjectPointerType *ObjCPointer + if (const ObjCObjectPointerType *ObjCPointer = Property->getType()->getAs()) { if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { // If this interface type is not provably derived from a known // collection, penalize the corresponding completions. if (!InheritsFromClassNamed(IFace, "NSMutableArray")) { - IndexedSetterPriority += CCD_ProbablyNotObjCCollection; + IndexedSetterPriority += CCD_ProbablyNotObjCCollection; if (!InheritsFromClassNamed(IFace, "NSArray")) IndexedGetterPriority += CCD_ProbablyNotObjCCollection; } if (!InheritsFromClassNamed(IFace, "NSMutableSet")) { - UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; + UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; if (!InheritsFromClassNamed(IFace, "NSSet")) UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; } @@ -6994,9 +6994,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; } - + // Add -(NSUInteger)countOf - if (IsInstanceMethod && + if (IsInstanceMethod && (ReturnType.isNull() || ReturnType->isIntegerType())) { std::string SelectorName = (Twine("countOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); @@ -7007,16 +7007,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSUInteger"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk( Allocator.CopyString(SelectorId->getName())); - Results.AddResult(Result(Builder.TakeString(), - std::min(IndexedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), + std::min(IndexedGetterPriority, UnorderedGetterPriority), CXCursor_ObjCInstanceMethodDecl)); } } - + // Indexed getters // Add -(id)objectInKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && @@ -7030,20 +7030,20 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("id"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSUInteger"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("index"); - Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && - (ReturnType.isNull() || + (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs()->getInterfaceDecl() && ReturnType->getAs()->getInterfaceDecl() @@ -7057,17 +7057,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSArray *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSIndexSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("indexes"); - Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // Add -(void)getKey:(type **)buffer range:(NSRange)inRange if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("get") + UpperKey).str(); @@ -7075,14 +7075,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, &Context.Idents.get(SelectorName), &Context.Idents.get("range") }; - + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("object-type"); @@ -7095,13 +7095,13 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSRange"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("inRange"); - Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // Mutable indexed accessors - + // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); @@ -7109,14 +7109,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, &Context.Idents.get("insertObject"), &Context.Idents.get(SelectorName) }; - + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk("insertObject:"); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("object-type"); @@ -7129,11 +7129,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddPlaceholderChunk("NSUInteger"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("index"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("insert") + UpperKey).str(); @@ -7141,14 +7141,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, &Context.Idents.get(SelectorName), &Context.Idents.get("atIndexes") }; - + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSArray *"); @@ -7160,55 +7160,55 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddPlaceholderChunk("NSIndexSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("indexes"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); - IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSUInteger"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("index"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str(); - IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSIndexSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("indexes"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName @@ -7217,14 +7217,14 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, &Context.Idents.get(SelectorName), &Context.Idents.get("withObject") }; - + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("NSUInteger"); @@ -7236,28 +7236,28 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("id"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName1 + std::string SelectorName1 = (Twine("replace") + UpperKey + "AtIndexes").str(); std::string SelectorName2 = (Twine("with") + UpperKey).str(); IdentifierInfo *SelectorIds[2] = { &Context.Idents.get(SelectorName1), &Context.Idents.get(SelectorName2) }; - + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("NSIndexSet *"); @@ -7269,15 +7269,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSArray *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("array"); - Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } - + } + // Unordered getters // - (NSEnumerator *)enumeratorOfKey - if (IsInstanceMethod && - (ReturnType.isNull() || + if (IsInstanceMethod && + (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs()->getInterfaceDecl() && ReturnType->getAs()->getInterfaceDecl() @@ -7291,15 +7291,15 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSEnumerator *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); - Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } // - (type *)memberOfKey:(type *)object - if (IsInstanceMethod && + if (IsInstanceMethod && (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { std::string SelectorName = (Twine("memberOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); @@ -7310,24 +7310,24 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk(" *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); if (ReturnType.isNull()) { Builder.AddPlaceholderChunk("object-type"); Builder.AddTextChunk(" *"); } else { - Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, + Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, Policy, Builder.getAllocator())); } Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); - Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, CXCursor_ObjCInstanceMethodDecl)); } } - + // Mutable unordered accessors // - (void)addKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { @@ -7340,17 +7340,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("object-type"); Builder.AddTextChunk(" *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); - Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } + } // - (void)addKey:(NSSet *)objects if (IsInstanceMethod && ReturnTypeMatchesVoid) { @@ -7362,17 +7362,17 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("objects"); - Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } - + } + // - (void)removeKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName @@ -7384,18 +7384,18 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("object-type"); Builder.AddTextChunk(" *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); - Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } - + } + // - (void)removeKey:(NSSet *)objects if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("remove") + UpperKey).str(); @@ -7406,16 +7406,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("objects"); - Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } + } // - (void)intersectKey:(NSSet *)objects if (IsInstanceMethod && ReturnTypeMatchesVoid) { @@ -7427,26 +7427,26 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("void"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddTextChunk("NSSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("objects"); - Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, CXCursor_ObjCInstanceMethodDecl)); } - } - + } + // Key-Value Observing // + (NSSet *)keyPathsForValuesAffectingKey - if (!IsInstanceMethod && - (ReturnType.isNull() || + if (!IsInstanceMethod && + (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs()->getInterfaceDecl() && ReturnType->getAs()->getInterfaceDecl() ->getName() == "NSSet"))) { - std::string SelectorName + std::string SelectorName = (Twine("keyPathsForValuesAffecting") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -7456,9 +7456,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("NSSet *"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); - Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCClassMethodDecl)); } } @@ -7466,9 +7466,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // + (BOOL)automaticallyNotifiesObserversForKey if (!IsInstanceMethod && (ReturnType.isNull() || - ReturnType->isIntegerType() || + ReturnType->isIntegerType() || ReturnType->isBooleanType())) { - std::string SelectorName + std::string SelectorName = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -7478,9 +7478,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTextChunk("BOOL"); Builder.AddChunk(CodeCompletionString::CK_RightParen); } - + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); - Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCClassMethodDecl)); } } @@ -7503,7 +7503,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, if (ObjCImplementationDecl *Impl = dyn_cast(D)) { SearchDecl = Impl->getClassInterface(); IsInImplementation = true; - } else if (ObjCCategoryImplDecl *CatImpl + } else if (ObjCCategoryImplDecl *CatImpl = dyn_cast(D)) { SearchDecl = CatImpl->getCategoryDecl(); IsInImplementation = true; @@ -7517,17 +7517,17 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, } if (!SearchDecl) { - HandleCodeCompleteResults(this, CodeCompleter, + HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_Other, nullptr, 0); return; } - + // Find all of the methods that we could declare/implement here. KnownMethodsMap KnownMethods; - FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, + FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType, KnownMethods); - + // Add declarations or definitions for each of the known methods. typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), @@ -7535,7 +7535,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, CodeCompletionContext::CCC_Other); Results.EnterNewScope(); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); - for (KnownMethodsMap::iterator M = KnownMethods.begin(), + for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) { ObjCMethodDecl *Method = M->second.getPointer(); @@ -7566,7 +7566,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, // Add parameters to the pattern. unsigned I = 0; - for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), PEnd = Method->param_end(); P != PEnd; (void)++P, ++I) { // Add the part of the selector name. @@ -7592,16 +7592,16 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, (*P)->getObjCDeclQualifier(), Context, Policy, Builder); - + if (IdentifierInfo *Id = (*P)->getIdentifier()) - Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); + Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); } if (Method->isVariadic()) { if (Method->param_size() > 0) Builder.AddChunk(CodeCompletionString::CK_Comma); Builder.AddTextChunk("..."); - } + } if (IsInImplementation && Results.includeCodePatterns()) { // We will be defining the method here, so add a compound statement. @@ -7616,7 +7616,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, Builder.AddChunk(CodeCompletionString::CK_SemiColon); } else Builder.AddPlaceholderChunk("statements"); - + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); Builder.AddChunk(CodeCompletionString::CK_RightBrace); } @@ -7624,28 +7624,28 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, unsigned Priority = CCP_CodePattern; if (!M->second.getInt()) Priority += CCD_InBaseClass; - + Results.AddResult(Result(Builder.TakeString(), Method, Priority)); } - // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of + // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of // the properties in this class and its categories. if (Context.getLangOpts().ObjC2) { SmallVector Containers; Containers.push_back(SearchDecl); - + VisitedSelectorSet KnownSelectors; - for (KnownMethodsMap::iterator M = KnownMethods.begin(), + for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) KnownSelectors.insert(M->first); - + ObjCInterfaceDecl *IFace = dyn_cast(SearchDecl); if (!IFace) if (ObjCCategoryDecl *Category = dyn_cast(SearchDecl)) IFace = Category->getClassInterface(); - + if (IFace) for (auto *Cat : IFace->visible_categories()) Containers.push_back(Cat); @@ -7657,14 +7657,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional IsInstanceMethod, KnownSelectors, Results); } } - + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } -void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, +void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, @@ -7687,21 +7687,21 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); - + if (ReturnTy) Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); - Results.EnterNewScope(); + Results.EnterNewScope(); for (GlobalMethodPool::iterator M = MethodPool.begin(), MEnd = MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : &M->second.second; - MethList && MethList->getMethod(); + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; - + if (AtParameterName) { // Suggest parameter names we've seen before. unsigned NumSelIdents = SelIdents.size(); @@ -7717,7 +7717,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, Results.AddResult(Builder.TakeString()); } } - + continue; } @@ -7729,7 +7729,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, Results.MaybeAddResult(R, CurContext); } } - + Results.ExitScope(); if (!AtParameterName && !SelIdents.empty() && @@ -7757,7 +7757,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorDirective); Results.EnterNewScope(); - + // #if CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -7765,13 +7765,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("condition"); Results.AddResult(Builder.TakeString()); - + // #ifdef Builder.AddTypedTextChunk("ifdef"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("macro"); Results.AddResult(Builder.TakeString()); - + // #ifndef Builder.AddTypedTextChunk("ifndef"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7793,7 +7793,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddTypedTextChunk("endif"); Results.AddResult(Builder.TakeString()); } - + // #include "header" Builder.AddTypedTextChunk("include"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7809,13 +7809,13 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("header"); Builder.AddTextChunk(">"); Results.AddResult(Builder.TakeString()); - + // #define Builder.AddTypedTextChunk("define"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("macro"); Results.AddResult(Builder.TakeString()); - + // #define () Builder.AddTypedTextChunk("define"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7824,7 +7824,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("args"); Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Builder.TakeString()); - + // #undef Builder.AddTypedTextChunk("undef"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7836,7 +7836,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("number"); Results.AddResult(Builder.TakeString()); - + // #line "filename" Builder.AddTypedTextChunk("line"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7846,7 +7846,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("filename"); Builder.AddTextChunk("\""); Results.AddResult(Builder.TakeString()); - + // #error Builder.AddTypedTextChunk("error"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7867,7 +7867,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("header"); Builder.AddTextChunk("\""); Results.AddResult(Builder.TakeString()); - + // #import
Builder.AddTypedTextChunk("import"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7876,7 +7876,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddTextChunk(">"); Results.AddResult(Builder.TakeString()); } - + // #include_next "header" Builder.AddTypedTextChunk("include_next"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7884,7 +7884,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("header"); Builder.AddTextChunk("\""); Results.AddResult(Builder.TakeString()); - + // #include_next
Builder.AddTypedTextChunk("include_next"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7912,7 +7912,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { CodeCompleteOrdinaryName(S, - S->getFnParent()? Sema::PCC_RecoveryInFunction + S->getFnParent()? Sema::PCC_RecoveryInFunction : Sema::PCC_Namespace); } @@ -7922,11 +7922,11 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { IsDefinition? CodeCompletionContext::CCC_MacroName : CodeCompletionContext::CCC_MacroNameUse); if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { - // Add just the names of macros, not their arguments. + // Add just the names of macros, not their arguments. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), + for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( @@ -7939,19 +7939,19 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { } else if (IsDefinition) { // FIXME: Can we detect when the user just wrote an include guard above? } - + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(), Results.size()); + Results.data(), Results.size()); } void Sema::CodeCompletePreprocessorExpression() { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_PreprocessorExpression); - + if (!CodeCompleter || CodeCompleter->includeMacros()) AddMacroResults(PP, Results, true); - + // defined () Results.EnterNewScope(); CodeCompletionBuilder Builder(Results.getAllocator(), @@ -7974,7 +7974,7 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, unsigned Argument) { // FIXME: In the future, we could provide "overload" results, much like we // do for function calls. - + // Now just ignore this. There will be another code-completion callback // for the expanded tokens. } @@ -8007,17 +8007,17 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, ResultBuilder Builder(*this, Allocator, CCTUInfo, CodeCompletionContext::CCC_Recovery); if (!CodeCompleter || CodeCompleter->includeGlobals()) { - CodeCompletionDeclConsumer Consumer(Builder, + CodeCompletionDeclConsumer Consumer(Builder, Context.getTranslationUnitDecl()); LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, Consumer, !CodeCompleter || CodeCompleter->loadExternal()); } - + if (!CodeCompleter || CodeCompleter->includeMacros()) AddMacroResults(PP, Builder, true); - + Results.clear(); - Results.insert(Results.end(), + Results.insert(Results.end(), Builder.data(), Builder.data() + Builder.size()); } -- GitLab From 60f7669eb5ab57464faf42a85d8b0219e6e1fdf9 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Thu, 5 Jul 2018 09:51:13 +0000 Subject: [PATCH 0410/1023] [ASTImporter] Fix import of objects with anonymous types Summary: Currently, anonymous types are merged into the same redecl chain even if they are structurally inequivalent. This results that global objects are not imported, if there are at least two global objects with different anonymous types. This patch provides a fix. Reviewers: a.sidorin, balazske, r.stahl Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D48773 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336332 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 13 ++----------- unittests/AST/ASTImporterTest.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index bc75d80a55..759f9da30b 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2072,17 +2072,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (auto *FoundRecord = dyn_cast(Found)) { if (!SearchName) { - // If both unnamed structs/unions are in a record context, make sure - // they occur in the same location in the context records. - if (Optional Index1 = - StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( - D)) { - if (Optional Index2 = StructuralEquivalenceContext:: - findUntaggedStructOrUnionIndex(FoundRecord)) { - if (*Index1 != *Index2) - continue; - } - } + if (!IsStructuralMatch(D, FoundRecord, false)) + continue; } PrevDecl = FoundRecord; diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index dfcb6c1893..1f86b91a88 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -1682,6 +1682,35 @@ TEST_P( .match(ToTU, classTemplateSpecializationDecl())); } +TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) { + Decl *FromTU = getTuDecl( + R"( + struct { int a; int b; } object0 = { 2, 3 }; + struct { int x; int y; int z; } object1; + )", + Lang_CXX, "input0.cc"); + + auto getRecordDecl = [](VarDecl *VD) { + auto *ET = cast(VD->getType().getTypePtr()); + return cast(ET->getNamedType().getTypePtr())->getDecl(); + }; + + auto *Obj0 = + FirstDeclMatcher().match(FromTU, varDecl(hasName("object0"))); + auto *From0 = getRecordDecl(Obj0); + auto *Obj1 = + FirstDeclMatcher().match(FromTU, varDecl(hasName("object1"))); + auto *From1 = getRecordDecl(Obj1); + + auto *To0 = Import(From0, Lang_CXX); + auto *To1 = Import(From1, Lang_CXX); + + EXPECT_TRUE(To0); + EXPECT_TRUE(To1); + EXPECT_NE(To0, To1); + EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl()); +} + struct ImportFunctions : ASTImporterTestBase {}; TEST_P(ImportFunctions, -- GitLab From e1d62757aefc3bd3766f2ac7b886f9cee2e33065 Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Thu, 5 Jul 2018 12:57:47 +0000 Subject: [PATCH 0411/1023] [X86] NFC - add more test cases for vector cmp intrinsics Add test cases with each predicate using the following intrinsics: _mm_cmp_pd _mm_cmp_ps _mm256_cmp_pd _mm256_cmp_ps _mm_cmp_pd_mask _mm_cmp_ps_mask _mm256_cmp_pd_mask _mm256_cmp_ps_mask _mm512_cmp_pd_mask _mm512_cmp_ps_mask _mm_mask_cmp_pd_mask _mm_mask_cmp_ps_mask _mm256_mask_cmp_pd_mask _mm256_mask_cmp_ps_mask _mm512_mask_cmp_pd_mask _mm512_mask_cmp_ps_mask Some of these are marked with FIXME, as there is bug in lowering e.g. _mm512_mask_cmp_ps_mask. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336346 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/avx-builtins.c | 888 ++++++++++++++-- test/CodeGen/avx512f-builtins.c | 813 ++++++++++++++- test/CodeGen/avx512vl-builtins.c | 1673 ++++++++++++++++++++++++++++-- 3 files changed, 3152 insertions(+), 222 deletions(-) diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index cbed537127..f0e232089b 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -212,28 +212,788 @@ __m256 test_mm_ceil_ps(__m256 x) { return _mm256_ceil_ps(x); } -__m128d test_mm_cmp_pd(__m128d A, __m128d B) { - // CHECK-LABEL: test_mm_cmp_pd - // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(A, B, _CMP_GE_OS); +__m256d test_mm256_cmp_pd_eq_oq(__m256d a, __m256d b) { + // CHECK-LABEL: @test_mm256_cmp_pd_eq_oq + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); } -__m256d test_mm256_cmp_pd(__m256d A, __m256d B) { - // CHECK-LABEL: test_mm256_cmp_pd - // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}} - return _mm256_cmp_pd(A, B, _CMP_GE_OS); +__m256d test_mm256_cmp_pd_lt_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_lt_os + // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_LT_OS); } -__m128 test_mm_cmp_ps(__m128 A, __m128 B) { - // CHECK-LABEL: test_mm_cmp_ps - // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(A, B, _CMP_GE_OS); +__m256d test_mm256_cmp_pd_le_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_le_os + // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_LE_OS); } -__m256 test_mm256_cmp_ps(__m256d A, __m256d B) { - // CHECK-LABEL: test_mm256_cmp_ps - // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}} - return _mm256_cmp_ps(A, B, _CMP_GE_OS); +__m256d test_mm256_cmp_pd_unord_q(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_unord_q + // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_UNORD_Q); +} + +__m256d test_mm256_cmp_pd_neq_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_neq_uq + // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); +} + +__m256d test_mm256_cmp_pd_nlt_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nlt_us + // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NLT_US); +} + +__m256d test_mm256_cmp_pd_nle_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nle_us + // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NLE_US); +} + +__m256d test_mm256_cmp_pd_ord_q(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ord_q + // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_ORD_Q); +} + +__m256d test_mm256_cmp_pd_eq_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_eq_uq + // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_EQ_UQ); +} + +__m256d test_mm256_cmp_pd_nge_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nge_us + // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NGE_US); +} + +__m256d test_mm256_cmp_pd_ngt_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ngt_us + // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NGT_US); +} + +__m256d test_mm256_cmp_pd_false_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_false_oq + // CHECK-NOT: call + // CHECK: ret <4 x double> zeroinitializer + return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ); +} + +__m256d test_mm256_cmp_pd_neq_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_neq_oq + // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NEQ_OQ); +} + +__m256d test_mm256_cmp_pd_ge_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ge_os + // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_GE_OS); +} + +__m256d test_mm256_cmp_pd_gt_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_gt_os + // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_GT_OS); +} + +__m256d test_mm256_cmp_pd_true_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_true_uq + // CHECK-NOT: call + // CHECK: ret <4 x double> + return _mm256_cmp_pd(a, b, _CMP_TRUE_UQ); +} + +__m256d test_mm256_cmp_pd_eq_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_eq_os + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_EQ_OS); +} + +__m256d test_mm256_cmp_pd_lt_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_lt_oq + // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_LT_OQ); +} + +__m256d test_mm256_cmp_pd_le_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_le_oq + // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_LE_OQ); +} + +__m256d test_mm256_cmp_pd_unord_s(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_unord_s + // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_UNORD_S); +} + +__m256d test_mm256_cmp_pd_neq_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_neq_us + // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NEQ_US); +} + +__m256d test_mm256_cmp_pd_nlt_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nlt_uq + // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NLT_UQ); +} + +__m256d test_mm256_cmp_pd_nle_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nle_uq + // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NLE_UQ); +} + +__m256d test_mm256_cmp_pd_ord_s(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ord_s + // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_ORD_S); +} + +__m256d test_mm256_cmp_pd_eq_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_eq_us + // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_EQ_US); +} + +__m256d test_mm256_cmp_pd_nge_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_nge_uq + // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NGE_UQ); +} + +__m256d test_mm256_cmp_pd_ngt_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ngt_uq + // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NGT_UQ); +} + +__m256d test_mm256_cmp_pd_false_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_false_os + // CHECK-NOT: call + // CHECK: ret <4 x double> zeroinitializer + return _mm256_cmp_pd(a, b, _CMP_FALSE_OS); +} + +__m256d test_mm256_cmp_pd_neq_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_neq_os + // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_NEQ_OS); +} + +__m256d test_mm256_cmp_pd_ge_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_ge_oq + // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_GE_OQ); +} + +__m256d test_mm256_cmp_pd_gt_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_gt_oq + // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd(a, b, _CMP_GT_OQ); +} + +__m256d test_mm256_cmp_pd_true_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_true_us + // CHECK-NOT: call + // CHECK: ret <4 x double> + return _mm256_cmp_pd(a, b, _CMP_TRUE_US); +} + +__m256 test_mm256_cmp_ps_eq_oq(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_ps_eq_oq + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); +} + +__m256 test_mm256_cmp_ps_lt_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_lt_os + // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_LT_OS); +} + +__m256 test_mm256_cmp_ps_le_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_le_os + // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_LE_OS); +} + +__m256 test_mm256_cmp_ps_unord_q(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_unord_q + // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_UNORD_Q); +} + +__m256 test_mm256_cmp_ps_neq_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_neq_uq + // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); +} + +__m256 test_mm256_cmp_ps_nlt_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nlt_us + // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NLT_US); +} + +__m256 test_mm256_cmp_ps_nle_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nle_us + // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NLE_US); +} + +__m256 test_mm256_cmp_ps_ord_q(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ord_q + // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_ORD_Q); +} + +__m256 test_mm256_cmp_ps_eq_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_eq_uq + // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_EQ_UQ); +} + +__m256 test_mm256_cmp_ps_nge_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nge_us + // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NGE_US); +} + +__m256 test_mm256_cmp_ps_ngt_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ngt_us + // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NGT_US); +} + +__m256 test_mm256_cmp_ps_false_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_false_oq + // CHECK-NOT: call + // CHECK: ret <8 x float> zeroinitializer + return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); +} + +__m256 test_mm256_cmp_ps_neq_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_neq_oq + // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NEQ_OQ); +} + +__m256 test_mm256_cmp_ps_ge_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ge_os + // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_GE_OS); +} + +__m256 test_mm256_cmp_ps_gt_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_gt_os + // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_GT_OS); +} + +__m256 test_mm256_cmp_ps_true_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_true_uq + // CHECK-NOT: call + // CHECK: ret <8 x float> + return _mm256_cmp_ps(a, b, _CMP_TRUE_UQ); +} + +__m256 test_mm256_cmp_ps_eq_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_eq_os + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_EQ_OS); +} + +__m256 test_mm256_cmp_ps_lt_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_lt_oq + // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_LT_OQ); +} + +__m256 test_mm256_cmp_ps_le_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_le_oq + // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_LE_OQ); +} + +__m256 test_mm256_cmp_ps_unord_s(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_unord_s + // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_UNORD_S); +} + +__m256 test_mm256_cmp_ps_neq_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_neq_us + // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NEQ_US); +} + +__m256 test_mm256_cmp_ps_nlt_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nlt_uq + // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NLT_UQ); +} + +__m256 test_mm256_cmp_ps_nle_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nle_uq + // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NLE_UQ); +} + +__m256 test_mm256_cmp_ps_ord_s(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ord_s + // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_ORD_S); +} + +__m256 test_mm256_cmp_ps_eq_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_eq_us + // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_EQ_US); +} + +__m256 test_mm256_cmp_ps_nge_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_nge_uq + // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NGE_UQ); +} + +__m256 test_mm256_cmp_ps_ngt_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ngt_uq + // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NGT_UQ); +} + +__m256 test_mm256_cmp_ps_false_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_false_os + // CHECK-NOT: call + // CHECK: ret <8 x float> zeroinitializer + return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); +} + +__m256 test_mm256_cmp_ps_neq_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_neq_os + // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_NEQ_OS); +} + +__m256 test_mm256_cmp_ps_ge_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_ge_oq + // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_GE_OQ); +} + +__m256 test_mm256_cmp_ps_gt_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_gt_oq + // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps(a, b, _CMP_GT_OQ); +} + +__m256 test_mm256_cmp_ps_true_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_true_us + // CHECK-NOT: call + // CHECK: ret <8 x float> + return _mm256_cmp_ps(a, b, _CMP_TRUE_US); +} + +__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) { + // CHECK-LABEL: @test_mm_cmp_pd_eq_oq + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_EQ_OQ); +} + +__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_lt_os + // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LT_OS); +} + +__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_le_os + // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LE_OS); +} + +__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_unord_q + // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_UNORD_Q); +} + +__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_neq_uq + // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NEQ_UQ); +} + +__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nlt_us + // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLT_US); +} + +__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nle_us + // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLE_US); +} + +__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ord_q + // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_ORD_Q); +} + +__m128d test_mm_cmp_pd_eq_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_eq_uq + // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_EQ_UQ); +} + +__m128d test_mm_cmp_pd_nge_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nge_us + // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NGE_US); +} + +__m128d test_mm_cmp_pd_ngt_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ngt_us + // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NGT_US); +} + +__m128d test_mm_cmp_pd_false_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_false_oq + // CHECK-NOT: call + // CHECK: ret <2 x double> zeroinitializer + return _mm_cmp_pd(a, b, _CMP_FALSE_OQ); +} + +__m128d test_mm_cmp_pd_neq_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_neq_oq + // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NEQ_OQ); +} + +__m128d test_mm_cmp_pd_ge_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ge_os + // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_GE_OS); +} + +__m128d test_mm_cmp_pd_gt_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_gt_os + // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_GT_OS); +} + +__m128d test_mm_cmp_pd_true_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_true_uq + // CHECK-NOT: call + // CHECK: ret <2 x double> + return _mm_cmp_pd(a, b, _CMP_TRUE_UQ); +} + +__m128d test_mm_cmp_pd_eq_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_eq_os + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_EQ_OS); +} + +__m128d test_mm_cmp_pd_lt_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_lt_oq + // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LT_OQ); +} + +__m128d test_mm_cmp_pd_le_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_le_oq + // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LE_OQ); +} + +__m128d test_mm_cmp_pd_unord_s(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_unord_s + // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_UNORD_S); +} + +__m128d test_mm_cmp_pd_neq_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_neq_us + // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NEQ_US); +} + +__m128d test_mm_cmp_pd_nlt_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nlt_uq + // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLT_UQ); +} + +__m128d test_mm_cmp_pd_nle_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nle_uq + // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLE_UQ); +} + +__m128d test_mm_cmp_pd_ord_s(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ord_s + // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_ORD_S); +} + +__m128d test_mm_cmp_pd_eq_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_eq_us + // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_EQ_US); +} + +__m128d test_mm_cmp_pd_nge_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nge_uq + // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NGE_UQ); +} + +__m128d test_mm_cmp_pd_ngt_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ngt_uq + // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NGT_UQ); +} + +__m128d test_mm_cmp_pd_false_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_false_os + // CHECK-NOT: call + // CHECK: ret <2 x double> zeroinitializer + return _mm_cmp_pd(a, b, _CMP_FALSE_OS); +} + +__m128d test_mm_cmp_pd_neq_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_neq_os + // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NEQ_OS); +} + +__m128d test_mm_cmp_pd_ge_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ge_oq + // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_GE_OQ); +} + +__m128d test_mm_cmp_pd_gt_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_gt_oq + // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_GT_OQ); +} + +__m128d test_mm_cmp_pd_true_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_true_us + // CHECK-NOT: call + // CHECK: ret <2 x double> + return _mm_cmp_pd(a, b, _CMP_TRUE_US); +} + +__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_ps_eq_oq + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_EQ_OQ); +} + +__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_lt_os + // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LT_OS); +} + +__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_le_os + // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LE_OS); +} + +__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_unord_q + // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_UNORD_Q); +} + +__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_neq_uq + // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NEQ_UQ); +} + +__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nlt_us + // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLT_US); +} + +__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nle_us + // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLE_US); +} + +__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ord_q + // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_ORD_Q); +} + +__m128 test_mm_cmp_ps_eq_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_eq_uq + // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_EQ_UQ); +} + +__m128 test_mm_cmp_ps_nge_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nge_us + // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NGE_US); +} + +__m128 test_mm_cmp_ps_ngt_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ngt_us + // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NGT_US); +} + +__m128 test_mm_cmp_ps_false_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_false_oq + // CHECK-NOT: call + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_ps(a, b, _CMP_FALSE_OQ); +} + +__m128 test_mm_cmp_ps_neq_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_neq_oq + // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NEQ_OQ); +} + +__m128 test_mm_cmp_ps_ge_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ge_os + // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_GE_OS); +} + +__m128 test_mm_cmp_ps_gt_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_gt_os + // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_GT_OS); +} + +__m128 test_mm_cmp_ps_true_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_true_uq + // CHECK-NOT: call + // CHECK: ret <4 x float> + return _mm_cmp_ps(a, b, _CMP_TRUE_UQ); +} + +__m128 test_mm_cmp_ps_eq_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_eq_os + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_EQ_OS); +} + +__m128 test_mm_cmp_ps_lt_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_lt_oq + // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LT_OQ); +} + +__m128 test_mm_cmp_ps_le_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_le_oq + // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LE_OQ); +} + +__m128 test_mm_cmp_ps_unord_s(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_unord_s + // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_UNORD_S); +} + +__m128 test_mm_cmp_ps_neq_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_neq_us + // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NEQ_US); +} + +__m128 test_mm_cmp_ps_nlt_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nlt_uq + // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLT_UQ); +} + +__m128 test_mm_cmp_ps_nle_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nle_uq + // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLE_UQ); +} + +__m128 test_mm_cmp_ps_ord_s(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ord_s + // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_ORD_S); +} + +__m128 test_mm_cmp_ps_eq_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_eq_us + // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_EQ_US); +} + +__m128 test_mm_cmp_ps_nge_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nge_uq + // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NGE_UQ); +} + +__m128 test_mm_cmp_ps_ngt_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ngt_uq + // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NGT_UQ); +} + +__m128 test_mm_cmp_ps_false_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_false_os + // CHECK-NOT: call + // CHECK: ret <4 x float> zeroinitializer + return _mm_cmp_ps(a, b, _CMP_FALSE_OS); +} + +__m128 test_mm_cmp_ps_neq_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_neq_os + // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NEQ_OS); +} + +__m128 test_mm_cmp_ps_ge_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ge_oq + // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_GE_OQ); +} + +__m128 test_mm_cmp_ps_gt_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_gt_oq + // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_GT_OQ); +} + +__m128 test_mm_cmp_ps_true_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_true_us + // CHECK-NOT: call + // CHECK: ret <4 x float> + return _mm_cmp_ps(a, b, _CMP_TRUE_US); } __m128d test_mm_cmp_sd(__m128d A, __m128d B) { @@ -1419,99 +2179,3 @@ float test_mm256_cvtss_f32(__m256 __a) // CHECK: extractelement <8 x float> %{{.*}}, i32 0 return _mm256_cvtss_f32(__a); } - -__m256 test_mm256_cmp_ps_true(__m256 a, __m256 b) { - // CHECK-LABEL: @test_mm256_cmp_ps_true - // CHECK: ret <8 x float> zeroinitializer - return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); -} - -__m256d test_mm256_cmp_pd_false(__m256d a, __m256d b) { - // CHECK-LABEL: @test_mm256_cmp_pd_false - // CHECK: ret <4 x double> zeroinitializer - return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ); -} - -__m256 test_mm256_cmp_ps_strue(__m256 a, __m256 b) { - // CHECK-LABEL: @test_mm256_cmp_ps_strue - // CHECK: ret <8 x float> zeroinitializer - return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); -} - -__m256d test_mm256_cmp_pd_sfalse(__m256d a, __m256d b) { - // CHECK-LABEL: @test_mm256_cmp_pd_sfalse - // CHECK: ret <4 x double> zeroinitializer - return _mm256_cmp_pd(a, b, _CMP_FALSE_OS); -} - -__m128 test_mm_cmp_ps_true(__m128 a, __m128 b) { - // CHECK-LABEL: @test_mm_cmp_ps_true - // CHECK: ret <4 x float> zeroinitializer - return _mm_cmp_ps(a, b, _CMP_FALSE_OQ); -} - -__m128 test_mm_cmp_pd_false(__m128 a, __m128 b) { - // CHECK-LABEL: @test_mm_cmp_pd_false - // CHECK: ret <4 x float> zeroinitializer - return _mm_cmp_pd(a, b, _CMP_FALSE_OQ); -} - -__m128 test_mm_cmp_ps_strue(__m128 a, __m128 b) { - // CHECK-LABEL: @test_mm_cmp_ps_strue - // CHECK: ret <4 x float> zeroinitializer - return _mm_cmp_ps(a, b, _CMP_FALSE_OS); -} - -__m128 test_mm_cmp_pd_sfalse(__m128 a, __m128 b) { - // CHECK-LABEL: @test_mm_cmp_pd_sfalse - // CHECK: ret <4 x float> zeroinitializer - return _mm_cmp_pd(a, b, _CMP_FALSE_OS); -} diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 0f35a56f22..7d77285801 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1290,45 +1290,422 @@ __mmask16 test_mm512_mask_cmp_round_ps_mask(__mmask16 m, __m512 a, __m512 b) { return _mm512_mask_cmp_round_ps_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION); } -__mmask16 test_mm512_cmp_ps_mask(__m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_cmp_ps_mask +__mmask16 test_mm512_cmp_ps_mask_eq_oq(__m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_cmp_ps_mask_eq_oq // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} - return _mm512_cmp_ps_mask(a, b, 0); + return _mm512_cmp_ps_mask(a, b, _CMP_EQ_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_lt_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_lt_os + // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_LT_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_le_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_le_os + // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_LE_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_unord_q(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_unord_q + // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_UNORD_Q); +} + +__mmask16 test_mm512_cmp_ps_mask_neq_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_uq + // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_nlt_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nlt_us + // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NLT_US); +} + +__mmask16 test_mm512_cmp_ps_mask_nle_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nle_us + // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NLE_US); +} + +__mmask16 test_mm512_cmp_ps_mask_ord_q(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ord_q + // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_ORD_Q); +} + +__mmask16 test_mm512_cmp_ps_mask_eq_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_uq + // CHECK: fcmp ueq <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_EQ_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_nge_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nge_us + // CHECK: fcmp ult <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NGE_US); +} + +__mmask16 test_mm512_cmp_ps_mask_ngt_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ngt_us + // CHECK: fcmp ule <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NGT_US); +} + +__mmask16 test_mm512_cmp_ps_mask_false_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i16 0 + return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_neq_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_oq + // CHECK: fcmp one <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_ge_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ge_os + // CHECK: fcmp oge <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_GE_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_gt_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_gt_os + // CHECK: fcmp ogt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_GT_OS); } __mmask16 test_mm512_cmp_ps_mask_true_uq(__m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_cmp_ps_mask_true_uq + // CHECK-LABEL: test_mm512_cmp_ps_mask_true_uq // CHECK-NOT: call // CHECK: ret i16 -1 return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_UQ); } +__mmask16 test_mm512_cmp_ps_mask_eq_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_os + // CHECK: fcmp oeq <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_EQ_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_lt_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_lt_oq + // CHECK: fcmp olt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_LT_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_le_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_le_oq + // CHECK: fcmp ole <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_LE_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_unord_s(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_unord_s + // CHECK: fcmp uno <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_UNORD_S); +} + +__mmask16 test_mm512_cmp_ps_mask_neq_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_us + // CHECK: fcmp une <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_US); +} + +__mmask16 test_mm512_cmp_ps_mask_nlt_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nlt_uq + // CHECK: fcmp uge <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NLT_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_nle_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nle_uq + // CHECK: fcmp ugt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NLE_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_ord_s(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ord_s + // CHECK: fcmp ord <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_ORD_S); +} + +__mmask16 test_mm512_cmp_ps_mask_eq_us(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_eq_us + // CHECK: fcmp ueq <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_EQ_US); +} + +__mmask16 test_mm512_cmp_ps_mask_nge_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_nge_uq + // CHECK: fcmp ult <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NGE_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_ngt_uq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ngt_uq + // CHECK: fcmp ule <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NGT_UQ); +} + +__mmask16 test_mm512_cmp_ps_mask_false_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i16 0 + return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_neq_os(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_neq_os + // CHECK: fcmp one <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_NEQ_OS); +} + +__mmask16 test_mm512_cmp_ps_mask_ge_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_ge_oq + // CHECK: fcmp oge <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_GE_OQ); +} + +__mmask16 test_mm512_cmp_ps_mask_gt_oq(__m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_cmp_ps_mask_gt_oq + // CHECK: fcmp ogt <16 x float> %{{.*}}, %{{.*}} + return _mm512_cmp_ps_mask(a, b, _CMP_GT_OQ); +} + __mmask16 test_mm512_cmp_ps_mask_true_us(__m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_cmp_ps_mask_true_us + // CHECK-LABEL: test_mm512_cmp_ps_mask_true_us // CHECK-NOT: call // CHECK: ret i16 -1 return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_US); } -__mmask16 test_mm512_cmp_ps_mask_false_oq(__m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_cmp_ps_mask_false_oq +__mmask16 test_mm512_mask_cmp_ps_mask_eq_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: @test_mm512_mask_cmp_ps_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_lt_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_le_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_unord_q(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_neq_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nlt_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nle_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ord_q(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_eq_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nge_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ngt_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_false_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_oq // CHECK-NOT: call // CHECK: ret i16 0 - return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OQ); + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); } -__mmask16 test_mm512_cmp_ps_mask_false_os(__m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_cmp_ps_mask_false_os +__mmask16 test_mm512_mask_cmp_ps_mask_neq_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ge_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_gt_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_true_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_uq + // FIXME + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_eq_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_lt_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_le_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_unord_s(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_neq_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nlt_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nle_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ord_s(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_eq_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_nge_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ngt_uq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_false_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_os // CHECK-NOT: call // CHECK: ret i16 0 - return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OS); + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } -__mmask16 test_mm512_mask_cmp_ps_mask(__mmask16 m, __m512 a, __m512 b) { - // CHECK-LABEL: @test_mm512_mask_cmp_ps_mask - // CHECK: [[CMP:%.*]] = fcmp oeq <16 x float> %{{.*}}, %{{.*}} +__mmask16 test_mm512_mask_cmp_ps_mask_neq_os(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_ge_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <16 x float> %{{.*}}, %{{.*}} // CHECK: and <16 x i1> [[CMP]], {{.*}} - return _mm512_mask_cmp_ps_mask(m, a, b, 0); + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_gt_oq(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask16 test_mm512_mask_cmp_ps_mask_true_us(__mmask16 m, __m512 a, __m512 b) { + // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_us + // FIXME + return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); } __mmask8 test_mm512_cmp_round_pd_mask(__m512d a, __m512d b) { @@ -1344,38 +1721,422 @@ __mmask8 test_mm512_mask_cmp_round_pd_mask(__mmask8 m, __m512d a, __m512d b) { return _mm512_mask_cmp_round_pd_mask(m, a, b, 0, _MM_FROUND_CUR_DIRECTION); } -__mmask8 test_mm512_cmp_pd_mask(__m512d a, __m512d b) { - // CHECK-LABEL: @test_mm512_cmp_pd_mask +__mmask8 test_mm512_cmp_pd_mask_eq_oq(__m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_cmp_pd_mask_eq_oq // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}} - return _mm512_cmp_pd_mask(a, b, 0); + return _mm512_cmp_pd_mask(a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_lt_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_lt_os + // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_LT_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_le_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_le_os + // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_LE_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_unord_q(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_unord_q + // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm512_cmp_pd_mask_neq_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_uq + // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_nlt_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nlt_us + // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NLT_US); +} + +__mmask8 test_mm512_cmp_pd_mask_nle_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nle_us + // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NLE_US); +} + +__mmask8 test_mm512_cmp_pd_mask_ord_q(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ord_q + // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm512_cmp_pd_mask_eq_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_uq + // CHECK: fcmp ueq <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_nge_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nge_us + // CHECK: fcmp ult <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NGE_US); +} + +__mmask8 test_mm512_cmp_pd_mask_ngt_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ngt_us + // CHECK: fcmp ule <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NGT_US); +} + +__mmask8 test_mm512_cmp_pd_mask_false_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_neq_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_oq + // CHECK: fcmp one <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_ge_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ge_os + // CHECK: fcmp oge <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_GE_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_gt_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_gt_os + // CHECK: fcmp ogt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_GT_OS); } __mmask8 test_mm512_cmp_pd_mask_true_uq(__m512d a, __m512d b) { - // CHECK-LABEL: @test_mm512_cmp_pd_mask_true_uq + // CHECK-LABEL: test_mm512_cmp_pd_mask_true_uq // CHECK-NOT: call // CHECK: ret i8 -1 return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_UQ); } +__mmask8 test_mm512_cmp_pd_mask_eq_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_os + // CHECK: fcmp oeq <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_lt_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_lt_oq + // CHECK: fcmp olt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_le_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_le_oq + // CHECK: fcmp ole <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_unord_s(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_unord_s + // CHECK: fcmp uno <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm512_cmp_pd_mask_neq_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_us + // CHECK: fcmp une <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm512_cmp_pd_mask_nlt_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nlt_uq + // CHECK: fcmp uge <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_nle_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nle_uq + // CHECK: fcmp ugt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_ord_s(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ord_s + // CHECK: fcmp ord <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_ORD_S); +} + +__mmask8 test_mm512_cmp_pd_mask_eq_us(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_eq_us + // CHECK: fcmp ueq <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_EQ_US); +} + +__mmask8 test_mm512_cmp_pd_mask_nge_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_nge_uq + // CHECK: fcmp ult <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_ngt_uq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ngt_uq + // CHECK: fcmp ule <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm512_cmp_pd_mask_false_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_neq_os(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_neq_os + // CHECK: fcmp one <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm512_cmp_pd_mask_ge_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_ge_oq + // CHECK: fcmp oge <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm512_cmp_pd_mask_gt_oq(__m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_cmp_pd_mask_gt_oq + // CHECK: fcmp ogt <8 x double> %{{.*}}, %{{.*}} + return _mm512_cmp_pd_mask(a, b, _CMP_GT_OQ); +} + __mmask8 test_mm512_cmp_pd_mask_true_us(__m512d a, __m512d b) { - // CHECK-LABEL: @test_mm512_cmp_pd_mask_true_us + // CHECK-LABEL: test_mm512_cmp_pd_mask_true_us // CHECK-NOT: call // CHECK: ret i8 -1 return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_US); } -__mmask8 test_mm512_cmp_pd_mask_false_oq(__m512d a, __m512d b) { - // CHECK-LABEL: @test_mm512_cmp_pd_mask_false_oq +__mmask8 test_mm512_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: @test_mm512_mask_cmp_pd_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_lt_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_le_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_unord_q(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nle_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ord_q(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nge_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_false_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_oq // CHECK-NOT: call // CHECK: ret i8 0 - return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OQ); + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); } -__mmask8 test_mm512_cmp_pd_mask_false_os(__m512d a, __m512d b) { - // CHECK-LABEL: @test_mm512_cmp_pd_mask_false_os +__mmask8 test_mm512_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ge_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_gt_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_true_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_uq + // FIXME + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_eq_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_le_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_unord_s(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_neq_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ord_s(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_eq_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_false_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_os // CHECK-NOT: call // CHECK: ret i8 0 - return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OS); + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_neq_os(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask8 test_mm512_mask_cmp_pd_mask_true_us(__mmask8 m, __m512d a, __m512d b) { + // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_us + // FIXME + return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); } __mmask8 test_mm512_mask_cmp_pd_mask(__mmask8 m, __m512d a, __m512d b) { diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 1b153cdc68..31822c6cd7 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -1071,171 +1071,1676 @@ __m128i test_mm_maskz_xor_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_maskz_xor_epi64( __U, __A, __B); } -__mmask8 test_mm256_cmp_ps_mask(__m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_cmp_ps_mask +__mmask8 test_mm256_cmp_ps_mask_eq_oq(__m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_cmp_ps_mask_eq_oq // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} - return (__mmask8)_mm256_cmp_ps_mask(__A, __B, 0); + return _mm256_cmp_ps_mask(a, b, _CMP_EQ_OQ); } -__mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_uq +__mmask8 test_mm256_cmp_ps_mask_lt_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_lt_os + // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_LT_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_le_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_le_os + // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_LE_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_unord_q(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_unord_q + // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm256_cmp_ps_mask_neq_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_uq + // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_nlt_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nlt_us + // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NLT_US); +} + +__mmask8 test_mm256_cmp_ps_mask_nle_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nle_us + // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NLE_US); +} + +__mmask8 test_mm256_cmp_ps_mask_ord_q(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ord_q + // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm256_cmp_ps_mask_eq_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_uq + // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_nge_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nge_us + // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NGE_US); +} + +__mmask8 test_mm256_cmp_ps_mask_ngt_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ngt_us + // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NGT_US); +} + +__mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_neq_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_oq + // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_ge_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ge_os + // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_GE_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_gt_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_gt_os + // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_GT_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_true_uq // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); + return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_eq_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_os + // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_lt_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_lt_oq + // CHECK: fcmp olt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_le_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_le_oq + // CHECK: fcmp ole <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_unord_s(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_unord_s + // CHECK: fcmp uno <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm256_cmp_ps_mask_neq_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_us + // CHECK: fcmp une <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm256_cmp_ps_mask_nlt_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nlt_uq + // CHECK: fcmp uge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_nle_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nle_uq + // CHECK: fcmp ugt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_ord_s(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ord_s + // CHECK: fcmp ord <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_ORD_S); +} + +__mmask8 test_mm256_cmp_ps_mask_eq_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_eq_us + // CHECK: fcmp ueq <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_EQ_US); +} + +__mmask8 test_mm256_cmp_ps_mask_nge_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_nge_uq + // CHECK: fcmp ult <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_ngt_uq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ngt_uq + // CHECK: fcmp ule <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm256_cmp_ps_mask_false_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_neq_os(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_neq_os + // CHECK: fcmp one <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm256_cmp_ps_mask_ge_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_ge_oq + // CHECK: fcmp oge <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm256_cmp_ps_mask_gt_oq(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_gt_oq + // CHECK: fcmp ogt <8 x float> %{{.*}}, %{{.*}} + return _mm256_cmp_ps_mask(a, b, _CMP_GT_OQ); } -__mmask8 test_mm256_cmp_ps_mask_true_us(__m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_cmp_ps_mask_true_us +__mmask8 test_mm256_cmp_ps_mask_true_us(__m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_cmp_ps_mask_true_us // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_TRUE_US); + return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_US); } -__mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_oq +__mmask8 test_mm256_mask_cmp_ps_mask_eq_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_lt_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_le_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_unord_q(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_neq_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nlt_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nle_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_ord_q(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_eq_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nge_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_false_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_oq // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_neq_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_ge_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_gt_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_true_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_uq + // FIXME + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_eq_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_lt_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_le_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_unord_s(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_neq_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nlt_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nle_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_ord_s(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S); } -__mmask8 test_mm256_cmp_ps_mask_false_os(__m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_cmp_ps_mask_false_os +__mmask8 test_mm256_mask_cmp_ps_mask_eq_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_nge_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_false_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_os // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm256_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } -__mmask8 test_mm256_mask_cmp_ps_mask(__mmask8 m, __m256 __A, __m256 __B) { - // CHECK-LABEL: @test_mm256_mask_cmp_ps_mask - // CHECK: fcmp oeq <8 x float> %{{.*}}, %{{.*}} - // CHECK: and <8 x i1> %{{.*}}, %{{.*}} - return _mm256_mask_cmp_ps_mask(m, __A, __B, 0); +__mmask8 test_mm256_mask_cmp_ps_mask_neq_os(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS); } -__mmask8 test_mm_cmp_ps_mask(__m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_cmp_ps_mask - // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} - return (__mmask8)_mm_cmp_ps_mask(__A, __B, 0); +__mmask8 test_mm256_mask_cmp_ps_mask_ge_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask8 test_mm256_mask_cmp_ps_mask_true_us(__mmask8 m, __m256 a, __m256 b) { + // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_us + // FIXME + return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm256_cmp_pd_mask_eq_oq(__m256d a, __m256d b) { + // CHECK-LABEL: @test_mm256_cmp_pd_mask_eq_oq + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_EQ_OQ); } -__mmask8 test_mm_cmp_ps_mask_true_uq(__m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_cmp_ps_mask_true_uq +__mmask8 test_mm256_cmp_pd_mask_lt_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_lt_os + // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_LT_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_le_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_le_os + // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_LE_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_unord_q(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_unord_q + // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm256_cmp_pd_mask_neq_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_uq + // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_nlt_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nlt_us + // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NLT_US); +} + +__mmask8 test_mm256_cmp_pd_mask_nle_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nle_us + // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NLE_US); +} + +__mmask8 test_mm256_cmp_pd_mask_ord_q(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ord_q + // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm256_cmp_pd_mask_eq_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_uq + // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_nge_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nge_us + // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NGE_US); +} + +__mmask8 test_mm256_cmp_pd_mask_ngt_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ngt_us + // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NGT_US); +} + +__mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_neq_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_oq + // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_ge_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ge_os + // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_GE_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_gt_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_gt_os + // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_GT_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_true_uq // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_UQ); + return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_eq_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_os + // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_lt_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_lt_oq + // CHECK: fcmp olt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_le_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_le_oq + // CHECK: fcmp ole <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_unord_s(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_unord_s + // CHECK: fcmp uno <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm256_cmp_pd_mask_neq_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_us + // CHECK: fcmp une <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm256_cmp_pd_mask_nlt_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nlt_uq + // CHECK: fcmp uge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_nle_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nle_uq + // CHECK: fcmp ugt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_ord_s(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ord_s + // CHECK: fcmp ord <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_ORD_S); +} + +__mmask8 test_mm256_cmp_pd_mask_eq_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_eq_us + // CHECK: fcmp ueq <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_EQ_US); +} + +__mmask8 test_mm256_cmp_pd_mask_nge_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_nge_uq + // CHECK: fcmp ult <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_ngt_uq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ngt_uq + // CHECK: fcmp ule <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm256_cmp_pd_mask_false_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_neq_os(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_neq_os + // CHECK: fcmp one <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm256_cmp_pd_mask_ge_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_ge_oq + // CHECK: fcmp oge <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm256_cmp_pd_mask_gt_oq(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_gt_oq + // CHECK: fcmp ogt <4 x double> %{{.*}}, %{{.*}} + return _mm256_cmp_pd_mask(a, b, _CMP_GT_OQ); } -__mmask8 test_mm_cmp_ps_mask_true_us(__m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_cmp_ps_mask_true_us +__mmask8 test_mm256_cmp_pd_mask_true_us(__m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_cmp_pd_mask_true_us // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_TRUE_US); + return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: @test_mm256_mask_cmp_pd_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_lt_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_le_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_unord_q(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nle_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US); } -__mmask8 test_mm_cmp_ps_mask_false_oq(__m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_cmp_ps_mask_false_oq +__mmask8 test_mm256_mask_cmp_pd_mask_ord_q(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nge_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_false_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_oq // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OQ); + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_ge_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_gt_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_true_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_uq + // FIXME + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); } -__mmask8 test_mm_cmp_ps_mask_false_os(__m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_cmp_ps_mask_false_os +__mmask8 test_mm256_mask_cmp_pd_mask_eq_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_le_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_unord_s(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_neq_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_ord_s(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_eq_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_false_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_os // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm_cmp_ps_mask(__A, __B, _CMP_FALSE_OS); + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_neq_os(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS); } -__mmask8 test_mm_mask_cmp_ps_mask(__mmask8 m, __m128 __A, __m128 __B) { - // CHECK-LABEL: @test_mm_mask_cmp_ps_mask +__mmask8 test_mm256_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask8 test_mm256_mask_cmp_pd_mask_true_us(__mmask8 m, __m256d a, __m256d b) { + // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_us + // FIXME + return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm_cmp_ps_mask_eq_oq(__m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_cmp_ps_mask_eq_oq // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} - // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> - // CHECK: and <4 x i1> %{{.*}}, %{{.*}} - return _mm_mask_cmp_ps_mask(m, __A, __B, 0); + return _mm_cmp_ps_mask(a, b, _CMP_EQ_OQ); } -__mmask8 test_mm256_cmp_pd_mask(__m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_cmp_pd_mask - // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} - return (__mmask8)_mm256_cmp_pd_mask(__A, __B, 0); +__mmask8 test_mm_cmp_ps_mask_lt_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_lt_os + // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_LT_OS); +} + +__mmask8 test_mm_cmp_ps_mask_le_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_le_os + // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_LE_OS); +} + +__mmask8 test_mm_cmp_ps_mask_unord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_unord_q + // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm_cmp_ps_mask_neq_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_neq_uq + // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_nlt_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nlt_us + // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NLT_US); +} + +__mmask8 test_mm_cmp_ps_mask_nle_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nle_us + // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NLE_US); +} + +__mmask8 test_mm_cmp_ps_mask_ord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ord_q + // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm_cmp_ps_mask_eq_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_eq_uq + // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_EQ_UQ); } -__mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_uq +__mmask8 test_mm_cmp_ps_mask_nge_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nge_us + // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NGE_US); +} + +__mmask8 test_mm_cmp_ps_mask_ngt_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ngt_us + // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NGT_US); +} + +__mmask8 test_mm_cmp_ps_mask_false_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_neq_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_neq_oq + // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_ge_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ge_os + // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_GE_OS); +} + +__mmask8 test_mm_cmp_ps_mask_gt_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_gt_os + // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_GT_OS); +} + +__mmask8 test_mm_cmp_ps_mask_true_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_true_uq // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_UQ); + return _mm_cmp_ps_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_eq_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_eq_os + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm_cmp_ps_mask_lt_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_lt_oq + // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_le_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_le_oq + // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_unord_s(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_unord_s + // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm_cmp_ps_mask_neq_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_neq_us + // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm_cmp_ps_mask_nlt_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nlt_uq + // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_nle_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nle_uq + // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_ord_s(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ord_s + // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_ORD_S); +} + +__mmask8 test_mm_cmp_ps_mask_eq_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_eq_us + // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_EQ_US); +} + +__mmask8 test_mm_cmp_ps_mask_nge_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_nge_uq + // CHECK: fcmp ult <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_ngt_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ngt_uq + // CHECK: fcmp ule <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm_cmp_ps_mask_false_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm_cmp_ps_mask_neq_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_neq_os + // CHECK: fcmp one <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm_cmp_ps_mask_ge_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_ge_oq + // CHECK: fcmp oge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm_cmp_ps_mask_gt_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_gt_oq + // CHECK: fcmp ogt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps_mask(a, b, _CMP_GT_OQ); } -__mmask8 test_mm256_cmp_pd_mask_true_us(__m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_cmp_pd_mask_true_us +__mmask8 test_mm_cmp_ps_mask_true_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_mask_true_us // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_TRUE_US); + return _mm_cmp_ps_mask(a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_eq_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: @test_mm_mask_cmp_ps_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_lt_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LT_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_le_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LE_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_unord_q(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm_mask_cmp_ps_mask_neq_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nlt_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLT_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nle_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLE_US); } -__mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_oq +__mmask8 test_mm_mask_cmp_ps_mask_ord_q(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm_mask_cmp_ps_mask_eq_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nge_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGE_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGT_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_false_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_oq // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_FALSE_OQ); + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_neq_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_ge_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GE_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_gt_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GT_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_true_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_uq + // FIXME + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); } -__mmask8 test_mm256_cmp_pd_mask_false_os(__m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_cmp_pd_mask_false_os +__mmask8 test_mm_mask_cmp_ps_mask_eq_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_lt_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_le_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_unord_s(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm_mask_cmp_ps_mask_neq_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nlt_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nle_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_ord_s(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_ORD_S); +} + +__mmask8 test_mm_mask_cmp_ps_mask_eq_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_EQ_US); +} + +__mmask8 test_mm_mask_cmp_ps_mask_nge_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_false_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_os // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm256_cmp_pd_mask(__A, __B, _CMP_FALSE_OS); + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } -__mmask8 test_mm256_mask_cmp_pd_mask(__mmask8 m, __m256d __A, __m256d __B) { - // CHECK-LABEL: @test_mm256_mask_cmp_pd_mask - // CHECK: fcmp oeq <4 x double> %{{.*}}, %{{.*}} - // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> - // CHECK: and <4 x i1> %{{.*}}, %{{.*}} - return _mm256_mask_cmp_pd_mask(m, __A, __B, 0); +__mmask8 test_mm_mask_cmp_ps_mask_neq_os(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm_mask_cmp_ps_mask_ge_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask8 test_mm_mask_cmp_ps_mask_true_us(__mmask8 m, __m128 a, __m128 b) { + // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_us + // FIXME + return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); } -__mmask8 test_mm_cmp_pd_mask(__m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_cmp_pd_mask +__mmask8 test_mm_cmp_pd_mask_eq_oq(__m128d a, __m128d b) { + // CHECK-LABEL: @test_mm_cmp_pd_mask_eq_oq // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} - return (__mmask8)_mm_cmp_pd_mask(__A, __B, 0); + return _mm_cmp_pd_mask(a, b, _CMP_EQ_OQ); } -__mmask8 test_mm_cmp_pd_mask_true_uq(__m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_cmp_pd_mask_true_uq +__mmask8 test_mm_cmp_pd_mask_lt_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_lt_os + // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_LT_OS); +} + +__mmask8 test_mm_cmp_pd_mask_le_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_le_os + // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_LE_OS); +} + +__mmask8 test_mm_cmp_pd_mask_unord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_unord_q + // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm_cmp_pd_mask_neq_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_neq_uq + // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_nlt_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nlt_us + // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NLT_US); +} + +__mmask8 test_mm_cmp_pd_mask_nle_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nle_us + // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NLE_US); +} + +__mmask8 test_mm_cmp_pd_mask_ord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ord_q + // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm_cmp_pd_mask_eq_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_eq_uq + // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_nge_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nge_us + // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NGE_US); +} + +__mmask8 test_mm_cmp_pd_mask_ngt_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ngt_us + // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NGT_US); +} + +__mmask8 test_mm_cmp_pd_mask_false_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_false_oq + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_neq_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_neq_oq + // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_ge_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ge_os + // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_GE_OS); +} + +__mmask8 test_mm_cmp_pd_mask_gt_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_gt_os + // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_GT_OS); +} + +__mmask8 test_mm_cmp_pd_mask_true_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_true_uq // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_TRUE_UQ); + return _mm_cmp_pd_mask(a, b, _CMP_TRUE_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_eq_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_eq_os + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm_cmp_pd_mask_lt_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_lt_oq + // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_le_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_le_oq + // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_unord_s(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_unord_s + // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm_cmp_pd_mask_neq_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_neq_us + // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm_cmp_pd_mask_nlt_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nlt_uq + // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_nle_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nle_uq + // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_ord_s(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ord_s + // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_ORD_S); +} + +__mmask8 test_mm_cmp_pd_mask_eq_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_eq_us + // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_EQ_US); +} + +__mmask8 test_mm_cmp_pd_mask_nge_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_nge_uq + // CHECK: fcmp ult <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_ngt_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ngt_uq + // CHECK: fcmp ule <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm_cmp_pd_mask_false_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_false_os + // CHECK-NOT: call + // CHECK: ret i8 0 + return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OS); +} + +__mmask8 test_mm_cmp_pd_mask_neq_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_neq_os + // CHECK: fcmp one <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm_cmp_pd_mask_ge_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_ge_oq + // CHECK: fcmp oge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm_cmp_pd_mask_gt_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_gt_oq + // CHECK: fcmp ogt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd_mask(a, b, _CMP_GT_OQ); } -__mmask8 test_mm_cmp_pd_mask_true_us(__m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_cmp_pd_mask_true_us +__mmask8 test_mm_cmp_pd_mask_true_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_mask_true_us // CHECK-NOT: call // CHECK: ret i8 -1 - return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_TRUE_US); + return _mm_cmp_pd_mask(a, b, _CMP_TRUE_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_eq_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: @test_mm_mask_cmp_pd_mask_eq_oq + // CHECK: [[CMP:%.*]] = fcmp oeq <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_lt_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_lt_os + // CHECK: [[CMP:%.*]] = fcmp olt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LT_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_le_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_le_os + // CHECK: [[CMP:%.*]] = fcmp ole <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LE_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_unord_q(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_unord_q + // CHECK: [[CMP:%.*]] = fcmp uno <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_Q); +} + +__mmask8 test_mm_mask_cmp_pd_mask_neq_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_uq + // CHECK: [[CMP:%.*]] = fcmp une <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nlt_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nlt_us + // CHECK: [[CMP:%.*]] = fcmp uge <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLT_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nle_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nle_us + // CHECK: [[CMP:%.*]] = fcmp ugt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLE_US); } -__mmask8 test_mm_cmp_pd_mask_false_oq(__m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_cmp_pd_mask_false_oq +__mmask8 test_mm_mask_cmp_pd_mask_ord_q(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ord_q + // CHECK: [[CMP:%.*]] = fcmp ord <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_ORD_Q); +} + +__mmask8 test_mm_mask_cmp_pd_mask_eq_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_uq + // CHECK: [[CMP:%.*]] = fcmp ueq <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nge_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nge_us + // CHECK: [[CMP:%.*]] = fcmp ult <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGE_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ngt_us + // CHECK: [[CMP:%.*]] = fcmp ule <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGT_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_false_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_oq // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_FALSE_OQ); + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_neq_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_oq + // CHECK: [[CMP:%.*]] = fcmp one <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_ge_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ge_os + // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GE_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_gt_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_gt_os + // CHECK: [[CMP:%.*]] = fcmp ogt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GT_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_true_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_uq + // FIXME + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); } -__mmask8 test_mm_cmp_pd_mask_false_os(__m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_cmp_pd_mask_false_os +__mmask8 test_mm_mask_cmp_pd_mask_eq_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_os + // CHECK: [[CMP:%.*]] = fcmp oeq <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_lt_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_lt_oq + // CHECK: [[CMP:%.*]] = fcmp olt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LT_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_le_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_le_oq + // CHECK: [[CMP:%.*]] = fcmp ole <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_LE_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_unord_s(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_unord_s + // CHECK: [[CMP:%.*]] = fcmp uno <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_UNORD_S); +} + +__mmask8 test_mm_mask_cmp_pd_mask_neq_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_us + // CHECK: [[CMP:%.*]] = fcmp une <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nlt_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nlt_uq + // CHECK: [[CMP:%.*]] = fcmp uge <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLT_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nle_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nle_uq + // CHECK: [[CMP:%.*]] = fcmp ugt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NLE_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_ord_s(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ord_s + // CHECK: [[CMP:%.*]] = fcmp ord <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_ORD_S); +} + +__mmask8 test_mm_mask_cmp_pd_mask_eq_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_eq_us + // CHECK: [[CMP:%.*]] = fcmp ueq <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_EQ_US); +} + +__mmask8 test_mm_mask_cmp_pd_mask_nge_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_nge_uq + // CHECK: [[CMP:%.*]] = fcmp ult <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGE_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ngt_uq + // CHECK: [[CMP:%.*]] = fcmp ule <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NGT_UQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_false_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_os // CHECK-NOT: call // CHECK: ret i8 0 - return (__mmask8)_mm_cmp_pd_mask(__A, __B, _CMP_FALSE_OS); + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); } -__mmask8 test_mm_mask_cmp_pd_mask(__mmask8 m, __m128d __A, __m128d __B) { - // CHECK-LABEL: @test_mm_mask_cmp_pd_mask - // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} - // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> - // CHECK: and <2 x i1> %{{.*}}, %{{.*}} - return _mm_mask_cmp_pd_mask(m, __A, __B, 0); +__mmask8 test_mm_mask_cmp_pd_mask_neq_os(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_neq_os + // CHECK: [[CMP:%.*]] = fcmp one <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_NEQ_OS); +} + +__mmask8 test_mm_mask_cmp_pd_mask_ge_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_ge_oq + // CHECK: [[CMP:%.*]] = fcmp oge <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GE_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_gt_oq + // CHECK: [[CMP:%.*]] = fcmp ogt <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_GT_OQ); +} + +__mmask8 test_mm_mask_cmp_pd_mask_true_us(__mmask8 m, __m128d a, __m128d b) { + // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_us + // FIXME + return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); } __m128d test_mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { -- GitLab From 570d2b6a4e6fec720347f6a8aa0db903bcb53e6f Mon Sep 17 00:00:00 2001 From: Vladimir Stefanovic Date: Thu, 5 Jul 2018 13:10:23 +0000 Subject: [PATCH 0412/1023] [mips] Add '-mcrc', '-mno-crc' options to enable/disable CRC ASE '-mcrc' is shared with ARM. '-mno-crc' is Mips-only (ARM uses '-mnocrc'). Differential revision: https://reviews.llvm.org/D48169 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336347 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 6 ++++-- lib/Driver/ToolChains/Arch/Mips.cpp | 2 ++ test/Driver/mips-features.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index c228e9e9d2..496cc12aa3 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1993,8 +1993,8 @@ def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group, HelpText<"Reserve the r9 register (ARM only)">; def mno_movt : Flag<["-"], "mno-movt">, Group, HelpText<"Disallow use of movt/movw pairs (ARM only)">; -def mcrc : Flag<["-"], "mcrc">, Group, - HelpText<"Allow use of CRC instructions (ARM only)">; +def mcrc : Flag<["-"], "mcrc">, Group, + HelpText<"Allow use of CRC instructions (ARM/Mips only)">; def mnocrc : Flag<["-"], "mnocrc">, Group, HelpText<"Disallow use of CRC instructions (ARM only)">; def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group, @@ -2212,6 +2212,8 @@ def mabicalls : Flag<["-"], "mabicalls">, Group, HelpText<"Enable SVR4-style position-independent code (Mips only)">; def mno_abicalls : Flag<["-"], "mno-abicalls">, Group, HelpText<"Disable SVR4-style position-independent code (Mips only)">; +def mno_crc : Flag<["-"], "mno-crc">, Group, + HelpText<"Disallow use of CRC instructions (Mips only)">; def mips1 : Flag<["-"], "mips1">, Alias, AliasArgs<["mips1"]>, Group, HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index 5aeb9288e7..0c0e090719 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -350,6 +350,8 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, "nomadd4"); AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); + AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, + "crc"); if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { StringRef Val = StringRef(A->getValue()); diff --git a/test/Driver/mips-features.c b/test/Driver/mips-features.c index 1284874b71..e90f3704f2 100644 --- a/test/Driver/mips-features.c +++ b/test/Driver/mips-features.c @@ -408,3 +408,15 @@ // RUN: -mindirect-jump=hazard 2>&1 \ // RUN: | FileCheck --check-prefix=INDIRECT-BH %s // INDIRECT-BH: "-target-feature" "+use-indirect-jump-hazard" +// +// -mcrc +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-crc -mcrc 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CRC %s +// CHECK-CRC: "-target-feature" "+crc" +// +// -mno-crc +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mcrc -mno-crc 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-CRC %s +// CHECK-NO-CRC: "-target-feature" "-crc" -- GitLab From aa316d40ec297e14b96d189f408f0a15ed92ddac Mon Sep 17 00:00:00 2001 From: Gabor Buella Date: Thu, 5 Jul 2018 14:26:56 +0000 Subject: [PATCH 0413/1023] [X86] Fix some vector cmp builtins - TRUE/FALSE predicates This patch removes on optimization used with the TRUE/FALSE predicates, as was suggested in https://reviews.llvm.org/D45616 for r335339. The optimization was buggy, since r335339 used it also for *_mask builtins, without actually applying the mask -- the mask argument was just ignored. Reviewers: craig.topper, uriel.k, RKSimon, andrew.w.kaylor, spatel, scanon, efriedma Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D48715 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336355 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 69 ++++++++++---------- test/CodeGen/avx-builtins.c | 48 +++++--------- test/CodeGen/avx512f-builtins.c | 52 +++++++--------- test/CodeGen/avx512vl-builtins.c | 104 ++++++++++++++----------------- 4 files changed, 120 insertions(+), 153 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 98626dcc1d..6edb802d91 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10158,43 +10158,38 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // e.g. both _CMP_GT_OS & _CMP_GT_OQ are translated to FCMP_OGT. FCmpInst::Predicate Pred; switch (CC) { - case 0x00: Pred = FCmpInst::FCMP_OEQ; break; - case 0x01: Pred = FCmpInst::FCMP_OLT; break; - case 0x02: Pred = FCmpInst::FCMP_OLE; break; - case 0x03: Pred = FCmpInst::FCMP_UNO; break; - case 0x04: Pred = FCmpInst::FCMP_UNE; break; - case 0x05: Pred = FCmpInst::FCMP_UGE; break; - case 0x06: Pred = FCmpInst::FCMP_UGT; break; - case 0x07: Pred = FCmpInst::FCMP_ORD; break; - case 0x08: Pred = FCmpInst::FCMP_UEQ; break; - case 0x09: Pred = FCmpInst::FCMP_ULT; break; - case 0x0a: Pred = FCmpInst::FCMP_ULE; break; - case 0x0c: Pred = FCmpInst::FCMP_ONE; break; - case 0x0d: Pred = FCmpInst::FCMP_OGE; break; - case 0x0e: Pred = FCmpInst::FCMP_OGT; break; - case 0x10: Pred = FCmpInst::FCMP_OEQ; break; - case 0x11: Pred = FCmpInst::FCMP_OLT; break; - case 0x12: Pred = FCmpInst::FCMP_OLE; break; - case 0x13: Pred = FCmpInst::FCMP_UNO; break; - case 0x14: Pred = FCmpInst::FCMP_UNE; break; - case 0x15: Pred = FCmpInst::FCMP_UGE; break; - case 0x16: Pred = FCmpInst::FCMP_UGT; break; - case 0x17: Pred = FCmpInst::FCMP_ORD; break; - case 0x18: Pred = FCmpInst::FCMP_UEQ; break; - case 0x19: Pred = FCmpInst::FCMP_ULT; break; - case 0x1a: Pred = FCmpInst::FCMP_ULE; break; - case 0x1c: Pred = FCmpInst::FCMP_ONE; break; - case 0x1d: Pred = FCmpInst::FCMP_OGE; break; - case 0x1e: Pred = FCmpInst::FCMP_OGT; break; - // _CMP_TRUE_UQ, _CMP_TRUE_US produce -1,-1... vector - // on any input and _CMP_FALSE_OQ, _CMP_FALSE_OS produce 0, 0... - case 0x0b: // FALSE_OQ - case 0x1b: // FALSE_OS - return llvm::Constant::getNullValue(ConvertType(E->getType())); - case 0x0f: // TRUE_UQ - case 0x1f: // TRUE_US - return llvm::Constant::getAllOnesValue(ConvertType(E->getType())); - + case 0x00: Pred = FCmpInst::FCMP_OEQ; break; + case 0x01: Pred = FCmpInst::FCMP_OLT; break; + case 0x02: Pred = FCmpInst::FCMP_OLE; break; + case 0x03: Pred = FCmpInst::FCMP_UNO; break; + case 0x04: Pred = FCmpInst::FCMP_UNE; break; + case 0x05: Pred = FCmpInst::FCMP_UGE; break; + case 0x06: Pred = FCmpInst::FCMP_UGT; break; + case 0x07: Pred = FCmpInst::FCMP_ORD; break; + case 0x08: Pred = FCmpInst::FCMP_UEQ; break; + case 0x09: Pred = FCmpInst::FCMP_ULT; break; + case 0x0a: Pred = FCmpInst::FCMP_ULE; break; + case 0x0b: Pred = FCmpInst::FCMP_FALSE; break; + case 0x0c: Pred = FCmpInst::FCMP_ONE; break; + case 0x0d: Pred = FCmpInst::FCMP_OGE; break; + case 0x0e: Pred = FCmpInst::FCMP_OGT; break; + case 0x0f: Pred = FCmpInst::FCMP_TRUE; break; + case 0x10: Pred = FCmpInst::FCMP_OEQ; break; + case 0x11: Pred = FCmpInst::FCMP_OLT; break; + case 0x12: Pred = FCmpInst::FCMP_OLE; break; + case 0x13: Pred = FCmpInst::FCMP_UNO; break; + case 0x14: Pred = FCmpInst::FCMP_UNE; break; + case 0x15: Pred = FCmpInst::FCMP_UGE; break; + case 0x16: Pred = FCmpInst::FCMP_UGT; break; + case 0x17: Pred = FCmpInst::FCMP_ORD; break; + case 0x18: Pred = FCmpInst::FCMP_UEQ; break; + case 0x19: Pred = FCmpInst::FCMP_ULT; break; + case 0x1a: Pred = FCmpInst::FCMP_ULE; break; + case 0x1b: Pred = FCmpInst::FCMP_FALSE; break; + case 0x1c: Pred = FCmpInst::FCMP_ONE; break; + case 0x1d: Pred = FCmpInst::FCMP_OGE; break; + case 0x1e: Pred = FCmpInst::FCMP_OGT; break; + case 0x1f: Pred = FCmpInst::FCMP_TRUE; break; default: llvm_unreachable("Unhandled CC"); } diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index f0e232089b..90344a935a 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -280,8 +280,7 @@ __m256d test_mm256_cmp_pd_ngt_us(__m256d a, __m256d b) { __m256d test_mm256_cmp_pd_false_oq(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_false_oq - // CHECK-NOT: call - // CHECK: ret <4 x double> zeroinitializer + // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd(a, b, _CMP_FALSE_OQ); } @@ -305,8 +304,7 @@ __m256d test_mm256_cmp_pd_gt_os(__m256d a, __m256d b) { __m256d test_mm256_cmp_pd_true_uq(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_true_uq - // CHECK-NOT: call - // CHECK: ret <4 x double> + // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd(a, b, _CMP_TRUE_UQ); } @@ -378,8 +376,7 @@ __m256d test_mm256_cmp_pd_ngt_uq(__m256d a, __m256d b) { __m256d test_mm256_cmp_pd_false_os(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_false_os - // CHECK-NOT: call - // CHECK: ret <4 x double> zeroinitializer + // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd(a, b, _CMP_FALSE_OS); } @@ -403,8 +400,7 @@ __m256d test_mm256_cmp_pd_gt_oq(__m256d a, __m256d b) { __m256d test_mm256_cmp_pd_true_us(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_true_us - // CHECK-NOT: call - // CHECK: ret <4 x double> + // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd(a, b, _CMP_TRUE_US); } @@ -476,8 +472,7 @@ __m256 test_mm256_cmp_ps_ngt_us(__m256 a, __m256 b) { __m256 test_mm256_cmp_ps_false_oq(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_false_oq - // CHECK-NOT: call - // CHECK: ret <8 x float> zeroinitializer + // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps(a, b, _CMP_FALSE_OQ); } @@ -501,8 +496,7 @@ __m256 test_mm256_cmp_ps_gt_os(__m256 a, __m256 b) { __m256 test_mm256_cmp_ps_true_uq(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_true_uq - // CHECK-NOT: call - // CHECK: ret <8 x float> + // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps(a, b, _CMP_TRUE_UQ); } @@ -574,8 +568,7 @@ __m256 test_mm256_cmp_ps_ngt_uq(__m256 a, __m256 b) { __m256 test_mm256_cmp_ps_false_os(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_false_os - // CHECK-NOT: call - // CHECK: ret <8 x float> zeroinitializer + // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps(a, b, _CMP_FALSE_OS); } @@ -599,8 +592,7 @@ __m256 test_mm256_cmp_ps_gt_oq(__m256 a, __m256 b) { __m256 test_mm256_cmp_ps_true_us(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_true_us - // CHECK-NOT: call - // CHECK: ret <8 x float> + // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps(a, b, _CMP_TRUE_US); } @@ -672,8 +664,7 @@ __m128d test_mm_cmp_pd_ngt_us(__m128d a, __m128d b) { __m128d test_mm_cmp_pd_false_oq(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_false_oq - // CHECK-NOT: call - // CHECK: ret <2 x double> zeroinitializer + // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd(a, b, _CMP_FALSE_OQ); } @@ -697,8 +688,7 @@ __m128d test_mm_cmp_pd_gt_os(__m128d a, __m128d b) { __m128d test_mm_cmp_pd_true_uq(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_true_uq - // CHECK-NOT: call - // CHECK: ret <2 x double> + // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd(a, b, _CMP_TRUE_UQ); } @@ -770,8 +760,7 @@ __m128d test_mm_cmp_pd_ngt_uq(__m128d a, __m128d b) { __m128d test_mm_cmp_pd_false_os(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_false_os - // CHECK-NOT: call - // CHECK: ret <2 x double> zeroinitializer + // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd(a, b, _CMP_FALSE_OS); } @@ -795,8 +784,7 @@ __m128d test_mm_cmp_pd_gt_oq(__m128d a, __m128d b) { __m128d test_mm_cmp_pd_true_us(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_true_us - // CHECK-NOT: call - // CHECK: ret <2 x double> + // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd(a, b, _CMP_TRUE_US); } @@ -868,8 +856,7 @@ __m128 test_mm_cmp_ps_ngt_us(__m128 a, __m128 b) { __m128 test_mm_cmp_ps_false_oq(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_false_oq - // CHECK-NOT: call - // CHECK: ret <4 x float> zeroinitializer + // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps(a, b, _CMP_FALSE_OQ); } @@ -893,8 +880,7 @@ __m128 test_mm_cmp_ps_gt_os(__m128 a, __m128 b) { __m128 test_mm_cmp_ps_true_uq(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_true_uq - // CHECK-NOT: call - // CHECK: ret <4 x float> + // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps(a, b, _CMP_TRUE_UQ); } @@ -966,8 +952,7 @@ __m128 test_mm_cmp_ps_ngt_uq(__m128 a, __m128 b) { __m128 test_mm_cmp_ps_false_os(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_false_os - // CHECK-NOT: call - // CHECK: ret <4 x float> zeroinitializer + // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps(a, b, _CMP_FALSE_OS); } @@ -991,8 +976,7 @@ __m128 test_mm_cmp_ps_gt_oq(__m128 a, __m128 b) { __m128 test_mm_cmp_ps_true_us(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_true_us - // CHECK-NOT: call - // CHECK: ret <4 x float> + // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps(a, b, _CMP_TRUE_US); } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 7d77285801..3a07d5ed6b 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -1358,8 +1358,7 @@ __mmask16 test_mm512_cmp_ps_mask_ngt_us(__m512 a, __m512 b) { __mmask16 test_mm512_cmp_ps_mask_false_oq(__m512 a, __m512 b) { // CHECK-LABEL: test_mm512_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i16 0 + // CHECK: fcmp false <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OQ); } @@ -1383,8 +1382,7 @@ __mmask16 test_mm512_cmp_ps_mask_gt_os(__m512 a, __m512 b) { __mmask16 test_mm512_cmp_ps_mask_true_uq(__m512 a, __m512 b) { // CHECK-LABEL: test_mm512_cmp_ps_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i16 -1 + // CHECK: fcmp true <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_UQ); } @@ -1456,8 +1454,7 @@ __mmask16 test_mm512_cmp_ps_mask_ngt_uq(__m512 a, __m512 b) { __mmask16 test_mm512_cmp_ps_mask_false_os(__m512 a, __m512 b) { // CHECK-LABEL: test_mm512_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i16 0 + // CHECK: fcmp false <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_ps_mask(a, b, _CMP_FALSE_OS); } @@ -1481,8 +1478,7 @@ __mmask16 test_mm512_cmp_ps_mask_gt_oq(__m512 a, __m512 b) { __mmask16 test_mm512_cmp_ps_mask_true_us(__m512 a, __m512 b) { // CHECK-LABEL: test_mm512_cmp_ps_mask_true_us - // CHECK-NOT: call - // CHECK: ret i16 -1 + // CHECK: fcmp true <16 x float> %{{.*}}, %{{.*}} return _mm512_cmp_ps_mask(a, b, _CMP_TRUE_US); } @@ -1565,8 +1561,8 @@ __mmask16 test_mm512_mask_cmp_ps_mask_ngt_us(__mmask16 m, __m512 a, __m512 b) { __mmask16 test_mm512_mask_cmp_ps_mask_false_oq(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i16 0 + // CHECK: [[CMP:%.*]] = fcmp false <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); } @@ -1593,7 +1589,8 @@ __mmask16 test_mm512_mask_cmp_ps_mask_gt_os(__mmask16 m, __m512 a, __m512 b) { __mmask16 test_mm512_mask_cmp_ps_mask_true_uq(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); } @@ -1676,8 +1673,8 @@ __mmask16 test_mm512_mask_cmp_ps_mask_ngt_uq(__mmask16 m, __m512 a, __m512 b) { __mmask16 test_mm512_mask_cmp_ps_mask_false_os(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i16 0 + // CHECK: [[CMP:%.*]] = fcmp false <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } @@ -1704,7 +1701,8 @@ __mmask16 test_mm512_mask_cmp_ps_mask_gt_oq(__mmask16 m, __m512 a, __m512 b) { __mmask16 test_mm512_mask_cmp_ps_mask_true_us(__mmask16 m, __m512 a, __m512 b) { // CHECK-LABEL: test_mm512_mask_cmp_ps_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <16 x float> %{{.*}}, %{{.*}} + // CHECK: and <16 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); } @@ -1789,8 +1787,7 @@ __mmask8 test_mm512_cmp_pd_mask_ngt_us(__m512d a, __m512d b) { __mmask8 test_mm512_cmp_pd_mask_false_oq(__m512d a, __m512d b) { // CHECK-LABEL: test_mm512_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OQ); } @@ -1814,8 +1811,7 @@ __mmask8 test_mm512_cmp_pd_mask_gt_os(__m512d a, __m512d b) { __mmask8 test_mm512_cmp_pd_mask_true_uq(__m512d a, __m512d b) { // CHECK-LABEL: test_mm512_cmp_pd_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_UQ); } @@ -1887,8 +1883,7 @@ __mmask8 test_mm512_cmp_pd_mask_ngt_uq(__m512d a, __m512d b) { __mmask8 test_mm512_cmp_pd_mask_false_os(__m512d a, __m512d b) { // CHECK-LABEL: test_mm512_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_pd_mask(a, b, _CMP_FALSE_OS); } @@ -1912,8 +1907,7 @@ __mmask8 test_mm512_cmp_pd_mask_gt_oq(__m512d a, __m512d b) { __mmask8 test_mm512_cmp_pd_mask_true_us(__m512d a, __m512d b) { // CHECK-LABEL: test_mm512_cmp_pd_mask_true_us - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <8 x double> %{{.*}}, %{{.*}} return _mm512_cmp_pd_mask(a, b, _CMP_TRUE_US); } @@ -1996,8 +1990,8 @@ __mmask8 test_mm512_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m512d a, __m512d b) { __mmask8 test_mm512_mask_cmp_pd_mask_false_oq(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); } @@ -2024,7 +2018,8 @@ __mmask8 test_mm512_mask_cmp_pd_mask_gt_os(__mmask8 m, __m512d a, __m512d b) { __mmask8 test_mm512_mask_cmp_pd_mask_true_uq(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); } @@ -2107,8 +2102,8 @@ __mmask8 test_mm512_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m512d a, __m512d b) { __mmask8 test_mm512_mask_cmp_pd_mask_false_os(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); } @@ -2135,7 +2130,8 @@ __mmask8 test_mm512_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m512d a, __m512d b) { __mmask8 test_mm512_mask_cmp_pd_mask_true_us(__mmask8 m, __m512d a, __m512d b) { // CHECK-LABEL: test_mm512_mask_cmp_pd_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <8 x double> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm512_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); } diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 31822c6cd7..9ce320071d 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -1139,8 +1139,7 @@ __mmask8 test_mm256_cmp_ps_mask_ngt_us(__m256 a, __m256 b) { __mmask8 test_mm256_cmp_ps_mask_false_oq(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OQ); } @@ -1164,8 +1163,7 @@ __mmask8 test_mm256_cmp_ps_mask_gt_os(__m256 a, __m256 b) { __mmask8 test_mm256_cmp_ps_mask_true_uq(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_UQ); } @@ -1237,8 +1235,7 @@ __mmask8 test_mm256_cmp_ps_mask_ngt_uq(__m256 a, __m256 b) { __mmask8 test_mm256_cmp_ps_mask_false_os(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps_mask(a, b, _CMP_FALSE_OS); } @@ -1262,8 +1259,7 @@ __mmask8 test_mm256_cmp_ps_mask_gt_oq(__m256 a, __m256 b) { __mmask8 test_mm256_cmp_ps_mask_true_us(__m256 a, __m256 b) { // CHECK-LABEL: test_mm256_cmp_ps_mask_true_us - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <8 x float> %{{.*}}, %{{.*}} return _mm256_cmp_ps_mask(a, b, _CMP_TRUE_US); } @@ -1346,8 +1342,8 @@ __mmask8 test_mm256_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m256 a, __m256 b) { __mmask8 test_mm256_mask_cmp_ps_mask_false_oq(__mmask8 m, __m256 a, __m256 b) { // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); } @@ -1374,7 +1370,8 @@ __mmask8 test_mm256_mask_cmp_ps_mask_gt_os(__mmask8 m, __m256 a, __m256 b) { __mmask8 test_mm256_mask_cmp_ps_mask_true_uq(__mmask8 m, __m256 a, __m256 b) { // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); } @@ -1457,8 +1454,8 @@ __mmask8 test_mm256_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m256 a, __m256 b) { __mmask8 test_mm256_mask_cmp_ps_mask_false_os(__mmask8 m, __m256 a, __m256 b) { // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } @@ -1485,7 +1482,8 @@ __mmask8 test_mm256_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m256 a, __m256 b) { __mmask8 test_mm256_mask_cmp_ps_mask_true_us(__mmask8 m, __m256 a, __m256 b) { // CHECK-LABEL: test_mm256_mask_cmp_ps_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <8 x float> %{{.*}}, %{{.*}} + // CHECK: and <8 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); } @@ -1557,8 +1555,7 @@ __mmask8 test_mm256_cmp_pd_mask_ngt_us(__m256d a, __m256d b) { __mmask8 test_mm256_cmp_pd_mask_false_oq(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OQ); } @@ -1582,8 +1579,7 @@ __mmask8 test_mm256_cmp_pd_mask_gt_os(__m256d a, __m256d b) { __mmask8 test_mm256_cmp_pd_mask_true_uq(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_UQ); } @@ -1655,8 +1651,7 @@ __mmask8 test_mm256_cmp_pd_mask_ngt_uq(__m256d a, __m256d b) { __mmask8 test_mm256_cmp_pd_mask_false_os(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd_mask(a, b, _CMP_FALSE_OS); } @@ -1680,8 +1675,7 @@ __mmask8 test_mm256_cmp_pd_mask_gt_oq(__m256d a, __m256d b) { __mmask8 test_mm256_cmp_pd_mask_true_us(__m256d a, __m256d b) { // CHECK-LABEL: test_mm256_cmp_pd_mask_true_us - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <4 x double> %{{.*}}, %{{.*}} return _mm256_cmp_pd_mask(a, b, _CMP_TRUE_US); } @@ -1764,8 +1758,8 @@ __mmask8 test_mm256_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m256d a, __m256d b) { __mmask8 test_mm256_mask_cmp_pd_mask_false_oq(__mmask8 m, __m256d a, __m256d b) { // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); } @@ -1792,7 +1786,8 @@ __mmask8 test_mm256_mask_cmp_pd_mask_gt_os(__mmask8 m, __m256d a, __m256d b) { __mmask8 test_mm256_mask_cmp_pd_mask_true_uq(__mmask8 m, __m256d a, __m256d b) { // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); } @@ -1875,8 +1870,8 @@ __mmask8 test_mm256_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m256d a, __m256d b) { __mmask8 test_mm256_mask_cmp_pd_mask_false_os(__mmask8 m, __m256d a, __m256d b) { // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); } @@ -1903,7 +1898,8 @@ __mmask8 test_mm256_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m256d a, __m256d b) { __mmask8 test_mm256_mask_cmp_pd_mask_true_us(__mmask8 m, __m256d a, __m256d b) { // CHECK-LABEL: test_mm256_mask_cmp_pd_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <4 x double> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm256_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); } @@ -1975,8 +1971,7 @@ __mmask8 test_mm_cmp_ps_mask_ngt_us(__m128 a, __m128 b) { __mmask8 test_mm_cmp_ps_mask_false_oq(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OQ); } @@ -2000,8 +1995,7 @@ __mmask8 test_mm_cmp_ps_mask_gt_os(__m128 a, __m128 b) { __mmask8 test_mm_cmp_ps_mask_true_uq(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps_mask(a, b, _CMP_TRUE_UQ); } @@ -2073,8 +2067,7 @@ __mmask8 test_mm_cmp_ps_mask_ngt_uq(__m128 a, __m128 b) { __mmask8 test_mm_cmp_ps_mask_false_os(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps_mask(a, b, _CMP_FALSE_OS); } @@ -2098,8 +2091,7 @@ __mmask8 test_mm_cmp_ps_mask_gt_oq(__m128 a, __m128 b) { __mmask8 test_mm_cmp_ps_mask_true_us(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_mask_true_us - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <4 x float> %{{.*}}, %{{.*}} return _mm_cmp_ps_mask(a, b, _CMP_TRUE_US); } @@ -2182,8 +2174,8 @@ __mmask8 test_mm_mask_cmp_ps_mask_ngt_us(__mmask8 m, __m128 a, __m128 b) { __mmask8 test_mm_mask_cmp_ps_mask_false_oq(__mmask8 m, __m128 a, __m128 b) { // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OQ); } @@ -2210,7 +2202,8 @@ __mmask8 test_mm_mask_cmp_ps_mask_gt_os(__mmask8 m, __m128 a, __m128 b) { __mmask8 test_mm_mask_cmp_ps_mask_true_uq(__mmask8 m, __m128 a, __m128 b) { // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_UQ); } @@ -2293,8 +2286,8 @@ __mmask8 test_mm_mask_cmp_ps_mask_ngt_uq(__mmask8 m, __m128 a, __m128 b) { __mmask8 test_mm_mask_cmp_ps_mask_false_os(__mmask8 m, __m128 a, __m128 b) { // CHECK-LABEL: test_mm_mask_cmp_ps_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_ps_mask(m, a, b, _CMP_FALSE_OS); } @@ -2321,7 +2314,8 @@ __mmask8 test_mm_mask_cmp_ps_mask_gt_oq(__mmask8 m, __m128 a, __m128 b) { __mmask8 test_mm_mask_cmp_ps_mask_true_us(__mmask8 m, __m128 a, __m128 b) { // CHECK-LABEL: test_mm_mask_cmp_ps_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <4 x float> %{{.*}}, %{{.*}} + // CHECK: and <4 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_ps_mask(m, a, b, _CMP_TRUE_US); } @@ -2393,8 +2387,7 @@ __mmask8 test_mm_cmp_pd_mask_ngt_us(__m128d a, __m128d b) { __mmask8 test_mm_cmp_pd_mask_false_oq(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OQ); } @@ -2418,8 +2411,7 @@ __mmask8 test_mm_cmp_pd_mask_gt_os(__m128d a, __m128d b) { __mmask8 test_mm_cmp_pd_mask_true_uq(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_mask_true_uq - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd_mask(a, b, _CMP_TRUE_UQ); } @@ -2491,8 +2483,7 @@ __mmask8 test_mm_cmp_pd_mask_ngt_uq(__m128d a, __m128d b) { __mmask8 test_mm_cmp_pd_mask_false_os(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: fcmp false <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd_mask(a, b, _CMP_FALSE_OS); } @@ -2516,8 +2507,7 @@ __mmask8 test_mm_cmp_pd_mask_gt_oq(__m128d a, __m128d b) { __mmask8 test_mm_cmp_pd_mask_true_us(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_mask_true_us - // CHECK-NOT: call - // CHECK: ret i8 -1 + // CHECK: fcmp true <2 x double> %{{.*}}, %{{.*}} return _mm_cmp_pd_mask(a, b, _CMP_TRUE_US); } @@ -2600,8 +2590,8 @@ __mmask8 test_mm_mask_cmp_pd_mask_ngt_us(__mmask8 m, __m128d a, __m128d b) { __mmask8 test_mm_mask_cmp_pd_mask_false_oq(__mmask8 m, __m128d a, __m128d b) { // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_oq - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OQ); } @@ -2628,7 +2618,8 @@ __mmask8 test_mm_mask_cmp_pd_mask_gt_os(__mmask8 m, __m128d a, __m128d b) { __mmask8 test_mm_mask_cmp_pd_mask_true_uq(__mmask8 m, __m128d a, __m128d b) { // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_uq - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_UQ); } @@ -2711,8 +2702,8 @@ __mmask8 test_mm_mask_cmp_pd_mask_ngt_uq(__mmask8 m, __m128d a, __m128d b) { __mmask8 test_mm_mask_cmp_pd_mask_false_os(__mmask8 m, __m128d a, __m128d b) { // CHECK-LABEL: test_mm_mask_cmp_pd_mask_false_os - // CHECK-NOT: call - // CHECK: ret i8 0 + // CHECK: [[CMP:%.*]] = fcmp false <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_pd_mask(m, a, b, _CMP_FALSE_OS); } @@ -2739,7 +2730,8 @@ __mmask8 test_mm_mask_cmp_pd_mask_gt_oq(__mmask8 m, __m128d a, __m128d b) { __mmask8 test_mm_mask_cmp_pd_mask_true_us(__mmask8 m, __m128d a, __m128d b) { // CHECK-LABEL: test_mm_mask_cmp_pd_mask_true_us - // FIXME + // CHECK: [[CMP:%.*]] = fcmp true <2 x double> %{{.*}}, %{{.*}} + // CHECK: and <2 x i1> [[CMP]], {{.*}} return _mm_mask_cmp_pd_mask(m, a, b, _CMP_TRUE_US); } -- GitLab From feb79d981fdf259f32f6b6353a20624f580db2c0 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 5 Jul 2018 15:52:58 +0000 Subject: [PATCH 0414/1023] Fix __builtin_*_overflow when out-param isn't constexpr As brought up on cfe-commits[1], r334650 causes the dependency of the out parameter to the __builtin_*_overflow functions to be ignored. The result was a usage that was otherwise constexpr (both operands to the operation were constexpr) would be evaluated, but the out parameter wouldn't be modified, so it would still be 'undef'. This patch correctly handles the return value of handleAssignment to ensure that this value is properly considered/evaluated. [1] http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20180702/233667.html git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336364 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 3 ++- test/CodeGenCXX/builtins.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c700da635b..828368a3e1 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -8346,7 +8346,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, } APValue APV{Result}; - handleAssignment(Info, E, ResultLValue, ResultType, APV); + if (!handleAssignment(Info, E, ResultLValue, ResultType, APV)) + return false; return Success(DidOverflow, E); } } diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp index a49deea252..33c714e9e1 100644 --- a/test/CodeGenCXX/builtins.cpp +++ b/test/CodeGenCXX/builtins.cpp @@ -30,3 +30,19 @@ long y = __builtin_abs(-2l); extern const char char_memchr_arg[32]; char *memchr_result = __builtin_char_memchr(char_memchr_arg, 123, 32); // CHECK: call i8* @memchr(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @char_memchr_arg, i32 0, i32 0), i32 123, i64 32) + +int constexpr_overflow_result() { + constexpr int x = 1; + // CHECK: alloca i32 + constexpr int y = 2; + // CHECK: alloca i32 + int z; + // CHECK: [[Z:%.+]] = alloca i32 + + __builtin_sadd_overflow(x, y, &z); + return z; + // CHECK: [[RET_PTR:%.+]] = extractvalue { i32, i1 } %0, 0 + // CHECK: store i32 [[RET_PTR]], i32* [[Z]] + // CHECK: [[RET_VAL:%.+]] = load i32, i32* [[Z]] + // CHECK: ret i32 [[RET_VAL]] +} -- GitLab From ba7b10ace863027ff37af5488e3e6bac66d141b4 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 5 Jul 2018 17:22:13 +0000 Subject: [PATCH 0415/1023] [clang-cl, PCH] Implement support for MS-style PCH through headers Implement support for MS-style PCH through headers. This enables support for /Yc and /Yu where the through header is either on the command line or included in the source. It replaces the current support the requires the header also be specified with /FI. This change adds a -cc1 option -pch-through-header that is used to either start or stop compilation during PCH create or use. When creating a PCH, the compilation ends after compilation of the through header. When using a PCH, tokens are skipped until after the through header is seen. Patch By: mikerice Differential Revision: https://reviews.llvm.org/D46652 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336379 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticLexKinds.td | 8 ++ include/clang/Driver/CC1Options.td | 7 +- include/clang/Frontend/FrontendOptions.h | 4 - include/clang/Lex/Preprocessor.h | 25 ++++++ include/clang/Lex/PreprocessorOptions.h | 7 ++ lib/Driver/Driver.cpp | 23 +----- lib/Driver/ToolChains/Clang.cpp | 79 ++++--------------- lib/Frontend/CompilerInstance.cpp | 31 +------- lib/Frontend/CompilerInvocation.cpp | 2 +- lib/Lex/PPDirectives.cpp | 35 ++++++++- lib/Lex/PPLexerChange.cpp | 27 ++++++- lib/Lex/Preprocessor.cpp | 71 +++++++++++++++++ lib/Parse/ParseAST.cpp | 6 ++ lib/Serialization/ASTReader.cpp | 11 +++ test/Driver/cl-pch-search.cpp | 2 +- test/Driver/cl-pch.cpp | 95 +++++++++++++---------- 16 files changed, 268 insertions(+), 165 deletions(-) diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 5d1e149eab..b5b5e8f654 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -404,6 +404,14 @@ def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_directive_required : Error< "%0 must be used within a preprocessing directive">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def err_pp_through_header_not_found : Error< + "'%0' required for precompiled header not found">, DefaultFatal; +def err_pp_through_header_not_seen : Error< + "#include of '%0' not seen while attempting to " + "%select{create|use}1 precompiled header">, DefaultFatal; +def warn_pp_macro_def_mismatch_with_pch : Warning< + "definition of macro %0 does not match definition in precompiled header">, + InGroup; def err_pp_file_not_found_not_fatal : Error< "'%0' file not found with include; use \"quotes\" instead">; def err_pp_error_opening_file : Error< diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 72e2697a44..9f5a64b8a9 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -607,10 +607,9 @@ def fixit_to_temp : Flag<["-"], "fixit-to-temporary">, def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; -def find_pch_source_EQ : Joined<["-"], "find-pch-source=">, - HelpText<"When building a pch, try to find the input file in include " - "directories, as if it had been included by the argument passed " - "to this flag.">; +def pch_through_header_EQ : Joined<["-"], "pch-through-header=">, + HelpText<"Stop PCH generation after including this file. When using a PCH, " + "skip tokens until after this file is included.">; def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, HelpText<"Disable inclusion of timestamp in precompiled headers">; def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">, diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index fa79a36eb2..668df83274 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -435,10 +435,6 @@ public: /// Auxiliary triple for CUDA compilation. std::string AuxTriple; - /// If non-empty, search the pch input file as if it was a header - /// included by this file. - std::string FindPchSource; - /// Filename to write statistics to. std::string StatsFile; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index a6d5f264f9..4ec29fe8f3 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -720,6 +720,12 @@ private: /// The file ID for the preprocessor predefines. FileID PredefinesFileID; + /// The file ID for the PCH through header. + FileID PCHThroughHeaderFileID; + + /// Whether tokens are being skipped until the through header is seen. + bool SkippingUntilPCHThroughHeader = false; + /// \{ /// Cache of macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; @@ -1140,6 +1146,22 @@ public: /// all macro expansions, macro definitions, etc. void createPreprocessingRecord(); + /// Returns true if the FileEntry is the PCH through header. + bool isPCHThroughHeader(const FileEntry *File); + + /// True if creating a PCH with a through header. + bool creatingPCHWithThroughHeader(); + + /// True if using a PCH with a through header. + bool usingPCHWithThroughHeader(); + + /// Skip tokens until after the #include of the through header. + void SkipTokensUntilPCHThroughHeader(); + + /// Process directives while skipping until the through header is found. + void HandleSkippedThroughHeaderDirective(Token &Result, + SourceLocation HashLoc); + /// Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); @@ -2020,6 +2042,9 @@ private: PredefinesFileID = FID; } + /// Set the FileID for the PCH through header. + void setPCHThroughHeaderFileID(FileID FID); + /// Returns true if we are lexing from a file and not a /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index 8cf1fc6058..f4ec2f27c4 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -54,6 +54,13 @@ public: /// definitions and expansions. bool DetailedRecord = false; + /// If non-empty, the filename used in an #include directive in the primary + /// source file (or command-line preinclude) that is used to implement + /// MSVC-style precompiled headers. When creating a PCH, after the #include + /// of this header, the PCH generation stops. When using a PCH, tokens are + /// skipped until after an #include of this header is seen. + std::string PCHThroughHeader; + /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 7b890d80f0..1fd7a6d718 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2991,22 +2991,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, Args.eraseArg(options::OPT__SLASH_Yu); YcArg = YuArg = nullptr; } - if (YcArg || YuArg) { - StringRef Val = YcArg ? YcArg->getValue() : YuArg->getValue(); - bool FoundMatchingInclude = false; - for (const Arg *Inc : Args.filtered(options::OPT_include)) { - // FIXME: Do case-insensitive matching and consider / and \ as equal. - if (Inc->getValue() == Val) - FoundMatchingInclude = true; - } - if (!FoundMatchingInclude) { - Diag(clang::diag::warn_drv_ycyu_no_fi_arg_clang_cl) - << (YcArg ? YcArg : YuArg)->getSpelling(); - Args.eraseArg(options::OPT__SLASH_Yc); - Args.eraseArg(options::OPT__SLASH_Yu); - YcArg = YuArg = nullptr; - } - } if (YcArg && Inputs.size() > 1) { Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl); Args.eraseArg(options::OPT__SLASH_Yc); @@ -3076,11 +3060,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType); llvm::SmallVector PCHPL; types::getCompilationPhases(HeaderType, PCHPL); - Arg *PchInputArg = MakeInputArg(Args, *Opts, YcArg->getValue()); - // Build the pipeline for the pch file. Action *ClangClPch = - C.MakeAction(*PchInputArg, HeaderType); + C.MakeAction(*InputArg, HeaderType); for (phases::ID Phase : PCHPL) ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch); assert(ClangClPch); @@ -4269,6 +4251,9 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const { // extension of .pch is assumed. " if (!llvm::sys::path::has_extension(Output)) Output += ".pch"; + } else if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc)) { + Output = YcArg->getValue(); + llvm::sys::path::replace_extension(Output, ".pch"); } else { Output = BaseName; llvm::sys::path::replace_extension(Output, ".pch"); diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 5999d0b3f9..d7092801df 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1060,77 +1060,28 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, // wonky, but we include looking for .gch so we can support seamless // replacement into a build system already set up to be generating // .gch files. - int YcIndex = -1, YuIndex = -1; - { - int AI = -1; + + if (getToolChain().getDriver().IsCLMode()) { const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc); const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu); - for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) { - // Walk the whole i_Group and skip non "-include" flags so that the index - // here matches the index in the next loop below. - ++AI; - if (!A->getOption().matches(options::OPT_include)) - continue; - if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0) - YcIndex = AI; - if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0) - YuIndex = AI; + if (YcArg && JA.getKind() >= Action::PrecompileJobClass && + JA.getKind() <= Action::AssembleJobClass) { + CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj")); + } + if (YcArg || YuArg) { + StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue(); + if (!isa(JA)) { + CmdArgs.push_back("-include-pch"); + CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader))); + } + CmdArgs.push_back( + Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); } - } - if (isa(JA) && YcIndex != -1) { - Driver::InputList Inputs; - D.BuildInputs(getToolChain(), C.getArgs(), Inputs); - assert(Inputs.size() == 1 && "Need one input when building pch"); - CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") + - Inputs[0].second->getValue())); - } - if (YcIndex != -1 && JA.getKind() >= Action::PrecompileJobClass && - JA.getKind() <= Action::AssembleJobClass) { - CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj")); } bool RenderedImplicitInclude = false; - int AI = -1; for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) { - ++AI; - - if (getToolChain().getDriver().IsCLMode() && - A->getOption().matches(options::OPT_include)) { - // In clang-cl mode, /Ycfoo.h means that all code up to a foo.h - // include is compiled into foo.h, and everything after goes into - // the .obj file. /Yufoo.h means that all includes prior to and including - // foo.h are completely skipped and replaced with a use of the pch file - // for foo.h. (Each flag can have at most one value, multiple /Yc flags - // just mean that the last one wins.) If /Yc and /Yu are both present - // and refer to the same file, /Yc wins. - // Note that OPT__SLASH_FI gets mapped to OPT_include. - // FIXME: The code here assumes that /Yc and /Yu refer to the same file. - // cl.exe seems to support both flags with different values, but that - // seems strange (which flag does /Fp now refer to?), so don't implement - // that until someone needs it. - int PchIndex = YcIndex != -1 ? YcIndex : YuIndex; - if (PchIndex != -1) { - if (isa(JA)) { - // When building the pch, skip all includes after the pch. - assert(YcIndex != -1 && PchIndex == YcIndex); - if (AI >= YcIndex) - continue; - } else { - // When using the pch, skip all includes prior to the pch. - if (AI < PchIndex) { - A->claim(); - continue; - } - if (AI == PchIndex) { - A->claim(); - CmdArgs.push_back("-include-pch"); - CmdArgs.push_back( - Args.MakeArgString(D.GetClPchPath(C, A->getValue()))); - continue; - } - } - } - } else if (A->getOption().matches(options::OPT_include)) { + if (A->getOption().matches(options::OPT_include)) { // Handling of gcc-style gch precompiled headers. bool IsFirstImplicitInclude = !RenderedImplicitInclude; RenderedImplicitInclude = true; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index c4863d6c03..5727aae5f1 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -853,36 +853,7 @@ bool CompilerInstance::InitializeSourceManager( // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File; - if (Opts.FindPchSource.empty()) { - File = FileMgr.getFile(InputFile, /*OpenFile=*/true); - } else { - // When building a pch file in clang-cl mode, the .h file is built as if - // it was included by a cc file. Since the driver doesn't know about - // all include search directories, the frontend must search the input - // file through HeaderSearch here, as if it had been included by the - // cc file at Opts.FindPchSource. - const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource); - if (!FindFile) { - Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource; - return false; - } - const DirectoryLookup *UnusedCurDir; - SmallVector, 16> - Includers; - Includers.push_back(std::make_pair(FindFile, FindFile->getDir())); - File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false, - /*FromDir=*/nullptr, - /*CurDir=*/UnusedCurDir, Includers, - /*SearchPath=*/nullptr, - /*RelativePath=*/nullptr, - /*RequestingModule=*/nullptr, - /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, - /*SkipCache=*/true); - // Also add the header to /showIncludes output. - if (File) - DepOpts.ShowIncludesPretendHeader = File->getName(); - } + const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3335ccb4fc..f57f23a0d4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1546,7 +1546,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = Args.getLastArgValue(OPT_foverride_record_layout_EQ); Opts.AuxTriple = llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple)); - Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ); Opts.StatsFile = Args.getLastArgValue(OPT_stats_file); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, @@ -2828,6 +2827,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, frontend::ActionKind Action) { Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); + Opts.PCHThroughHeader = Args.getLastArgValue(OPT_pch_through_header_EQ); if (const Arg *A = Args.getLastArg(OPT_token_cache)) Opts.TokenCache = A->getValue(); else diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 949dbf1756..4ea0f485d3 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -887,6 +887,22 @@ private: bool save; }; +/// Process a directive while looking for the through header. +/// Only #include (to check if it is the through header) and #define (to warn +/// about macros that don't match the PCH) are handled. All other directives +/// are completely discarded. +void Preprocessor::HandleSkippedThroughHeaderDirective(Token &Result, + SourceLocation HashLoc) { + if (const IdentifierInfo *II = Result.getIdentifierInfo()) { + if (II->getPPKeywordID() == tok::pp_include) + return HandleIncludeDirective(HashLoc, Result); + if (II->getPPKeywordID() == tok::pp_define) + return HandleDefineDirective(Result, + /*ImmediatelyAfterHeaderGuard=*/false); + } + DiscardUntilEndOfDirective(); +} + /// HandleDirective - This callback is invoked when the lexer sees a # token /// at the start of a line. This consumes the directive, modifies the /// lexer/preprocessor state, and advances the lexer(s) so that the next token @@ -948,6 +964,9 @@ void Preprocessor::HandleDirective(Token &Result) { // and reset to previous state when returning from this function. ResetMacroExpansionHelper helper(this); + if (SkippingUntilPCHThroughHeader) + return HandleSkippedThroughHeaderDirective(Result, SavedHash.getLocation()); + switch (Result.getKind()) { case tok::eod: return; // null directive. @@ -1862,6 +1881,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } + if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) { + if (isPCHThroughHeader(File)) + SkippingUntilPCHThroughHeader = false; + return; + } + // Should we enter the source file? Set to false if either the source file is // known to have no effect beyond its effect on module visibility -- that is, // if it's got an include guard that is already defined or is a modular header @@ -2587,7 +2612,15 @@ void Preprocessor::HandleDefineDirective( } } - + // When skipping just warn about macros that do not match. + if (SkippingUntilPCHThroughHeader) { + const MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo()); + if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this, + /*Syntactic=*/LangOpts.MicrosoftExt)) + Diag(MI->getDefinitionLoc(), diag::warn_pp_macro_def_mismatch_with_pch) + << MacroNameTok.getIdentifierInfo(); + return; + } // Finally, if this identifier already had a macro defined for it, verify that // the macro bodies are identical, and issue diagnostics if they are not. diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index c7e0d2c7c2..352814d715 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/HeaderSearch.h" @@ -425,6 +426,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { PragmaAssumeNonNullLoc = SourceLocation(); } + bool LeavingPCHThroughHeader = false; + // If this is a #include'd file, pop it off the include stack and continue // lexing the #includer file. if (!IncludeMacroStack.empty()) { @@ -481,6 +484,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { Result.setAnnotationValue(M); } + bool FoundPCHThroughHeader = false; + if (CurPPLexer && creatingPCHWithThroughHeader() && + isPCHThroughHeader( + SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) + FoundPCHThroughHeader = true; + // We're done with the #included file. RemoveTopOfLexerStack(); @@ -500,8 +509,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (ExitedFromPredefinesFile) replayPreambleConditionalStack(); - // Client should lex another token unless we generated an EOM. - return LeavingSubmodule; + if (!isEndOfMacro && CurPPLexer && FoundPCHThroughHeader && + (isInPrimaryFile() || + CurPPLexer->getFileID() == getPredefinesFileID())) { + // Leaving the through header. Continue directly to end of main file + // processing. + LeavingPCHThroughHeader = true; + } else { + // Client should lex another token unless we generated an EOM. + return LeavingSubmodule; + } } // If this is the end of the main file, form an EOF token. @@ -522,6 +539,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { Result.setLocation(Result.getLocation().getLocWithOffset(-1)); } + if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) { + // Reached the end of the compilation without finding the through header. + Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen) + << PPOpts->PCHThroughHeader << 0; + } + if (!isIncrementalProcessingEnabled()) // We're done with lexing. CurLexer.reset(); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 358103d43d..0217a2e60e 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -149,6 +149,11 @@ Preprocessor::Preprocessor(std::shared_ptr PPOpts, Ident_AbnormalTermination = nullptr; } + // If using a PCH with a through header, start skipping tokens. + if (!this->PPOpts->PCHThroughHeader.empty() && + !this->PPOpts->ImplicitPCHInclude.empty()) + SkippingUntilPCHThroughHeader = true; + if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); } @@ -551,6 +556,72 @@ void Preprocessor::EnterMainSourceFile() { // Start parsing the predefines. EnterSourceFile(FID, nullptr, SourceLocation()); + + if (!PPOpts->PCHThroughHeader.empty()) { + // Lookup and save the FileID for the through header. If it isn't found + // in the search path, it's a fatal error. + const DirectoryLookup *CurDir; + const FileEntry *File = LookupFile( + SourceLocation(), PPOpts->PCHThroughHeader, + /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, + /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, + /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr); + if (!File) { + Diag(SourceLocation(), diag::err_pp_through_header_not_found) + << PPOpts->PCHThroughHeader; + return; + } + setPCHThroughHeaderFileID( + SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User)); + } + + // Skip tokens from the Predefines and if needed the main file. + if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) + SkipTokensUntilPCHThroughHeader(); +} + +void Preprocessor::setPCHThroughHeaderFileID(FileID FID) { + assert(PCHThroughHeaderFileID.isInvalid() && + "PCHThroughHeaderFileID already set!"); + PCHThroughHeaderFileID = FID; +} + +bool Preprocessor::isPCHThroughHeader(const FileEntry *FE) { + assert(PCHThroughHeaderFileID.isValid() && + "Invalid PCH through header FileID"); + return FE == SourceMgr.getFileEntryForID(PCHThroughHeaderFileID); +} + +bool Preprocessor::creatingPCHWithThroughHeader() { + return TUKind == TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +bool Preprocessor::usingPCHWithThroughHeader() { + return TUKind != TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +/// Skip tokens until after the #include of the through header. +/// Tokens in the predefines file and the main file may be skipped. If the end +/// of the predefines file is reached, skipping continues into the main file. +/// If the end of the main file is reached, it's a fatal error. +void Preprocessor::SkipTokensUntilPCHThroughHeader() { + bool ReachedMainFileEOF = false; + Token Tok; + while (true) { + bool InPredefines = (CurLexer->getFileID() == getPredefinesFileID()); + CurLexer->Lex(Tok); + if (Tok.is(tok::eof) && !InPredefines) { + ReachedMainFileEOF = true; + break; + } + if (!SkippingUntilPCHThroughHeader) + break; + } + if (ReachedMainFileEOF) + Diag(SourceLocation(), diag::err_pp_through_header_not_seen) + << PPOpts->PCHThroughHeader << 1; } void Preprocessor::replayPreambleConditionalStack() { diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index 354b380079..696506099e 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -141,6 +141,12 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); + if (!S.getPreprocessor().getCurrentLexer()) { + // If a PCH through header is specified that does not have an include in + // the source, there won't be any tokens or a Lexer. + return; + } + P.Initialize(); Parser::DeclGroupPtrTy ADecl; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index f56afeb892..84286ca380 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -704,6 +704,17 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, // Compute the #include and #include_macros lines we need. for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) { StringRef File = ExistingPPOpts.Includes[I]; + + if (!ExistingPPOpts.ImplicitPCHInclude.empty() && + !ExistingPPOpts.PCHThroughHeader.empty()) { + // In case the through header is an include, we must add all the includes + // to the predefines so the start point can be determined. + SuggestedPredefines += "#include \""; + SuggestedPredefines += File; + SuggestedPredefines += "\"\n"; + continue; + } + if (File == ExistingPPOpts.ImplicitPCHInclude) continue; diff --git a/test/Driver/cl-pch-search.cpp b/test/Driver/cl-pch-search.cpp index 5c072c3b7f..3ba4a11753 100644 --- a/test/Driver/cl-pch-search.cpp +++ b/test/Driver/cl-pch-search.cpp @@ -3,4 +3,4 @@ // REQUIRES: x86-registered-target // Check that pchfile.h next to pchfile.cc is found correctly. -// RUN: %clang_cl -Werror --target=x86_64-windows /Ycpchfile.h /FIpchfile.h /c /Fo%t.obj /Fp%t.pch -- %S/Inputs/pchfile.cpp +// RUN: %clang_cl -Werror -Wno-microsoft-include --target=x86_64-windows /Ycpchfile.h /FIpchfile.h /c /Fo%t.obj /Fp%t.pch -- %S/Inputs/pchfile.cpp diff --git a/test/Driver/cl-pch.cpp b/test/Driver/cl-pch.cpp index bef5ce6bd0..8521d3576a 100644 --- a/test/Driver/cl-pch.cpp +++ b/test/Driver/cl-pch.cpp @@ -157,26 +157,37 @@ // 1. Build .pch file: Includes foo1.h (but NOT foo3.h) and compiles foo2.h // CHECK-YCFIFIFI: cc1 // CHECK-YCFIFIFI: -emit-pch +// CHECK-YCFIFIFI: -pch-through-header=foo2.h // CHECK-YCFIFIFI: -include // CHECK-YCFIFIFI: foo1.h -// CHECK-YCFIFIFI-NOT: foo2.h -// CHECK-YCFIFIFI-NOT: foo3.h +// CHECK-YCFIFIFI: -include +// CHECK-YCFIFIFI: foo2.h +// CHECK-YCFIFIFI: -include +// CHECK-YCFIFIFI: foo3.h // CHECK-YCFIFIFI: -o // CHECK-YCFIFIFI: foo2.pch // CHECK-YCFIFIFI: -x // CHECK-YCFIFIFI: "c++-header" -// CHECK-YCFIFIFI: foo2.h +// CHECK-YCFIFIFI: cl-pch.cpp // 2. Use .pch file: Inlucdes foo2.pch and foo3.h // CHECK-YCFIFIFI: cc1 // CHECK-YCFIFIFI: -emit-obj -// CHECK-YCFIFIFI-NOT: foo1.h -// CHECK-YCFIFIFI-NOT: foo2.h // CHECK-YCFIFIFI: -include-pch // CHECK-YCFIFIFI: foo2.pch +// CHECK-YCFIFIFI: -pch-through-header=foo2.h +// CHECK-YCFIFIFI: -include +// CHECK-YCFIFIFI: foo1.h +// CHECK-YCFIFIFI: -include +// CHECK-YCFIFIFI: foo2.h // CHECK-YCFIFIFI: -include // CHECK-YCFIFIFI: foo3.h +// CHECK-YCFIFIFI: -o +// CHECK-YCFIFIFI: cl-pch.obj +// CHECK-YCFIFIFI: -x +// CHECK-YCFIFIFI: "c++" +// CHECK-YCFIFIFI: cl-pch.cpp -// /Yucfoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h +// /Yufoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h // => foo1 foo2 filtered out, foo3 into main compilation // RUN: %clang_cl -Werror /Yufoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YUFIFIFI %s @@ -184,38 +195,47 @@ // CHECK-YUFIFIFI-NOT: -emit-pch // CHECK-YUFIFIFI: cc1 // CHECK-YUFIFIFI: -emit-obj -// CHECK-YUFIFIFI-NOT: foo1.h -// CHECK-YUFIFIFI-NOT: foo2.h // CHECK-YUFIFIFI: -include-pch // CHECK-YUFIFIFI: foo2.pch +// CHECK-YUFIFIFI: -pch-through-header=foo2.h +// CHECK-YUFIFIFI: -include +// CHECK-YUFIFIFI: foo1.h +// CHECK-YUFIFIFI: -include +// CHECK-YUFIFIFI: foo2.h // CHECK-YUFIFIFI: -include // CHECK-YUFIFIFI: foo3.h -// FIXME: Implement support for /Ycfoo.h / /Yufoo.h without /FIfoo.h +// Test /Ycfoo.h / /Yufoo.h without /FIfoo.h // RUN: %clang_cl -Werror /Ycfoo.h /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YC-NOFI %s -// CHECK-YC-NOFI: error: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored +// 1. Precompile +// CHECK-YC-NOFI: cc1 +// CHECK-YC-NOFI: -emit-pch +// CHECK-YC-NOFI: -pch-through-header=foo.h +// CHECK-YC-NOFI: -o +// CHECK-YC-NOFI: foo.pch +// CHECK-YC-NOFI: -x +// CHECK-YC-NOFI: c++-header +// CHECK-YC-NOFI: cl-pch.cpp +// 2. Build PCH object +// CHECK-YC-NOFI: cc1 +// CHECK-YC-NOFI: -emit-obj +// CHECK-YC-NOFI: -include-pch +// CHECK-YC-NOFI: foo.pch +// CHECK-YC-NOFI: -pch-through-header=foo.h +// CHECK-YC-NOFI: -x +// CHECK-YC-NOFI: c++ +// CHECK-YC-NOFI: cl-pch.cpp // RUN: %clang_cl -Werror /Yufoo.h /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YU-NOFI %s -// CHECK-YU-NOFI: error: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored - -// /Yc and /FI relative to /I paths... -// The rules are: -// Yu/Yc and FI parameter must match exactly, else it's not found -// Must match literally exactly: /FI./foo.h /Ycfoo.h does _not_ work. -// However, the path can be relative to /I paths. -// FIXME: Update the error messages below once /FI is no longer required, but -// these test cases all should stay failures as they fail with cl.exe. - -// Check that ./ isn't canonicalized away. -// RUN: %clang_cl -Werror /Ycpchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-YC-I1 %s -// CHECK-YC-I1: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored - -// Check that ./ isn't canonicalized away. -// RUN: %clang_cl -Werror /Yc./pchfile.h /FIpchfile.h /c -### -- %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-YC-I2 %s -// CHECK-YC-I2: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored +// CHECK-YU-NOFI: cc1 +// CHECK-YU-NOFI: -emit-obj +// CHECK-YU-NOFI: -include-pch +// CHECK-YU-NOFI: foo.pch +// CHECK-YU-NOFI: -pch-through-header=foo.h +// CHECK-YU-NOFI: -x +// CHECK-YU-NOFI: c++ +// CHECK-YU-NOFI: cl-pch.cpp // With an actual /I argument. // RUN: %clang_cl -Werror /Ifoo /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \ @@ -232,20 +252,17 @@ // CHECK-YC-I3: -include-pch // CHECK-YC-I3: pchfile.pch -// Check that ./ isn't canonicalized away for /Yu either. -// RUN: %clang_cl -Werror /Yupchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-YU-I1 %s -// CHECK-YU-I1: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored - // But /FIfoo/bar.h /Ycfoo\bar.h does work, as does /FIfOo.h /Ycfoo.H -// FIXME: This part isn't implemented yet. The following two tests should not -// show an error but do regular /Yu handling. // RUN: %clang_cl -Werror /YupchFILE.h /FI./pchfile.h /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YU-CASE %s -// CHECK-YU-CASE: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored -// RUN: %clang_cl -Werror /Yu./pchfile.h /FI.\pchfile.h /c -### -- %s 2>&1 \ +// CHECK-YU-CASE: -pch-through-header=pchFILE.h +// CHECK-YU-CASE: -include +// CHECK-YU-CASE: "./pchfile.h" +// RUN: %clang_cl -Werror /Yu./pchfile.h /FI.\\pchfile.h /c -### -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YU-SLASH %s -// CHECK-YU-SLASH: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored +// CHECK-YU-SLASH: -pch-through-header=./pchfile.h +// CHECK-YU-SLASH: -include +// CHECK-YU-SLASH: ".{{[/\\]+}}pchfile.h" // cl.exe warns on multiple /Yc, /Yu, /Fp arguments, but clang-cl silently just // uses the last one. This is true for e.g. /Fo too, so not warning on this -- GitLab From 6aaa2f4b453456b0f82b4ffcef4c8fa10c94bfc7 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 5 Jul 2018 17:23:15 +0000 Subject: [PATCH 0416/1023] Add PCH tests for R336379 I seemingly forgot the tests for this commit, added here. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336380 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/PCH/Inputs/pch-through-use0.cpp | 2 ++ test/PCH/Inputs/pch-through-use1.cpp | 5 ++++ test/PCH/Inputs/pch-through-use2.cpp | 3 +++ test/PCH/Inputs/pch-through-use3a.cpp | 2 ++ test/PCH/Inputs/pch-through-use3b.cpp | 3 +++ test/PCH/Inputs/pch-through1.h | 2 ++ test/PCH/Inputs/pch-through2.h | 2 ++ test/PCH/Inputs/pch-through3.h | 2 ++ test/PCH/Inputs/pch-through4.h | 2 ++ test/PCH/pch-through1.cpp | 34 +++++++++++++++++++++++++++ test/PCH/pch-through2.cpp | 28 ++++++++++++++++++++++ test/PCH/pch-through3a.cpp | 10 ++++++++ test/PCH/pch-through3b.cpp | 14 +++++++++++ 13 files changed, 109 insertions(+) create mode 100644 test/PCH/Inputs/pch-through-use0.cpp create mode 100644 test/PCH/Inputs/pch-through-use1.cpp create mode 100644 test/PCH/Inputs/pch-through-use2.cpp create mode 100644 test/PCH/Inputs/pch-through-use3a.cpp create mode 100644 test/PCH/Inputs/pch-through-use3b.cpp create mode 100644 test/PCH/Inputs/pch-through1.h create mode 100644 test/PCH/Inputs/pch-through2.h create mode 100644 test/PCH/Inputs/pch-through3.h create mode 100644 test/PCH/Inputs/pch-through4.h create mode 100644 test/PCH/pch-through1.cpp create mode 100644 test/PCH/pch-through2.cpp create mode 100644 test/PCH/pch-through3a.cpp create mode 100644 test/PCH/pch-through3b.cpp diff --git a/test/PCH/Inputs/pch-through-use0.cpp b/test/PCH/Inputs/pch-through-use0.cpp new file mode 100644 index 0000000000..a39080144f --- /dev/null +++ b/test/PCH/Inputs/pch-through-use0.cpp @@ -0,0 +1,2 @@ +void foo() { +} diff --git a/test/PCH/Inputs/pch-through-use1.cpp b/test/PCH/Inputs/pch-through-use1.cpp new file mode 100644 index 0000000000..4eda7cecc9 --- /dev/null +++ b/test/PCH/Inputs/pch-through-use1.cpp @@ -0,0 +1,5 @@ +#include "Inputs/pch-through1.h" +#include "Inputs/pch-through3.h" +void foo() { + through2(0); +} diff --git a/test/PCH/Inputs/pch-through-use2.cpp b/test/PCH/Inputs/pch-through-use2.cpp new file mode 100644 index 0000000000..217803ba39 --- /dev/null +++ b/test/PCH/Inputs/pch-through-use2.cpp @@ -0,0 +1,3 @@ +void foo() { + through4(0); +} diff --git a/test/PCH/Inputs/pch-through-use3a.cpp b/test/PCH/Inputs/pch-through-use3a.cpp new file mode 100644 index 0000000000..dfd1d11071 --- /dev/null +++ b/test/PCH/Inputs/pch-through-use3a.cpp @@ -0,0 +1,2 @@ +#define AFOO 0 +#include "Inputs/pch-through1.h" diff --git a/test/PCH/Inputs/pch-through-use3b.cpp b/test/PCH/Inputs/pch-through-use3b.cpp new file mode 100644 index 0000000000..5b547647d8 --- /dev/null +++ b/test/PCH/Inputs/pch-through-use3b.cpp @@ -0,0 +1,3 @@ +#define AFOO 1 +#define BFOO 2 +#include "Inputs/pch-through1.h" diff --git a/test/PCH/Inputs/pch-through1.h b/test/PCH/Inputs/pch-through1.h new file mode 100644 index 0000000000..7ebfa7d5df --- /dev/null +++ b/test/PCH/Inputs/pch-through1.h @@ -0,0 +1,2 @@ +#define THROUGH1 +int through1(int); diff --git a/test/PCH/Inputs/pch-through2.h b/test/PCH/Inputs/pch-through2.h new file mode 100644 index 0000000000..4c1f2981f9 --- /dev/null +++ b/test/PCH/Inputs/pch-through2.h @@ -0,0 +1,2 @@ +#define THROUGH2 +int through2(int); diff --git a/test/PCH/Inputs/pch-through3.h b/test/PCH/Inputs/pch-through3.h new file mode 100644 index 0000000000..2836865500 --- /dev/null +++ b/test/PCH/Inputs/pch-through3.h @@ -0,0 +1,2 @@ +#define THROUGH3 +int through3(int); diff --git a/test/PCH/Inputs/pch-through4.h b/test/PCH/Inputs/pch-through4.h new file mode 100644 index 0000000000..95860edd19 --- /dev/null +++ b/test/PCH/Inputs/pch-through4.h @@ -0,0 +1,2 @@ +#define THROUGH4 +int through4(int); diff --git a/test/PCH/pch-through1.cpp b/test/PCH/pch-through1.cpp new file mode 100644 index 0000000000..b7e7fa82a1 --- /dev/null +++ b/test/PCH/pch-through1.cpp @@ -0,0 +1,34 @@ +// Through header not found (anywhere) +// RUN: not %clang_cc1 -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-does-not-exist.h -o %t %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TEST0A %s +// CHECK-TEST0A: fatal error:{{.*}} 'Inputs/pch-does-not-exist.h' +// CHECK-TEST0A-SAME: required for precompiled header not found + +// Through header not found in search path +// RUN: not %clang_cc1 -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through2.h -o %t \ +// RUN: %S/Inputs/pch-through-use0.cpp 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TEST0B %s +// CHECK-TEST0B: fatal error:{{.*}}'Inputs/pch-through2.h' +// CHECK-TEST0B-SAME: required for precompiled header not found + +// No #include of through header during pch create +// RUN: not %clang_cc1 -I %S -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through2.h -o %t %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TEST1A %s +// CHECK-TEST1A: fatal error:{{.*}} #include of +// CHECK-TEST1A-SAME: 'Inputs/pch-through2.h' not seen while attempting to +// CHECK-TEST1A-SAME: create precompiled header + +// checks for through headers that are also -includes +// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \ +// RUN: -pch-through-header=Inputs/pch-through1.h -emit-pch -o %t.s3t1 %s +// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \ +// RUN: -include Inputs/pch-through2.h -include Inputs/pch-through3.h \ +// RUN: -pch-through-header=Inputs/pch-through2.h -emit-pch -o %t.s3t2 %s +// Use through header from -includes +// RUN: %clang_cc1 -I %S -include Inputs/pch-through1.h \ +// RUN: -include Inputs/pch-through2.h -include Inputs/pch-through4.h \ +// RUN: -pch-through-header=Inputs/pch-through2.h -include-pch %t.s3t2 \ +// RUN: %S/Inputs/pch-through-use2.cpp -o %t.out diff --git a/test/PCH/pch-through2.cpp b/test/PCH/pch-through2.cpp new file mode 100644 index 0000000000..6bf7a29d9a --- /dev/null +++ b/test/PCH/pch-through2.cpp @@ -0,0 +1,28 @@ +// Create +// RUN: %clang_cc1 -I %S -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through2.h -o %t.1 %s + +// Use +// RUN: %clang_cc1 -I %S -include-pch %t.1 \ +// RUN: -pch-through-header=Inputs/pch-through2.h %s + +// No #include of through header during pch use +// RUN: not %clang_cc1 -I %S -include-pch %t.1 \ +// RUN: -pch-through-header=Inputs/pch-through2.h \ +// RUN: %S/Inputs/pch-through-use1.cpp 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TEST2A %s +// CHECK-TEST2A: fatal error:{{.*}} #include of +// CHECK-TEST2A-SAME: 'Inputs/pch-through2.h' not seen while attempting to +// CHECK-TEST2A-SAME: use precompiled header + +// check that pch only contains code before the through header. +// RUN: %clang_cc1 -I %S -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.2 %s +// RUN: not %clang_cc1 -I %S -include-pch %t.2 \ +// RUN: -pch-through-header=Inputs/pch-through1.h \ +// RUN: %S/Inputs/pch-through-use1.cpp 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TEST3 %s +// CHECK-TEST3: error: use of undeclared identifier 'through2' + +#include "Inputs/pch-through1.h" +#include "Inputs/pch-through2.h" diff --git a/test/PCH/pch-through3a.cpp b/test/PCH/pch-through3a.cpp new file mode 100644 index 0000000000..3a134e9310 --- /dev/null +++ b/test/PCH/pch-through3a.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify -I %S -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.s3at1 %s + +// RUN: %clang_cc1 -I %S -include-pch %t.s3at1 \ +// RUN: -pch-through-header=Inputs/pch-through1.h \ +// RUN: %S/Inputs/pch-through-use3a.cpp +//expected-no-diagnostics + +#define AFOO 0 +#include "Inputs/pch-through1.h" diff --git a/test/PCH/pch-through3b.cpp b/test/PCH/pch-through3b.cpp new file mode 100644 index 0000000000..2a7695a709 --- /dev/null +++ b/test/PCH/pch-through3b.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -I %S -emit-pch \ +// RUN: -pch-through-header=Inputs/pch-through1.h -o %t.s3bt1 %s + +// RUN: %clang_cc1 -I %S -include-pch %t.s3bt1 \ +// RUN: -pch-through-header=Inputs/pch-through1.h \ +// RUN: %S/Inputs/pch-through-use3b.cpp 2>&1 | FileCheck %s + +//CHECK: warning: definition of macro 'AFOO' does not match definition in +//CHECK-SAME: precompiled header +//CHECK: warning: definition of macro 'BFOO' does not match definition in +//CHECK-SAME: precompiled header + +#define AFOO 0 +#include "Inputs/pch-through1.h" -- GitLab From 62c4c0fac382ca37cf8b1ace72f201d10f92cb18 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 5 Jul 2018 20:38:31 +0000 Subject: [PATCH 0417/1023] [X86] Use shufflevector instead of a select with a constant mask for fmaddsub/fmsubadd IR emission. Shufflevector is easier to generate and matches what the backend pattern matches without relying on constant selects being turned into shuffles. While I was there I also made the IR regular expressions a little stricter to ensure operand order on the shuffle. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336388 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 12 +- test/CodeGen/avx512f-builtins.c | 128 ++++++++++----------- test/CodeGen/avx512vl-builtins.c | 192 +++++++++++++++---------------- test/CodeGen/fma-builtins.c | 48 ++++---- test/CodeGen/fma4-builtins.c | 48 ++++---- 5 files changed, 212 insertions(+), 216 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 6edb802d91..56cf6a9952 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8660,17 +8660,13 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef Ops, if (IsAddSub) { // Negate even elts in C using a mask. unsigned NumElts = Ty->getVectorNumElements(); - SmallVector NMask; - Constant *Zero = ConstantInt::get(CGF.Builder.getInt1Ty(), 0); - Constant *One = ConstantInt::get(CGF.Builder.getInt1Ty(), 1); - for (unsigned i = 0; i < NumElts; ++i) { - NMask.push_back(i % 2 == 0 ? One : Zero); - } - Value *NegMask = ConstantVector::get(NMask); + SmallVector Indices(NumElts); + for (unsigned i = 0; i != NumElts; ++i) + Indices[i] = i + (i % 2) * NumElts; Value *NegC = CGF.Builder.CreateFNeg(C); Value *FMSub = CGF.Builder.CreateCall(FMA, {A, B, NegC} ); - Res = CGF.Builder.CreateSelect(NegMask, FMSub, Res); + Res = CGF.Builder.CreateShuffleVector(FMSub, Res, Indices); } } diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 3a07d5ed6b..1dea46621d 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -846,66 +846,66 @@ __m512d test_mm512_maskz_fmsubadd_round_pd(__mmask8 __U, __m512d __A, __m512d __ } __m512d test_mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_fmaddsub_pd - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> return _mm512_fmaddsub_pd(__A, __B, __C); } __m512d test_mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_mask_fmaddsub_pd - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_fmaddsub_pd(__A, __U, __B, __C); } __m512d test_mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm512_mask3_fmaddsub_pd - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask3_fmaddsub_pd(__A, __B, __C, __U); } __m512d test_mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_maskz_fmaddsub_pd - // check: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // check: fsub <8 x double> , %{{.*}} - // check: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // check: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: shufflevector <8 x double> [[SUB]], <8 x double> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmaddsub_pd(__U, __A, __B, __C); } __m512d test_mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_fmsubadd_pd - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> return _mm512_fmsubadd_pd(__A, __B, __C); } __m512d test_mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_mask_fmsubadd_pd - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_fmsubadd_pd(__A, __U, __B, __C); } __m512d test_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { // CHECK-LABEL: @test_mm512_maskz_fmsubadd_pd - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> zeroinitializer return _mm512_maskz_fmsubadd_pd(__U, __A, __B, __C); @@ -960,66 +960,66 @@ __m512 test_mm512_maskz_fmsubadd_round_ps(__mmask16 __U, __m512 __A, __m512 __B, } __m512 test_mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_fmaddsub_ps - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> return _mm512_fmaddsub_ps(__A, __B, __C); } __m512 test_mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_mask_fmaddsub_ps - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_fmaddsub_ps(__A, __U, __B, __C); } __m512 test_mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { // CHECK-LABEL: @test_mm512_mask3_fmaddsub_ps - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask3_fmaddsub_ps(__A, __B, __C, __U); } __m512 test_mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_maskz_fmaddsub_ps - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: shufflevector <16 x float> [[SUB]], <16 x float> [[ADD]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmaddsub_ps(__U, __A, __B, __C); } __m512 test_mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_fmsubadd_ps - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> return _mm512_fmsubadd_ps(__A, __B, __C); } __m512 test_mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_mask_fmsubadd_ps - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_fmsubadd_ps(__A, __U, __B, __C); } __m512 test_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { // CHECK-LABEL: @test_mm512_maskz_fmsubadd_ps - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> zeroinitializer return _mm512_maskz_fmsubadd_ps(__U, __A, __B, __C); @@ -1066,10 +1066,10 @@ __m512d test_mm512_mask3_fmsubadd_round_pd(__m512d __A, __m512d __B, __m512d __C } __m512d test_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm512_mask3_fmsubadd_pd - // CHECK: fsub <8 x double> , %{{.*}} - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) - // CHECK: select <8 x i1> , <8 x double> %{{.*}}, <8 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x double> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x double> @llvm.fma.v8f64(<8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}) + // CHECK: shufflevector <8 x double> [[ADD]], <8 x double> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask3_fmsubadd_pd(__A, __B, __C, __U); @@ -1084,10 +1084,10 @@ __m512 test_mm512_mask3_fmsubadd_round_ps(__m512 __A, __m512 __B, __m512 __C, __ } __m512 test_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { // CHECK-LABEL: @test_mm512_mask3_fmsubadd_ps - // CHECK: fsub <16 x float> , %{{.*}} - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) - // CHECK: select <16 x i1> , <16 x float> %{{.*}}, <16 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <16 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <16 x float> @llvm.fma.v16f32(<16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}) + // CHECK: shufflevector <16 x float> [[ADD]], <16 x float> [[SUB]], <16 x i32> // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask3_fmsubadd_ps(__A, __B, __C, __U); diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 9ce320071d..540ea223d9 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -3041,10 +3041,10 @@ __m256 test_mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 _ __m128d test_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_mask_fmaddsub_pd - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3053,10 +3053,10 @@ __m128d test_mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __m128d test_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_mask_fmsubadd_pd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3065,10 +3065,10 @@ __m128d test_mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __m128d test_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmaddsub_pd - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3077,10 +3077,10 @@ __m128d test_mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask __m128d test_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_maskz_fmaddsub_pd - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3089,10 +3089,10 @@ __m128d test_mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128 __m128d test_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { // CHECK-LABEL: @test_mm_maskz_fmsubadd_pd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3101,10 +3101,10 @@ __m128d test_mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128 __m256d test_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_mask_fmaddsub_pd - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3113,10 +3113,10 @@ __m256d test_mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m2 __m256d test_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_mask_fmsubadd_pd - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3125,10 +3125,10 @@ __m256d test_mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m2 __m256d test_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmaddsub_pd - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3137,10 +3137,10 @@ __m256d test_mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mm __m256d test_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_maskz_fmaddsub_pd - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3149,10 +3149,10 @@ __m256d test_mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m __m256d test_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { // CHECK-LABEL: @test_mm256_maskz_fmsubadd_pd - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3161,10 +3161,10 @@ __m256d test_mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m __m128 test_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_mask_fmaddsub_ps - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3173,10 +3173,10 @@ __m128 test_mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C __m128 test_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_mask_fmsubadd_ps - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3185,10 +3185,10 @@ __m128 test_mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C __m128 test_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmaddsub_ps - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3197,10 +3197,10 @@ __m128 test_mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __ __m128 test_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_maskz_fmaddsub_ps - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3209,10 +3209,10 @@ __m128 test_mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __ __m128 test_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { // CHECK-LABEL: @test_mm_maskz_fmsubadd_ps - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3221,10 +3221,10 @@ __m128 test_mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __ __m256 test_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_mask_fmaddsub_ps - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_fmaddsub_ps(__A, __U, __B, __C); @@ -3232,10 +3232,10 @@ __m256 test_mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __m256 test_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_mask_fmsubadd_ps - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask_fmsubadd_ps(__A, __U, __B, __C); @@ -3243,10 +3243,10 @@ __m256 test_mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __m256 test_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmaddsub_ps - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask3_fmaddsub_ps(__A, __B, __C, __U); @@ -3254,10 +3254,10 @@ __m256 test_mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __m256 test_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_maskz_fmaddsub_ps - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_fmaddsub_ps(__U, __A, __B, __C); @@ -3265,10 +3265,10 @@ __m256 test_mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __m256 test_mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { // CHECK-LABEL: @test_mm256_maskz_fmsubadd_ps - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_maskz_fmsubadd_ps(__U, __A, __B, __C); @@ -3315,10 +3315,10 @@ __m256 test_mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __ __m128d test_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmsubadd_pd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <2 x i32> // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}} @@ -3327,10 +3327,10 @@ __m128d test_mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask __m256d test_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmsubadd_pd - // CHECK: fsub <4 x double> , %{{.*}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}} @@ -3339,10 +3339,10 @@ __m256d test_mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mm __m128 test_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm_mask3_fmsubadd_ps - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: shufflevector <8 x i1> %{{.*}}, <8 x i1> %{{.*}}, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -3351,10 +3351,10 @@ __m128 test_mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __ __m256 test_mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { // CHECK-LABEL: @test_mm256_mask3_fmsubadd_ps - // CHECK: fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}} return _mm256_mask3_fmsubadd_ps(__A, __B, __C, __U); diff --git a/test/CodeGen/fma-builtins.c b/test/CodeGen/fma-builtins.c index 5ccbe1c875..ff047f3d83 100644 --- a/test/CodeGen/fma-builtins.c +++ b/test/CodeGen/fma-builtins.c @@ -149,37 +149,37 @@ __m128d test_mm_fnmsub_sd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_fmaddsub_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_fmaddsub_ps - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> return _mm_fmaddsub_ps(a, b, c); } __m128d test_mm_fmaddsub_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_fmaddsub_pd - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> return _mm_fmaddsub_pd(a, b, c); } __m128 test_mm_fmsubadd_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_fmsubadd_ps // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> return _mm_fmsubadd_ps(a, b, c); } __m128d test_mm_fmsubadd_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_fmsubadd_pd // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> return _mm_fmsubadd_pd(a, b, c); } @@ -241,36 +241,36 @@ __m256d test_mm256_fnmsub_pd(__m256d a, __m256d b, __m256d c) { __m256 test_mm256_fmaddsub_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_fmaddsub_ps - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> return _mm256_fmaddsub_ps(a, b, c); } __m256d test_mm256_fmaddsub_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_fmaddsub_pd - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> return _mm256_fmaddsub_pd(a, b, c); } __m256 test_mm256_fmsubadd_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_fmsubadd_ps // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> return _mm256_fmsubadd_ps(a, b, c); } __m256d test_mm256_fmsubadd_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_fmsubadd_pd // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> return _mm256_fmsubadd_pd(a, b, c); } diff --git a/test/CodeGen/fma4-builtins.c b/test/CodeGen/fma4-builtins.c index 12624dc46e..8d88a51519 100644 --- a/test/CodeGen/fma4-builtins.c +++ b/test/CodeGen/fma4-builtins.c @@ -117,37 +117,37 @@ __m128d test_mm_nmsub_sd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_maddsub_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_maddsub_ps - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: shufflevector <4 x float> [[SUB]], <4 x float> [[ADD]], <4 x i32> return _mm_maddsub_ps(a, b, c); } __m128d test_mm_maddsub_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_maddsub_pd - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: shufflevector <2 x double> [[SUB]], <2 x double> [[ADD]], <2 x i32> return _mm_maddsub_pd(a, b, c); } __m128 test_mm_msubadd_ps(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_msubadd_ps // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) - // CHECK: select <4 x i1> , <4 x float> %{{.*}}, <4 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}) + // CHECK: shufflevector <4 x float> [[ADD]], <4 x float> [[SUB]], <4 x i32> return _mm_msubadd_ps(a, b, c); } __m128d test_mm_msubadd_pd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_msubadd_pd // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) - // CHECK: select <2 x i1> , <2 x double> %{{.*}}, <2 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}) + // CHECK: shufflevector <2 x double> [[ADD]], <2 x double> [[SUB]], <2 x i32> return _mm_msubadd_pd(a, b, c); } @@ -209,36 +209,36 @@ __m256d test_mm256_nmsub_pd(__m256d a, __m256d b, __m256d c) { __m256 test_mm256_maddsub_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_maddsub_ps - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: shufflevector <8 x float> [[SUB]], <8 x float> [[ADD]], <8 x i32> return _mm256_maddsub_ps(a, b, c); } __m256d test_mm256_maddsub_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_maddsub_pd - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[SUB]], <4 x double> [[ADD]], <4 x i32> return _mm256_maddsub_pd(a, b, c); } __m256 test_mm256_msubadd_ps(__m256 a, __m256 b, __m256 c) { // CHECK-LABEL: test_mm256_msubadd_ps // CHECK: [[NEG:%.+]] = fsub <8 x float> , %{{.*}} - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) - // CHECK: select <8 x i1> , <8 x float> %{{.*}}, <8 x float> %{{.*}} + // CHECK: [[SUB:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> [[NEG]] + // CHECK: [[ADD:%.+]] = call <8 x float> @llvm.fma.v8f32(<8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}) + // CHECK: shufflevector <8 x float> [[ADD]], <8 x float> [[SUB]], <8 x i32> return _mm256_msubadd_ps(a, b, c); } __m256d test_mm256_msubadd_pd(__m256d a, __m256d b, __m256d c) { // CHECK-LABEL: test_mm256_msubadd_pd // CHECK: [[NEG:%.+]] = fsub <4 x double> , %{{.+}} - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) - // CHECK: select <4 x i1> , <4 x double> %{{.*}}, <4 x double> %{{.*}} + // CHECK: [[SUB:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> [[NEG]] + // CHECK: [[ADD:%.+]] = call <4 x double> @llvm.fma.v4f64(<4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}) + // CHECK: shufflevector <4 x double> [[ADD]], <4 x double> [[SUB]], <4 x i32> return _mm256_msubadd_pd(a, b, c); } -- GitLab From 7d013cb1a231fb165b41120e8aa786b044b0b8bd Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 5 Jul 2018 22:51:11 +0000 Subject: [PATCH 0418/1023] [Sema] -Wformat-pedantic only for NSInteger/NSUInteger %tu/%td on Darwin The '%tu'/'%td' as formatting specifiers have been used to print out the NSInteger/NSUInteger values for a long time. Typically their ABI matches, but that's not the case on watchOS. The ABI difference boils down to the following: - Regular 32-bit darwin targets (like armv7) use 'ptrdiff_t' of type 'int', which matches 'NSInteger'. - WatchOS arm target (armv7k) uses 'ptrdiff_t' of type 'long', which doesn't match 'NSInteger' of type 'int'. Because of this ABI difference these specifiers trigger -Wformat warnings only for watchOS builds, which is really inconvenient for cross-platform code. This patch avoids this -Wformat warning for '%tu'/'%td' and NS[U]Integer only, and instead uses the new -Wformat-pedantic warning that JF introduced in https://reviews.llvm.org/D47290. This is acceptable because Darwin guarantees that, despite the watchOS ABI differences, sizeof(ptrdiff_t) == sizeof(NS[U]Integer), and alignof(ptrdiff_t) == alignof(NS[U]Integer) so the warning is therefore noisy for pedantic reasons. I'll update public documentation to ensure that this behaviour is properly communicated. rdar://41739204 Differential Revision: https://reviews.llvm.org/D48852 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336396 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Analysis/Analyses/FormatString.h | 21 +++++++++++++++--- lib/Analysis/PrintfFormatString.cpp | 6 +++-- lib/Sema/SemaChecking.cpp | 5 +++-- test/SemaObjC/format-size-spec-nsinteger.m | 22 +++++++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 6d76718048..6f8bb9b409 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -257,7 +257,12 @@ private: const Kind K; QualType T; const char *Name = nullptr; - bool Ptr = false, IsSizeT = false; + bool Ptr = false; + + /// The TypeKind identifies certain well-known types like size_t and + /// ptrdiff_t. + enum class TypeKind { DontCare, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::DontCare; public: ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} @@ -267,7 +272,9 @@ public: static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } - bool isSizeT() const { return IsSizeT; } + bool isSizeT() const { return TK == TypeKind::SizeT; } + + bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } /// Create an ArgType which corresponds to the type pointer to A. static ArgType PtrTo(const ArgType& A) { @@ -280,7 +287,15 @@ public: /// Create an ArgType which corresponds to the size_t/ssize_t type. static ArgType makeSizeT(const ArgType &A) { ArgType Res = A; - Res.IsSizeT = true; + Res.TK = TypeKind::SizeT; + return Res; + } + + /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t + /// type. + static ArgType makePtrdiffT(const ArgType &A) { + ArgType Res = A; + Res.TK = TypeKind::PtrdiffT; return Res; } diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 93d64f03ea..688b2031a3 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -472,7 +472,8 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, ? ArgType(Ctx.LongLongTy, "__int64") : ArgType(Ctx.IntTy, "__int32"); case LengthModifier::AsPtrDiff: - return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); + return ArgType::makePtrdiffT( + ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: @@ -505,7 +506,8 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); case LengthModifier::AsPtrDiff: - return ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"); + return ArgType::makePtrdiffT( + ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: case LengthModifier::AsWide: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 98aeb61fa7..cd2aabb894 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6894,10 +6894,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, QualType CastTy; std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { - // %zi/%zu are OK to use for NSInteger/NSUInteger of type int + // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int // (long in ASTContext). Only complain to pedants. if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && - AT.isSizeT() && AT.matchesType(S.Context, CastTy)) + (AT.isSizeT() || AT.isPtrdiffT()) && + AT.matchesType(S.Context, CastTy)) Pedantic = true; IntendedTy = CastTy; ShouldNotPrintDirectly = true; diff --git a/test/SemaObjC/format-size-spec-nsinteger.m b/test/SemaObjC/format-size-spec-nsinteger.m index 9eb954ec51..e7c0a0dd10 100644 --- a/test/SemaObjC/format-size-spec-nsinteger.m +++ b/test/SemaObjC/format-size-spec-nsinteger.m @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat %s // RUN: %clang_cc1 -triple thumbv7-apple-ios -Wno-objc-root-class -fsyntax-only -verify -Wformat-pedantic -DPEDANTIC %s +// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify %s +// RUN: %clang_cc1 -triple thumbv7k-apple-watchos2.0.0 -fsyntax-only -fblocks -verify -Wformat-pedantic -DPEDANTIC %s #if !defined(PEDANTIC) // expected-no-diagnostics @@ -8,9 +10,16 @@ #if __LP64__ typedef unsigned long NSUInteger; typedef long NSInteger; +typedef long ptrdiff_t; #else typedef unsigned int NSUInteger; typedef int NSInteger; +#if __is_target_os(watchos) + // Watch ABI uses long for ptrdiff_t. + typedef long ptrdiff_t; +#else + typedef int ptrdiff_t; +#endif #endif @class NSString; @@ -28,3 +37,16 @@ void testSizeSpecifier() { // expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} #endif } + +void testPtrdiffSpecifier(ptrdiff_t x) { + NSInteger i = 0; + NSUInteger j = 0; + + NSLog(@"ptrdiff_t NSUinteger: %tu", j); + NSLog(@"ptrdiff_t NSInteger: %td", i); + NSLog(@"ptrdiff_t %tu, %td", x, x); +#if __is_target_os(watchos) && defined(PEDANTIC) + // expected-warning@-4 {{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} + // expected-warning@-4 {{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} +#endif +} -- GitLab From 1f48bb4b74dc925dcbe898dce21dfc69a0cc5681 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 6 Jul 2018 06:54:16 +0000 Subject: [PATCH 0419/1023] [ms] Fix mangling of string literals used to initialize arrays larger or smaller than the literal A Chromium developer reported a bug which turned out to be a mangling collision between these two literals: char s[] = "foo"; char t[32] = "foo"; They may look the same, but for the initialization of t we will (under some circumstances) use a literal that's extended with zeros, and both the length and those zeros should be accounted for by the mangling. This actually makes the mangling code simpler: where it previously had special logic for null terminators, which are not part of the StringLiteral, that is now covered by the general algorithm. (The problem was reported at https://crbug.com/857442) Differential Revision: https://reviews.llvm.org/D48928 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336415 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 44 +++++++++++++----------- test/CodeGen/mangle-ms-string-literals.c | 10 ++++++ 2 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 test/CodeGen/mangle-ms-string-literals.c diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index e6235cc625..32c26270ec 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -3171,7 +3171,7 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // ::= # the length of the literal // // ::= + @ # crc of the literal including - // # null-terminator + // # trailing null bytes // // ::= # uninteresting character // ::= '?$' # these two nibbles @@ -3186,6 +3186,18 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << "??_C@_"; + // The actual string length might be different from that of the string literal + // in cases like: + // char foo[3] = "foobar"; + // char bar[42] = "foobar"; + // Where it is truncated or zero-padded to fit the array. This is the length + // used for mangling, and any trailing null-bytes also need to be mangled. + unsigned StringLength = getASTContext() + .getAsConstantArrayType(SL->getType()) + ->getSize() + .getZExtValue(); + unsigned StringByteLength = StringLength * SL->getCharByteWidth(); + // : The "kind" of string literal is encoded into the mangled name. if (SL->isWide()) Mangler.getStream() << '1'; @@ -3193,14 +3205,13 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << '0'; // : The next part of the mangled name consists of the length - // of the string. - // The StringLiteral does not consider the NUL terminator byte(s) but the - // mangling does. - // N.B. The length is in terms of bytes, not characters. - Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth()); + // of the string in bytes. + Mangler.mangleNumber(StringByteLength); auto GetLittleEndianByte = [&SL](unsigned Index) { unsigned CharByteWidth = SL->getCharByteWidth(); + if (Index / CharByteWidth >= SL->getLength()) + return static_cast(0); uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); unsigned OffsetInCodeUnit = Index % CharByteWidth; return static_cast((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); @@ -3208,6 +3219,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, auto GetBigEndianByte = [&SL](unsigned Index) { unsigned CharByteWidth = SL->getCharByteWidth(); + if (Index / CharByteWidth >= SL->getLength()) + return static_cast(0); uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth); return static_cast((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); @@ -3215,15 +3228,9 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // CRC all the bytes of the StringLiteral. llvm::JamCRC JC; - for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I) + for (unsigned I = 0, E = StringByteLength; I != E; ++I) JC.update(GetLittleEndianByte(I)); - // The NUL terminator byte(s) were not present earlier, - // we need to manually process those bytes into the CRC. - for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); - ++NullTerminator) - JC.update('\x00'); - // : The CRC is encoded utilizing the standard number mangling // scheme. Mangler.mangleNumber(JC.getCRC()); @@ -3260,18 +3267,13 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // Enforce our 32 bytes max, except wchar_t which gets 32 chars instead. unsigned MaxBytesToMangle = SL->isWide() ? 64U : 32U; - unsigned NumBytesToMangle = std::min(MaxBytesToMangle, SL->getByteLength()); - for (unsigned I = 0; I != NumBytesToMangle; ++I) + unsigned NumBytesToMangle = std::min(MaxBytesToMangle, StringByteLength); + for (unsigned I = 0; I != NumBytesToMangle; ++I) { if (SL->isWide()) MangleByte(GetBigEndianByte(I)); else MangleByte(GetLittleEndianByte(I)); - - // Encode the NUL terminator if there is room. - if (NumBytesToMangle < MaxBytesToMangle) - for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); - ++NullTerminator) - MangleByte(0); + } Mangler.getStream() << '@'; } diff --git a/test/CodeGen/mangle-ms-string-literals.c b/test/CodeGen/mangle-ms-string-literals.c new file mode 100644 index 0000000000..41dd78c1fa --- /dev/null +++ b/test/CodeGen/mangle-ms-string-literals.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s + +void crbug857442(int x) { + // Make sure to handle truncated or padded literals. The truncation is only valid in C. + struct {int x; char s[2]; } truncatedAscii = {x, "hello"}; + // CHECK: "??_C@_01CONKJJHI@he@" + struct {int x; char s[16]; } paddedAscii = {x, "hello"}; + // CHECK: "??_C@_0BA@EAAINDNC@hello?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$AA@" +} -- GitLab From 5727c8bbbff503fcd8bafd5409f01e78feeb27c5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 6 Jul 2018 07:14:47 +0000 Subject: [PATCH 0420/1023] [X86] Implement _builtin_ia32_vfmaddss and _builtin_ia32_vfmaddsd with native IR using llvm.fma intrinsic. This generates some extra zeroing currently, but we should be able to quickly address that with some isel patterns. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336417 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 10 ++++++++ test/CodeGen/fma4-builtins.c | 48 ++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 56cf6a9952..f2efca8cc9 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9134,6 +9134,16 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *Res = Builder.CreateCall(FMA, {A, B, C} ); return Builder.CreateInsertElement(Ops[0], Res, (uint64_t)0); } + case X86::BI__builtin_ia32_vfmaddss: + case X86::BI__builtin_ia32_vfmaddsd: { + Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); + Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); + Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); + Function *FMA = CGM.getIntrinsic(Intrinsic::fma, A->getType()); + Value *Res = Builder.CreateCall(FMA, {A, B, C} ); + Value *Zero = Constant::getNullValue(Ops[0]->getType()); + return Builder.CreateInsertElement(Zero, Res, (uint64_t)0); + } case X86::BI__builtin_ia32_vfmaddps: case X86::BI__builtin_ia32_vfmaddpd: case X86::BI__builtin_ia32_vfmaddps256: diff --git a/test/CodeGen/fma4-builtins.c b/test/CodeGen/fma4-builtins.c index 8d88a51519..8078a6ed69 100644 --- a/test/CodeGen/fma4-builtins.c +++ b/test/CodeGen/fma4-builtins.c @@ -17,13 +17,21 @@ __m128d test_mm_macc_pd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_macc_ss(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_macc_ss - // CHECK: @llvm.x86.fma4.vfmadd.ss + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) + // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0 return _mm_macc_ss(a, b, c); } __m128d test_mm_macc_sd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_macc_sd - // CHECK: @llvm.x86.fma4.vfmadd.sd + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) + // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0 return _mm_macc_sd(a, b, c); } @@ -44,14 +52,22 @@ __m128d test_mm_msub_pd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_msub_ss(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_msub_ss // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> %{{.+}}, <4 x float> %{{.+}}, <4 x float> [[NEG]]) + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float [[C]]) + // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0 return _mm_msub_ss(a, b, c); } __m128d test_mm_msub_sd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_msub_sd // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> %{{.+}}, <2 x double> %{{.+}}, <2 x double> [[NEG]]) + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double [[C]]) + // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0 return _mm_msub_sd(a, b, c); } @@ -72,14 +88,22 @@ __m128d test_mm_nmacc_pd(__m128d a, __m128d b, __m128d c) { __m128 test_mm_nmacc_ss(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_nmacc_ss // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> %{{.+}}) + // CHECK: [[A:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: call float @llvm.fma.f32(float [[A]], float %{{.*}}, float %{{.*}}) + // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0 return _mm_nmacc_ss(a, b, c); } __m128d test_mm_nmacc_sd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_nmacc_sd // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> %{{.+}}) + // CHECK: [[A:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: call double @llvm.fma.f64(double [[A]], double %{{.*}}, double %{{.*}}) + // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0 return _mm_nmacc_sd(a, b, c); } @@ -103,7 +127,11 @@ __m128 test_mm_nmsub_ss(__m128 a, __m128 b, __m128 c) { // CHECK-LABEL: test_mm_nmsub_ss // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.+}} // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.ss(<4 x float> [[NEG]], <4 x float> %{{.+}}, <4 x float> [[NEG2]]) + // CHECK: [[A:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK: call float @llvm.fma.f32(float [[A]], float %{{.*}}, float [[C]]) + // CHECK: insertelement <4 x float> zeroinitializer, float %{{.*}}, i64 0 return _mm_nmsub_ss(a, b, c); } @@ -111,7 +139,11 @@ __m128d test_mm_nmsub_sd(__m128d a, __m128d b, __m128d c) { // CHECK-LABEL: test_mm_nmsub_sd // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.+}} // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.+}} - // CHECK: @llvm.x86.fma4.vfmadd.sd(<2 x double> [[NEG]], <2 x double> %{{.+}}, <2 x double> [[NEG2]]) + // CHECK: [[A:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK: call double @llvm.fma.f64(double [[A]], double %{{.*}}, double [[C]]) + // CHECK: insertelement <2 x double> zeroinitializer, double %{{.*}}, i64 0 return _mm_nmsub_sd(a, b, c); } -- GitLab From 809e94c9b56303616c9593d6cd555b58f2f4ce61 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Fri, 6 Jul 2018 09:43:57 +0000 Subject: [PATCH 0421/1023] [SemaCodeComplete] Expose a method to create CodeCompletionString for macros. Summary: The method only takes PPreprocessor and don't require structures that might not be available (e.g. Sema and ASTContext) when CodeCompletionString needs to be generated for macros. Reviewers: sammccall Reviewed By: sammccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48973 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336427 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/CodeCompleteConsumer.h | 7 ++ lib/Sema/SemaCodeComplete.cpp | 93 ++++++++++++----------- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index d3f6b651b7..8022fa74c4 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -918,6 +918,13 @@ public: CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments); + /// Creates a new code-completion string for the macro result. Similar to the + /// above overloads, except this only requires preprocessor information. + /// The result kind must be `RK_Macro`. + CodeCompletionString * + CreateCodeCompletionStringForMacro(Preprocessor &PP, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo); /// Retrieve the name that should be used to order a result. /// diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index a2252f2ace..9beefc05a2 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2745,6 +2745,52 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, CCTUInfo, IncludeBriefComments); } +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro( + Preprocessor &PP, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) { + assert(Kind == RK_Macro); + CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); + const MacroInfo *MI = PP.getMacroInfo(Macro); + Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName())); + + if (!MI || !MI->isFunctionLike()) + return Result.TakeString(); + + // Format a function-like macro with placeholders for the arguments. + Result.AddChunk(CodeCompletionString::CK_LeftParen); + MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); + + // C99 variadic macros add __VA_ARGS__ at the end. Skip it. + if (MI->isC99Varargs()) { + --AEnd; + + if (A == AEnd) { + Result.AddPlaceholderChunk("..."); + } + } + + for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { + if (A != MI->param_begin()) + Result.AddChunk(CodeCompletionString::CK_Comma); + + if (MI->isVariadic() && (A + 1) == AEnd) { + SmallString<32> Arg = (*A)->getName(); + if (MI->isC99Varargs()) + Arg += ", ..."; + else + Arg += "..."; + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + break; + } + + // Non-variadic macros are simple. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString((*A)->getName())); + } + Result.AddChunk(CodeCompletionString::CK_RightParen); + return Result.TakeString(); +} + /// If possible, create a new code completion string for the given /// result. /// @@ -2758,6 +2804,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) { + if (Kind == RK_Macro) + return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo); + CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); @@ -2782,50 +2831,6 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddTypedTextChunk(Keyword); return Result.TakeString(); } - - if (Kind == RK_Macro) { - const MacroInfo *MI = PP.getMacroInfo(Macro); - Result.AddTypedTextChunk( - Result.getAllocator().CopyString(Macro->getName())); - - if (!MI || !MI->isFunctionLike()) - return Result.TakeString(); - - // Format a function-like macro with placeholders for the arguments. - Result.AddChunk(CodeCompletionString::CK_LeftParen); - MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); - - // C99 variadic macros add __VA_ARGS__ at the end. Skip it. - if (MI->isC99Varargs()) { - --AEnd; - - if (A == AEnd) { - Result.AddPlaceholderChunk("..."); - } - } - - for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { - if (A != MI->param_begin()) - Result.AddChunk(CodeCompletionString::CK_Comma); - - if (MI->isVariadic() && (A+1) == AEnd) { - SmallString<32> Arg = (*A)->getName(); - if (MI->isC99Varargs()) - Arg += ", ..."; - else - Arg += "..."; - Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); - break; - } - - // Non-variadic macros are simple. - Result.AddPlaceholderChunk( - Result.getAllocator().CopyString((*A)->getName())); - } - Result.AddChunk(CodeCompletionString::CK_RightParen); - return Result.TakeString(); - } - assert(Kind == RK_Declaration && "Missed a result kind?"); const NamedDecl *ND = Declaration; Result.addParentContext(ND->getDeclContext()); -- GitLab From 86c991513001535af6b82bcb1f7c45ab60d2adf0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 6 Jul 2018 10:49:59 +0000 Subject: [PATCH 0422/1023] [Driver,AArch64] Add support for -mcpu=native. This patches adds support for passing -mcpu=native for AArch64. It will get turned into the host CPU name, before we get the target features. CPU = native is handled in a similar fashion in getAArch64MicroArchFetauresFromMtune and getAArch64TargetCPU already. Having a good test case for this is hard, as it depends on the host CPU of the machine running the test. But we can check that native has been replaced with something else. When cross-compiling, we will get a CPU name from the host architecture and get ` the clang compiler does not support '-mcpu=native'` as error message, which seems reasonable to me. Reviewers: rengolin, peter.smith, dlj, javed.absar, t.p.northover Reviewed By: peter.smith Tags: #clang Differential Revision: https://reviews.llvm.org/D48931 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336429 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Arch/AArch64.cpp | 3 +++ test/Driver/aarch64-cpus.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp index 7bac69687a..5114279b4b 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -69,6 +69,9 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, std::pair Split = Mcpu.split("+"); CPU = Split.first; + if (CPU == "native") + CPU = llvm::sys::getHostCPUName(); + if (CPU == "generic") { Features.push_back("+neon"); } else { diff --git a/test/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c index 8c7f06052f..330af35118 100644 --- a/test/Driver/aarch64-cpus.c +++ b/test/Driver/aarch64-cpus.c @@ -15,6 +15,11 @@ // ARM64-GENERIC: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" +// We cannot check much for -mcpu=native, but it should be replaced by either generic or a valid +// Arm cpu string, depending on the host. +// RUN: %clang -target arm64 -mcpu=native -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-NATIVE %s +// ARM64-NATIVE-NOT: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "native" + // RUN: %clang -target arm64-apple-darwin -arch arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-DARWIN %s // ARM64-DARWIN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "cyclone" -- GitLab From 8980f32f68df0b659923702e9df0b4f8538fdf4f Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 6 Jul 2018 19:35:42 +0000 Subject: [PATCH 0423/1023] [OPENMP] Make clauses closing loc point to right bracket. For some of the clauses the closing location erroneously points to the beginning of the next clause rather than on the location of the closing bracket of the clause. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336460 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 1 + lib/Parse/ParseOpenMP.cpp | 33 ++++++++++++++++++++------------- test/OpenMP/dump.cpp | 6 +++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 29cd9e82d7..416691ccc8 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -2822,6 +2822,7 @@ public: struct OpenMPVarListDataTy { Expr *TailExpr = nullptr; SourceLocation ColonLoc; + SourceLocation RLoc; CXXScopeSpec ReductionIdScopeSpec; DeclarationNameInfo ReductionId; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index d06e101423..a413e96a91 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -424,13 +424,15 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { // Match the ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && "Unexpected number of commas!"); - ExprResult Initializer = Actions.ActOnParenListExpr( - T.getOpenLocation(), T.getCloseLocation(), Exprs); + ExprResult Initializer = + Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), /*DirectInit=*/true); } @@ -1378,9 +1380,10 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. - T.consumeClose(); + RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); - RLoc = T.getCloseLocation(); return Val; } @@ -1457,12 +1460,13 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, ConsumeAnyToken(); // Parse ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); if (ParseOnly) return nullptr; - return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, - Tok.getLocation()); + return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); } /// Parsing of OpenMP clauses like 'ordered'. @@ -1633,7 +1637,9 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, } // Parse ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); if (NeedAnExpression && Val.isInvalid()) return nullptr; @@ -1641,8 +1647,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, if (ParseOnly) return nullptr; return Actions.ActOnOpenMPSingleExprWithArgClause( - Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, - T.getCloseLocation()); + Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); } static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, @@ -1914,7 +1919,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } // Parse ')'. - T.consumeClose(); + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && Vars.empty()) || (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || @@ -1979,7 +1986,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, if (ParseOnly) return nullptr; return Actions.ActOnOpenMPVarListClause( - Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(), + Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc, Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp index 162136b20b..f54d25f197 100644 --- a/test/OpenMP/dump.cpp +++ b/test/OpenMP/dump.cpp @@ -44,10 +44,10 @@ struct S { }; // CHECK: | `-OMPParallelForDirective {{.+}} {{|}} -// CHECK-NEXT: | |-OMPDefaultClause {{.+}} -// CHECK-NEXT: | |-OMPPrivateClause {{.+}} +// CHECK-NEXT: | |-OMPDefaultClause {{.+}} +// CHECK-NEXT: | |-OMPPrivateClause {{.+}} // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &' -// CHECK-NEXT: | |-OMPSharedClause {{.+}} +// CHECK-NEXT: | |-OMPSharedClause {{.+}} // CHECK-NEXT: | | `-MemberExpr {{.+}} 'int' lvalue ->b // CHECK-NEXT: | | `-CXXThisExpr {{.+}} 'S *' this // CHECK-NEXT: | |-OMPScheduleClause {{.+}} -- GitLab From 5137aa79b9f66e61c5665fb88f8d2e906496cca9 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 6 Jul 2018 21:13:41 +0000 Subject: [PATCH 0424/1023] [OPENMP] Fix PR38026: Link -latomic when -fopenmp is used. On Linux atomic constructs in OpenMP require libatomic library. Patch links libatomic when -fopenmp is used. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336467 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Gnu.cpp | 6 +++++- test/OpenMP/linking.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 1ecf127c4b..ee3096813e 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -479,6 +479,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, bool WantPthread = Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads); + bool WantAtomic = false; // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. @@ -487,13 +488,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. // FIXME: Does this really make sense for all GNU toolchains? - WantPthread = true; + WantAtomic = WantPthread = true; AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (WantPthread && !isAndroid) CmdArgs.push_back("-lpthread"); + if (WantAtomic) + CmdArgs.push_back("-latomic"); + if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("--wrap=pthread_create"); diff --git a/test/OpenMP/linking.c b/test/OpenMP/linking.c index 802553c1be..e2f83f9571 100644 --- a/test/OpenMP/linking.c +++ b/test/OpenMP/linking.c @@ -8,14 +8,14 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s // CHECK-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-LD-32: "-lpthread" "-lc" +// CHECK-LD-32: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-LD-64 %s // CHECK-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-LD-64: "-lpthread" "-lc" +// CHECK-LD-64: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libgomp -target i386-unknown-linux -rtlib=platform \ @@ -27,7 +27,7 @@ // SIMD-ONLY2-NOT: liomp // CHECK-GOMP-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-GOMP-LD-32: "-lgomp" "-lrt" -// CHECK-GOMP-LD-32: "-lpthread" "-lc" +// CHECK-GOMP-LD-32: "-lpthread" "-latomic" "-lc" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target i386-unknown-linux -rtlib=platform | FileCheck --check-prefix SIMD-ONLY2 %s // SIMD-ONLY2-NOT: lgomp @@ -39,21 +39,21 @@ // RUN: | FileCheck --check-prefix=CHECK-GOMP-LD-64 %s // CHECK-GOMP-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-GOMP-LD-64: "-lgomp" "-lrt" -// CHECK-GOMP-LD-64: "-lpthread" "-lc" +// CHECK-GOMP-LD-64: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target i386-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-32 %s // CHECK-IOMP5-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-IOMP5-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-IOMP5-LD-32: "-lpthread" "-lc" +// CHECK-IOMP5-LD-32: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-64 %s // CHECK-IOMP5-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-IOMP5-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-IOMP5-LD-64: "-lpthread" "-lc" +// CHECK-IOMP5-LD-64: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=lib -target i386-unknown-linux \ @@ -71,7 +71,7 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-32 %s // CHECK-LD-OVERRIDE-32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-OVERRIDE-32: "-lgomp" "-lrt" -// CHECK-LD-OVERRIDE-32: "-lpthread" "-lc" +// CHECK-LD-OVERRIDE-32: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -fopenmp=libgomp -target x86_64-unknown-linux \ @@ -79,7 +79,7 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-64 %s // CHECK-LD-OVERRIDE-64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-OVERRIDE-64: "-lgomp" "-lrt" -// CHECK-LD-OVERRIDE-64: "-lpthread" "-lc" +// CHECK-LD-OVERRIDE-64: "-lpthread" "-latomic" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libomp -target x86_64-msvc-win32 -rtlib=platform \ -- GitLab From 2ffe81c7bfe4f3c2a42f06b5c2e7aa4e9ff98ff6 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 6 Jul 2018 21:36:04 +0000 Subject: [PATCH 0425/1023] [ASTMatchers] A matcher for Objective-C @autoreleasepool Differential Revision: https://reviews.llvm.org/D48910 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336468 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 74 +++++++++++++++++-- include/clang/ASTMatchers/ASTMatchers.h | 13 ++++ lib/ASTMatchers/ASTMatchersInternal.cpp | 2 + lib/ASTMatchers/Dynamic/Registry.cpp | 1 + unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 12 +++ 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 6c67fd5b60..3f0ded2270 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -662,6 +662,18 @@ Example matches __atomic_load_n(ptr, 1) +Matcher<Stmt>autoreleasePoolStmtMatcher<ObjCAutoreleasePoolStmt>... +
Matches an Objective-C autorelease pool statement.
+
+Given
+  @autoreleasepool {
+    int x = 0;
+  }
+autoreleasePoolStmt(stmt()) matches the declaration of "x"
+inside the autorelease pool.
+
+ + Matcher<Stmt>binaryConditionalOperatorMatcher<BinaryConditionalOperator>...
Matches binary conditional operator expressions (GNU extension).
 
@@ -5222,8 +5234,8 @@ actual casts "explicit" casts.)
 
-Matcher<Expr>hasTypeMatcher<Decl> InnerMatcher -
Overloaded to match the declaration of the expression's or value
+Matcher<Expr>hasTypeMatcher<Decl> InnerMatcher
+
Overloaded to match the declaration of the expression's or value
 declaration's type.
 
 In case of a value declaration (for example a variable declaration),
@@ -5234,8 +5246,10 @@ declaration of x.
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and friend class X (matcher = friendDecl(hasType("X"))
  class X {};
  void y(X &x) { x; X z; }
+ class Y { friend class X; };
 
 Usable as: Matcher<Expr>, Matcher<ValueDecl>
 
@@ -5248,9 +5262,11 @@ matcher. Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) and U (matcher = typedefDecl(hasType(asString("int"))) + and friend class X (matcher = friendDecl(hasType("X")) class X {}; void y(X &x) { x; X z; } typedef int U; + class Y { friend class X; };
@@ -5396,6 +5412,42 @@ matches 'int x = 0' in +Matcher<FriendDecl>hasTypeMatcher<Decl> InnerMatcher +
Overloaded to match the declaration of the expression's or value
+declaration's type.
+
+In case of a value declaration (for example a variable declaration),
+this resolves one layer of indirection. For example, in the value
+declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of
+X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
+declaration of x.
+
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+            and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and friend class X (matcher = friendDecl(hasType("X"))
+ class X {};
+ void y(X &x) { x; X z; }
+ class Y { friend class X; };
+
+Usable as: Matcher<Expr>, Matcher<ValueDecl>
+
+ + +Matcher<FriendDecl>hasTypeMatcher<QualType> InnerMatcher +
Matches if the expression's or declaration's type matches a type
+matcher.
+
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+            and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and U (matcher = typedefDecl(hasType(asString("int")))
+            and friend class X (matcher = friendDecl(hasType("X"))
+ class X {};
+ void y(X &x) { x; X z; }
+ typedef int U;
+ class Y { friend class X; };
+
+ + Matcher<FunctionDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher
Matches any parameter of a function or an ObjC method declaration or a
 block.
@@ -6432,16 +6484,18 @@ Usable as: Any Matcher
 
-Matcher<TypedefNameDecl>hasTypeMatcher<QualType> InnerMatcher -
Matches if the expression's or declaration's type matches a type
+Matcher<TypedefNameDecl>hasTypeMatcher<QualType> InnerMatcher
+
Matches if the expression's or declaration's type matches a type
 matcher.
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
             and U (matcher = typedefDecl(hasType(asString("int")))
+            and friend class X (matcher = friendDecl(hasType("X"))
  class X {};
  void y(X &x) { x; X z; }
  typedef int U;
+ class Y { friend class X; };
 
@@ -6564,8 +6618,8 @@ usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl()))) matches using X::b but not using X::a
-Matcher<ValueDecl>hasTypeMatcher<Decl> InnerMatcher -
Overloaded to match the declaration of the expression's or value
+Matcher<ValueDecl>hasTypeMatcher<Decl> InnerMatcher
+
Overloaded to match the declaration of the expression's or value
 declaration's type.
 
 In case of a value declaration (for example a variable declaration),
@@ -6576,23 +6630,27 @@ declaration of x.
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and friend class X (matcher = friendDecl(hasType("X"))
  class X {};
  void y(X &x) { x; X z; }
+ class Y { friend class X; };
 
 Usable as: Matcher<Expr>, Matcher<ValueDecl>
 
-Matcher<ValueDecl>hasTypeMatcher<QualType> InnerMatcher -
Matches if the expression's or declaration's type matches a type
+Matcher<ValueDecl>hasTypeMatcher<QualType> InnerMatcher
+
Matches if the expression's or declaration's type matches a type
 matcher.
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
             and U (matcher = typedefDecl(hasType(asString("int")))
+            and friend class X (matcher = friendDecl(hasType("X"))
  class X {};
  void y(X &x) { x; X z; }
  typedef int U;
+ class Y { friend class X; };
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 87a971082b..1c8d1da37f 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -966,6 +966,19 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue, return Node.getAsIntegral().toString(10) == Value; } +/// Matches an Objective-C autorelease pool statement. +/// +/// Given +/// \code +/// @autoreleasepool { +/// int x = 0; +/// } +/// \endcode +/// autoreleasePoolStmt(stmt()) matches the declaration of "x" +/// inside the autorelease pool. +extern const internal::VariadicDynCastAllOfMatcher autoreleasePoolStmt; + /// Matches any value declaration. /// /// Example matches A, B, C and F diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp index 92b680fd17..d8af47d750 100644 --- a/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -548,6 +548,8 @@ bool HasNameMatcher::matchesNode(const NamedDecl &Node) const { } // end namespace internal +const internal::VariadicDynCastAllOfMatcher + autoreleasePoolStmt; const internal::VariadicDynCastAllOfMatcher translationUnitDecl; const internal::VariadicDynCastAllOfMatcher typedefDecl; diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 84e6e450f2..384dd8d4e3 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -134,6 +134,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(atomicExpr); REGISTER_MATCHER(atomicType); REGISTER_MATCHER(autoType); + REGISTER_MATCHER(autoreleasePoolStmt) REGISTER_MATCHER(binaryOperator); REGISTER_MATCHER(binaryConditionalOperator); REGISTER_MATCHER(blockDecl); diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 8947ccde7a..fc1a57c488 100644 --- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1687,5 +1687,17 @@ TEST(ObjCStmtMatcher, ExceptionStmts) { objcFinallyStmt())); } +TEST(ObjCAutoreleaseMatcher, AutoreleasePool) { + std::string ObjCString = + "void f() {" + "@autoreleasepool {" + " int x = 1;" + "}" + "}"; + EXPECT_TRUE(matchesObjC(ObjCString, autoreleasePoolStmt())); + std::string ObjCStringNoPool = "void f() { int x = 1; }"; + EXPECT_FALSE(matchesObjC(ObjCStringNoPool, autoreleasePoolStmt())); +} + } // namespace ast_matchers } // namespace clang -- GitLab From 4ad65cd262150f7e5930824cc68afb528cff515f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 6 Jul 2018 22:08:43 +0000 Subject: [PATCH 0426/1023] [X86] Add missing scalar fma intrinsics with rounding, but no mask. We had the mask versions of the rounding intrinsics, but not one without masking. Also change the rounding tests to not use the CUR_DIRECTION rounding mode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336470 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 48 +++++++++++++++++ test/CodeGen/avx512f-builtins.c | 96 ++++++++++++++++++++++++--------- 2 files changed, 120 insertions(+), 24 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index b20d48cf15..be4ee62fc6 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -7824,6 +7824,12 @@ _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) return __W; } +#define _mm_fmadd_round_ss(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddss3_mask((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), \ + (__v2df)(__m128d)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fmadd_round_ss(W, U, A, B, R) \ (__m128d)__builtin_ia32_vfmaddss3_mask((__v2df)(__m128d)(W), \ (__v2df)(__m128d)(A), \ @@ -7872,6 +7878,12 @@ _mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) return __W; } +#define _mm_fmsub_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), \ + -(__v4sf)(__m128)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fmsub_round_ss(W, U, A, B, R) \ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \ (__v4sf)(__m128)(A), \ @@ -7920,6 +7932,12 @@ _mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) return __W; } +#define _mm_fnmadd_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \ + -(__v4sf)(__m128)(B), \ + (__v4sf)(__m128)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fnmadd_round_ss(W, U, A, B, R) \ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \ -(__v4sf)(__m128)(A), \ @@ -7968,6 +7986,12 @@ _mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) return __W; } +#define _mm_fnmsub_round_ss(A, B, C, R) \ + (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \ + -(__v4sf)(__m128)(B), \ + -(__v4sf)(__m128)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fnmsub_round_ss(W, U, A, B, R) \ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \ -(__v4sf)(__m128)(A), \ @@ -8016,6 +8040,12 @@ _mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) return __W; } +#define _mm_fmadd_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), \ + (__v2df)(__m128d)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fmadd_round_sd(W, U, A, B, R) \ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \ (__v2df)(__m128d)(A), \ @@ -8064,6 +8094,12 @@ _mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) return __W; } +#define _mm_fmsub_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), \ + -(__v2df)(__m128d)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fmsub_round_sd(W, U, A, B, R) \ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \ (__v2df)(__m128d)(A), \ @@ -8112,6 +8148,12 @@ _mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) return __W; } +#define _mm_fnmadd_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \ + -(__v2df)(__m128d)(B), \ + (__v2df)(__m128d)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fnmadd_round_sd(W, U, A, B, R) \ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \ -(__v2df)(__m128d)(A), \ @@ -8160,6 +8202,12 @@ _mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) return __W; } +#define _mm_fnmsub_round_sd(A, B, C, R) \ + (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \ + -(__v2df)(__m128d)(B), \ + -(__v2df)(__m128d)(C), (__mmask8)-1, \ + (int)(R)) + #define _mm_mask_fnmsub_round_sd(W, U, A, B, R) \ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \ -(__v2df)(__m128d)(A), \ diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 1dea46621d..2cfaf0cc4c 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -7234,10 +7234,16 @@ __m128 test_mm_mask_fmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ return _mm_mask_fmadd_ss(__W, __U, __A, __B); } +__m128 test_mm_fmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ + // CHECK-LABEL: @test_mm_fmadd_round_ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + return _mm_fmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128 test_mm_mask_fmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_ss // CHECK: @llvm.x86.avx512.mask.vfmadd.ss - return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ @@ -7265,7 +7271,7 @@ __m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_ss // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss - return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ @@ -7294,7 +7300,7 @@ __m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_ss // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss - return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ @@ -7321,10 +7327,16 @@ __m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ return _mm_mask_fmsub_ss(__W, __U, __A, __B); } +__m128 test_mm_fmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ + // CHECK-LABEL: @test_mm_fmsub_round_ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + return _mm_fmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128 test_mm_mask_fmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_ss // CHECK: @llvm.x86.avx512.mask.vfmadd.ss - return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ @@ -7353,7 +7365,7 @@ __m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_ss // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss - return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ @@ -7383,7 +7395,7 @@ __m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_ss // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss - return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ @@ -7410,10 +7422,16 @@ __m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ return _mm_mask_fnmadd_ss(__W, __U, __A, __B); } +__m128 test_mm_fnmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ + // CHECK-LABEL: @test_mm_fnmadd_round_ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + return _mm_fnmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128 test_mm_mask_fnmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_ss // CHECK: @llvm.x86.avx512.mask.vfmadd.ss - return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ @@ -7442,7 +7460,7 @@ __m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_ss // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss - return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ @@ -7472,7 +7490,7 @@ __m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_ss // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss - return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ @@ -7500,10 +7518,16 @@ __m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ return _mm_mask_fnmsub_ss(__W, __U, __A, __B); } +__m128 test_mm_fnmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ + // CHECK-LABEL: @test_mm_fnmsub_round_ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + return _mm_fnmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128 test_mm_mask_fnmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_ss // CHECK: @llvm.x86.avx512.mask.vfmadd.ss - return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ @@ -7533,7 +7557,7 @@ __m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_ss // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss - return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ @@ -7564,7 +7588,7 @@ __m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_ss // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss - return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ @@ -7590,10 +7614,16 @@ __m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ return _mm_mask_fmadd_sd(__W, __U, __A, __B); } +__m128d test_mm_fmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ + // CHECK-LABEL: @test_mm_fmadd_round_sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + return _mm_fmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128d test_mm_mask_fmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_sd // CHECK: @llvm.x86.avx512.mask.vfmadd.sd - return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ @@ -7621,7 +7651,7 @@ __m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_sd // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd - return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ @@ -7650,7 +7680,7 @@ __m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_sd // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd - return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ @@ -7677,10 +7707,16 @@ __m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ return _mm_mask_fmsub_sd(__W, __U, __A, __B); } +__m128d test_mm_fmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ + // CHECK-LABEL: @test_mm_fmsub_round_sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + return _mm_fmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128d test_mm_mask_fmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_sd // CHECK: @llvm.x86.avx512.mask.vfmadd.sd - return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ @@ -7709,7 +7745,7 @@ __m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_sd // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd - return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ @@ -7739,7 +7775,7 @@ __m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_sd // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd - return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ @@ -7766,10 +7802,16 @@ __m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ return _mm_mask_fnmadd_sd(__W, __U, __A, __B); } +__m128d test_mm_fnmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ + // CHECK-LABEL: @test_mm_fnmadd_round_sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + return _mm_fnmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128d test_mm_mask_fnmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_sd // CHECK: @llvm.x86.avx512.mask.vfmadd.sd - return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ @@ -7798,7 +7840,7 @@ __m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_sd // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd - return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ @@ -7828,7 +7870,7 @@ __m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_sd // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd - return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ @@ -7856,10 +7898,16 @@ __m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ return _mm_mask_fnmsub_sd(__W, __U, __A, __B); } +__m128d test_mm_fnmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ + // CHECK-LABEL: @test_mm_fnmsub_round_sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + return _mm_fnmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); +} + __m128d test_mm_mask_fnmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_sd // CHECK: @llvm.x86.avx512.mask.vfmadd.sd - return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ @@ -7889,7 +7937,7 @@ __m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_sd // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd - return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_CUR_DIRECTION); + return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ @@ -7920,7 +7968,7 @@ __m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_sd // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd - return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION); + return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512d test_mm512_permutex_pd(__m512d __X) { -- GitLab From f3ac792d41b6b98ea71ee4b433dcee005be7922e Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Fri, 6 Jul 2018 22:24:56 +0000 Subject: [PATCH 0427/1023] [MachineOutliner] Properly pass -moutline along to the toolchain This moves the LTO-specific code for outlining from ToolChains/Clang.cpp to ToolChains/Darwin.cpp. Passing -mllvm flags isn't sufficient for making sure that the specified pass will actually run in LTO. This makes sure that when -moutline is passed, the MachineOutliner will actually be added to the LTO pass pipeline as expected. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336471 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 10 +--------- lib/Driver/ToolChains/Darwin.cpp | 12 ++++++++++++ test/Driver/aarch64-outliner.c | 4 ---- test/Driver/darwin-ld.c | 6 ++++++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index d7092801df..4129139718 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4757,16 +4757,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Triple.getArch() != llvm::Triple::aarch64) { D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); } else { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-machine-outliner"); - - // The outliner shouldn't compete with linkers that dedupe linkonceodr - // functions in LTO. Enable that behaviour by default when compiling with - // LTO. - if (getToolChain().getDriver().isUsingLTO()) { CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-enable-linkonceodr-outlining"); - } + CmdArgs.push_back("-enable-machine-outliner"); } } else { // Disable all outlining behaviour. diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 11f77096ae..9205dd52de 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -479,6 +479,18 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } + // Propagate the -moutline flag to the linker in LTO. + if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { + if (getMachOToolChain().getMachOArchName(Args) == "arm64") { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-outliner"); + + // Outline from linkonceodr functions by default in LTO. + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-linkonceodr-outlining"); + } + } + // It seems that the 'e' option is completely ignored for dynamic executables // (the default), and with static executables, the last one wins, as expected. Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t, diff --git a/test/Driver/aarch64-outliner.c b/test/Driver/aarch64-outliner.c index 82f02ff99f..eaf4e8ad96 100644 --- a/test/Driver/aarch64-outliner.c +++ b/test/Driver/aarch64-outliner.c @@ -3,10 +3,6 @@ // ON: "-mllvm" "-enable-machine-outliner" // RUN: %clang -target aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF // OFF: "-mllvm" "-enable-machine-outliner=never" -// RUN: %clang -target aarch64 -moutline -flto=thin -S %s -### 2>&1 | FileCheck %s -check-prefix=FLTO -// FLTO: "-mllvm" "-enable-linkonceodr-outlining" -// RUN: %clang -target aarch64 -moutline -flto=full -S %s -### 2>&1 | FileCheck %s -check-prefix=TLTO -// TLTO: "-mllvm" "-enable-linkonceodr-outlining" // RUN: %clang -target x86_64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=WARN // WARN: warning: The 'x86_64' architecture does not support -moutline; flag ignored [-Woption-ignored] // WARN-NOT: "-mllvm" "-enable-machine-outliner" diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c index 14f84bb053..c98d1abcab 100644 --- a/test/Driver/darwin-ld.c +++ b/test/Driver/darwin-ld.c @@ -371,3 +371,9 @@ // RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log // RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log // NO_PROFILE_EXPORT-NOT: "-exported_symbol" +// +// Check that we can pass the outliner down to the linker. +// RUN: env IPHONEOS_DEPLOYMENT_TARGET=7.0 \ +// RUN: %clang -target arm64-apple-darwin -moutline -### %t.o 2> %t.log +// MOUTLINE: ld +// MOUTLINE-SAME: "-mllvm" "-enable-machine-outliner" "-mllvm" "-enable-linkonceodr-outlining" -- GitLab From 4cc1cb57a30cfd11a25427ef52224efc40980a03 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 6 Jul 2018 22:46:52 +0000 Subject: [PATCH 0428/1023] [X86] When creating a select for scalar masked sqrt and div builtins make sure we optimize the all ones mask case. This case occurs in the intrinsic headers so we should avoid emitting the mask in those cases. Factor the code into a helper function to make this easy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336472 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 31 +++--- test/CodeGen/avx512f-builtins.c | 184 ++++++++++++++++---------------- 2 files changed, 109 insertions(+), 106 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index f2efca8cc9..3ebf584ac8 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8517,6 +8517,21 @@ static Value *EmitX86Select(CodeGenFunction &CGF, return CGF.Builder.CreateSelect(Mask, Op0, Op1); } +static Value *EmitX86ScalarSelect(CodeGenFunction &CGF, + Value *Mask, Value *Op0, Value *Op1) { + // If the mask is all ones just return first argument. + if (const auto *C = dyn_cast(Mask)) + if (C->isAllOnesValue()) + return Op0; + + llvm::VectorType *MaskTy = + llvm::VectorType::get(CGF.Builder.getInt1Ty(), + Mask->getType()->getIntegerBitWidth()); + Mask = CGF.Builder.CreateBitCast(Mask, MaskTy); + Mask = CGF.Builder.CreateExtractElement(Mask, (uint64_t)0); + return CGF.Builder.CreateSelect(Mask, Op0, Op1); +} + static Value *EmitX86MaskedCompareResult(CodeGenFunction &CGF, Value *Cmp, unsigned NumElts, Value *MaskIn) { if (MaskIn) { @@ -9884,12 +9899,9 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0); Function *F = CGM.getIntrinsic(Intrinsic::sqrt, A->getType()); + A = Builder.CreateCall(F, A); Value *Src = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - int MaskSize = Ops[3]->getType()->getScalarSizeInBits(); - llvm::Type *MaskTy = llvm::VectorType::get(Builder.getInt1Ty(), MaskSize); - Value *Mask = Builder.CreateBitCast(Ops[3], MaskTy); - Mask = Builder.CreateExtractElement(Mask, (uint64_t)0); - A = Builder.CreateSelect(Mask, Builder.CreateCall(F, {A}), Src); + A = EmitX86ScalarSelect(*this, Ops[3], A, Src); return Builder.CreateInsertElement(Ops[0], A, (uint64_t)0); } case X86::BI__builtin_ia32_sqrtpd256: @@ -10024,14 +10036,9 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - Value *Mask = Ops[3]; Value *Div = Builder.CreateFDiv(A, B); - llvm::VectorType *MaskTy = llvm::VectorType::get(Builder.getInt1Ty(), - cast(Mask->getType())->getBitWidth()); - Mask = Builder.CreateBitCast(Mask, MaskTy); - Mask = Builder.CreateExtractElement(Mask, (uint64_t)0); - Value *Select = Builder.CreateSelect(Mask, Div, C); - return Builder.CreateInsertElement(Ops[0], Select, (uint64_t)0); + Div = EmitX86ScalarSelect(*this, Ops[3], Div, C); + return Builder.CreateInsertElement(Ops[0], Div, (uint64_t)0); } // 3DNow! diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 2cfaf0cc4c..c72167e9c4 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -3581,27 +3581,26 @@ __m128 test_mm_maskz_div_round_ss(__mmask8 __U, __m128 __A, __m128 __B) { } __m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_div_ss - // CHECK-NOT: @llvm.x86.avx512.mask.div.ss.round // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: fdiv float %{{.*}}, %{{.*}} - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: fdiv float %{{.*}}, %{{.*}} + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_div_ss(__W,__U,__A,__B); } __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_maskz_div_ss - // CHECK-NOT: @llvm.x86.avx512.mask.div.ss.round // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: fdiv float %{{.*}}, %{{.*}} - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: fdiv float %{{.*}}, %{{.*}} + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_div_ss(__U,__A,__B); } __m128d test_mm_div_round_sd(__m128d __A, __m128d __B) { @@ -3621,27 +3620,26 @@ __m128d test_mm_maskz_div_round_sd(__mmask8 __U, __m128d __A, __m128d __B) { } __m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_mask_div_sd - // CHECK-NOT: @llvm.x86.avx512.mask.div.sd.round - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: fdiv double %{{.*}}, %{{.*}} - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: fdiv double %{{.*}}, %{{.*}} + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_div_sd(__W,__U,__A,__B); } __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_maskz_div_sd - // CHECK-NOT: @llvm.x86.avx512.mask.div.sd.round - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: fdiv double %{{.*}}, %{{.*}} - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: fdiv double %{{.*}}, %{{.*}} + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_div_sd(__U,__A,__B); } __m128 test_mm_max_round_ss(__m128 __A, __m128 __B) { @@ -5948,117 +5946,115 @@ __m512 test_mm512_maskz_shuffle_ps(__mmask16 __U, __m512 __M, __m512 __V) { __m128d test_mm_sqrt_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_sqrt_round_sd // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 + // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 return _mm_sqrt_round_sd(__A, __B, 4); } __m128d test_mm_mask_sqrt_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_sqrt_sd // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_mask_sqrt_sd(__W,__U,__A,__B); + // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 + return _mm_mask_sqrt_sd(__W,__U,__A,__B); } __m128d test_mm_mask_sqrt_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_sqrt_round_sd // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 + return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m128d test_mm_maskz_sqrt_sd(__mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_sd // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_maskz_sqrt_sd(__U,__A,__B); + // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 + return _mm_maskz_sqrt_sd(__U,__A,__B); } __m128d test_mm_maskz_sqrt_round_sd(__mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_round_sd // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 + return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m128 test_mm_sqrt_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_sqrt_round_ss // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 + // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 return _mm_sqrt_round_ss(__A, __B, 4); } __m128 test_mm_mask_sqrt_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_sqrt_ss // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_mask_sqrt_ss(__W,__U,__A,__B); + // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 + return _mm_mask_sqrt_ss(__W,__U,__A,__B); } __m128 test_mm_mask_sqrt_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_sqrt_round_ss // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 + return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m128 test_mm_maskz_sqrt_ss(__mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_ss // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_maskz_sqrt_ss(__U,__A,__B); + // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 + return _mm_maskz_sqrt_ss(__U,__A,__B); } __m128 test_mm_maskz_sqrt_round_ss(__mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_round_ss // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: bitcast i8 %{{.*}} to <8 x i1> - // CHECK: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 + return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_broadcast_f32x4(float const* __A) { -- GitLab From 2af72fe5e815083513b80862541e312b92ced5f0 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Sat, 7 Jul 2018 00:17:25 +0000 Subject: [PATCH 0429/1023] Check returned type is valid before using it. Add a .isNull() check to returned QualType. Fixes PR38077 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336475 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCXXScopeSpec.cpp | 3 +++ test/SemaCXX/overloaded-name.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 61a82aa721..f2fad825c3 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -846,6 +846,9 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + if (T.isNull()) + return true; + if (!T->isDependentType() && !T->getAs()) { Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace) << T << getLangOpts().CPlusPlus; diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp index 6da0354400..8f1dc2f59c 100644 --- a/test/SemaCXX/overloaded-name.cpp +++ b/test/SemaCXX/overloaded-name.cpp @@ -28,3 +28,11 @@ namespace rdar9623945 { } }; } + +namespace PR38077 { + template void bar() {} // expected-note {{possible target for call}} + + int run() { + decltype(bar)::does_not_exist; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + } +} -- GitLab From d377dc1b8e5206ee4cf6fc1f66e12fbda6d51519 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Sat, 7 Jul 2018 01:50:20 +0000 Subject: [PATCH 0430/1023] [Sema] Emit -Wincomplete-implementation for partial methods. Fixes rdar://40634455 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336478 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclObjC.cpp | 12 ++---------- test/SemaObjC/incomplete-implementation.m | 7 +++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 6809b48dc8..8c621dfa40 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2188,17 +2188,9 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc, unsigned DiagID, NamedDecl *NeededFor = nullptr) { // No point warning no definition of method which is 'unavailable'. - switch (method->getAvailability()) { - case AR_Available: - case AR_Deprecated: - break; - - // Don't warn about unavailable or not-yet-introduced methods. - case AR_NotYetIntroduced: - case AR_Unavailable: + if (method->getAvailability() == AR_Unavailable) return; - } - + // FIXME: For now ignore 'IncompleteImpl'. // Previously we grouped all unimplemented methods under a single // warning, but some users strongly voiced that they would prefer diff --git a/test/SemaObjC/incomplete-implementation.m b/test/SemaObjC/incomplete-implementation.m index 74dea2aa86..910cda5f07 100644 --- a/test/SemaObjC/incomplete-implementation.m +++ b/test/SemaObjC/incomplete-implementation.m @@ -13,6 +13,13 @@ - Meth {return 0;} // expected-warning {{category is implementing a method which will also be implemented by its primary class}} @end +// rdar://40634455 +@interface MyClass +-(void)mymeth __attribute__((availability(macos, introduced=100))); // expected-note{{here}} +@end +@implementation MyClass // expected-warning{{'mymeth' not found}} +@end + #pragma GCC diagnostic ignored "-Wincomplete-implementation" @interface I2 - Meth; // expected-note{{method 'Meth' declared here}} -- GitLab From 27dd885739e60dcea9da632b0f35e73ba267aa56 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 7 Jul 2018 05:58:48 +0000 Subject: [PATCH 0431/1023] P0806R2 Implicit capture of this with a capture-default of [=] is deprecated. Add a -Wdeprecated warning for this in C++2a onwards. (In C++17 and before, there isn't a reasonable alternative because [=,this] is ill-formed.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336480 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 2 ++ include/clang/Basic/DiagnosticSemaKinds.td | 5 +++++ lib/Sema/SemaLambda.cpp | 11 +++++++++++ test/SemaCXX/cxx2a-lambda-equals-this.cpp | 12 ++++++++++-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index a7fe5032df..e021cf6975 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -120,6 +120,7 @@ def DeprecatedDynamicExceptionSpec def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">; def DeprecatedRegister : DiagGroup<"deprecated-register">; +def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">; def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings", [CXX11CompatDeprecatedWritableStr]>; // FIXME: Why is DeprecatedImplementations not in this group? @@ -128,6 +129,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes, DeprecatedDynamicExceptionSpec, DeprecatedIncrementBool, DeprecatedRegister, + DeprecatedThisCapture, DeprecatedWritableStr]>, DiagCategory<"Deprecations">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c02e7d2780..0f1ce0e120 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6545,6 +6545,11 @@ let CategoryName = "Lambda Issue" in { def ext_equals_this_lambda_capture_cxx2a : ExtWarn< "explicit capture of 'this' with a capture default of '=' " "is a C++2a extension">, InGroup; + def warn_deprecated_this_capture : Warning< + "implicit capture of 'this' with a capture default of '=' is deprecated">, + InGroup, DefaultIgnore; + def note_deprecated_this_capture : Note< + "add an explicit capture of 'this' to capture '*this' by reference">; } def err_return_in_captured_stmt : Error< diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index fcacc2a17c..5e69feceda 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1548,6 +1548,17 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Handle 'this' capture. if (From.isThisCapture()) { + // Capturing 'this' implicitly with a default of '[=]' is deprecated, + // because it results in a reference capture. Don't warn prior to + // C++2a; there's nothing that can be done about it before then. + if (getLangOpts().CPlusPlus2a && IsImplicit && + CaptureDefault == LCD_ByCopy) { + Diag(From.getLocation(), diag::warn_deprecated_this_capture); + Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture) + << FixItHint::CreateInsertion( + getLocForEndOfToken(CaptureDefaultLoc), ", this"); + } + Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, From.isCopyCapture() ? LCK_StarThis : LCK_This)); diff --git a/test/SemaCXX/cxx2a-lambda-equals-this.cpp b/test/SemaCXX/cxx2a-lambda-equals-this.cpp index ce6916322e..652fb8da9b 100644 --- a/test/SemaCXX/cxx2a-lambda-equals-this.cpp +++ b/test/SemaCXX/cxx2a-lambda-equals-this.cpp @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++2a -verify %s -Wdeprecated // This test does two things. // Deleting the copy constructor ensures that an [=, this] capture doesn't copy the object. @@ -13,3 +12,12 @@ class A { L(); } }; + +struct B { + int i; + void f() { + (void) [=] { // expected-note {{add an explicit capture of 'this'}} + return i; // expected-warning {{implicit capture of 'this' with a capture default of '=' is deprecated}} + }; + } +}; -- GitLab From 1d754e855c2f60783bbae9eb54199e67c8371e98 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 7 Jul 2018 17:03:32 +0000 Subject: [PATCH 0432/1023] [X86] Fix various type mismatches in intrinsic headers and intrinsic tests that cause extra bitcasts to be emitted in the IR. Found via imprecise grepping of the -O0 IR. There could still be more bugs out there. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336487 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 78 ++++++++++++++--------------- lib/Headers/avx512vlintrin.h | 10 ++-- lib/Headers/avxintrin.h | 8 +-- test/CodeGen/avx-builtins.c | 14 +++--- test/CodeGen/avx-shuffle-builtins.c | 8 +-- test/CodeGen/avx512dq-builtins.c | 12 ++--- test/CodeGen/avx512f-builtins.c | 30 +++++------ 7 files changed, 80 insertions(+), 80 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index be4ee62fc6..cbee4413be 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -3374,7 +3374,7 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, #define _mm512_extractf64x4_pd(A, I) \ (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(I), \ - (__v4df)_mm256_undefined_si256(), \ + (__v4df)_mm256_undefined_pd(), \ (__mmask8)-1) #define _mm512_mask_extractf64x4_pd(W, U, A, imm) \ @@ -5544,7 +5544,7 @@ _mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A, (__v4sf) __B, - (__v4sf) _mm_setzero_pd (), + (__v4sf) _mm_setzero_ps (), (__mmask8) __U, _MM_FROUND_CUR_DIRECTION); } @@ -5634,7 +5634,7 @@ _mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B) (__m128)__builtin_ia32_getmantss_round_mask((__v4sf)(__m128)(A), \ (__v4sf)(__m128)(B), \ (int)(((D)<<2) | (C)), \ - (__v4sf)_mm_setzero_pd(), \ + (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), \ _MM_FROUND_CUR_DIRECTION) @@ -6721,24 +6721,24 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v8df)_mm512_setzero_pd()) #define _mm512_shuffle_ps(A, B, M) \ - (__m512d)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - 0 + (((M) >> 0) & 0x3), \ - 0 + (((M) >> 2) & 0x3), \ - 16 + (((M) >> 4) & 0x3), \ - 16 + (((M) >> 6) & 0x3), \ - 4 + (((M) >> 0) & 0x3), \ - 4 + (((M) >> 2) & 0x3), \ - 20 + (((M) >> 4) & 0x3), \ - 20 + (((M) >> 6) & 0x3), \ - 8 + (((M) >> 0) & 0x3), \ - 8 + (((M) >> 2) & 0x3), \ - 24 + (((M) >> 4) & 0x3), \ - 24 + (((M) >> 6) & 0x3), \ - 12 + (((M) >> 0) & 0x3), \ - 12 + (((M) >> 2) & 0x3), \ - 28 + (((M) >> 4) & 0x3), \ - 28 + (((M) >> 6) & 0x3)) + (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), \ + 0 + (((M) >> 0) & 0x3), \ + 0 + (((M) >> 2) & 0x3), \ + 16 + (((M) >> 4) & 0x3), \ + 16 + (((M) >> 6) & 0x3), \ + 4 + (((M) >> 0) & 0x3), \ + 4 + (((M) >> 2) & 0x3), \ + 20 + (((M) >> 4) & 0x3), \ + 20 + (((M) >> 6) & 0x3), \ + 8 + (((M) >> 0) & 0x3), \ + 8 + (((M) >> 2) & 0x3), \ + 24 + (((M) >> 4) & 0x3), \ + 24 + (((M) >> 6) & 0x3), \ + 12 + (((M) >> 0) & 0x3), \ + 12 + (((M) >> 2) & 0x3), \ + 28 + (((M) >> 4) & 0x3), \ + 28 + (((M) >> 6) & 0x3)) #define _mm512_mask_shuffle_ps(W, U, A, B, M) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ @@ -7651,7 +7651,7 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) (__mmask8)(mask), (int)(scale)) #define _mm512_i64gather_epi32(index, addr, scale) \ - (__m256i)__builtin_ia32_gatherdiv16si((__v8si)_mm256_undefined_ps(), \ + (__m256i)__builtin_ia32_gatherdiv16si((__v8si)_mm256_undefined_si256(), \ (int const *)(addr), \ (__v8di)(__m512i)(index), \ (__mmask8)-1, (int)(scale)) @@ -7675,7 +7675,7 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) (__mmask8)(mask), (int)(scale)) #define _mm512_i64gather_epi64(index, addr, scale) \ - (__m512i)__builtin_ia32_gatherdiv8di((__v8di)_mm512_undefined_pd(), \ + (__m512i)__builtin_ia32_gatherdiv8di((__v8di)_mm512_undefined_epi32(), \ (long long const *)(addr), \ (__v8di)(__m512i)(index), (__mmask8)-1, \ (int)(scale)) @@ -7825,16 +7825,16 @@ _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) } #define _mm_fmadd_round_ss(A, B, C, R) \ - (__m128d)__builtin_ia32_vfmaddss3_mask((__v2df)(__m128d)(A), \ - (__v2df)(__m128d)(B), \ - (__v2df)(__m128d)(C), (__mmask8)-1, \ - (int)(R)) + (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), \ + (__v4sf)(__m128)(C), (__mmask8)-1, \ + (int)(R)) #define _mm_mask_fmadd_round_ss(W, U, A, B, R) \ - (__m128d)__builtin_ia32_vfmaddss3_mask((__v2df)(__m128d)(W), \ - (__v2df)(__m128d)(A), \ - (__v2df)(__m128d)(B), (__mmask8)(U), \ - (int)(R)) + (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \ + (__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (__mmask8)(U), \ + (int)(R)) static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) @@ -8780,7 +8780,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_expand_epi64 ( __mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A, - (__v8di) _mm512_setzero_pd (), + (__v8di) _mm512_setzero_si512 (), (__mmask8) __U); } @@ -8812,7 +8812,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *)__P, - (__v8di) _mm512_setzero_pd(), + (__v8di) _mm512_setzero_si512(), (__mmask8) __U); } @@ -8844,7 +8844,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *)__P, - (__v16si) _mm512_setzero_ps(), + (__v16si) _mm512_setzero_si512(), (__mmask16) __U); } @@ -8876,7 +8876,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_expand_epi32 (__mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A, - (__v16si) _mm512_setzero_ps(), + (__v16si) _mm512_setzero_si512(), (__mmask16) __U); } @@ -8917,16 +8917,16 @@ _mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_cvtpslo_pd (__m512 __A) { - return (__m512) _mm512_cvtps_pd(_mm512_castps512_ps256(__A)); + return (__m512d) _mm512_cvtps_pd(_mm512_castps512_ps256(__A)); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A) { - return (__m512) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A)); + return (__m512d) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A)); } static __inline__ __m512d __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index a3bb589864..66f92abcb0 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -3582,7 +3582,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { _mm_maskz_sqrt_ps(__mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_sqrt_ps(__A), - (__v4sf)_mm_setzero_pd()); + (__v4sf)_mm_setzero_ps()); } static __inline__ __m256 __DEFAULT_FN_ATTRS @@ -6413,7 +6413,7 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) #define _mm256_mask_shuffle_f64x2(W, U, A, B, imm) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ (__v4df)_mm256_shuffle_f64x2((A), (B), (imm)), \ - (__v4df)(__m256)(W)) + (__v4df)(__m256d)(W)) #define _mm256_maskz_shuffle_f64x2(U, A, B, imm) \ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \ @@ -6427,7 +6427,7 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) #define _mm256_mask_shuffle_i32x4(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ (__v8si)_mm256_shuffle_i32x4((A), (B), (imm)), \ - (__v8si)(__m256)(W)) + (__v8si)(__m256i)(W)) #define _mm256_maskz_shuffle_i32x4(U, A, B, imm) \ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \ @@ -6441,7 +6441,7 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) #define _mm256_mask_shuffle_i64x2(W, U, A, B, imm) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ (__v4di)_mm256_shuffle_i64x2((A), (B), (imm)), \ - (__v4di)(__m256)(W)) + (__v4di)(__m256i)(W)) #define _mm256_maskz_shuffle_i64x2(U, A, B, imm) \ @@ -7872,7 +7872,7 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v4df)_mm256_setzero_pd()) #define _mm256_permutex_epi64(X, C) \ - (__m256d)__builtin_ia32_permdi256((__v4di)(__m256i)(X), (int)(C)) + (__m256i)__builtin_ia32_permdi256((__v4di)(__m256i)(X), (int)(C)) #define _mm256_mask_permutex_epi64(W, U, X, C) \ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \ diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 3bf7783db3..3ba6c95604 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -4966,7 +4966,7 @@ _mm256_set_m128 (__m128 __hi, __m128 __lo) static __inline __m256d __DEFAULT_FN_ATTRS _mm256_set_m128d (__m128d __hi, __m128d __lo) { - return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo); + return (__m256d) __builtin_shufflevector((__v2df)__lo, (__v2df)__hi, 0, 1, 2, 3); } /// Constructs a 256-bit integer vector by concatenating two 128-bit @@ -4986,7 +4986,7 @@ _mm256_set_m128d (__m128d __hi, __m128d __lo) static __inline __m256i __DEFAULT_FN_ATTRS _mm256_set_m128i (__m128i __hi, __m128i __lo) { - return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo); + return (__m256i) __builtin_shufflevector((__v2di)__lo, (__v2di)__hi, 0, 1, 2, 3); } /// Constructs a 256-bit floating-point vector of [8 x float] by @@ -5032,7 +5032,7 @@ _mm256_setr_m128 (__m128 __lo, __m128 __hi) static __inline __m256d __DEFAULT_FN_ATTRS _mm256_setr_m128d (__m128d __lo, __m128d __hi) { - return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo); + return (__m256d)_mm256_set_m128d(__hi, __lo); } /// Constructs a 256-bit integer vector by concatenating two 128-bit @@ -5053,7 +5053,7 @@ _mm256_setr_m128d (__m128d __lo, __m128d __hi) static __inline __m256i __DEFAULT_FN_ATTRS _mm256_setr_m128i (__m128i __lo, __m128i __hi) { - return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo); + return (__m256i)_mm256_set_m128i(__hi, __lo); } #undef __DEFAULT_FN_ATTRS diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c index 90344a935a..3e7709b1b7 100644 --- a/test/CodeGen/avx-builtins.c +++ b/test/CodeGen/avx-builtins.c @@ -1570,13 +1570,13 @@ __m256 test_mm256_set_m128(__m128 A, __m128 B) { __m256d test_mm256_set_m128d(__m128d A, __m128d B) { // CHECK-LABEL: test_mm256_set_m128d - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> return _mm256_set_m128d(A, B); } __m256i test_mm256_set_m128i(__m128i A, __m128i B) { // CHECK-LABEL: test_mm256_set_m128i - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> return _mm256_set_m128i(A, B); } @@ -1796,13 +1796,13 @@ __m256 test_mm256_setr_m128(__m128 A, __m128 B) { __m256d test_mm256_setr_m128d(__m128d A, __m128d B) { // CHECK-LABEL: test_mm256_setr_m128d - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <2 x double> %{{.*}}, <2 x double> %{{.*}}, <4 x i32> return _mm256_setr_m128d(A, B); } __m256i test_mm256_setr_m128i(__m128i A, __m128i B) { // CHECK-LABEL: test_mm256_setr_m128i - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <8 x i32> + // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <4 x i32> return _mm256_setr_m128i(A, B); } @@ -1990,7 +1990,7 @@ int test_mm256_testc_ps(__m256 A, __m256 B) { return _mm256_testc_ps(A, B); } -int test_mm256_testc_si256(__m256 A, __m256 B) { +int test_mm256_testc_si256(__m256i A, __m256i B) { // CHECK-LABEL: test_mm256_testc_si256 // CHECK: call i32 @llvm.x86.avx.ptestc.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}) return _mm256_testc_si256(A, B); @@ -2020,7 +2020,7 @@ int test_mm256_testnzc_ps(__m256 A, __m256 B) { return _mm256_testnzc_ps(A, B); } -int test_mm256_testnzc_si256(__m256 A, __m256 B) { +int test_mm256_testnzc_si256(__m256i A, __m256i B) { // CHECK-LABEL: test_mm256_testnzc_si256 // CHECK: call i32 @llvm.x86.avx.ptestnzc.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}) return _mm256_testnzc_si256(A, B); @@ -2050,7 +2050,7 @@ int test_mm256_testz_ps(__m256 A, __m256 B) { return _mm256_testz_ps(A, B); } -int test_mm256_testz_si256(__m256 A, __m256 B) { +int test_mm256_testz_si256(__m256i A, __m256i B) { // CHECK-LABEL: test_mm256_testz_si256 // CHECK: call i32 @llvm.x86.avx.ptestz.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}}) return _mm256_testz_si256(A, B); diff --git a/test/CodeGen/avx-shuffle-builtins.c b/test/CodeGen/avx-shuffle-builtins.c index 0830015961..fef2879abd 100644 --- a/test/CodeGen/avx-shuffle-builtins.c +++ b/test/CodeGen/avx-shuffle-builtins.c @@ -171,13 +171,13 @@ __m256 test_mm256_set_m128(__m128 hi, __m128 lo) { __m256d test_mm256_set_m128d(__m128d hi, __m128d lo) { // CHECK-LABEL: @test_mm256_set_m128d - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_set_m128d(hi, lo); } __m256i test_mm256_set_m128i(__m128i hi, __m128i lo) { // CHECK-LABEL: @test_mm256_set_m128i - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_set_m128i(hi, lo); } @@ -189,12 +189,12 @@ __m256 test_mm256_setr_m128(__m128 hi, __m128 lo) { __m256d test_mm256_setr_m128d(__m128d hi, __m128d lo) { // CHECK-LABEL: @test_mm256_setr_m128d - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_setr_m128d(lo, hi); } __m256i test_mm256_setr_m128i(__m128i hi, __m128i lo) { // CHECK-LABEL: @test_mm256_setr_m128i - // CHECK: shufflevector{{.*}} + // CHECK: shufflevector{{.*}} return _mm256_setr_m128i(lo, hi); } diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c index 242b9d3995..e08501b397 100644 --- a/test/CodeGen/avx512dq-builtins.c +++ b/test/CodeGen/avx512dq-builtins.c @@ -691,13 +691,13 @@ __m128d test_mm512_maskz_range_round_sd(__mmask8 __U, __m128d __A, __m128d __B) return _mm_maskz_range_round_sd(__U, __A, __B, 4, 8); } -__m128d test_mm512_range_round_ss(__m128d __A, __m128d __B) { +__m128 test_mm512_range_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm512_range_round_ss // CHECK: @llvm.x86.avx512.mask.range.ss return _mm_range_round_ss(__A, __B, 4, 8); } -__m128d test_mm512_mask_range_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { +__m128 test_mm512_mask_range_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm512_mask_range_round_ss // CHECK: @llvm.x86.avx512.mask.range.ss return _mm_mask_range_round_ss(__W, __U, __A, __B, 4, 8); @@ -727,13 +727,13 @@ __m128d test_mm_maskz_range_sd(__mmask8 __U, __m128d __A, __m128d __B) { return _mm_maskz_range_sd(__U, __A, __B, 4); } -__m128d test_mm_range_ss(__m128d __A, __m128d __B) { +__m128 test_mm_range_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_range_ss // CHECK: @llvm.x86.avx512.mask.range.ss return _mm_range_ss(__A, __B, 4); } -__m128d test_mm_mask_range_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { +__m128 test_mm_mask_range_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_range_ss // CHECK: @llvm.x86.avx512.mask.range.ss return _mm_mask_range_ss(__W, __U, __A, __B, 4); @@ -1256,13 +1256,13 @@ __mmask16 test_mm512_fpclass_ps_mask(__m512 __A) { return _mm512_fpclass_ps_mask(__A, 4); } -__mmask8 test_mm_fpclass_sd_mask(__m128 __A) { +__mmask8 test_mm_fpclass_sd_mask(__m128d __A) { // CHECK-LABEL: @test_mm_fpclass_sd_mask // CHECK: @llvm.x86.avx512.mask.fpclass.sd return _mm_fpclass_sd_mask (__A, 2); } -__mmask8 test_mm_mask_fpclass_sd_mask(__mmask8 __U, __m128 __A) { +__mmask8 test_mm_mask_fpclass_sd_mask(__mmask8 __U, __m128d __A) { // CHECK-LABEL: @test_mm_mask_fpclass_sd_mask // CHECK: @llvm.x86.avx512.mask.fpclass.sd return _mm_mask_fpclass_sd_mask (__U, __A, 2); diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index c72167e9c4..0a817938f6 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -2378,14 +2378,14 @@ __m128 test_mm512_extractf32x4_ps(__m512 a) return _mm512_extractf32x4_ps(a, 1); } -__m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512d __A){ +__m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512 __A){ // CHECK-LABEL:@test_mm512_mask_extractf32x4_ps // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} return _mm512_mask_extractf32x4_ps( __W, __U, __A, 1); } -__m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512d __A){ +__m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512 __A){ // CHECK-LABEL:@test_mm512_maskz_extractf32x4_ps // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> undef, <4 x i32> // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}} @@ -5341,19 +5341,19 @@ __m128 test_mm_roundscale_ss(__m128 __A, __m128 __B) { return _mm_roundscale_ss(__A, __B, 3); } -__m128 test_mm_mask_roundscale_ss(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ +__m128 test_mm_mask_roundscale_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_roundscale_ss // CHECK: @llvm.x86.avx512.mask.rndscale.ss return _mm_mask_roundscale_ss(__W,__U,__A,__B,3); } -__m128 test_mm_maskz_roundscale_round_ss( __mmask8 __U, __m128d __A, __m128d __B){ +__m128 test_mm_maskz_roundscale_round_ss( __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_roundscale_round_ss // CHECK: @llvm.x86.avx512.mask.rndscale.ss return _mm_maskz_roundscale_round_ss(__U,__A,__B,3,_MM_FROUND_CUR_DIRECTION); } -__m128 test_mm_maskz_roundscale_ss(__mmask8 __U, __m128d __A, __m128d __B){ +__m128 test_mm_maskz_roundscale_ss(__mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_roundscale_ss // CHECK: @llvm.x86.avx512.mask.rndscale.ss return _mm_maskz_roundscale_ss(__U,__A,__B,3); @@ -6077,24 +6077,24 @@ __m512 test_mm512_maskz_broadcast_f32x4(__mmask16 __M, float const* __A) { return _mm512_maskz_broadcast_f32x4(__M, _mm_loadu_ps(__A)); } -__m512d test_mm512_broadcast_f64x4(float const* __A) { +__m512d test_mm512_broadcast_f64x4(double const* __A) { // CHECK-LABEL: @test_mm512_broadcast_f64x4 // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> - return _mm512_broadcast_f64x4(_mm256_loadu_ps(__A)); + return _mm512_broadcast_f64x4(_mm256_loadu_pd(__A)); } -__m512d test_mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, float const* __A) { +__m512d test_mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, double const* __A) { // CHECK-LABEL: @test_mm512_mask_broadcast_f64x4 // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} - return _mm512_mask_broadcast_f64x4(__O, __M, _mm256_loadu_ps(__A)); + return _mm512_mask_broadcast_f64x4(__O, __M, _mm256_loadu_pd(__A)); } -__m512d test_mm512_maskz_broadcast_f64x4(__mmask8 __M, float const* __A) { +__m512d test_mm512_maskz_broadcast_f64x4(__mmask8 __M, double const* __A) { // CHECK-LABEL: @test_mm512_maskz_broadcast_f64x4 // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <8 x i32> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} - return _mm512_maskz_broadcast_f64x4(__M, _mm256_loadu_ps(__A)); + return _mm512_maskz_broadcast_f64x4(__M, _mm256_loadu_pd(__A)); } __m512i test_mm512_broadcast_i32x4(__m128i const* __A) { @@ -8630,7 +8630,7 @@ __m512d test_mm512_castpd128_pd512(__m128d __A) { return _mm512_castpd128_pd512(__A); } -__m512d test_mm512_set1_epi8(char d) +__m512i test_mm512_set1_epi8(char d) { // CHECK-LABEL: @test_mm512_set1_epi8 // CHECK: insertelement <64 x i8> {{.*}}, i32 0 @@ -8645,7 +8645,7 @@ __m512d test_mm512_set1_epi8(char d) return _mm512_set1_epi8(d); } -__m512d test_mm512_set1_epi16(short d) +__m512i test_mm512_set1_epi16(short d) { // CHECK-LABEL: @test_mm512_set1_epi16 // CHECK: insertelement <32 x i16> {{.*}}, i32 0 @@ -8702,14 +8702,14 @@ __m512i test_mm512_setr4_epi32(int e0, int e1, int e2, int e3) return _mm512_setr4_epi64(e0, e1, e2, e3); } -__m512i test_mm512_setr4_pd(double e0, double e1, double e2, double e3) +__m512d test_mm512_setr4_pd(double e0, double e1, double e2, double e3) { // CHECK-LABEL: @test_mm512_setr4_pd // CHECK: insertelement <8 x double> {{.*}}, i32 7 return _mm512_setr4_pd(e0,e1,e2,e3); } - __m512i test_mm512_setr4_ps(float e0, float e1, float e2, float e3) + __m512 test_mm512_setr4_ps(float e0, float e1, float e2, float e3) { // CHECK-LABEL: @test_mm512_setr4_ps // CHECK: insertelement <16 x float> {{.*}}, i32 15 -- GitLab From 15349a004a06780980702064429c03f23bd296c7 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 7 Jul 2018 17:03:34 +0000 Subject: [PATCH 0433/1023] [X86] Change _mm512_shuffle_pd and _mm512_shuffle_ps to use target specific shuffle builtins instead of generic __builtin_shufflevector. I added the builtins for 128, 256, and 512 bits recently but looks like I failed to convert to using the 512 bit one. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336488 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index cbee4413be..a3ca7e730a 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -6699,16 +6699,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v8di)_mm512_setzero_si512()) #define _mm512_shuffle_pd(A, B, M) \ - (__m512d)__builtin_shufflevector((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - 0 + (((M) >> 0) & 0x1), \ - 8 + (((M) >> 1) & 0x1), \ - 2 + (((M) >> 2) & 0x1), \ - 10 + (((M) >> 3) & 0x1), \ - 4 + (((M) >> 4) & 0x1), \ - 12 + (((M) >> 5) & 0x1), \ - 6 + (((M) >> 6) & 0x1), \ - 14 + (((M) >> 7) & 0x1)) + (__m512d)__builtin_ia32_shufpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(M)) #define _mm512_mask_shuffle_pd(W, U, A, B, M) \ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ @@ -6721,24 +6713,8 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v8df)_mm512_setzero_pd()) #define _mm512_shuffle_ps(A, B, M) \ - (__m512)__builtin_shufflevector((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - 0 + (((M) >> 0) & 0x3), \ - 0 + (((M) >> 2) & 0x3), \ - 16 + (((M) >> 4) & 0x3), \ - 16 + (((M) >> 6) & 0x3), \ - 4 + (((M) >> 0) & 0x3), \ - 4 + (((M) >> 2) & 0x3), \ - 20 + (((M) >> 4) & 0x3), \ - 20 + (((M) >> 6) & 0x3), \ - 8 + (((M) >> 0) & 0x3), \ - 8 + (((M) >> 2) & 0x3), \ - 24 + (((M) >> 4) & 0x3), \ - 24 + (((M) >> 6) & 0x3), \ - 12 + (((M) >> 0) & 0x3), \ - 12 + (((M) >> 2) & 0x3), \ - 28 + (((M) >> 4) & 0x3), \ - 28 + (((M) >> 6) & 0x3)) + (__m512)__builtin_ia32_shufps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(M)) #define _mm512_mask_shuffle_ps(W, U, A, B, M) \ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ -- GitLab From 9f82dc375b2501b5b21a8a741fccea649d897495 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 7 Jul 2018 17:22:45 +0000 Subject: [PATCH 0434/1023] [analyzer] Highlight container object destruction in MallocChecker. Extend MallocBugVisitor to place a note at the point where objects with AF_InternalBuffer allocation family are destroyed. Differential Revision: https://reviews.llvm.org/D48521 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336489 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 60 ++++++++++++++----- test/Analysis/dangling-internal-buffer.cpp | 8 +-- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 1fa2e3b53e..c8c7a5a573 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -480,8 +480,13 @@ private: inline bool isReleased(const RefState *S, const RefState *SPrev, const Stmt *Stmt) { // Did not track -> released. Other state (allocated) -> released. - return (Stmt && (isa(Stmt) || isa(Stmt)) && - (S && S->isReleased()) && (!SPrev || !SPrev->isReleased())); + // The statement associated with the release might be missing. + bool IsReleased = (S && S->isReleased()) && + (!SPrev || !SPrev->isReleased()); + assert(!IsReleased || + (Stmt && (isa(Stmt) || isa(Stmt))) || + (!Stmt && S->getAllocationFamily() == AF_InternalBuffer)); + return IsReleased; } inline bool isRelinquished(const RefState *S, const RefState *SPrev, @@ -2850,8 +2855,17 @@ static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) { std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { + + ProgramStateRef state = N->getState(); + ProgramStateRef statePrev = PrevN->getState(); + + const RefState *RS = state->get(Sym); + const RefState *RSPrev = statePrev->get(Sym); + const Stmt *S = PathDiagnosticLocation::getStmt(N); - if (!S) + // When dealing with containers, we sometimes want to give a note + // even if the statement is missing. + if (!S && (!RS || RS->getAllocationFamily() != AF_InternalBuffer)) return nullptr; const LocationContext *CurrentLC = N->getLocationContext(); @@ -2876,14 +2890,6 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( } } - ProgramStateRef state = N->getState(); - ProgramStateRef statePrev = PrevN->getState(); - - const RefState *RS = state->get(Sym); - const RefState *RSPrev = statePrev->get(Sym); - if (!RS) - return nullptr; - // FIXME: We will eventually need to handle non-statement-based events // (__attribute__((cleanup))). @@ -2896,7 +2902,22 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( StackHint = new StackHintGeneratorForSymbol(Sym, "Returned allocated memory"); } else if (isReleased(RS, RSPrev, S)) { - Msg = "Memory is released"; + const auto Family = RS->getAllocationFamily(); + switch(Family) { + case AF_Alloca: + case AF_Malloc: + case AF_CXXNew: + case AF_CXXNewArray: + case AF_IfNameIndex: + Msg = "Memory is released"; + break; + case AF_InternalBuffer: + Msg = "Internal buffer is released because the object was destroyed"; + break; + case AF_None: + default: + llvm_unreachable("Unhandled allocation family!"); + } StackHint = new StackHintGeneratorForSymbol(Sym, "Returning; memory was released"); @@ -2967,8 +2988,19 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( assert(StackHint); // Generate the extra diagnostic. - PathDiagnosticLocation Pos(S, BRC.getSourceManager(), - N->getLocationContext()); + PathDiagnosticLocation Pos; + if (!S) { + assert(RS->getAllocationFamily() == AF_InternalBuffer); + auto PostImplCall = N->getLocation().getAs(); + if (!PostImplCall) + return nullptr; + Pos = PathDiagnosticLocation(PostImplCall->getLocation(), + BRC.getSourceManager()); + } else { + Pos = PathDiagnosticLocation(S, BRC.getSourceManager(), + N->getLocationContext()); + } + return std::make_shared(Pos, Msg, true, StackHint); } diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp index 791bb96047..cd7ebb17c6 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -26,7 +26,7 @@ void deref_after_scope_char() { { std::string s; c = s.c_str(); - } + } // expected-note {{Internal buffer is released because the object was destroyed}} consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } @@ -36,7 +36,7 @@ void deref_after_scope_wchar_t() { { std::wstring ws; w = ws.c_str(); - } + } // expected-note {{Internal buffer is released because the object was destroyed}} consume(w); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } @@ -46,7 +46,7 @@ void deref_after_scope_char16_t() { { std::u16string s16; c16 = s16.c_str(); - } + } // expected-note {{Internal buffer is released because the object was destroyed}} consume(c16); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } @@ -56,7 +56,7 @@ void deref_after_scope_char32_t() { { std::u32string s32; c32 = s32.c_str(); - } + } // expected-note {{Internal buffer is released because the object was destroyed}} consume(c32); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -- GitLab From a8cfadd9a957e1fdd6dd289c957e31dca395d5c8 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 7 Jul 2018 18:37:37 +0000 Subject: [PATCH 0435/1023] [analyzer] Fix -Wcovered-switch-default warning in MallocChecker. Remove unnecessary default case that caused buildbot failures. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336493 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index c8c7a5a573..fa50014b07 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2915,7 +2915,6 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( Msg = "Internal buffer is released because the object was destroyed"; break; case AF_None: - default: llvm_unreachable("Unhandled allocation family!"); } StackHint = new StackHintGeneratorForSymbol(Sym, -- GitLab From ffbe9fa4c0a662713e32ca276eaa5de60d5a777b Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 7 Jul 2018 19:27:18 +0000 Subject: [PATCH 0436/1023] [analyzer] Highlight c_str() call in DanglingInternalBufferChecker. Add a bug visitor to DanglingInternalBufferChecker that places a note at the point where the dangling pointer was obtained. The visitor is handed over to MallocChecker and attached to the report there. Differential Revision: https://reviews.llvm.org/D48522 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336495 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/AllocationState.h | 6 ++ .../DanglingInternalBufferChecker.cpp | 87 ++++++++++++++++--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 5 ++ test/Analysis/dangling-internal-buffer.cpp | 22 +++-- 4 files changed, 105 insertions(+), 15 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/AllocationState.h b/lib/StaticAnalyzer/Checkers/AllocationState.h index f87c093a4e..16d3eb6476 100644 --- a/lib/StaticAnalyzer/Checkers/AllocationState.h +++ b/lib/StaticAnalyzer/Checkers/AllocationState.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_ALLOCATIONSTATE_H +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" namespace clang { @@ -20,6 +21,11 @@ namespace allocation_state { ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin); +/// This function provides an additional visitor that augments the bug report +/// with information relevant to memory errors caused by the misuse of +/// AF_InternalBuffer symbols. +std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym); + } // end namespace allocation_state } // end namespace ento diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp index 18f0a22e4a..3716f8b3e2 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -7,30 +7,66 @@ // //===----------------------------------------------------------------------===// // -// This file defines a check that marks a raw pointer to a C++ standard library -// container's inner buffer released when the object is destroyed. This -// information can be used by MallocChecker to detect use-after-free problems. +// This file defines a check that marks a raw pointer to a C++ container's +// inner buffer released when the object is destroyed. This information can +// be used by MallocChecker to detect use-after-free problems. // //===----------------------------------------------------------------------===// +#include "AllocationState.h" #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "AllocationState.h" using namespace clang; using namespace ento; +// FIXME: c_str() may be called on a string object many times, so it should +// have a list of symbols associated with it. +REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) + namespace { -class DanglingInternalBufferChecker : public Checker { +class DanglingInternalBufferChecker + : public Checker { CallDescription CStrFn; public: + class DanglingBufferBRVisitor : public BugReporterVisitor { + SymbolRef PtrToBuf; + + public: + DanglingBufferBRVisitor(SymbolRef Sym) : PtrToBuf(Sym) {} + + static void *getTag() { + static int Tag = 0; + return &Tag; + } + + void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.AddPointer(getTag()); + } + + std::shared_ptr VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; + + // FIXME: Scan the map once in the visitor's constructor and do a direct + // lookup by region. + bool isSymbolTracked(ProgramStateRef State, SymbolRef Sym) { + RawPtrMapTy Map = State->get(); + for (const auto Entry : Map) { + if (Entry.second == Sym) + return true; + } + return false; + } + }; + DanglingInternalBufferChecker() : CStrFn("c_str") {} /// Record the connection between the symbol returned by c_str() and the @@ -44,10 +80,6 @@ public: } // end anonymous namespace -// FIXME: c_str() may be called on a string object many times, so it should -// have a list of symbols associated with it. -REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) - void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { const auto *ICall = dyn_cast(&Call); @@ -103,6 +135,41 @@ void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, C.addTransition(State); } +std::shared_ptr +DanglingInternalBufferChecker::DanglingBufferBRVisitor::VisitNode( + const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, + BugReport &BR) { + + if (!isSymbolTracked(N->getState(), PtrToBuf) || + isSymbolTracked(PrevN->getState(), PtrToBuf)) + return nullptr; + + const Stmt *S = PathDiagnosticLocation::getStmt(N); + if (!S) + return nullptr; + + SmallString<256> Buf; + llvm::raw_svector_ostream OS(Buf); + OS << "Pointer to dangling buffer was obtained here"; + PathDiagnosticLocation Pos(S, BRC.getSourceManager(), + N->getLocationContext()); + return std::make_shared(Pos, OS.str(), true, + nullptr); +} + +namespace clang { +namespace ento { +namespace allocation_state { + +std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym) { + return llvm::make_unique< + DanglingInternalBufferChecker::DanglingBufferBRVisitor>(Sym); +} + +} // end namespace allocation_state +} // end namespace ento +} // end namespace clang + void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) { registerNewDeleteChecker(Mgr); Mgr.registerChecker(); diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index fa50014b07..fd2699320d 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1993,6 +1993,11 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range, R->markInteresting(Sym); R->addRange(Range); R->addVisitor(llvm::make_unique(Sym)); + + const RefState *RS = C.getState()->get(Sym); + if (RS->getAllocationFamily() == AF_InternalBuffer) + R->addVisitor(allocation_state::getDanglingBufferBRVisitor(Sym)); + C.emitReport(std::move(R)); } } diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp index cd7ebb17c6..c4228f4e32 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -6,7 +6,7 @@ template< typename CharT > class basic_string { public: ~basic_string(); - const CharT *c_str(); + const CharT *c_str() const; }; typedef basic_string string; @@ -25,8 +25,20 @@ void deref_after_scope_char() { const char *c; { std::string s; - c = s.c_str(); + c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} + } // expected-note {{Internal buffer is released because the object was destroyed}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_char2() { + const char *c; + { + std::string s; + c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::string s; + const char *c2 = s.c_str(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } @@ -35,7 +47,7 @@ void deref_after_scope_wchar_t() { const wchar_t *w; { std::wstring ws; - w = ws.c_str(); + w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} consume(w); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} @@ -45,7 +57,7 @@ void deref_after_scope_char16_t() { const char16_t *c16; { std::u16string s16; - c16 = s16.c_str(); + c16 = s16.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} consume(c16); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} @@ -55,7 +67,7 @@ void deref_after_scope_char32_t() { const char32_t *c32; { std::u32string s32; - c32 = s32.c_str(); + c32 = s32.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} consume(c32); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} -- GitLab From 5c22565f8c6f0912cbe7e9c65b0625667bd0f7f7 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Sat, 7 Jul 2018 20:29:24 +0000 Subject: [PATCH 0437/1023] [analyzer] Add support for data() in DanglingInternalBufferChecker. DanglingInternalBufferChecker now tracks use-after-free problems related to the incorrect usage of std::basic_string::data(). Differential Revision: https://reviews.llvm.org/D48532 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336497 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../DanglingInternalBufferChecker.cpp | 11 ++-- test/Analysis/dangling-internal-buffer.cpp | 62 ++++++++++++++++--- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp index 3716f8b3e2..fe575cc5fc 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -24,15 +24,16 @@ using namespace clang; using namespace ento; -// FIXME: c_str() may be called on a string object many times, so it should -// have a list of symbols associated with it. +// FIXME: member functions that return a pointer to the container's internal +// buffer may be called on the object many times, so the object's memory +// region should have a list of pointer symbols associated with it. REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) namespace { class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn; + CallDescription CStrFn, DataFn; public: class DanglingBufferBRVisitor : public BugReporterVisitor { @@ -67,7 +68,7 @@ public: } }; - DanglingInternalBufferChecker() : CStrFn("c_str") {} + DanglingInternalBufferChecker() : CStrFn("c_str"), DataFn("data") {} /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol @@ -97,7 +98,7 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, ProgramStateRef State = C.getState(); - if (Call.isCalled(CStrFn)) { + if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) { SVal RawPtr = Call.getReturnValue(); if (!RawPtr.isUnknown()) { State = State->set(TypedR, RawPtr.getAsSymbol()); diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp index c4228f4e32..d5a8940bae 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -7,6 +7,8 @@ class basic_string { public: ~basic_string(); const CharT *c_str() const; + const CharT *data() const; + CharT *data(); }; typedef basic_string string; @@ -21,59 +23,92 @@ void consume(const wchar_t *) {} void consume(const char16_t *) {} void consume(const char32_t *) {} -void deref_after_scope_char() { +void deref_after_scope_char_cstr() { const char *c; { std::string s; c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::string s; + const char *c2 = s.c_str(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_char2() { +void deref_after_scope_char_data() { const char *c; { std::string s; - c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} + c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} std::string s; - const char *c2 = s.c_str(); + const char *c2 = s.data(); + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_char_data_non_const() { + char *c; + { + std::string s; + c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + } // expected-note {{Internal buffer is released because the object was destroyed}} + std::string s; + char *c2 = s.data(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_wchar_t() { + +void deref_after_scope_wchar_t_cstr() { const wchar_t *w; { std::wstring ws; w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::wstring ws; + const wchar_t *w2 = ws.c_str(); + consume(w); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_wchar_t_data() { + const wchar_t *w; + { + std::wstring ws; + w = ws.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + } // expected-note {{Internal buffer is released because the object was destroyed}} + std::wstring ws; + const wchar_t *w2 = ws.data(); consume(w); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_char16_t() { +void deref_after_scope_char16_t_cstr() { const char16_t *c16; { std::u16string s16; c16 = s16.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::u16string s16; + const char16_t *c16_2 = s16.c_str(); consume(c16); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_char32_t() { +void deref_after_scope_char32_t_data() { const char32_t *c32; { std::u32string s32; - c32 = s32.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} + c32 = s32.data(); // expected-note {{Pointer to dangling buffer was obtained here}} } // expected-note {{Internal buffer is released because the object was destroyed}} + std::u32string s32; + const char32_t *c32_2 = s32.data(); consume(c32); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_ok() { +void deref_after_scope_cstr_ok() { const char *c; std::string s; { @@ -81,3 +116,12 @@ void deref_after_scope_ok() { } consume(c); // no-warning } + +void deref_after_scope_data_ok() { + const char *c; + std::string s; + { + c = s.data(); + } + consume(c); // no-warning +} -- GitLab From 08497c156c9c6bdfe076c1004e5dea0a6e70feb5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 7 Jul 2018 22:03:16 +0000 Subject: [PATCH 0438/1023] [X86] Fix a few intrinsics that were ignoring their rounding mode argument and hardcoded _MM_FROUND_CUR_DIRECTION internally. I believe these have been broken since their introduction into clang. I've enhanced the tests for these intrinsics to using a real rounding mode and checking all the intrinsic arguments instead of just the name. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336498 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 10 ++-- test/CodeGen/avx512f-builtins.c | 88 ++++++++++++++++----------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index a3ca7e730a..5e86aae70b 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -6597,7 +6597,7 @@ _mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(B), \ (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), \ - _MM_FROUND_CUR_DIRECTION) + (int)(R)) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_srai_epi32(__m512i __A, int __B) @@ -7826,7 +7826,7 @@ _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \ (__v4sf)(__m128)(B), \ (__v4sf)(__m128)(C), (__mmask8)(U), \ - _MM_FROUND_CUR_DIRECTION) + (int)(R)) static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) @@ -7988,7 +7988,7 @@ _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__m128)__builtin_ia32_vfmaddss3_maskz((__v4sf)(__m128)(A), \ -(__v4sf)(__m128)(B), \ -(__v4sf)(__m128)(C), (__mmask8)(U), \ - _MM_FROUND_CUR_DIRECTION) + (int)(R)) static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) @@ -8042,7 +8042,7 @@ _mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__m128d)__builtin_ia32_vfmaddsd3_maskz((__v2df)(__m128d)(A), \ (__v2df)(__m128d)(B), \ (__v2df)(__m128d)(C), (__mmask8)(U), \ - _MM_FROUND_CUR_DIRECTION) + (int)(R)) static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) @@ -8205,7 +8205,7 @@ _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) -(__v2df)(__m128d)(B), \ -(__v2df)(__m128d)(C), \ (__mmask8)(U), \ - _MM_FROUND_CUR_DIRECTION) + (int)(R)) static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 0a817938f6..d90f5d03ec 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -5433,8 +5433,8 @@ __m512 test_mm512_maskz_scalef_ps(__mmask16 __U, __m512 __A, __m512 __B) { __m128d test_mm_scalef_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_scalef_round_sd - // CHECK: @llvm.x86.avx512.mask.scalef - return _mm_scalef_round_sd(__A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %2, i8 -1, i32 8) + return _mm_scalef_round_sd(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_scalef_sd(__m128d __A, __m128d __B) { @@ -5451,8 +5451,8 @@ __m128d test_mm_mask_scalef_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ __m128d test_mm_mask_scalef_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_scalef_round_sd - // CHECK: @llvm.x86.avx512.mask.scalef.sd - return _mm_mask_scalef_round_sd(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_mask_scalef_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_scalef_sd(__mmask8 __U, __m128d __A, __m128d __B){ @@ -5463,14 +5463,14 @@ __m128d test_mm_maskz_scalef_sd(__mmask8 __U, __m128d __A, __m128d __B){ __m128d test_mm_maskz_scalef_round_sd(__mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_maskz_scalef_round_sd - // CHECK: @llvm.x86.avx512.mask.scalef.sd - return _mm_maskz_scalef_round_sd(__U, __A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_maskz_scalef_round_sd(__U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_scalef_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_scalef_round_ss - // CHECK: @llvm.x86.avx512.mask.scalef.ss - return _mm_scalef_round_ss(__A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + return _mm_scalef_round_ss(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_scalef_ss(__m128 __A, __m128 __B) { @@ -5487,8 +5487,8 @@ __m128 test_mm_mask_scalef_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_mask_scalef_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_scalef_round_ss - // CHECK: @llvm.x86.avx512.mask.scalef.ss - return _mm_mask_scalef_round_ss(__W, __U, __A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_mask_scalef_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_scalef_ss(__mmask8 __U, __m128 __A, __m128 __B){ @@ -5499,8 +5499,8 @@ __m128 test_mm_maskz_scalef_ss(__mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_maskz_scalef_round_ss(__mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_scalef_round_ss - // CHECK: @llvm.x86.avx512.mask.scalef.ss - return _mm_maskz_scalef_round_ss(__U, __A, __B, _MM_FROUND_CUR_DIRECTION); + // CHECK: @llvm.x86.avx512.mask.scalef.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_maskz_scalef_round_ss(__U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512i test_mm512_srai_epi32(__m512i __A) { @@ -7232,13 +7232,13 @@ __m128 test_mm_mask_fmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) return _mm_fmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7266,7 +7266,7 @@ __m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss + // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7295,7 +7295,7 @@ __m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7325,13 +7325,13 @@ __m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) return _mm_fmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7360,7 +7360,7 @@ __m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss + // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7390,7 +7390,7 @@ __m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss + // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7420,13 +7420,13 @@ __m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fnmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) return _mm_fnmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7455,7 +7455,7 @@ __m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss + // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7485,7 +7485,7 @@ __m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7516,13 +7516,13 @@ __m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fnmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) return _mm_fnmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss + // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7552,7 +7552,7 @@ __m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss + // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7583,7 +7583,7 @@ __m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss + // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7612,13 +7612,13 @@ __m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ __m128d test_mm_fmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) return _mm_fmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7646,7 +7646,7 @@ __m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd + // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7675,7 +7675,7 @@ __m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7705,13 +7705,13 @@ __m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ __m128d test_mm_fmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) return _mm_fmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7740,7 +7740,7 @@ __m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd + // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7770,7 +7770,7 @@ __m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd + // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7800,13 +7800,13 @@ __m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ __m128d test_mm_fnmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) return _mm_fnmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7835,7 +7835,7 @@ __m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd + // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7865,7 +7865,7 @@ __m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7896,13 +7896,13 @@ __m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ __m128d test_mm_fnmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) return _mm_fnmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd + // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7932,7 +7932,7 @@ __m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd + // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7963,7 +7963,7 @@ __m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd + // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } -- GitLab From de1ae274b1db277649262f1d13978f114b5e5267 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 7 Jul 2018 22:03:19 +0000 Subject: [PATCH 0439/1023] [X86] Remove some unnecessarily escaped new lines from avx512fintrin.h git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336499 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 5e86aae70b..fc942e98da 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -4061,9 +4061,9 @@ _mm512_cvtps_epu32 ( __m512 __A) { return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,\ (__v16si)\ - _mm512_undefined_epi32 (),\ + _mm512_undefined_epi32 (), (__mmask16) -1,\ - _MM_FROUND_CUR_DIRECTION);\ + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512i __DEFAULT_FN_ATTRS @@ -6608,15 +6608,15 @@ _mm512_srai_epi32(__m512i __A, int __B) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) { - return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, \ - (__v16si)_mm512_srai_epi32(__A, __B), \ + return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, + (__v16si)_mm512_srai_epi32(__A, __B), (__v16si)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A, int __B) { - return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, \ - (__v16si)_mm512_srai_epi32(__A, __B), \ + return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, + (__v16si)_mm512_srai_epi32(__A, __B), (__v16si)_mm512_setzero_si512()); } @@ -6629,16 +6629,16 @@ _mm512_srai_epi64(__m512i __A, int __B) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) { - return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, \ - (__v8di)_mm512_srai_epi64(__A, __B), \ + return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, + (__v8di)_mm512_srai_epi64(__A, __B), (__v8di)__W); } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) { - return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, \ - (__v8di)_mm512_srai_epi64(__A, __B), \ + return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, + (__v8di)_mm512_srai_epi64(__A, __B), (__v8di)_mm512_setzero_si512()); } -- GitLab From 11b0a91ad96a1a636399660e3e99410af66ba553 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 7 Jul 2018 22:03:20 +0000 Subject: [PATCH 0440/1023] [X86] Remove __builtin_ia32_vfnmsubsd3_mask3 and __builtin_ia32_vfnmsubss3_mask3 from clang. They are no longer used by clang. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336500 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 726346dc82..db7055136b 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1712,8 +1712,6 @@ TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "nc", "avx512 TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "nc", "avx512bw") -- GitLab From 1d7e46ba487d09f5a899ede8466831e1fdea8a6c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 8 Jul 2018 01:10:47 +0000 Subject: [PATCH 0441/1023] [X86] Add new scalar fma intrinsics with rounding mode that use f32/f64 types. This allows us to handle masking in a very similar way to the default rounding version that uses llvm.fma git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336507 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 75 ++++++-- test/CodeGen/avx512f-builtins.c | 300 ++++++++++++++++++++++++++++---- 2 files changed, 326 insertions(+), 49 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 3ebf584ac8..a0afb08653 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8718,6 +8718,47 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef Ops, return Res; } +static Value * +EmitScalarFMAExpr(CodeGenFunction &CGF, MutableArrayRef Ops, + Value *Upper, bool ZeroMask = false, unsigned PTIdx = 0, + bool NegAcc = false) { + unsigned Rnd = 4; + if (Ops.size() > 4) + Rnd = cast(Ops[4])->getZExtValue(); + + if (NegAcc) + Ops[2] = CGF.Builder.CreateFNeg(Ops[2]); + + Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], (uint64_t)0); + Ops[1] = CGF.Builder.CreateExtractElement(Ops[1], (uint64_t)0); + Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], (uint64_t)0); + Value *Res; + if (Rnd != 4) { + Intrinsic::ID IID = Ops[0]->getType()->getPrimitiveSizeInBits() == 32 ? + Intrinsic::x86_avx512_vfmadd_f32 : + Intrinsic::x86_avx512_vfmadd_f64; + Res = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID), + {Ops[0], Ops[1], Ops[2], Ops[4]}); + } else { + Function *FMA = CGF.CGM.getIntrinsic(Intrinsic::fma, Ops[0]->getType()); + Res = CGF.Builder.CreateCall(FMA, Ops.slice(0, 3)); + } + // If we have more than 3 arguments, we need to do masking. + if (Ops.size() > 3) { + Value *PassThru = ZeroMask ? Constant::getNullValue(Res->getType()) + : Ops[PTIdx]; + + // If we negated the accumulator and the its the PassThru value we need to + // bypass the negate. Conveniently Upper should be the same thing in this + // case. + if (NegAcc && PTIdx == 2) + PassThru = CGF.Builder.CreateExtractElement(Upper, (uint64_t)0); + + Res = EmitX86ScalarSelect(CGF, Ops[3], Res, PassThru); + } + return CGF.Builder.CreateInsertElement(Upper, Res, (uint64_t)0); +} + static Value *EmitX86Muldq(CodeGenFunction &CGF, bool IsSigned, ArrayRef Ops) { llvm::Type *Ty = Ops[0]->getType(); @@ -9141,24 +9182,24 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return EmitX86ConvertToMask(*this, Ops[0]); case X86::BI__builtin_ia32_vfmaddss3: - case X86::BI__builtin_ia32_vfmaddsd3: { - Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); - Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - Function *FMA = CGM.getIntrinsic(Intrinsic::fma, A->getType()); - Value *Res = Builder.CreateCall(FMA, {A, B, C} ); - return Builder.CreateInsertElement(Ops[0], Res, (uint64_t)0); - } + case X86::BI__builtin_ia32_vfmaddsd3: + case X86::BI__builtin_ia32_vfmaddss3_mask: + case X86::BI__builtin_ia32_vfmaddsd3_mask: + return EmitScalarFMAExpr(*this, Ops, Ops[0]); case X86::BI__builtin_ia32_vfmaddss: - case X86::BI__builtin_ia32_vfmaddsd: { - Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); - Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - Function *FMA = CGM.getIntrinsic(Intrinsic::fma, A->getType()); - Value *Res = Builder.CreateCall(FMA, {A, B, C} ); - Value *Zero = Constant::getNullValue(Ops[0]->getType()); - return Builder.CreateInsertElement(Zero, Res, (uint64_t)0); - } + case X86::BI__builtin_ia32_vfmaddsd: + return EmitScalarFMAExpr(*this, Ops, + Constant::getNullValue(Ops[0]->getType())); + case X86::BI__builtin_ia32_vfmaddss3_maskz: + case X86::BI__builtin_ia32_vfmaddsd3_maskz: + return EmitScalarFMAExpr(*this, Ops, Ops[0], /*ZeroMask*/true); + case X86::BI__builtin_ia32_vfmaddss3_mask3: + case X86::BI__builtin_ia32_vfmaddsd3_mask3: + return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2); + case X86::BI__builtin_ia32_vfmsubss3_mask3: + case X86::BI__builtin_ia32_vfmsubsd3_mask3: + return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2, + /*NegAcc*/true); case X86::BI__builtin_ia32_vfmaddps: case X86::BI__builtin_ia32_vfmaddpd: case X86::BI__builtin_ia32_vfmaddps256: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index d90f5d03ec..be5fcb207c 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -7232,13 +7232,24 @@ __m128 test_mm_mask_fmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0 return _mm_fmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7266,7 +7277,14 @@ __m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7295,7 +7313,14 @@ __m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7325,13 +7350,26 @@ __m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0 return _mm_fmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7360,7 +7398,15 @@ __m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ __m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7390,7 +7436,16 @@ __m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ __m128 test_mm_mask3_fmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7420,13 +7475,26 @@ __m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fnmadd_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0 return _mm_fnmadd_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fnmadd_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7455,7 +7523,15 @@ __m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fnmadd_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7485,7 +7561,15 @@ __m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fnmadd_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7516,13 +7600,28 @@ __m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_fnmsub_round_ss(__m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[FMA]], i64 0 return _mm_fnmsub_round_ss(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_fnmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fnmsub_round_ss(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7552,7 +7651,16 @@ __m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) __m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.maskz.vfmadd.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fnmsub_round_ss(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7583,7 +7691,17 @@ __m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) __m128 test_mm_mask3_fnmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_ss - // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.x86.avx512.vfmadd.f32(float [[A]], float [[B]], float [[C]], i32 8) + // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7612,13 +7730,24 @@ __m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ __m128d test_mm_fmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0 return _mm_fmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7646,7 +7775,14 @@ __m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7675,7 +7811,14 @@ __m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7705,13 +7848,26 @@ __m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __ __m128d test_mm_fmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0 return _mm_fmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7740,7 +7896,15 @@ __m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d _ __m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7770,7 +7934,16 @@ __m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 _ __m128d test_mm_mask3_fmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7800,13 +7973,26 @@ __m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ __m128d test_mm_fnmadd_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0 return _mm_fnmadd_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fnmadd_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7835,7 +8021,15 @@ __m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fnmadd_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7865,7 +8059,15 @@ __m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fnmadd_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7896,13 +8098,28 @@ __m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d _ __m128d test_mm_fnmsub_round_sd(__m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[FMA]], i64 0 return _mm_fnmsub_round_sd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_fnmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fnmsub_round_sd(__W, __U, __A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7932,7 +8149,16 @@ __m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.maskz.vfmadd.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fnmsub_round_sd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } @@ -7963,7 +8189,17 @@ __m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __m128d test_mm_mask3_fnmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_round_sd - // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.x86.avx512.vfmadd.f64(double [[A]], double [[B]], double [[C]], i32 8) + // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } -- GitLab From d3e19c829cf4adba7dacf8a93791104797626e3b Mon Sep 17 00:00:00 2001 From: Jacek Olesiak Date: Mon, 9 Jul 2018 05:58:51 +0000 Subject: [PATCH 0442/1023] [clang-format/ObjC] Fix counting selector name parts for ObjC Summary: Counts selector parts also for method declarations and counts correctly for methods without arguments. This is an internal change and doesn't influence formatting on its own (at the current state). Its lack would be visible after applying D48719. Reviewers: benhamilton, klimek Reviewed By: benhamilton Subscribers: acoomans, cfe-commits Differential Revision: https://reviews.llvm.org/D48716 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336518 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/FormatToken.h | 5 +++-- lib/Format/TokenAnnotator.cpp | 30 +++++++++++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index 7d13d09da7..f5047953af 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -243,8 +243,9 @@ struct FormatToken { /// e.g. because several of them are block-type. unsigned LongestObjCSelectorName = 0; - /// How many parts ObjC selector have (i.e. how many parameters method - /// has). + /// If this is the first ObjC selector name in an ObjC method + /// definition or call, this contains the number of parts that the whole + /// selector consist of. unsigned ObjCSelectorNameParts = 0; /// Stores the number of required fake parentheses and the diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index ec8d351725..b6127bc8d4 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -515,11 +515,23 @@ private: } Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; + // FirstObjCSelectorName is set when a colon is found. This does + // not work, however, when the method has no parameters. + // Here, we set FirstObjCSelectorName when the end of the method call is + // reached, in case it was not set already. + if (!Contexts.back().FirstObjCSelectorName) { + FormatToken* Previous = CurrentToken->getPreviousNonComment(); + if (Previous && Previous->is(TT_SelectorName)) { + Previous->ObjCSelectorNameParts = 1; + Contexts.back().FirstObjCSelectorName = Previous; + } + } else { + Left->ParameterCount = + Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; + } if (Contexts.back().FirstObjCSelectorName) { Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = Contexts.back().LongestObjCSelectorName; - Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts = - Left->ParameterCount; if (Left->BlockParameterCount > 1) Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0; } @@ -539,11 +551,6 @@ private: TT_DesignatedInitializerLSquare)) { Left->Type = TT_ObjCMethodExpr; StartsObjCMethodExpr = true; - // ParameterCount might have been set to 1 before expression was - // recognized as ObjCMethodExpr (as '1 + number of commas' formula is - // used for other expression types). Parameter counter has to be, - // therefore, reset to 0. - Left->ParameterCount = 0; Contexts.back().ColonIsObjCMethodExpr = true; if (Parent && Parent->is(tok::r_paren)) // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. @@ -617,12 +624,12 @@ private: } void updateParameterCount(FormatToken *Left, FormatToken *Current) { + // For ObjC methods, the number of parameters is calculated differently as + // method declarations have a different structure (the parameters are not + // inside a bracket scope). if (Current->is(tok::l_brace) && Current->BlockKind == BK_Block) ++Left->BlockParameterCount; - if (Left->Type == TT_ObjCMethodExpr) { - if (Current->is(tok::colon)) - ++Left->ParameterCount; - } else if (Current->is(tok::comma)) { + if (Current->is(tok::comma)) { ++Left->ParameterCount; if (!Left->Role) Left->Role.reset(new CommaSeparatedList(Style)); @@ -718,6 +725,7 @@ private: Contexts.back().LongestObjCSelectorName) Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth; + ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; } } else if (Contexts.back().ColonIsForRangeExpr) { Tok->Type = TT_RangeBasedForLoopColon; -- GitLab From 1e3b4b4fba6dcc8af4df69add4180e9e047f76e0 Mon Sep 17 00:00:00 2001 From: Jacek Olesiak Date: Mon, 9 Jul 2018 06:04:58 +0000 Subject: [PATCH 0443/1023] [clang-format/ObjC] Prohibit breaking after a bracket opening ObjC method expression Summary: Don't break after a "[" opening an ObjC method expression. Tests are added in D48719 where formatting is improved (to avoid adding and changing tests immediately). Reviewers: benhamilton, klimek Reviewed By: benhamilton Subscribers: acoomans, cfe-commits Differential Revision: https://reviews.llvm.org/D48718 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336519 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index bb8efd61a3..0862a4e0f9 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -321,6 +321,9 @@ bool ContinuationIndenter::canBreak(const LineState &State) { State.Stack.back().NoLineBreakInOperand) return false; + if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr)) + return false; + return !State.Stack.back().NoLineBreak; } -- GitLab From 33d0472e942860cca83bff49a8c65031a2e583c4 Mon Sep 17 00:00:00 2001 From: Jacek Olesiak Date: Mon, 9 Jul 2018 06:54:52 +0000 Subject: [PATCH 0444/1023] [clang-format/ObjC] Improve split priorities for ObjC methods Reduce penalty for aligning ObjC method arguments using the colon alignment as this is the canonical way. Trying to fit a whole expression into one line should not force other line breaks (e.g. when ObjC method expression is a part of other expression). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336520 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/FormatToken.h | 5 +++++ lib/Format/TokenAnnotator.cpp | 18 ++++++++++++++++-- unittests/Format/FormatTestObjC.cpp | 21 +++++++++++++++++++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h index f5047953af..9094e7689e 100644 --- a/lib/Format/FormatToken.h +++ b/lib/Format/FormatToken.h @@ -248,6 +248,11 @@ struct FormatToken { /// selector consist of. unsigned ObjCSelectorNameParts = 0; + /// The 0-based index of the parameter/argument. For ObjC it is set + /// for the selector name token. + /// For now calculated only for ObjC. + unsigned ParameterIndex = 0; + /// Stores the number of required fake parentheses and the /// corresponding operator precedence. /// diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index b6127bc8d4..3a19215e18 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -725,6 +725,8 @@ private: Contexts.back().LongestObjCSelectorName) Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth; + Tok->Previous->ParameterIndex = + Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts; } } else if (Contexts.back().ColonIsForRangeExpr) { @@ -2142,8 +2144,20 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { // FIXME: Only calculate this if CanBreakBefore is true once static // initializers etc. are sorted out. // FIXME: Move magic numbers to a better place. - Current->SplitPenalty = 20 * Current->BindingStrength + - splitPenalty(Line, *Current, InFunctionDecl); + + // Reduce penalty for aligning ObjC method arguments using the colon + // alignment as this is the canonical way (still prefer fitting everything + // into one line if possible). Trying to fit a whole expression into one + // line should not force other line breaks (e.g. when ObjC method + // expression is a part of other expression). + Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl); + if (Style.Language == FormatStyle::LK_ObjC && + Current->is(TT_SelectorName) && Current->ParameterIndex > 0) { + if (Current->ParameterIndex == 1) + Current->SplitPenalty += 5 * Current->BindingStrength; + } else { + Current->SplitPenalty += 20 * Current->BindingStrength; + } Current = Current->Next; } diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 9d086551b2..58e75363a5 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -678,6 +678,18 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { verifyFormat("[(id)foo bar:(id) ? baz : quux];"); verifyFormat("4 > 4 ? (id)a : (id)baz;"); + unsigned PreviousColumnLimit = Style.ColumnLimit; + Style.ColumnLimit = 50; + // Instead of: + // bool a = + // ([object a:42] == 0 || [object a:42 + // b:42] == 0); + verifyFormat("bool a = ([object a:42] == 0 ||\n" + " [object a:42 b:42] == 0);"); + Style.ColumnLimit = PreviousColumnLimit; + verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n" + " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);"); + // This tests that the formatter doesn't break after "backing" but before ":", // which would be at 80 columns. verifyFormat( @@ -754,11 +766,10 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { "[self aaaaaaaaaaaaa:aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaa, aaaaaaaaaaaaaaa];"); + verifyFormat("[self // break\n" " a:a\n" " aaa:aaa];"); - verifyFormat("bool a = ([aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaa ||\n" - " [aaaaaaaa aaaaa] == aaaaaaaaaaaaaaaaaaaa);"); // Formats pair-parameters. verifyFormat("[I drawRectOn:surface ofSize:aa:bbb atOrigin:cc:dd];"); @@ -803,6 +814,12 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { verifyFormat("[((Foo *)foo) bar];"); verifyFormat("[((Foo *)foo) bar:1 blech:2];"); + Style.ColumnLimit = 20; + verifyFormat("aaaaa = [a aa:aa\n" + " aa:aa];"); + verifyFormat("aaaaaa = [aa aa:aa\n" + " aa:aa];"); + Style.ColumnLimit = 70; verifyFormat( "void f() {\n" -- GitLab From 15e70438359dad2206c30f87afc1c4f6cb063b5e Mon Sep 17 00:00:00 2001 From: Jacek Olesiak Date: Mon, 9 Jul 2018 07:08:45 +0000 Subject: [PATCH 0445/1023] [clang-format/ObjC] Put ObjC method arguments into one line when they fit Reapply D47195: Currently BreakBeforeParameter is set to true everytime message receiver spans multiple lines, e.g.: ``` [[object block:^{ return 42; }] aa:42 bb:42]; ``` will be formatted: ``` [[object block:^{ return 42; }] aa:42 bb:42]; ``` even though arguments could fit into one line. This change fixes this behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336521 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 24 +++++++++++++++++ unittests/Format/FormatTestObjC.cpp | 42 +++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 0862a4e0f9..90d2a99971 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -1398,6 +1398,30 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) { (Current.is(tok::greater) && Current.is(TT_DictLiteral)))) State.Stack.pop_back(); + // Reevaluate whether ObjC message arguments fit into one line. + // If a receiver spans multiple lines, e.g.: + // [[object block:^{ + // return 42; + // }] a:42 b:42]; + // BreakBeforeParameter is calculated based on an incorrect assumption + // (it is checked whether the whole expression fits into one line without + // considering a line break inside a message receiver). + // We check whether arguements fit after receiver scope closer (into the same + // line). + if (State.Stack.back().BreakBeforeParameter && Current.MatchingParen && + Current.MatchingParen->Previous) { + const FormatToken &CurrentScopeOpener = *Current.MatchingParen->Previous; + if (CurrentScopeOpener.is(TT_ObjCMethodExpr) && + CurrentScopeOpener.MatchingParen) { + int NecessarySpaceInLine = + getLengthToMatchingParen(CurrentScopeOpener, State.Stack) + + CurrentScopeOpener.TotalLength - Current.TotalLength - 1; + if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <= + Style.ColumnLimit) + State.Stack.back().BreakBeforeParameter = false; + } + } + if (Current.is(tok::r_square)) { // If this ends the array subscript expr, reset the corresponding value. const FormatToken *NextNonComment = Current.getNextNonComment(); diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 58e75363a5..e56df6d130 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -820,6 +820,48 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) { verifyFormat("aaaaaa = [aa aa:aa\n" " aa:aa];"); + // Message receiver taking multiple lines. + // Non-corner case. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] a:42 b:42];"); + // Arguments just fit into one line. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] aaaaaaa:42 b:42];"); + // Arguments just over a column limit. + verifyFormat("[[object block:^{\n" + " return 42;\n" + "}] aaaaaaa:42\n" + " bb:42];"); + // Arguments just fit into one line. + Style.ColumnLimit = 23; + verifyFormat("[[obj a:42\n" + " b:42\n" + " c:42\n" + " d:42] e:42 f:42];"); + + // Arguments do not fit into one line with a receiver. + Style.ColumnLimit = 20; + verifyFormat("[[obj a:42] a:42\n" + " b:42];"); + verifyFormat("[[obj a:42] a:42\n" + " b:42\n" + " c:42];"); + verifyFormat("[[obj aaaaaa:42\n" + " b:42]\n" + " cc:42\n" + " d:42];"); + + // Avoid breaking receiver expression. + Style.ColumnLimit = 30; + verifyFormat("fooooooo =\n" + " [[obj fooo] aaa:42\n" + " aaa:42];"); + verifyFormat("[[[obj foo] bar] aa:42\n" + " bb:42\n" + " cc:42];"); + Style.ColumnLimit = 70; verifyFormat( "void f() {\n" -- GitLab From 72faa33b45d4a43de5587623948b1635059a5ab5 Mon Sep 17 00:00:00 2001 From: Rafael Stahl Date: Mon, 9 Jul 2018 08:40:17 +0000 Subject: [PATCH 0446/1023] [ASTImporter] import FunctionDecl end locations Summary: On constructors that do not take the end source location, it was not imported. Fixes test from D47698 / rC336269. Reviewers: martong, a.sidorin, balazske, xazax.hun, a_sidorin Reviewed By: martong, a_sidorin Subscribers: a_sidorin, rnkovacs, cfe-commits Differential Revision: https://reviews.llvm.org/D48941 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336523 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 5 +++-- unittests/AST/ASTImporterTest.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 759f9da30b..0e3756265e 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2554,7 +2554,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { D->isInlineSpecified(), FromConversion->isExplicit(), D->isConstexpr(), - Importer.Import(D->getLocEnd())); + SourceLocation()); } else if (auto *Method = dyn_cast(D)) { ToFunction = CXXMethodDecl::Create(Importer.getToContext(), cast(DC), @@ -2563,7 +2563,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Method->getStorageClass(), Method->isInlineSpecified(), D->isConstexpr(), - Importer.Import(D->getLocEnd())); + SourceLocation()); } else { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, InnerLocStart, @@ -2580,6 +2580,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); + ToFunction->setRangeEnd(Importer.Import(D->getLocEnd())); Importer.Imported(D, ToFunction); // Set the parameters. diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 1f86b91a88..34ed5b93a8 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -1620,7 +1620,7 @@ TEST_P(ASTImporterTestBase, ImportSourceLocs) { FromSM); } -TEST_P(ASTImporterTestBase, DISABLED_ImportNestedMacro) { +TEST_P(ASTImporterTestBase, ImportNestedMacro) { Decl *FromTU = getTuDecl( R"( #define FUNC_INT void declToImport -- GitLab From 8576df59f2fe52ae305fdb91b36cbed8946981a1 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Mon, 9 Jul 2018 08:44:05 +0000 Subject: [PATCH 0447/1023] [Index] Add indexing support for MACROs. Reviewers: akyrtzi, arphaman, sammccall Reviewed By: sammccall Subscribers: malaperle, sammccall, cfe-commits Differential Revision: https://reviews.llvm.org/D48961 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336524 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/IndexSymbol.h | 44 +++++----- include/clang/Index/IndexingAction.h | 13 +++ lib/Index/IndexSymbol.cpp | 12 +++ lib/Index/IndexingAction.cpp | 116 +++++++++++++++++++-------- lib/Index/IndexingContext.cpp | 23 ++++++ lib/Index/IndexingContext.h | 11 +++ test/Index/Core/index-macros.c | 12 +++ tools/c-index-test/core_main.cpp | 38 +++++++++ 8 files changed, 216 insertions(+), 53 deletions(-) create mode 100644 test/Index/Core/index-macros.c diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 3355dd2f28..1e8439ed5a 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_INDEXSYMBOL_H #include "clang/Basic/LLVM.h" +#include "clang/Lex/MacroInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/DataTypes.h" @@ -93,28 +94,31 @@ static const unsigned SymbolPropertyBitNum = 8; /// Low 9 bits of clang-c/include/Index.h CXSymbolRole mirrors this enum. enum class SymbolRole : uint32_t { Declaration = 1 << 0, - Definition = 1 << 1, - Reference = 1 << 2, - Read = 1 << 3, - Write = 1 << 4, - Call = 1 << 5, - Dynamic = 1 << 6, - AddressOf = 1 << 7, - Implicit = 1 << 8, + Definition = 1 << 1, + Reference = 1 << 2, + Read = 1 << 3, + Write = 1 << 4, + Call = 1 << 5, + Dynamic = 1 << 6, + AddressOf = 1 << 7, + Implicit = 1 << 8, + // FIXME: this is not mirrored in CXSymbolRole. + // Note that macro occurrences aren't currently supported in libclang. + Undefinition = 1 << 9, // macro #undef // Relation roles. - RelationChildOf = 1 << 9, - RelationBaseOf = 1 << 10, - RelationOverrideOf = 1 << 11, - RelationReceivedBy = 1 << 12, - RelationCalledBy = 1 << 13, - RelationExtendedBy = 1 << 14, - RelationAccessorOf = 1 << 15, - RelationContainedBy = 1 << 16, - RelationIBTypeOf = 1 << 17, - RelationSpecializationOf = 1 << 18, + RelationChildOf = 1 << 10, + RelationBaseOf = 1 << 11, + RelationOverrideOf = 1 << 12, + RelationReceivedBy = 1 << 13, + RelationCalledBy = 1 << 14, + RelationExtendedBy = 1 << 15, + RelationAccessorOf = 1 << 16, + RelationContainedBy = 1 << 17, + RelationIBTypeOf = 1 << 18, + RelationSpecializationOf = 1 << 19, }; -static const unsigned SymbolRoleBitNum = 19; +static const unsigned SymbolRoleBitNum = 20; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. @@ -135,6 +139,8 @@ struct SymbolInfo { SymbolInfo getSymbolInfo(const Decl *D); +SymbolInfo getSymbolInfoForMacro(const MacroInfo &MI); + bool isFunctionLocalSymbol(const Decl *D); void applyForEachSymbolRole(SymbolRoleSet Roles, diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h index 98e2455417..48385b396f 100644 --- a/include/clang/Index/IndexingAction.h +++ b/include/clang/Index/IndexingAction.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_INDEXINGACTION_H #include "clang/Basic/LLVM.h" +#include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/ArrayRef.h" #include @@ -40,18 +41,30 @@ struct IndexingOptions { bool IndexFunctionLocals = false; }; +/// Creates a frontend action that indexes all symbols (macros and AST decls). /// \param WrappedAction another frontend action to wrap over or null. std::unique_ptr createIndexingAction(std::shared_ptr DataConsumer, IndexingOptions Opts, std::unique_ptr WrappedAction); +/// Recursively indexes all decls in the AST. +/// Note that this does not index macros. void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer, IndexingOptions Opts); +/// Recursively indexes \p Decls. +/// Note that this does not index macros. void indexTopLevelDecls(ASTContext &Ctx, ArrayRef Decls, IndexDataConsumer &DataConsumer, IndexingOptions Opts); +/// Creates a PPCallbacks that indexes macros and feeds macros to \p Consumer. +/// The caller is responsible for calling `Consumer.setPreprocessor()`. +std::unique_ptr indexMacrosCallback(IndexDataConsumer &Consumer, + IndexingOptions Opts); + +/// Recursively indexes all top-level decls in the module. +/// FIXME: make this index macros as well. void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader, IndexDataConsumer &DataConsumer, IndexingOptions Opts); diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index 733d4dbc2f..03b55ffe8a 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -12,6 +12,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/Lex/MacroInfo.h" using namespace clang; using namespace clang::index; @@ -348,6 +349,15 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { return Info; } +SymbolInfo index::getSymbolInfoForMacro(const MacroInfo &) { + SymbolInfo Info; + Info.Kind = SymbolKind::Macro; + Info.SubKind = SymbolSubKind::None; + Info.Properties = SymbolPropertySet(); + Info.Lang = SymbolLanguage::C; + return Info; +} + bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, llvm::function_ref Fn) { #define APPLY_FOR_ROLE(Role) \ @@ -364,6 +374,7 @@ bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, APPLY_FOR_ROLE(Dynamic); APPLY_FOR_ROLE(AddressOf); APPLY_FOR_ROLE(Implicit); + APPLY_FOR_ROLE(Undefinition); APPLY_FOR_ROLE(RelationChildOf); APPLY_FOR_ROLE(RelationBaseOf); APPLY_FOR_ROLE(RelationOverrideOf); @@ -405,6 +416,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { case SymbolRole::Dynamic: OS << "Dyn"; break; case SymbolRole::AddressOf: OS << "Addr"; break; case SymbolRole::Implicit: OS << "Impl"; break; + case SymbolRole::Undefinition: OS << "Undef"; break; case SymbolRole::RelationChildOf: OS << "RelChild"; break; case SymbolRole::RelationBaseOf: OS << "RelBase"; break; case SymbolRole::RelationOverrideOf: OS << "RelOver"; break; diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp index e378a092be..b8faf7075e 100644 --- a/lib/Index/IndexingAction.cpp +++ b/lib/Index/IndexingAction.cpp @@ -13,8 +13,11 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Index/IndexDataConsumer.h" +#include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/STLExtras.h" +#include using namespace clang; using namespace clang::index; @@ -43,21 +46,22 @@ namespace { class IndexASTConsumer : public ASTConsumer { std::shared_ptr PP; - IndexingContext &IndexCtx; + std::shared_ptr IndexCtx; public: - IndexASTConsumer(std::shared_ptr PP, IndexingContext &IndexCtx) - : PP(std::move(PP)), IndexCtx(IndexCtx) {} + IndexASTConsumer(std::shared_ptr PP, + std::shared_ptr IndexCtx) + : PP(std::move(PP)), IndexCtx(std::move(IndexCtx)) {} protected: void Initialize(ASTContext &Context) override { - IndexCtx.setASTContext(Context); - IndexCtx.getDataConsumer().initialize(Context); - IndexCtx.getDataConsumer().setPreprocessor(PP); + IndexCtx->setASTContext(Context); + IndexCtx->getDataConsumer().initialize(Context); + IndexCtx->getDataConsumer().setPreprocessor(PP); } bool HandleTopLevelDecl(DeclGroupRef DG) override { - return IndexCtx.indexDeclGroupRef(DG); + return IndexCtx->indexDeclGroupRef(DG); } void HandleInterestingDecl(DeclGroupRef DG) override { @@ -65,22 +69,50 @@ protected: } void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { - IndexCtx.indexDeclGroupRef(DG); + IndexCtx->indexDeclGroupRef(DG); } void HandleTranslationUnit(ASTContext &Ctx) override { } }; +class IndexPPCallbacks : public PPCallbacks { + std::shared_ptr IndexCtx; + +public: + IndexPPCallbacks(std::shared_ptr IndexCtx) + : IndexCtx(std::move(IndexCtx)) {} + + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range, const MacroArgs *Args) override { + IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(), + Range.getBegin(), *MD.getMacroInfo()); + } + + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override { + IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD->getMacroInfo()); + } + + void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, + const MacroDirective *Undef) override { + IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD.getMacroInfo()); + } +}; + class IndexActionBase { protected: std::shared_ptr DataConsumer; - IndexingContext IndexCtx; + std::shared_ptr IndexCtx; IndexActionBase(std::shared_ptr dataConsumer, IndexingOptions Opts) - : DataConsumer(std::move(dataConsumer)), - IndexCtx(Opts, *DataConsumer) {} + : DataConsumer(std::move(dataConsumer)), + IndexCtx(new IndexingContext(Opts, *DataConsumer)) {} std::unique_ptr createIndexASTConsumer(CompilerInstance &CI) { @@ -88,6 +120,10 @@ protected: IndexCtx); } + std::unique_ptr createIndexPPCallbacks() { + return llvm::make_unique(IndexCtx); + } + void finish() { DataConsumer->finish(); } @@ -105,6 +141,11 @@ protected: return createIndexASTConsumer(CI); } + bool BeginSourceFileAction(clang::CompilerInstance &CI) override { + CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks()); + return true; + } + void EndSourceFileAction() override { FrontendAction::EndSourceFileAction(); finish(); @@ -123,32 +164,34 @@ public: protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; - void EndSourceFileAction() override; -}; - -} // anonymous namespace + StringRef InFile) override { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) { + IndexActionFailed = true; + return nullptr; + } + + std::vector> Consumers; + Consumers.push_back(std::move(OtherConsumer)); + Consumers.push_back(createIndexASTConsumer(CI)); + return llvm::make_unique(std::move(Consumers)); + } -void WrappingIndexAction::EndSourceFileAction() { - // Invoke wrapped action's method. - WrapperFrontendAction::EndSourceFileAction(); - if (!IndexActionFailed) - finish(); -} + bool BeginSourceFileAction(clang::CompilerInstance &CI) override { + WrapperFrontendAction::BeginSourceFileAction(CI); + CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks()); + return true; + } -std::unique_ptr -WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); - if (!OtherConsumer) { - IndexActionFailed = true; - return nullptr; + void EndSourceFileAction() override { + // Invoke wrapped action's method. + WrapperFrontendAction::EndSourceFileAction(); + if (!IndexActionFailed) + finish(); } +}; - std::vector> Consumers; - Consumers.push_back(std::move(OtherConsumer)); - Consumers.push_back(createIndexASTConsumer(CI)); - return llvm::make_unique(std::move(Consumers)); -} +} // anonymous namespace std::unique_ptr index::createIndexingAction(std::shared_ptr DataConsumer, @@ -161,7 +204,6 @@ index::createIndexingAction(std::shared_ptr DataConsumer, return llvm::make_unique(std::move(DataConsumer), Opts); } - static bool topLevelDeclVisitor(void *context, const Decl *D) { IndexingContext &IndexCtx = *static_cast(context); return IndexCtx.indexTopLevelDecl(D); @@ -193,6 +235,12 @@ void index::indexTopLevelDecls(ASTContext &Ctx, ArrayRef Decls, DataConsumer.finish(); } +std::unique_ptr +index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) { + return llvm::make_unique( + std::make_shared(Opts, Consumer)); +} + void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader, IndexDataConsumer &DataConsumer, IndexingOptions Opts) { diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index 97b3e10450..71b92bc6bf 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "IndexingContext.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" @@ -290,6 +291,7 @@ static bool shouldReportOccurrenceForSystemDeclOnlyMode( case SymbolRole::Dynamic: case SymbolRole::AddressOf: case SymbolRole::Implicit: + case SymbolRole::Undefinition: case SymbolRole::RelationReceivedBy: case SymbolRole::RelationCalledBy: case SymbolRole::RelationContainedBy: @@ -406,3 +408,24 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC}; return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node); } + +void IndexingContext::handleMacroDefined(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Definition; + DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); +} + +void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition; + DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); +} + +void IndexingContext::handleMacroReference(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Reference; + DataConsumer.handleMacroOccurence(&Name, &MI, Roles, Loc); +} diff --git a/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h index 566651c83a..f05eaae696 100644 --- a/lib/Index/IndexingContext.h +++ b/lib/Index/IndexingContext.h @@ -10,9 +10,11 @@ #ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H #define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/IndexingAction.h" +#include "clang/Lex/MacroInfo.h" #include "llvm/ADT/ArrayRef.h" namespace clang { @@ -80,6 +82,15 @@ public: const Expr *RefE = nullptr, const Decl *RefD = nullptr); + void handleMacroDefined(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MI); + + void handleMacroUndefined(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MI); + + void handleMacroReference(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MD); + bool importedModule(const ImportDecl *ImportD); bool indexDecl(const Decl *D); diff --git a/test/Index/Core/index-macros.c b/test/Index/Core/index-macros.c new file mode 100644 index 0000000000..9e38c44e99 --- /dev/null +++ b/test/Index/Core/index-macros.c @@ -0,0 +1,12 @@ +// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s + +// CHECK: [[@LINE+1]]:9 | macro/C | X1 | c:index-macros.c@157@macro@X1 | Def | +#define X1 1 +// CHECK: [[@LINE+1]]:9 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Def | +#define DEF(x) int x +// CHECK: [[@LINE+1]]:8 | macro/C | X1 | c:index-macros.c@157@macro@X1 | Undef | +#undef X1 + +// CHECK: [[@LINE+2]]:1 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Ref | +// CHECK: [[@LINE+1]]:5 | variable/C | i | c:@i | i | Def | rel: 0 +DEF(i); diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp index 6093df5285..a7732c09d5 100644 --- a/tools/c-index-test/core_main.cpp +++ b/tools/c-index-test/core_main.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/LangOptions.h" #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" @@ -16,6 +17,7 @@ #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/USRGeneration.h" #include "clang/Index/CodegenNameGenerator.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" @@ -77,6 +79,7 @@ namespace { class PrintIndexDataConsumer : public IndexDataConsumer { raw_ostream &OS; std::unique_ptr CGNameGen; + std::shared_ptr PP; public: PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) { @@ -86,6 +89,10 @@ public: CGNameGen.reset(new CodegenNameGenerator(Ctx)); } + void setPreprocessor(std::shared_ptr PP) override { + this->PP = std::move(PP); + } + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, SourceLocation Loc, ASTNodeInfo ASTNode) override { @@ -145,6 +152,37 @@ public: return true; } + + bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, + SymbolRoleSet Roles, SourceLocation Loc) override { + assert(PP); + SourceManager &SM = PP->getSourceManager(); + + Loc = SM.getFileLoc(Loc); + FileID FID = SM.getFileID(Loc); + unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc)); + unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc)); + OS << Line << ':' << Col << " | "; + + printSymbolInfo(getSymbolInfoForMacro(*MI), OS); + OS << " | "; + + OS << Name->getName(); + OS << " | "; + + SmallString<256> USRBuf; + if (generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM, + USRBuf)) { + OS << ""; + } else { + OS << USRBuf; + } + OS << " | "; + + printSymbolRoles(Roles, OS); + OS << " |\n"; + return true; + } }; } // anonymous namespace -- GitLab From d7f8ffeea4699cbf87133dc75c1cfeda85d5ff68 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 9 Jul 2018 08:54:42 +0000 Subject: [PATCH 0448/1023] [Index] Add clangLex to LINK_LIBS Without this, builds with `-DSHARED_LIB=ON` fail. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336526 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Index/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt index c9fbfafcf9..1362143fb0 100644 --- a/lib/Index/CMakeLists.txt +++ b/lib/Index/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangIndex clangBasic clangFormat clangFrontend + clangLex clangRewrite clangSerialization clangToolingCore -- GitLab From a92e7cfddc69074e8adbd414e65a76be030df405 Mon Sep 17 00:00:00 2001 From: Rafael Stahl Date: Mon, 9 Jul 2018 09:02:53 +0000 Subject: [PATCH 0449/1023] [ASTImporter] fix test failure corrected by fixed func end locs fix to rC336523 / D48941 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336527 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Import/attr/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Import/attr/test.cpp b/test/Import/attr/test.cpp index 01ea6c1b0e..c9b2d6ed34 100644 --- a/test/Import/attr/test.cpp +++ b/test/Import/attr/test.cpp @@ -1,6 +1,6 @@ // RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s // CHECK: FunctionDecl -// CHECK-SAME: S.cpp:1:1, col:13 +// CHECK-SAME: S.cpp:1:1, col:38 // CHECK-NEXT: ConstAttr // CHECK-SAME: col:32 -- GitLab From d46ee151e6630cd8d1866f4f1619a0e10e7c1637 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Mon, 9 Jul 2018 09:07:01 +0000 Subject: [PATCH 0450/1023] [Preamble] Check system dependencies in preamble too Summary: PrecompiledPreamble hasn't checked if the system dependencies changed before. This resulted in invalid preamble not being rebuilt if headers that changed were found in -isystem include paths. This pattern is sometimes used to avoid showing warnings in third party code, so we want to correctly handle those cases. Tested in clangd, see the follow-up patch. Reviewers: sammccall, ioeric Reviewed By: sammccall Subscribers: omtcyfz, cfe-commits Differential Revision: https://reviews.llvm.org/D48946 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336528 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Frontend/PrecompiledPreamble.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp index 23371d1f42..30ae2db26d 100644 --- a/lib/Frontend/PrecompiledPreamble.cpp +++ b/lib/Frontend/PrecompiledPreamble.cpp @@ -63,6 +63,16 @@ createVFSOverlayForPreamblePCH(StringRef PCHFilename, return Overlay; } +class PreambleDependencyCollector : public DependencyCollector { +public: + // We want to collect all dependencies for correctness. Avoiding the real + // system dependencies (e.g. stl from /usr/lib) would probably be a good idea, + // but there is no way to distinguish between those and the ones that can be + // spuriously added by '-isystem' (e.g. to suppress warnings from those + // headers). + bool needSystemDependencies() override { return true; } +}; + /// Keeps a track of files to be deleted in destructor. class TemporaryFiles { public: @@ -311,7 +321,7 @@ llvm::ErrorOr PrecompiledPreamble::Build( Clang->setSourceManager( new SourceManager(Diagnostics, Clang->getFileManager())); - auto PreambleDepCollector = std::make_shared(); + auto PreambleDepCollector = std::make_shared(); Clang->addDependencyCollector(PreambleDepCollector); // Remap the main source file to the preamble buffer. -- GitLab From 9ac30449eb6ff992f22e86c42ea7d626e4ef6973 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Mon, 9 Jul 2018 09:17:25 +0000 Subject: [PATCH 0451/1023] Try to fix build bot after r336524 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336532 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/Core/index-macros.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Index/Core/index-macros.c b/test/Index/Core/index-macros.c index 9e38c44e99..61e7e76175 100644 --- a/test/Index/Core/index-macros.c +++ b/test/Index/Core/index-macros.c @@ -8,5 +8,5 @@ #undef X1 // CHECK: [[@LINE+2]]:1 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Ref | -// CHECK: [[@LINE+1]]:5 | variable/C | i | c:@i | i | Def | rel: 0 +// CHECK: [[@LINE+1]]:5 | variable/C | i | c:@i | {{.*}} | Def | rel: 0 DEF(i); -- GitLab From b5784f85be57b6010e656f881e64ac3d2ad25f6a Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Mon, 9 Jul 2018 11:33:23 +0000 Subject: [PATCH 0452/1023] [PCH] Add an option to not write comments into PCH Summary: Will be used in clangd, see the follow-up change. Clangd does not use comments read from PCH to avoid crashes due to changed contents of the file. However, reading them considerably slows down code completion on files with large preambles. Reviewers: sammccall Reviewed By: sammccall Subscribers: ioeric, cfe-commits Differential Revision: https://reviews.llvm.org/D48942 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336539 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/PreprocessorOptions.h | 5 +++++ lib/Serialization/ASTWriter.cpp | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index f4ec2f27c4..3d7e5ab4a8 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -95,6 +95,11 @@ public: /// processing the rest of the file. bool GeneratePreamble = false; + /// Whether to write comment locations into the PCH when building it. + /// Reading the comments from the PCH can be a performance hit even if the + /// clients don't use them. + bool WriteCommentListToPCH = true; + /// The implicit PTH input included at the start of the translation unit, or /// empty. std::string ImplicitPTHInclude; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 279960a129..bc569d17f2 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -78,6 +78,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -3252,6 +3253,9 @@ void ASTWriter::WriteFileDeclIDsMap() { void ASTWriter::WriteComments() { Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3); + auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); }); + if (!PP->getPreprocessorOpts().WriteCommentListToPCH) + return; ArrayRef RawComments = Context->Comments.getComments(); RecordData Record; for (const auto *I : RawComments) { @@ -3262,7 +3266,6 @@ void ASTWriter::WriteComments() { Record.push_back(I->isAlmostTrailingComment()); Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record); } - Stream.ExitBlock(); } //===----------------------------------------------------------------------===// -- GitLab From 4a1455fb1c852ecc711d694480cd65eb98b37ad1 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 9 Jul 2018 17:43:58 +0000 Subject: [PATCH 0453/1023] [OPENMP, NVPTX] Do not globalize local variables in parallel regions. In generic data-sharing mode we are allowed to not globalize local variables that escape their declaration context iff they are declared inside of the parallel region. We can do this because L2 parallel regions are executed sequentially and, thus, we do not need to put shared local variables in the global memory. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336567 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 13 ++------ .../declare_target_codegen_globalization.cpp | 7 ++--- test/OpenMP/nvptx_data_sharing.cpp | 7 ++--- ...stribute_parallel_generic_mode_codegen.cpp | 4 +-- ...bute_parallel_for_generic_mode_codegen.cpp | 31 +++++++++++++------ 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 8cf5bb2f44..0ef093fd05 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -1554,29 +1554,22 @@ void CGOpenMPRuntimeNVPTX::emitNumTeamsClause(CodeGenFunction &CGF, llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction( const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { - SourceLocation Loc = D.getLocStart(); - // Emit target region as a standalone region. class NVPTXPrePostActionTy : public PrePostActionTy { - SourceLocation &Loc; bool &IsInParallelRegion; bool PrevIsInParallelRegion; public: - NVPTXPrePostActionTy(SourceLocation &Loc, bool &IsInParallelRegion) - : Loc(Loc), IsInParallelRegion(IsInParallelRegion) {} + NVPTXPrePostActionTy(bool &IsInParallelRegion) + : IsInParallelRegion(IsInParallelRegion) {} void Enter(CodeGenFunction &CGF) override { - static_cast(CGF.CGM.getOpenMPRuntime()) - .emitGenericVarsProlog(CGF, Loc); PrevIsInParallelRegion = IsInParallelRegion; IsInParallelRegion = true; } void Exit(CodeGenFunction &CGF) override { IsInParallelRegion = PrevIsInParallelRegion; - static_cast(CGF.CGM.getOpenMPRuntime()) - .emitGenericVarsEpilog(CGF); } - } Action(Loc, IsInParallelRegion); + } Action(IsInParallelRegion); CodeGen.setAction(Action); bool PrevIsInTargetMasterThreadRegion = IsInTargetMasterThreadRegion; IsInTargetMasterThreadRegion = false; diff --git a/test/OpenMP/declare_target_codegen_globalization.cpp b/test/OpenMP/declare_target_codegen_globalization.cpp index c8a0f7a3e3..7ef4f8af3d 100644 --- a/test/OpenMP/declare_target_codegen_globalization.cpp +++ b/test/OpenMP/declare_target_codegen_globalization.cpp @@ -24,12 +24,11 @@ int maini1() { // parallel region // CHECK: define {{.*}}void @{{.*}}(i32* noalias {{.*}}, i32* noalias {{.*}}, i32* dereferenceable{{.*}}) -// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0) -// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_ST:%struct[.].*]]* -// CHECK: [[B_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_ST]], [[GLOBAL_ST]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack( +// CHECK: [[B_ADDR:%.+]] = alloca i32, // CHECK: call {{.*}}[[FOO:@.*foo.*]](i32* dereferenceable{{.*}} [[B_ADDR]]) // CHECK: call {{.*}}[[BAR:@.*bar.*]]() -// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]]) +// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack( // CHECK: ret void // CHECK: define {{.*}}[[FOO]](i32* dereferenceable{{.*}}) diff --git a/test/OpenMP/nvptx_data_sharing.cpp b/test/OpenMP/nvptx_data_sharing.cpp index 634681b2f7..eb0acde299 100644 --- a/test/OpenMP/nvptx_data_sharing.cpp +++ b/test/OpenMP/nvptx_data_sharing.cpp @@ -83,11 +83,10 @@ void test_ds(){ /// outlined function for the second parallel region /// // CK1: define internal void @{{.+}}(i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable{{.+}}, i32* dereferenceable{{.+}}) -// CK1: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i64 4, i16 0) -// CK1: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_TY:%.+]]* -// CK1: [[C_ADDR:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i32 0, i32 0 +// CK1-NOT: call i8* @__kmpc_data_sharing_push_stack( +// CK1: [[C_ADDR:%.+]] = alloca i32, // CK1: store i32* [[C_ADDR]], i32** % -// CK1: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]]) +// CK1i-NOT: call void @__kmpc_data_sharing_pop_stack( /// ========= In the data sharing wrapper function ========= /// diff --git a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp index 5dc440e46d..2b18f6d3f9 100644 --- a/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp +++ b/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp @@ -44,8 +44,8 @@ int main(int argc, char **argv) { // CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]]) // CHECK: define internal void [[PARALLEL]]( -// CHECK: [[PTR:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 4, i16 0) +// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack( -// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[PTR]]) +// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack( #endif diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp index 2e712e2d51..d75a102109 100644 --- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp +++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp @@ -34,20 +34,33 @@ int main(int argc, char **argv) { // CHECK: call void @__kmpc_spmd_kernel_deinit() -// CHECK: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i32* dereferenceable{{.*}}) -// CHECK: [[RES:%.+]] = call i8* @__kmpc_data_sharing_push_stack(i{{64|32}} 8, i16 0) -// CHECK: [[GLOBALS:%.+]] = bitcast i8* [[RES]] to [[GLOBAL_TY:%.+]]* -// CHECK: [[I:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 -// CHECK: [[ARGC_VAL:%.+]] = load i32, i32* % -// CHECK: [[ARGC:%.+]] = getelementptr inbounds [[GLOBAL_TY]], [[GLOBAL_TY]]* [[GLOBALS]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 -// CHECK: store i32 [[ARGC_VAL]], i32* [[ARGC]], +// CHECK: define internal void [[PARALLEL]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} %{{.+}}, i{{64|32}} [[ARGC:%.+]], i32* dereferenceable{{.*}}) +// CHECK-NOT: call i8* @__kmpc_data_sharing_push_stack( +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[ARGC_ADDR:%.+]] = alloca i{{32|64}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[I:%.+]] = alloca i32, +// CHECK-32: store i32 [[ARGC]], i32* [[ARGC_ADDR]], +// CHECK-64: store i{{64|32}} [[ARGC]], i{{64|32}}* [[ARGC_ADDR]], +// CHECK-64: [[ARGC:%.+]] = bitcast i64* [[ARGC_ADDR]] to i32* // CHECK: call void @__kmpc_for_static_init_4( // CHECK: call i32 [[FOO:@.+foo.+]](i32* [[I]]) // CHECK: call i32 [[FOO]](i32* %{{.+}}) -// CHECK: call i32 [[FOO]](i32* [[ARGC]]) +// CHECK-32: call i32 [[FOO]](i32* [[ARGC_ADDR]]) +// CHECK-64: call i32 [[FOO]](i32* [[ARGC]]) // CHECK: call void @__kmpc_for_static_fini( -// CHECK: call void @__kmpc_data_sharing_pop_stack(i8* [[RES]]) +// CHECK-NOT: call void @__kmpc_data_sharing_pop_stack( #endif -- GitLab From b5e377665ba2ae38aa94f4c671411b56af826077 Mon Sep 17 00:00:00 2001 From: Stefan Pintilie Date: Mon, 9 Jul 2018 18:50:40 +0000 Subject: [PATCH 0454/1023] [Power9] Add __float128 builtins for Round To Odd Add a number of builtins for __float128 Round To Odd. This is the Clang portion of the builtins work. Differential Revision: https://reviews.llvm.org/D47548 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336579 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsPPC.def | 8 +++++ test/CodeGen/builtins-ppc-p9-f128.c | 45 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 test/CodeGen/builtins-ppc-p9-f128.c diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index faa70a48ed..e3d71385eb 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -423,6 +423,14 @@ BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "") BUILTIN(__builtin_vsx_xxpermdi, "v.", "t") BUILTIN(__builtin_vsx_xxsldwi, "v.", "t") +// Float 128 built-ins +BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "") +BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "") + // HTM builtins BUILTIN(__builtin_tbegin, "UiUIi", "") BUILTIN(__builtin_tend, "UiUIi", "") diff --git a/test/CodeGen/builtins-ppc-p9-f128.c b/test/CodeGen/builtins-ppc-p9-f128.c new file mode 100644 index 0000000000..c0e8f6485c --- /dev/null +++ b/test/CodeGen/builtins-ppc-p9-f128.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm \ +// RUN: -target-cpu pwr9 -target-feature +float128 -o - %s | FileCheck %s + +__float128 A; +__float128 B; +__float128 C; + + +__float128 testSqrtOdd() { + return __builtin_sqrtf128_round_to_odd(A); +// CHECK: @llvm.ppc.sqrtf128.round.to.odd(fp128 +// CHECK-NEXT: ret fp128 +} + +__float128 testFMAOdd() { + return __builtin_fmaf128_round_to_odd(A, B, C); +// CHECK: @llvm.ppc.fmaf128.round.to.odd(fp128 %{{.+}}, fp128 %{{.+}}, fp128 +// CHECK-NEXT: ret fp128 +} + +__float128 testAddOdd() { + return __builtin_addf128_round_to_odd(A, B); +// CHECK: @llvm.ppc.addf128.round.to.odd(fp128 %{{.+}}, fp128 +// CHECK-NEXT: ret fp128 +} + +__float128 testSubOdd() { + return __builtin_subf128_round_to_odd(A, B); +// CHECK: @llvm.ppc.subf128.round.to.odd(fp128 %{{.+}}, fp128 +// CHECK-NEXT: ret fp128 +} + +__float128 testMulOdd() { + return __builtin_mulf128_round_to_odd(A, B); +// CHECK: @llvm.ppc.mulf128.round.to.odd(fp128 %{{.+}}, fp128 +// CHECK-NEXT: ret fp128 +} + +__float128 testDivOdd() { + return __builtin_divf128_round_to_odd(A, B); +// CHECK: @llvm.ppc.divf128.round.to.odd(fp128 %{{.+}}, fp128 +// CHECK-NEXT: ret fp128 +} + + -- GitLab From dc74ef665f0b4a7eb2a78428a3fd85c86c708c57 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 9 Jul 2018 19:00:16 +0000 Subject: [PATCH 0455/1023] [Builtins][Attributes][X86] Tag all X86 builtins with their required vector width. Add a min_vector_width function attribute and tag all x86 instrinsics with it This is part of an ongoing attempt at making 512 bit vectors illegal in the X86 backend type legalizer due to CPU frequency penalties associated with wide vectors on Skylake Server CPUs. We want the loop vectorizer to be able to emit IR containing wide vectors as intermediate operations in vectorized code and allow these wide vectors to be legalized to 256 bits by the X86 backend even though we are targetting a CPU that supports 512 bit vectors. This is similar to what happens with an AVX2 CPU, the vectorizer can emit wide vectors and the backend will split them. We want this splitting behavior, but still be able to use new Skylake instructions that work on 256-bit vectors and support things like masking and gather/scatter. Of course if the user uses explicit vector code in their source code we need to not split those operations. Especially if they have used any of the 512-bit vector intrinsics from immintrin.h. And we need to make it so that merely using the intrinsics produces the expected code in order to be backwards compatible. To support this goal, this patch adds a new IR function attribute "min-legal-vector-width" that can indicate the need for a minimum vector width to be legal in the backend. We need to ensure this attribute is set to the largest vector width needed by any intrinsics from immintrin.h that the function uses. The inliner will be reponsible for merging this attribute when a function is inlined. We may also need a way to limit inlining in the future as well, but we can discuss that in the future. To make things more complicated, there are two different ways intrinsics are implemented in immintrin.h. Either as an always_inline function containing calls to builtins(can be target specific or target independent) or vector extension code. Or as a macro wrapper around a taget specific builtin. I believe I've removed all cases where the macro was around a target independent builtin. To support the always_inline function case this patch adds attribute((min_vector_width(128))) that can be used to tag these functions with their vector width. All x86 intrinsic functions that operate on vectors have been tagged with this attribute. To support the macro case, all x86 specific builtins have also been tagged with the vector width that they require. Use of any builtin with this property will implicitly increase the min_vector_width of the function that calls it. I've done this as a new property in the attribute string for the builtin rather than basing it on the type string so that we can opt into it on a per builtin basis and avoid any impact to target independent builtins. There will be future work to support vectors passed as function arguments and supporting inline assembly. And whatever else we can find that isn't covered by this patch. Special thanks to Chandler who suggested this direction and reviewed a preview version of this patch. And thanks to Eric Christopher who has had many conversations with me about this issue. Differential Revision: https://reviews.llvm.org/D48617 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336583 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 7 + include/clang/Basic/AttrDocs.td | 24 + include/clang/Basic/Builtins.def | 1 + include/clang/Basic/Builtins.h | 2 + include/clang/Basic/BuiltinsX86.def | 3192 ++++++++--------- include/clang/Basic/BuiltinsX86_64.def | 40 +- lib/Basic/Builtins.cpp | 16 + lib/CodeGen/CGBuiltin.cpp | 3 + lib/CodeGen/CodeGenFunction.cpp | 13 +- lib/CodeGen/CodeGenFunction.h | 4 + lib/Headers/__wmmintrin_aes.h | 2 +- lib/Headers/ammintrin.h | 2 +- lib/Headers/avx2intrin.h | 288 +- lib/Headers/avx512bitalgintrin.h | 2 +- lib/Headers/avx512bwintrin.h | 2 +- lib/Headers/avx512cdintrin.h | 2 +- lib/Headers/avx512dqintrin.h | 2 +- lib/Headers/avx512fintrin.h | 1642 ++++----- lib/Headers/avx512ifmaintrin.h | 2 +- lib/Headers/avx512ifmavlintrin.h | 30 +- lib/Headers/avx512vbmi2intrin.h | 2 +- lib/Headers/avx512vbmiintrin.h | 2 +- lib/Headers/avx512vbmivlintrin.h | 46 +- lib/Headers/avx512vlbitalgintrin.h | 38 +- lib/Headers/avx512vlbwintrin.h | 622 ++-- lib/Headers/avx512vlcdintrin.h | 62 +- lib/Headers/avx512vldqintrin.h | 272 +- lib/Headers/avx512vlintrin.h | 1786 ++++----- lib/Headers/avx512vlvbmi2intrin.h | 134 +- lib/Headers/avx512vlvnniintrin.h | 54 +- lib/Headers/avx512vnniintrin.h | 2 +- lib/Headers/avx512vpopcntdqintrin.h | 3 +- lib/Headers/avx512vpopcntdqvlintrin.h | 37 +- lib/Headers/avxintrin.h | 34 +- lib/Headers/emmintrin.h | 8 +- lib/Headers/f16cintrin.h | 15 +- lib/Headers/fma4intrin.h | 70 +- lib/Headers/fmaintrin.h | 70 +- lib/Headers/gfniintrin.h | 20 +- lib/Headers/mm3dnow.h | 6 +- lib/Headers/mmintrin.h | 4 +- lib/Headers/pmmintrin.h | 2 +- lib/Headers/shaintrin.h | 2 +- lib/Headers/smmintrin.h | 2 +- lib/Headers/tmmintrin.h | 4 +- lib/Headers/vaesintrin.h | 4 +- lib/Headers/xmmintrin.h | 4 +- lib/Headers/xopintrin.h | 10 +- lib/Sema/SemaDeclAttr.cpp | 22 + test/CodeGen/function-min-vector-width.c | 7 + test/CodeGen/x86-builtins-vector-width.c | 32 + ...a-attribute-supported-attributes-list.test | 3 +- test/Sema/attr-min-vector-width.c | 16 + 53 files changed, 4429 insertions(+), 4242 deletions(-) create mode 100644 test/CodeGen/function-min-vector-width.c create mode 100644 test/CodeGen/x86-builtins-vector-width.c create mode 100644 test/Sema/attr-min-vector-width.c diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index cddf67d45c..c2edbbd47d 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1943,6 +1943,13 @@ def Target : InheritableAttr { }]; } +def MinVectorWidth : InheritableAttr { + let Spellings = [Clang<"min_vector_width">]; + let Args = [UnsignedArgument<"VectorWidth">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [MinVectorWidthDocs]; +} + def TransparentUnion : InheritableAttr { let Spellings = [GCC<"transparent_union">]; // let Subjects = SubjectList<[Record, TypedefName]>; diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 53ae80b0ff..15aa77e357 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -1496,6 +1496,30 @@ Additionally, a function may not become multiversioned after its first use. }]; } +def MinVectorWidthDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This +attribute may be attached to a function and informs the backend that this +function desires vectors of at least this width to be generated. Target-specific +maximum vector widths still apply. This means even if you ask for something +larger than the target supports, you will only get what the target supports. +This attribute is meant to be a hint to control target heuristics that may +generate narrower vectors than what the target hardware supports. + +This is currently used by the X86 target to allow some CPUs that support 512-bit +vectors to be limited to using 256-bit vectors to avoid frequency penalties. +This is currently enabled with the ``-prefer-vector-width=256`` command line +option. The ``min_vector_width`` attribute can be used to prevent the backend +from trying to split vector operations to match the ``prefer-vector-width``. All +X86 vector intrinsics from x86intrin.h already set this attribute. Additionally, +use of any of the X86-specific vector builtins will implicitly set this +attribute on the calling function. The intent is that explicitly writing vector +code using the X86 intrinsics will prevent ``prefer-vector-width`` from +affecting the code. +}]; +} + def DocCatAMDGPUAttributes : DocumentationCategory<"AMD GPU Attributes">; def AMDGPUFlatWorkGroupSizeDocs : Documentation { diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index dd0730f961..e549582cd5 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -92,6 +92,7 @@ // e -> const, but only when -fno-math-errno // j -> returns_twice (like setjmp) // u -> arguments are not evaluated for their side-effects +// V:N: -> requires vectors of at least N bits to be legal // FIXME: gcc has nonnull #if defined(BUILTIN) && !defined(LIBBUILTIN) diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 1f82d90cf8..fa2bcc4c7a 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -206,6 +206,8 @@ public: return getRecord(ID).Features; } + unsigned getRequiredVectorWidth(unsigned ID) const; + /// Return true if builtin ID belongs to AuxTarget. bool isAuxBuiltinID(unsigned ID) const { return ID >= (Builtin::FirstTSBuiltin + TSRecords.size()); diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index db7055136b..0b08e03764 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -36,9 +36,9 @@ BUILTIN(__builtin_cpu_is, "bcC*", "nc") // Undefined Values // -TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "") +TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "") +TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "ncV:256:", "") +TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "ncV:512:", "") // FLAGS // @@ -48,32 +48,32 @@ TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "") // 3DNow! // TARGET_BUILTIN(__builtin_ia32_femms, "v", "n", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "ncV:64:", "3dnow") // 3DNow! Extensions (3dnowa). -TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "ncV:64:", "3dnowa") // MMX // @@ -85,258 +85,258 @@ TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa") // doesn't work in the presence of re-declaration of _mm_prefetch for windows. TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx") TARGET_BUILTIN(__builtin_ia32_emms, "v", "n", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "n", "mmx") -TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "n", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2iIi", "nc", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "nV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "nV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "ncV:64:", "mmx") // MMX2 (MMX+SSE) intrinsics -TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "nc", "mmx,sse") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "nc", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "ncV:64:", "mmx,sse") // MMX+SSE2 -TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "nc", "mmx,sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "nc", "mmx,sse2") -TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "nc", "mmx,sse2") -TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "nc", "mmx,sse2") -TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "nc", "mmx,sse2") -TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "nc", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2") // MMX+SSSE3 -TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "nc", "mmx,ssse3") -TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "nc", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") // SSE intrinsics. -TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "nc", "sse") - -TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "nc", "sse2") - -TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "nc", "sse") - -TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "nc", "sse2") - -TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "nc", "sse3") -TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "nc", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "nc", "ssse3") +TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "ncV:128:", "sse2") + +TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "ncV:128:", "sse2") + +TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "ncV:128:", "ssse3") TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "n", "sse") TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "nh","xmmintrin.h", ALL_LANGUAGES, "sse") TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "n", "sse") TARGET_HEADER_BUILTIN(_mm_getcsr, "Ui", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse") -TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "n", "sse") -TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "n", "sse") -TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "n", "sse") +TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "nV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "nV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "nV:128:", "sse") TARGET_BUILTIN(__builtin_ia32_sfence, "v", "n", "sse") TARGET_HEADER_BUILTIN(_mm_sfence, "v", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse") -TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fIi", "nc", "sse") - -TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "n", "sse2") -TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fIi", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "nV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "n", "sse2") -TARGET_BUILTIN(__builtin_ia32_pshufd, "V4iV4iIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pshuflw, "V8sV8sIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2dIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufd, "V4iV4iIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshuflw, "V8sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2dIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "n", "sse2") TARGET_HEADER_BUILTIN(_mm_clflush, "vvC*", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2") TARGET_BUILTIN(__builtin_ia32_lfence, "v", "n", "sse2") @@ -345,342 +345,342 @@ TARGET_BUILTIN(__builtin_ia32_mfence, "v", "n", "sse2") TARGET_HEADER_BUILTIN(_mm_mfence, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2") TARGET_BUILTIN(__builtin_ia32_pause, "v", "n", "") TARGET_HEADER_BUILTIN(_mm_pause, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "") -TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_pslldqi128_byteshift, "V2LLiV2LLiIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrldqi128_byteshift, "V2LLiV2LLiIi", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "n", "sse3") TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "n", "sse3") -TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "n", "sse3") - -TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "nc", "ssse3") - -TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "nc", "sse4.1") - -TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "nc", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "nV:128:", "sse3") + +TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "ncV:128:", "ssse3") + +TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "ncV:128:", "sse4.1") + +TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "ncV:128:", "sse4.1") // SSE 4.2 -TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","nc", "sse4.2") - -TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","nc", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","ncV:128:", "sse4.2") + +TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","ncV:128:", "sse4.2") TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "nc", "sse4.2") TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "nc", "sse4.2") TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "nc", "sse4.2") // SSE4a -TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "nc", "sse4a") -TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "nc", "sse4a") -TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "nc", "sse4a") -TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "nc", "sse4a") -TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "n", "sse4a") -TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "n", "sse4a") +TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "nV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "nV:128:", "sse4a") // AES -TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "nc", "aes") -TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "nc", "aes") -TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "nc", "aes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "nc", "aes") -TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "nc", "aes") -TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "nc", "aes") +TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "ncV:128:", "aes") // VAES -TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "nc", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "nc", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "nc", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "nc", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "nc", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "nc", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "nc", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "nc", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") // GFNI -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "nc", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "nc", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "nc", "avx512bw,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "nc", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "nc", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "nc", "avx512bw,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "nc", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "nc", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "nc", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "ncV:512:", "avx512bw,gfni") // CLMUL -TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "nc", "pclmul") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "ncV:128:", "pclmul") // VPCLMULQDQ -TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "nc", "vpclmulqdq") -TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "nc", "avx512f,vpclmulqdq") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "ncV:256:", "vpclmulqdq") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "ncV:512:", "avx512f,vpclmulqdq") // AVX -TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "n", "avx") TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "n", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "ncV:256:", "avx") // AVX2 -TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pshufd256, "V8iV8iIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pshuflw256, "V16sV16sIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pshufhw256, "V16sV16sIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pslldqi256_byteshift, "V4LLiV4LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrldqi256_byteshift, "V4LLiV4LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permdf256, "V4dV4dIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "nc", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "nc", "avx2") +TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufd256, "V8iV8iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshuflw256, "V16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufhw256, "V16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdf256, "V4dV4dIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2") // GATHER -TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "n", "avx2") - -TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "n", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "n", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "nV:256:", "avx2") + +TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "nV:256:", "avx2") // F16C -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "nc", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "nc", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "nc", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "nc", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "ncV:128:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "ncV:256:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "ncV:128:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "ncV:256:", "f16c") // RDRAND TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "n", "rdrnd") @@ -745,109 +745,109 @@ TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "n", "lwp") TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "n", "lwp") // SHA -TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "nc", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "nc", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "ncV:128:", "sha") // FMA -TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "nc", "fma") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "nc", "fma") -TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "nc", "fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "nc", "fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "nc", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "nc", "fma|fma4") - -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "ncV:128:", "fma") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "ncV:128:", "fma") +TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "ncV:128:", "fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "ncV:128:", "fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4") + +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") // XOP -TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "nc", "xop") - -TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "nc", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "nc", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "ncV:128:", "xop") + +TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "ncV:256:", "xop") TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "n", "rtm") TARGET_BUILTIN(__builtin_ia32_xend, "v", "n", "rtm") @@ -866,874 +866,874 @@ TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku") TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "n", "pku") // AVX-512 -TARGET_BUILTIN(__builtin_ia32_sqrtpd512, "V8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_sqrtps512, "V16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "nc", "avx512er") - -TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "nc", "avx512er") -TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "nc", "avx512er") - -TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "nc", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pabsd512, "V16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pabsq512, "V8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxsd512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxsq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxud512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxuq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminsd512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminsq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminud512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminuq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_alignq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_alignd512, "V16iV16iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd512, "V16iV16iV16iV16i", "nc", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds512, "V16iV16iV16iV16i", "nc", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd512, "V16iV16iV16iV16i", "nc", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "nc", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "nc", "avx512vnni") - -TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "n", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "n", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "n", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_sqrtpd512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtps512, "V16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") + +TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") + +TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "ncV:128:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pabsd512, "V16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pabsq512, "V8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxsd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxud512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminsd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminud512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd512, "V16iV16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") + +TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "nV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "nV:512:", "avx512pf") TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "nc", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pabsb512, "V64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pabsw512, "V32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxsb512, "V64cV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxsw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxub512, "V64cV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxuw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminsb512, "V64cV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminsw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminub512, "V64cV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminuw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "nc", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "nc", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_512, "V16iV16i", "nc", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_512, "V8LLiV8LLi", "nc", "avx512cd") - -TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "nc", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "nc", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "nc", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "nc", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "nc", "avx512vpopcntdq") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "nc", "avx512vpopcntdq") - -TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "nc", "avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "nc", "avx512bitalg") - -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "nc", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "nc", "avx512bitalg") - -TARGET_BUILTIN(__builtin_ia32_pmulhrsw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmulhuw512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmulhw512, "V32sV32sV32s", "nc", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_addpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_addps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subps512, "V16fV16fV16fIi", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_pmaddubsw512, "V32sV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaddwd512, "V16iV32sV32s", "nc", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "nc", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi", "nc", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "n", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "n", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "nc", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "nc", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2dC*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4dC*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLiC*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLiC*V4LLiUc", "n", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "n", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "n", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4fC*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8fC*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4iC*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8iC*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pabsq128, "V2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pabsq256, "V4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxsq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxsq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxuq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxuq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminsq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminsq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminuq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminuq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "nc", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "n", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2vard512, "V16iV16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128, "V2dV2dV2LLiV2d", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256, "V4dV4dV4LLiV4d", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512, "V8dV8dV8LLiV8d", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps128, "V4fV4fV4iV4f", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps256, "V8fV8fV8iV8f", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps512, "V16fV16fV16iV16f", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq128, "V2LLiV2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq256, "V4LLiV4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq512, "V8LLiV8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128, "V16cV16cV16cV16c", "nc", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256, "V32cV32cV32cV32c", "nc", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512, "V64cV64cV64cV64c", "nc", "avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128, "V8sV8sV8sV8s", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256, "V16sV16sV16sV16s", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512, "V32sV32sV32sV32s", "nc", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_vpshldd128, "V4iV4iV4iIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd256, "V8iV8iV8iIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd512, "V16iV16iV16iIi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "nc", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "nc", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "nc", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd512, "V16iV16iV16iIi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq128, "V2LLiV2LLiV2LLiIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq512, "V8LLiV8LLiV8LLiIi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw128, "V8sV8sV8sIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw256, "V16sV16sV16sIi", "nc", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw512, "V32sV32sV32sIi", "nc", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "nc", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "nc", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_prold512, "V16iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolq512, "V8LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prold128, "V4iV4iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prold256, "V8iV8iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq128, "V2LLiV2LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq256, "V4LLiV4LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prord512, "V16iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorq512, "V8LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvd128, "V4iV4iV4i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd256, "V8iV8iV8i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord128, "V4iV4iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord256, "V8iV8iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq128, "V2LLiV2LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq256, "V4LLiV4LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvq512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvd128, "V4iV4iV4i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd256, "V8iV8iV8i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "nc ", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "nc ", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pslldqi512_byteshift, "V8LLiV8LLiIi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrldqi512_byteshift, "V8LLiV8LLiIi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512, "V8LLiV8LLiV8LLiV8LLi", "nc", "avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512, "V8LLiV8LLiV8LLiV8LLi", "nc", "avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128, "V2LLiV2LLiV2LLiV2LLi", "nc", "avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256, "V4LLiV4LLiV4LLiV4LLi", "nc", "avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128, "V2LLiV2LLiV2LLiV2LLi", "nc", "avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256, "V4LLiV4LLiV4LLiV4LLi", "nc", "avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_pabsb512, "V64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pabsw512, "V32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxsb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxub512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminsb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminub512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_512, "V16iV16i", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512cd") + +TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "ncV:128:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "ncV:256:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "ncV:512:", "avx512vpopcntdq") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512vpopcntdq") + +TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "ncV:512:", "avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "ncV:512:", "avx512bitalg") + +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "ncV:512:", "avx512bitalg") + +TARGET_BUILTIN(__builtin_ia32_pmulhrsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmulhuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmulhw512, "V32sV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_addpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_pmaddubsw512, "V32sV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaddwd512, "V16iV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4dC*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLiC*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "nV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "nV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8fC*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4iC*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8iC*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pabsq128, "V2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pabsq256, "V4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2vard512, "V16iV16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128, "V2dV2dV2LLiV2d", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256, "V4dV4dV4LLiV4d", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512, "V8dV8dV8LLiV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps128, "V4fV4fV4iV4f", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps256, "V8fV8fV8iV8f", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps512, "V16fV16fV16iV16f", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128, "V16cV16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256, "V32cV32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512, "V64cV64cV64cV64c", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512, "V32sV32sV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_vpshldd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_prold512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prold128, "V4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prold256, "V8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prord512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvd128, "V4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd256, "V8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord128, "V4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord256, "V8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvd128, "V4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd256, "V8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pslldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_kunpckdi, "ULLiULLiULLi", "nc", "avx512bw") TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc", "n", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs", "n", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs", "n", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi", "n", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2d*V2dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4f*V4fUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV2d*V2dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV4f*V4fUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_128, "V4iV4i", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_256, "V8iV8i", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_128, "V2LLiV2LLi", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_256, "V4LLiV4LLi", "nc", "avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilpd512, "V8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilps512, "V16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shufpd512, "V8dV8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shufps512, "V16fV16fV16fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256, "V4LLiV4LLiV4LLiIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi", "n", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs", "n", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "n", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf32x8_mask, "V8fV16fIiV8fUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_inserti64x2_512, "V8LLiV8LLiV2LLiIi", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_insertf64x4, "V8dV8dV4dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_inserti64x4, "V8LLiV8LLiV4LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_insertf64x2_256, "V4dV4dV2dIi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_inserti64x2_256, "V4LLiV4LLiV2LLiIi", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_insertf32x4_256, "V8fV8fV4fIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_inserti32x4_256, "V8iV8iV4iIi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_insertf32x4, "V16fV16fV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_inserti32x4, "V16iV16iV4iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2dIiV2dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4dIiV4dUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fIiV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fIiV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8dIiV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fIiV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_permvardf512, "V8dV8dV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvardi512, "V8LLiV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarsf512, "V16fV16fV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarsi512, "V16iV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarqi512, "V64cV64cV64c", "nc", "avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_permvarqi128, "V16cV16cV16c", "nc", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarqi256, "V32cV32cV32c", "nc", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarhi128, "V8sV8sV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarhi256, "V16sV16sV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvardf256, "V4dV4dV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvardi256, "V4LLiV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc", "nc", "avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc", "nc", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc", "nc", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc", "nV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs", "nV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs", "nV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi", "nV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV2d*V2dUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV4f*V4fUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_128, "V4iV4i", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_256, "V8iV8i", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilpd512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilps512, "V16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x8_mask, "V8fV16fIiV8fUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_512, "V8LLiV8LLiV2LLiIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x4, "V8dV8dV4dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti64x4, "V8LLiV8LLiV4LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_256, "V4dV4dV2dIi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4_256, "V8fV8fV4fIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti32x4_256, "V8iV8iV4iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4, "V16fV16fV4fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti32x4, "V16iV16iV4iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_permvardf512, "V8dV8dV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvardi512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarsf512, "V16fV16fV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarsi512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarqi512, "V64cV64cV64c", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_permvarqi128, "V16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarqi256, "V32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarhi128, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarhi256, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvardf256, "V4dV4dV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvardi256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc", "ncV:128:", "avx512dq") TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs", "nc", "avx512f") @@ -1742,73 +1742,73 @@ TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw512, "V32sV64cV64cIi", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pshufd512, "V16iV16iIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi", "nc", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi", "n", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi", "n", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi", "n", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi", "n", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs", "n", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "nc", "avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "nc", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "nc", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw512, "V32sV64cV64cIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pshufd512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "ncV:256:", "avx512vbmi,avx512vl") // generic select intrinsics -TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "nc", "avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "nc", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "nc", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "ncV:512:", "avx512f") // MONITORX/MWAITX TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx") diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def index f3d4d1794c..cc400c0697 100644 --- a/include/clang/Basic/BuiltinsX86_64.def +++ b/include/clang/Basic/BuiltinsX86_64.def @@ -44,16 +44,16 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "") TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "") -TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "nc", "sse") -TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "nc", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "n", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "nc", "sse2") -TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "nc", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "ncV:128:", "sse4.1") TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "nc", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "nc", "avx") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "nc", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "n", "fsgsbase") TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "n", "fsgsbase") TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "n", "fsgsbase") @@ -86,18 +86,18 @@ TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "nc", "bmi2") TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "nc", "tbm") TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "n", "lwp") TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "n", "lwp") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri") TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vULLi", "n", "ptwrite") diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp index bb04384fd6..a3210ba090 100644 --- a/lib/Basic/Builtins.cpp +++ b/lib/Basic/Builtins.cpp @@ -107,6 +107,22 @@ void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) { Table.get(getRecord(ID).Name).setBuiltinID(0); } +unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const { + const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V'); + if (!WidthPos) + return 0; + + ++WidthPos; + assert(*WidthPos == ':' && + "Vector width specifier must be followed by a ':'"); + ++WidthPos; + + char *EndPos; + unsigned Width = ::strtol(WidthPos, &EndPos, 10); + assert(*EndPos == ':' && "Vector width specific must end with a ':'"); + return Width; +} + bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, const char *Fmt) const { assert(Fmt && "Not passed a format string"); diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a0afb08653..6b1198d64e 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -3654,6 +3654,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // can move this up to the beginning of the function. checkTargetFeatures(E, FD); + if (unsigned VectorWidth = getContext().BuiltinInfo.getRequiredVectorWidth(BuiltinID)) + LargestVectorWidth = std::max(LargestVectorWidth, VectorWidth); + // See if we have a target specific intrinsic. const char *Name = getContext().BuiltinInfo.getName(BuiltinID); Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 916051556a..9ccc0910c3 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -81,7 +81,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) CXXStructorImplicitParamDecl(nullptr), CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), CurLexicalScope(nullptr), TerminateLandingPad(nullptr), - TerminateHandler(nullptr), TrapBB(nullptr), + TerminateHandler(nullptr), TrapBB(nullptr), LargestVectorWidth(0), ShouldEmitLifetimeMarkers( shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) @@ -445,6 +445,11 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { cast(NormalCleanupDest.getPointer()), DT); NormalCleanupDest = Address::invalid(); } + + // Add the required-vector-width attribute. + if (LargestVectorWidth != 0) + CurFn->addFnAttr("min-legal-vector-width", + llvm::utostr(LargestVectorWidth)); } /// ShouldInstrumentFunction - Return true if the current function should be @@ -1186,6 +1191,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, // Emit a location at the end of the prologue. if (CGDebugInfo *DI = getDebugInfo()) DI->EmitLocation(Builder, StartLoc); + + // TODO: Do we need to handle this in two places like we do with + // target-features/target-cpu? + if (CurFuncDecl) + if (const auto *VecWidth = CurFuncDecl->getAttr()) + LargestVectorWidth = VecWidth->getVectorWidth(); } void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args, diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 548a4178ef..b2bcd1cfbd 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1463,6 +1463,10 @@ private: /// Terminate funclets keyed by parent funclet pad. llvm::MapVector TerminateFunclets; + /// Largest vector width used in ths function. Will be used to create a + /// function attribute. + unsigned LargestVectorWidth; + /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; diff --git a/lib/Headers/__wmmintrin_aes.h b/lib/Headers/__wmmintrin_aes.h index a3f4da24ed..70c355efc4 100644 --- a/lib/Headers/__wmmintrin_aes.h +++ b/lib/Headers/__wmmintrin_aes.h @@ -29,7 +29,7 @@ #define __WMMINTRIN_AES_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("aes"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("aes"), __min_vector_width__(128))) /// Performs a single round of AES encryption using the Equivalent /// Inverse Cipher, transforming the state value from the first source diff --git a/lib/Headers/ammintrin.h b/lib/Headers/ammintrin.h index d91e4d194c..680b4465ea 100644 --- a/lib/Headers/ammintrin.h +++ b/lib/Headers/ammintrin.h @@ -27,7 +27,7 @@ #include /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a"), __min_vector_width__(128))) /// Extracts the specified bits from the lower 64 bits of the 128-bit /// integer vector operand at the index \a idx and of the length \a len. diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h index 22c00f9b8e..9688a96fde 100644 --- a/lib/Headers/avx2intrin.h +++ b/lib/Headers/avx2intrin.h @@ -29,98 +29,99 @@ #define __AVX2INTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx2"))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx2"), __min_vector_width__(256))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx2"), __min_vector_width__(128))) /* SSE4 Multiple Packed Sums of Absolute Difference. */ #define _mm256_mpsadbw_epu8(X, Y, M) \ (__m256i)__builtin_ia32_mpsadbw256((__v32qi)(__m256i)(X), \ (__v32qi)(__m256i)(Y), (int)(M)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_abs_epi8(__m256i __a) { return (__m256i)__builtin_ia32_pabsb256((__v32qi)__a); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_abs_epi16(__m256i __a) { return (__m256i)__builtin_ia32_pabsw256((__v16hi)__a); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_abs_epi32(__m256i __a) { return (__m256i)__builtin_ia32_pabsd256((__v8si)__a); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_packs_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_packsswb256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_packs_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_packssdw256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_packus_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_packuswb256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_packus_epi32(__m256i __V1, __m256i __V2) { return (__m256i) __builtin_ia32_packusdw256((__v8si)__V1, (__v8si)__V2); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_add_epi8(__m256i __a, __m256i __b) { return (__m256i)((__v32qu)__a + (__v32qu)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_add_epi16(__m256i __a, __m256i __b) { return (__m256i)((__v16hu)__a + (__v16hu)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_add_epi32(__m256i __a, __m256i __b) { return (__m256i)((__v8su)__a + (__v8su)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_add_epi64(__m256i __a, __m256i __b) { return (__m256i)((__v4du)__a + (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_adds_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_paddsb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_adds_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_paddsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_adds_epu8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_paddusb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_adds_epu16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_paddusw256((__v16hi)__a, (__v16hi)__b); @@ -130,19 +131,19 @@ _mm256_adds_epu16(__m256i __a, __m256i __b) (__m256i)__builtin_ia32_palignr256((__v32qi)(__m256i)(a), \ (__v32qi)(__m256i)(b), (n)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_and_si256(__m256i __a, __m256i __b) { return (__m256i)((__v4du)__a & (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_andnot_si256(__m256i __a, __m256i __b) { return (__m256i)(~(__v4du)__a & (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_avg_epu8(__m256i __a, __m256i __b) { typedef unsigned short __v32hu __attribute__((__vector_size__(64))); @@ -152,7 +153,7 @@ _mm256_avg_epu8(__m256i __a, __m256i __b) >> 1, __v32qu); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_avg_epu16(__m256i __a, __m256i __b) { typedef unsigned int __v16su __attribute__((__vector_size__(64))); @@ -162,7 +163,7 @@ _mm256_avg_epu16(__m256i __a, __m256i __b) >> 1, __v16hu); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M) { return (__m256i)__builtin_ia32_pblendvb256((__v32qi)__V1, (__v32qi)__V2, @@ -173,31 +174,31 @@ _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M) (__m256i)__builtin_ia32_pblendw256((__v16hi)(__m256i)(V1), \ (__v16hi)(__m256i)(V2), (int)(M)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpeq_epi8(__m256i __a, __m256i __b) { return (__m256i)((__v32qi)__a == (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpeq_epi16(__m256i __a, __m256i __b) { return (__m256i)((__v16hi)__a == (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpeq_epi32(__m256i __a, __m256i __b) { return (__m256i)((__v8si)__a == (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpeq_epi64(__m256i __a, __m256i __b) { return (__m256i)((__v4di)__a == (__v4di)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpgt_epi8(__m256i __a, __m256i __b) { /* This function always performs a signed comparison, but __v32qi is a char @@ -205,151 +206,151 @@ _mm256_cmpgt_epi8(__m256i __a, __m256i __b) return (__m256i)((__v32qs)__a > (__v32qs)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpgt_epi16(__m256i __a, __m256i __b) { return (__m256i)((__v16hi)__a > (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpgt_epi32(__m256i __a, __m256i __b) { return (__m256i)((__v8si)__a > (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmpgt_epi64(__m256i __a, __m256i __b) { return (__m256i)((__v4di)__a > (__v4di)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hadd_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phaddw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hadd_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phaddd256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hadds_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phaddsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hsub_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phsubw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hsub_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phsubd256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_hsubs_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_phsubsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maddubs_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaddubsw256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_madd_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaddwd256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxsb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxsd256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epu8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxub256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epu16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxuw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epu32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmaxud256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminsb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminsd256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epu8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminub256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epu16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminuw256 ((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epu32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pminud256((__v8si)__a, (__v8si)__b); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS256 _mm256_movemask_epi8(__m256i __a) { return __builtin_ia32_pmovmskb256((__v32qi)__a); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi8_epi16(__m128i __V) { /* This function always performs a signed extension, but __v16qi is a char @@ -357,7 +358,7 @@ _mm256_cvtepi8_epi16(__m128i __V) return (__m256i)__builtin_convertvector((__v16qs)__V, __v16hi); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi8_epi32(__m128i __V) { /* This function always performs a signed extension, but __v16qi is a char @@ -365,7 +366,7 @@ _mm256_cvtepi8_epi32(__m128i __V) return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8si); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi8_epi64(__m128i __V) { /* This function always performs a signed extension, but __v16qi is a char @@ -373,115 +374,115 @@ _mm256_cvtepi8_epi64(__m128i __V) return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3), __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi16_epi32(__m128i __V) { return (__m256i)__builtin_convertvector((__v8hi)__V, __v8si); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi16_epi64(__m128i __V) { return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1, 2, 3), __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepi32_epi64(__m128i __V) { return (__m256i)__builtin_convertvector((__v4si)__V, __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu8_epi16(__m128i __V) { return (__m256i)__builtin_convertvector((__v16qu)__V, __v16hi); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu8_epi32(__m128i __V) { return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8si); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu8_epi64(__m128i __V) { return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__V, (__v16qu)__V, 0, 1, 2, 3), __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu16_epi32(__m128i __V) { return (__m256i)__builtin_convertvector((__v8hu)__V, __v8si); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu16_epi64(__m128i __V) { return (__m256i)__builtin_convertvector(__builtin_shufflevector((__v8hu)__V, (__v8hu)__V, 0, 1, 2, 3), __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtepu32_epi64(__m128i __V) { return (__m256i)__builtin_convertvector((__v4su)__V, __v4di); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mul_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mulhrs_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmulhrsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mulhi_epu16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmulhuw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mulhi_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pmulhw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mullo_epi16(__m256i __a, __m256i __b) { return (__m256i)((__v16hu)__a * (__v16hu)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mullo_epi32 (__m256i __a, __m256i __b) { return (__m256i)((__v8su)__a * (__v8su)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mul_epu32(__m256i __a, __m256i __b) { return __builtin_ia32_pmuludq256((__v8si)__a, (__v8si)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_or_si256(__m256i __a, __m256i __b) { return (__m256i)((__v4du)__a | (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sad_epu8(__m256i __a, __m256i __b) { return __builtin_ia32_psadbw256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shuffle_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_pshufb256((__v32qi)__a, (__v32qi)__b); @@ -496,19 +497,19 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b) #define _mm256_shufflelo_epi16(a, imm) \ (__m256i)__builtin_ia32_pshuflw256((__v16hi)(__m256i)(a), (int)(imm)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sign_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psignb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sign_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psignw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sign_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psignd256((__v8si)__a, (__v8si)__b); @@ -520,61 +521,61 @@ _mm256_sign_epi32(__m256i __a, __m256i __b) #define _mm256_bslli_epi128(a, imm) \ (__m256i)__builtin_ia32_pslldqi256_byteshift((__v4di)(__m256i)(a), (int)(imm)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_slli_epi16(__m256i __a, int __count) { return (__m256i)__builtin_ia32_psllwi256((__v16hi)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sll_epi16(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_psllw256((__v16hi)__a, (__v8hi)__count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_slli_epi32(__m256i __a, int __count) { return (__m256i)__builtin_ia32_pslldi256((__v8si)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sll_epi32(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_pslld256((__v8si)__a, (__v4si)__count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_slli_epi64(__m256i __a, int __count) { return __builtin_ia32_psllqi256((__v4di)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sll_epi64(__m256i __a, __m128i __count) { return __builtin_ia32_psllq256((__v4di)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srai_epi16(__m256i __a, int __count) { return (__m256i)__builtin_ia32_psrawi256((__v16hi)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sra_epi16(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_psraw256((__v16hi)__a, (__v8hi)__count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srai_epi32(__m256i __a, int __count) { return (__m256i)__builtin_ia32_psradi256((__v8si)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sra_epi32(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_psrad256((__v8si)__a, (__v4si)__count); @@ -586,176 +587,176 @@ _mm256_sra_epi32(__m256i __a, __m128i __count) #define _mm256_bsrli_epi128(a, imm) \ (__m256i)__builtin_ia32_psrldqi256_byteshift((__m256i)(a), (int)(imm)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srli_epi16(__m256i __a, int __count) { return (__m256i)__builtin_ia32_psrlwi256((__v16hi)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srl_epi16(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_psrlw256((__v16hi)__a, (__v8hi)__count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srli_epi32(__m256i __a, int __count) { return (__m256i)__builtin_ia32_psrldi256((__v8si)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srl_epi32(__m256i __a, __m128i __count) { return (__m256i)__builtin_ia32_psrld256((__v8si)__a, (__v4si)__count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srli_epi64(__m256i __a, int __count) { return __builtin_ia32_psrlqi256((__v4di)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srl_epi64(__m256i __a, __m128i __count) { return __builtin_ia32_psrlq256((__v4di)__a, __count); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sub_epi8(__m256i __a, __m256i __b) { return (__m256i)((__v32qu)__a - (__v32qu)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sub_epi16(__m256i __a, __m256i __b) { return (__m256i)((__v16hu)__a - (__v16hu)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sub_epi32(__m256i __a, __m256i __b) { return (__m256i)((__v8su)__a - (__v8su)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sub_epi64(__m256i __a, __m256i __b) { return (__m256i)((__v4du)__a - (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_subs_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psubsb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_subs_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psubsw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_subs_epu8(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psubusb256((__v32qi)__a, (__v32qi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_subs_epu16(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_psubusw256((__v16hi)__a, (__v16hi)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpackhi_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 8, 32+8, 9, 32+9, 10, 32+10, 11, 32+11, 12, 32+12, 13, 32+13, 14, 32+14, 15, 32+15, 24, 32+24, 25, 32+25, 26, 32+26, 27, 32+27, 28, 32+28, 29, 32+29, 30, 32+30, 31, 32+31); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpackhi_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpackhi_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 2, 8+2, 3, 8+3, 6, 8+6, 7, 8+7); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpackhi_epi64(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v4di)__a, (__v4di)__b, 1, 4+1, 3, 4+3); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpacklo_epi8(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b, 0, 32+0, 1, 32+1, 2, 32+2, 3, 32+3, 4, 32+4, 5, 32+5, 6, 32+6, 7, 32+7, 16, 32+16, 17, 32+17, 18, 32+18, 19, 32+19, 20, 32+20, 21, 32+21, 22, 32+22, 23, 32+23); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpacklo_epi16(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)__b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpacklo_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)__b, 0, 8+0, 1, 8+1, 4, 8+4, 5, 8+5); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_unpacklo_epi64(__m256i __a, __m256i __b) { return (__m256i)__builtin_shufflevector((__v4di)__a, (__v4di)__b, 0, 4+0, 2, 4+2); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_xor_si256(__m256i __a, __m256i __b) { return (__m256i)((__v4du)__a ^ (__v4du)__b); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_stream_load_si256(__m256i const *__V) { typedef __v4di __v4di_aligned __attribute__((aligned(32))); return (__m256i)__builtin_nontemporal_load((const __v4di_aligned *)__V); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_broadcastss_ps(__m128 __X) { return (__m128)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_broadcastsd_pd(__m128d __a) { return __builtin_shufflevector((__v2df)__a, (__v2df)__a, 0, 0); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_broadcastss_ps(__m128 __X) { return (__m256)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_broadcastsd_pd(__m128d __X) { return (__m256d)__builtin_shufflevector((__v2df)__X, (__v2df)__X, 0, 0, 0, 0); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastsi128_si256(__m128i __X) { return (__m256i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 1, 0, 1); @@ -769,56 +770,56 @@ _mm256_broadcastsi128_si256(__m128i __X) (__m256i)__builtin_ia32_pblendd256((__v8si)(__m256i)(V1), \ (__v8si)(__m256i)(V2), (int)(M)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastb_epi8(__m128i __X) { return (__m256i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastw_epi16(__m128i __X) { return (__m256i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastd_epi32(__m128i __X) { return (__m256i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastq_epi64(__m128i __X) { return (__m256i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 0, 0, 0); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastb_epi8(__m128i __X) { return (__m128i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastw_epi16(__m128i __X) { return (__m128i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastd_epi32(__m128i __X) { return (__m128i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastq_epi64(__m128i __X) { return (__m128i)__builtin_shufflevector((__v2di)__X, (__v2di)__X, 0, 0); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutevar8x32_epi32(__m256i __a, __m256i __b) { return (__m256i)__builtin_ia32_permvarsi256((__v8si)__a, (__v8si)__b); @@ -827,7 +828,7 @@ _mm256_permutevar8x32_epi32(__m256i __a, __m256i __b) #define _mm256_permute4x64_pd(V, M) \ (__m256d)__builtin_ia32_permdf256((__v4df)(__m256d)(V), (int)(M)) -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) { return (__m256)__builtin_ia32_permvarsf256((__v8sf)__a, (__v8si)__b); @@ -846,109 +847,109 @@ _mm256_permutevar8x32_ps(__m256 __a, __m256i __b) (__m256i)__builtin_ia32_insert128i256((__v4di)(__m256i)(V1), \ (__v2di)(__m128i)(V2), (int)(M)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskload_epi32(int const *__X, __m256i __M) { return (__m256i)__builtin_ia32_maskloadd256((const __v8si *)__X, (__v8si)__M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskload_epi64(long long const *__X, __m256i __M) { return (__m256i)__builtin_ia32_maskloadq256((const __v4di *)__X, (__v4di)__M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskload_epi32(int const *__X, __m128i __M) { return (__m128i)__builtin_ia32_maskloadd((const __v4si *)__X, (__v4si)__M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskload_epi64(long long const *__X, __m128i __M) { return (__m128i)__builtin_ia32_maskloadq((const __v2di *)__X, (__v2di)__M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_maskstore_epi32(int *__X, __m256i __M, __m256i __Y) { __builtin_ia32_maskstored256((__v8si *)__X, (__v8si)__M, (__v8si)__Y); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_maskstore_epi64(long long *__X, __m256i __M, __m256i __Y) { __builtin_ia32_maskstoreq256((__v4di *)__X, (__v4di)__M, (__v4di)__Y); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_maskstore_epi32(int *__X, __m128i __M, __m128i __Y) { __builtin_ia32_maskstored((__v4si *)__X, (__v4si)__M, (__v4si)__Y); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_maskstore_epi64(long long *__X, __m128i __M, __m128i __Y) { __builtin_ia32_maskstoreq(( __v2di *)__X, (__v2di)__M, (__v2di)__Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sllv_epi32(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psllv8si((__v8si)__X, (__v8si)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_sllv_epi32(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psllv4si((__v4si)__X, (__v4si)__Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sllv_epi64(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psllv4di((__v4di)__X, (__v4di)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_sllv_epi64(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psllv2di((__v2di)__X, (__v2di)__Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srav_epi32(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psrav8si((__v8si)__X, (__v8si)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srav_epi32(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psrav4si((__v4si)__X, (__v4si)__Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srlv_epi32(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psrlv8si((__v8si)__X, (__v8si)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srlv_epi32(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psrlv4si((__v4si)__X, (__v4si)__Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srlv_epi64(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psrlv4di((__v4di)__X, (__v4di)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srlv_epi64(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psrlv2di((__v2di)__X, (__v2di)__Y); @@ -1161,6 +1162,7 @@ _mm_srlv_epi64(__m128i __X, __m128i __Y) (__v4di)(__m256i)(i), \ (__v4di)_mm256_set1_epi64x(-1), (s)) -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS256 +#undef __DEFAULT_FN_ATTRS128 #endif /* __AVX2INTRIN_H */ diff --git a/lib/Headers/avx512bitalgintrin.h b/lib/Headers/avx512bitalgintrin.h index 20c0645dd5..56046f8c49 100644 --- a/lib/Headers/avx512bitalgintrin.h +++ b/lib/Headers/avx512bitalgintrin.h @@ -29,7 +29,7 @@ #define __AVX512BITALGINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bitalg"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bitalg"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi16(__m512i __A) diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h index 444df35c3e..fc46323749 100644 --- a/lib/Headers/avx512bwintrin.h +++ b/lib/Headers/avx512bwintrin.h @@ -32,7 +32,7 @@ typedef unsigned int __mmask32; typedef unsigned long long __mmask64; /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw"), __min_vector_width__(512))) /* Integer compare */ diff --git a/lib/Headers/avx512cdintrin.h b/lib/Headers/avx512cdintrin.h index 9cea9481b4..e63902743c 100644 --- a/lib/Headers/avx512cdintrin.h +++ b/lib/Headers/avx512cdintrin.h @@ -29,7 +29,7 @@ #define __AVX512CDINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512cd"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512cd"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_conflict_epi64 (__m512i __A) diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h index 6181c15d02..1ce1b212cb 100644 --- a/lib/Headers/avx512dqintrin.h +++ b/lib/Headers/avx512dqintrin.h @@ -29,7 +29,7 @@ #define __AVX512DQINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mullo_epi64 (__m512i __A, __m512i __B) { diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index fc942e98da..9024168483 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -173,11 +173,12 @@ typedef enum } _MM_MANTISSA_SIGN_ENUM; /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512f"))) +#define __DEFAULT_FN_ATTRS512 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(512))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512f"), __min_vector_width__(128))) /* Create vectors with repeated elements */ -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_setzero_si512(void) { return __extension__ (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -185,38 +186,38 @@ _mm512_setzero_si512(void) #define _mm512_setzero_epi32 _mm512_setzero_si512 -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_undefined_pd(void) { return (__m512d)__builtin_ia32_undef512(); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_undefined(void) { return (__m512)__builtin_ia32_undef512(); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_undefined_ps(void) { return (__m512)__builtin_ia32_undef512(); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_undefined_epi32(void) { return (__m512i)__builtin_ia32_undef512(); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_broadcastd_epi32 (__m128i __A) { return (__m512i)__builtin_shufflevector((__v4si) __A, (__v4si) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_broadcastd_epi32 (__m512i __O, __mmask16 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512(__M, @@ -224,7 +225,7 @@ _mm512_mask_broadcastd_epi32 (__m512i __O, __mmask16 __M, __m128i __A) (__v16si) __O); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512(__M, @@ -232,14 +233,14 @@ _mm512_maskz_broadcastd_epi32 (__mmask16 __M, __m128i __A) (__v16si) _mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_broadcastq_epi64 (__m128i __A) { return (__m512i)__builtin_shufflevector((__v2di) __A, (__v2di) __A, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_broadcastq_epi64 (__m512i __O, __mmask8 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512(__M, @@ -248,7 +249,7 @@ _mm512_mask_broadcastq_epi64 (__m512i __O, __mmask8 __M, __m128i __A) } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512(__M, @@ -257,7 +258,7 @@ _mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_setzero_ps(void) { return __extension__ (__m512){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -266,26 +267,26 @@ _mm512_setzero_ps(void) #define _mm512_setzero _mm512_setzero_ps -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_setzero_pd(void) { return __extension__ (__m512d){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_set1_ps(float __w) { return __extension__ (__m512){ __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w, __w }; } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_set1_pd(double __w) { return __extension__ (__m512d){ __w, __w, __w, __w, __w, __w, __w, __w }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set1_epi8(char __w) { return __extension__ (__m512i)(__v64qi){ @@ -299,7 +300,7 @@ _mm512_set1_epi8(char __w) __w, __w, __w, __w, __w, __w, __w, __w }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set1_epi16(short __w) { return __extension__ (__m512i)(__v32hi){ @@ -309,7 +310,7 @@ _mm512_set1_epi16(short __w) __w, __w, __w, __w, __w, __w, __w, __w }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set1_epi32(int __s) { return __extension__ (__m512i)(__v16si){ @@ -317,7 +318,7 @@ _mm512_set1_epi32(int __s) __s, __s, __s, __s, __s, __s, __s, __s }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_set1_epi32(__mmask16 __M, int __A) { return (__m512i)__builtin_ia32_selectd_512(__M, @@ -325,13 +326,13 @@ _mm512_maskz_set1_epi32(__mmask16 __M, int __A) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set1_epi64(long long __d) { return __extension__(__m512i)(__v8di){ __d, __d, __d, __d, __d, __d, __d, __d }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_set1_epi64(__mmask8 __M, long long __A) { return (__m512i)__builtin_ia32_selectq_512(__M, @@ -339,14 +340,14 @@ _mm512_maskz_set1_epi64(__mmask8 __M, long long __A) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_broadcastss_ps(__m128 __A) { return (__m512)__builtin_shufflevector((__v4sf) __A, (__v4sf) __A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set4_epi32 (int __A, int __B, int __C, int __D) { return __extension__ (__m512i)(__v16si) @@ -354,7 +355,7 @@ _mm512_set4_epi32 (int __A, int __B, int __C, int __D) __D, __C, __B, __A, __D, __C, __B, __A }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set4_epi64 (long long __A, long long __B, long long __C, long long __D) { @@ -362,14 +363,14 @@ _mm512_set4_epi64 (long long __A, long long __B, long long __C, { __D, __C, __B, __A, __D, __C, __B, __A }; } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_set4_pd (double __A, double __B, double __C, double __D) { return __extension__ (__m512d) { __D, __C, __B, __A, __D, __C, __B, __A }; } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_set4_ps (float __A, float __B, float __C, float __D) { return __extension__ (__m512) @@ -389,7 +390,7 @@ _mm512_set4_ps (float __A, float __B, float __C, float __D) #define _mm512_setr4_ps(e0,e1,e2,e3) \ _mm512_set4_ps((e3),(e2),(e1),(e0)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_broadcastsd_pd(__m128d __A) { return (__m512d)__builtin_shufflevector((__v2df) __A, (__v2df) __A, @@ -398,122 +399,122 @@ _mm512_broadcastsd_pd(__m128d __A) /* Cast between vector types */ -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_castpd256_pd512(__m256d __a) { return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, -1, -1, -1, -1); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_castps256_ps512(__m256 __a) { return __builtin_shufflevector(__a, __a, 0, 1, 2, 3, 4, 5, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1); } -static __inline __m128d __DEFAULT_FN_ATTRS +static __inline __m128d __DEFAULT_FN_ATTRS512 _mm512_castpd512_pd128(__m512d __a) { return __builtin_shufflevector(__a, __a, 0, 1); } -static __inline __m256d __DEFAULT_FN_ATTRS +static __inline __m256d __DEFAULT_FN_ATTRS512 _mm512_castpd512_pd256 (__m512d __A) { return __builtin_shufflevector(__A, __A, 0, 1, 2, 3); } -static __inline __m128 __DEFAULT_FN_ATTRS +static __inline __m128 __DEFAULT_FN_ATTRS512 _mm512_castps512_ps128(__m512 __a) { return __builtin_shufflevector(__a, __a, 0, 1, 2, 3); } -static __inline __m256 __DEFAULT_FN_ATTRS +static __inline __m256 __DEFAULT_FN_ATTRS512 _mm512_castps512_ps256 (__m512 __A) { return __builtin_shufflevector(__A, __A, 0, 1, 2, 3, 4, 5, 6, 7); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_castpd_ps (__m512d __A) { return (__m512) (__A); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_castpd_si512 (__m512d __A) { return (__m512i) (__A); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_castpd128_pd512 (__m128d __A) { return __builtin_shufflevector( __A, __A, 0, 1, -1, -1, -1, -1, -1, -1); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_castps_pd (__m512 __A) { return (__m512d) (__A); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_castps_si512 (__m512 __A) { return (__m512i) (__A); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_castps128_ps512 (__m128 __A) { return __builtin_shufflevector( __A, __A, 0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_castsi128_si512 (__m128i __A) { return __builtin_shufflevector( __A, __A, 0, 1, -1, -1, -1, -1, -1, -1); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_castsi256_si512 (__m256i __A) { return __builtin_shufflevector( __A, __A, 0, 1, 2, 3, -1, -1, -1, -1); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_castsi512_ps (__m512i __A) { return (__m512) (__A); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_castsi512_pd (__m512i __A) { return (__m512d) (__A); } -static __inline __m128i __DEFAULT_FN_ATTRS +static __inline __m128i __DEFAULT_FN_ATTRS512 _mm512_castsi512_si128 (__m512i __A) { return (__m128i)__builtin_shufflevector(__A, __A , 0, 1); } -static __inline __m256i __DEFAULT_FN_ATTRS +static __inline __m256i __DEFAULT_FN_ATTRS512 _mm512_castsi512_si256 (__m512i __A) { return (__m256i)__builtin_shufflevector(__A, __A , 0, 1, 2, 3); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_int2mask(int __a) { return (__mmask16)__a; } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask2int(__mmask16 __a) { return (int)__a; @@ -532,7 +533,7 @@ _mm512_mask2int(__mmask16 __a) /// A 128-bit vector of [2 x double]. /// \returns A 512-bit floating-point vector of [8 x double]. The lower 128 bits /// contain the value of the parameter. The upper 384 bits are set to zero. -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_zextpd128_pd512(__m128d __a) { return __builtin_shufflevector((__v2df)__a, (__v2df)_mm_setzero_pd(), 0, 1, 2, 3, 2, 3, 2, 3); @@ -551,7 +552,7 @@ _mm512_zextpd128_pd512(__m128d __a) /// A 256-bit vector of [4 x double]. /// \returns A 512-bit floating-point vector of [8 x double]. The lower 256 bits /// contain the value of the parameter. The upper 256 bits are set to zero. -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_zextpd256_pd512(__m256d __a) { return __builtin_shufflevector((__v4df)__a, (__v4df)_mm256_setzero_pd(), 0, 1, 2, 3, 4, 5, 6, 7); @@ -569,7 +570,7 @@ _mm512_zextpd256_pd512(__m256d __a) /// A 128-bit vector of [4 x float]. /// \returns A 512-bit floating-point vector of [16 x float]. The lower 128 bits /// contain the value of the parameter. The upper 384 bits are set to zero. -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_zextps128_ps512(__m128 __a) { return __builtin_shufflevector((__v4sf)__a, (__v4sf)_mm_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7); @@ -587,7 +588,7 @@ _mm512_zextps128_ps512(__m128 __a) /// A 256-bit vector of [8 x float]. /// \returns A 512-bit floating-point vector of [16 x float]. The lower 256 bits /// contain the value of the parameter. The upper 256 bits are set to zero. -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_zextps256_ps512(__m256 __a) { return __builtin_shufflevector((__v8sf)__a, (__v8sf)_mm256_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); @@ -605,7 +606,7 @@ _mm512_zextps256_ps512(__m256 __a) /// A 128-bit integer vector. /// \returns A 512-bit integer vector. The lower 128 bits contain the value of /// the parameter. The upper 384 bits are set to zero. -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_zextsi128_si512(__m128i __a) { return __builtin_shufflevector((__v2di)__a, (__v2di)_mm_setzero_si128(), 0, 1, 2, 3, 2, 3, 2, 3); @@ -623,20 +624,20 @@ _mm512_zextsi128_si512(__m128i __a) /// A 256-bit integer vector. /// \returns A 512-bit integer vector. The lower 256 bits contain the value of /// the parameter. The upper 256 bits are set to zero. -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_zextsi256_si512(__m256i __a) { return __builtin_shufflevector((__v4di)__a, (__v4di)_mm256_setzero_si256(), 0, 1, 2, 3, 4, 5, 6, 7); } /* Bitwise operators */ -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_and_epi32(__m512i __a, __m512i __b) { return (__m512i)((__v16su)__a & (__v16su)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k, @@ -644,20 +645,20 @@ _mm512_mask_and_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) (__v16si) __src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_and_epi32(__mmask16 __k, __m512i __a, __m512i __b) { return (__m512i) _mm512_mask_and_epi32(_mm512_setzero_si512 (), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_and_epi64(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a & (__v8du)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) { return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __k, @@ -665,26 +666,26 @@ _mm512_mask_and_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) (__v8di) __src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_and_epi64(__mmask8 __k, __m512i __a, __m512i __b) { return (__m512i) _mm512_mask_and_epi64(_mm512_setzero_si512 (), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_andnot_si512 (__m512i __A, __m512i __B) { return (__m512i)(~(__v8du)__A & (__v8du)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_andnot_epi32 (__m512i __A, __m512i __B) { return (__m512i)(~(__v16su)__A & (__v16su)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_andnot_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -692,20 +693,20 @@ _mm512_mask_andnot_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_andnot_epi32(__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)_mm512_mask_andnot_epi32(_mm512_setzero_si512(), __U, __A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_andnot_epi64(__m512i __A, __m512i __B) { return (__m512i)(~(__v8du)__A & (__v8du)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_andnot_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -713,20 +714,20 @@ _mm512_mask_andnot_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_andnot_epi64(__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)_mm512_mask_andnot_epi64(_mm512_setzero_si512(), __U, __A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_or_epi32(__m512i __a, __m512i __b) { return (__m512i)((__v16su)__a | (__v16su)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k, @@ -734,19 +735,19 @@ _mm512_mask_or_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) (__v16si)__src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_or_epi32(__mmask16 __k, __m512i __a, __m512i __b) { return (__m512i)_mm512_mask_or_epi32(_mm512_setzero_si512(), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_or_epi64(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a | (__v8du)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__k, @@ -754,19 +755,19 @@ _mm512_mask_or_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) (__v8di)__src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_or_epi64(__mmask8 __k, __m512i __a, __m512i __b) { return (__m512i)_mm512_mask_or_epi64(_mm512_setzero_si512(), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_xor_epi32(__m512i __a, __m512i __b) { return (__m512i)((__v16su)__a ^ (__v16su)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__k, @@ -774,19 +775,19 @@ _mm512_mask_xor_epi32(__m512i __src, __mmask16 __k, __m512i __a, __m512i __b) (__v16si)__src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_xor_epi32(__mmask16 __k, __m512i __a, __m512i __b) { return (__m512i)_mm512_mask_xor_epi32(_mm512_setzero_si512(), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_xor_epi64(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a ^ (__v8du)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__k, @@ -794,25 +795,25 @@ _mm512_mask_xor_epi64(__m512i __src, __mmask8 __k, __m512i __a, __m512i __b) (__v8di)__src); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_xor_epi64(__mmask8 __k, __m512i __a, __m512i __b) { return (__m512i)_mm512_mask_xor_epi64(_mm512_setzero_si512(), __k, __a, __b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_and_si512(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a & (__v8du)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_or_si512(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a | (__v8du)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_xor_si512(__m512i __a, __m512i __b) { return (__m512i)((__v8du)__a ^ (__v8du)__b); @@ -820,49 +821,49 @@ _mm512_xor_si512(__m512i __a, __m512i __b) /* Arithmetic */ -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_add_pd(__m512d __a, __m512d __b) { return (__m512d)((__v8df)__a + (__v8df)__b); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_add_ps(__m512 __a, __m512 __b) { return (__m512)((__v16sf)__a + (__v16sf)__b); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_mul_pd(__m512d __a, __m512d __b) { return (__m512d)((__v8df)__a * (__v8df)__b); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_mul_ps(__m512 __a, __m512 __b) { return (__m512)((__v16sf)__a * (__v16sf)__b); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_sub_pd(__m512d __a, __m512d __b) { return (__m512d)((__v8df)__a - (__v8df)__b); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_sub_ps(__m512 __a, __m512 __b) { return (__m512)((__v16sf)__a - (__v16sf)__b); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_add_epi64 (__m512i __A, __m512i __B) { return (__m512i) ((__v8du) __A + (__v8du) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_add_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -870,7 +871,7 @@ _mm512_mask_add_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_add_epi64(__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -878,13 +879,13 @@ _mm512_maskz_add_epi64(__mmask8 __U, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sub_epi64 (__m512i __A, __m512i __B) { return (__m512i) ((__v8du) __A - (__v8du) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sub_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -892,7 +893,7 @@ _mm512_mask_sub_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sub_epi64(__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -900,13 +901,13 @@ _mm512_maskz_sub_epi64(__mmask8 __U, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_add_epi32 (__m512i __A, __m512i __B) { return (__m512i) ((__v16su) __A + (__v16su) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_add_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -914,7 +915,7 @@ _mm512_mask_add_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -922,13 +923,13 @@ _mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sub_epi32 (__m512i __A, __m512i __B) { return (__m512i) ((__v16su) __A - (__v16su) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sub_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -936,7 +937,7 @@ _mm512_mask_sub_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -958,14 +959,14 @@ _mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B) (__v8df)_mm512_max_round_pd((A), (B), (R)), \ (__v8df)_mm512_setzero_pd()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_max_pd(__m512d __A, __m512d __B) { return (__m512d) __builtin_ia32_maxpd512((__v8df) __A, (__v8df) __B, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -973,7 +974,7 @@ _mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -995,14 +996,14 @@ _mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) (__v16sf)_mm512_max_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps()) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_max_ps(__m512 __A, __m512 __B) { return (__m512) __builtin_ia32_maxps512((__v16sf) __A, (__v16sf) __B, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1010,7 +1011,7 @@ _mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1018,7 +1019,7 @@ _mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_max_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_maxss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -1027,7 +1028,7 @@ _mm_mask_max_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_max_ss(__mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_maxss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -1054,7 +1055,7 @@ _mm_maskz_max_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_max_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_maxsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -1063,7 +1064,7 @@ _mm_mask_max_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_max_sd(__mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_maxsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -1091,13 +1092,13 @@ _mm_maskz_max_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__mmask8)(U), (int)(R)) static __inline __m512i -__DEFAULT_FN_ATTRS +__DEFAULT_FN_ATTRS512 _mm512_max_epi32(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pmaxsd512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_max_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1105,7 +1106,7 @@ _mm512_mask_max_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_max_epi32 (__mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1113,13 +1114,13 @@ _mm512_maskz_max_epi32 (__mmask16 __M, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_max_epu32(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pmaxud512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_max_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1127,7 +1128,7 @@ _mm512_mask_max_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_max_epu32 (__mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1135,13 +1136,13 @@ _mm512_maskz_max_epu32 (__mmask16 __M, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_max_epi64(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pmaxsq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_max_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1149,7 +1150,7 @@ _mm512_mask_max_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_max_epi64 (__mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1157,13 +1158,13 @@ _mm512_maskz_max_epi64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_max_epu64(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pmaxuq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_max_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1171,7 +1172,7 @@ _mm512_mask_max_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1193,14 +1194,14 @@ _mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8df)_mm512_min_round_pd((A), (B), (R)), \ (__v8df)_mm512_setzero_pd()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_min_pd(__m512d __A, __m512d __B) { return (__m512d) __builtin_ia32_minpd512((__v8df) __A, (__v8df) __B, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -1208,7 +1209,7 @@ _mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -1230,14 +1231,14 @@ _mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) (__v16sf)_mm512_min_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps()) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_min_ps(__m512 __A, __m512 __B) { return (__m512) __builtin_ia32_minps512((__v16sf) __A, (__v16sf) __B, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1245,7 +1246,7 @@ _mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1253,7 +1254,7 @@ _mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_min_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_minss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -1262,7 +1263,7 @@ _mm_mask_min_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_min_ss(__mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_minss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -1289,7 +1290,7 @@ _mm_maskz_min_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_min_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_minsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -1298,7 +1299,7 @@ _mm_mask_min_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_min_sd(__mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_minsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -1326,13 +1327,13 @@ _mm_maskz_min_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__mmask8)(U), (int)(R)) static __inline __m512i -__DEFAULT_FN_ATTRS +__DEFAULT_FN_ATTRS512 _mm512_min_epi32(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pminsd512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_min_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1340,7 +1341,7 @@ _mm512_mask_min_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_min_epi32 (__mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1348,13 +1349,13 @@ _mm512_maskz_min_epi32 (__mmask16 __M, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_min_epu32(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pminud512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_min_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1362,7 +1363,7 @@ _mm512_mask_min_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_min_epu32 (__mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1370,13 +1371,13 @@ _mm512_maskz_min_epu32 (__mmask16 __M, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_min_epi64(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pminsq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_min_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1384,7 +1385,7 @@ _mm512_mask_min_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_min_epi64 (__mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1392,13 +1393,13 @@ _mm512_maskz_min_epi64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_min_epu64(__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_pminuq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_min_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1406,7 +1407,7 @@ _mm512_mask_min_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1414,13 +1415,13 @@ _mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mul_epi32(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_pmuldq512((__v16si)__X, (__v16si) __Y); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mul_epi32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1428,7 +1429,7 @@ _mm512_mask_mul_epi32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) (__v8di)__W); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1436,13 +1437,13 @@ _mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y) (__v8di)_mm512_setzero_si512 ()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mul_epu32(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_pmuludq512((__v16si)__X, (__v16si)__Y); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mul_epu32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1450,7 +1451,7 @@ _mm512_mask_mul_epu32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) (__v8di)__W); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_mul_epu32(__mmask8 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -1458,13 +1459,13 @@ _mm512_maskz_mul_epu32(__mmask8 __M, __m512i __X, __m512i __Y) (__v8di)_mm512_setzero_si512 ()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mullo_epi32 (__m512i __A, __m512i __B) { return (__m512i) ((__v16su) __A * (__v16su) __B); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_mullo_epi32(__mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1472,7 +1473,7 @@ _mm512_maskz_mullo_epi32(__mmask16 __M, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mullo_epi32(__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -1480,12 +1481,12 @@ _mm512_mask_mullo_epi32(__m512i __W, __mmask16 __M, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mullox_epi64 (__m512i __A, __m512i __B) { return (__m512i) ((__v8du) __A * (__v8du) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mullox_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, (__v8di)_mm512_mullox_epi64(__A, __B), @@ -1505,14 +1506,14 @@ _mm512_mask_mullox_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { (__v8df)_mm512_sqrt_round_pd((A), (R)), \ (__v8df)_mm512_setzero_pd()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_sqrt_pd(__m512d __A) { return (__m512d)__builtin_ia32_sqrtpd512((__v8df)__A, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -1520,7 +1521,7 @@ _mm512_mask_sqrt_pd (__m512d __W, __mmask8 __U, __m512d __A) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -1541,14 +1542,14 @@ _mm512_maskz_sqrt_pd (__mmask8 __U, __m512d __A) (__v16sf)_mm512_sqrt_round_ps((A), (R)), \ (__v16sf)_mm512_setzero_ps()) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_sqrt_ps(__m512 __A) { return (__m512)__builtin_ia32_sqrtps512((__v16sf)__A, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_sqrt_ps(__m512 __W, __mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1556,7 +1557,7 @@ _mm512_mask_sqrt_ps(__m512 __W, __mmask16 __U, __m512 __A) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -1564,7 +1565,7 @@ _mm512_maskz_sqrt_ps( __mmask16 __U, __m512 __A) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_rsqrt14_pd(__m512d __A) { return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, @@ -1572,7 +1573,7 @@ _mm512_rsqrt14_pd(__m512d __A) _mm512_setzero_pd (), (__mmask8) -1);} -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_rsqrt14_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, @@ -1580,7 +1581,7 @@ _mm512_mask_rsqrt14_pd (__m512d __W, __mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_rsqrt14_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rsqrt14pd512_mask ((__v8df) __A, @@ -1589,7 +1590,7 @@ _mm512_maskz_rsqrt14_pd (__mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_rsqrt14_ps(__m512 __A) { return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, @@ -1598,7 +1599,7 @@ _mm512_rsqrt14_ps(__m512 __A) (__mmask16) -1); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_rsqrt14_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, @@ -1606,7 +1607,7 @@ _mm512_mask_rsqrt14_ps (__m512 __W, __mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_rsqrt14_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rsqrt14ps512_mask ((__v16sf) __A, @@ -1615,7 +1616,7 @@ _mm512_maskz_rsqrt14_ps (__mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_rsqrt14_ss(__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A, @@ -1625,7 +1626,7 @@ _mm_rsqrt14_ss(__m128 __A, __m128 __B) (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_rsqrt14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A, @@ -1634,7 +1635,7 @@ _mm_mask_rsqrt14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_rsqrt14_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A, @@ -1643,7 +1644,7 @@ _mm_maskz_rsqrt14_ss (__mmask8 __U, __m128 __A, __m128 __B) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_rsqrt14_sd(__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __A, @@ -1653,7 +1654,7 @@ _mm_rsqrt14_sd(__m128d __A, __m128d __B) (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_rsqrt14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rsqrt14sd_mask ( (__v2df) __A, @@ -1662,7 +1663,7 @@ _mm_mask_rsqrt14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_rsqrt14_sd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rsqrt14sd_mask ( (__v2df) __A, @@ -1671,7 +1672,7 @@ _mm_maskz_rsqrt14_sd (__mmask8 __U, __m128d __A, __m128d __B) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_rcp14_pd(__m512d __A) { return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, @@ -1680,7 +1681,7 @@ _mm512_rcp14_pd(__m512d __A) (__mmask8) -1); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_rcp14_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, @@ -1688,7 +1689,7 @@ _mm512_mask_rcp14_pd (__m512d __W, __mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_rcp14_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rcp14pd512_mask ((__v8df) __A, @@ -1697,7 +1698,7 @@ _mm512_maskz_rcp14_pd (__mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_rcp14_ps(__m512 __A) { return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, @@ -1706,7 +1707,7 @@ _mm512_rcp14_ps(__m512 __A) (__mmask16) -1); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_rcp14_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, @@ -1714,7 +1715,7 @@ _mm512_mask_rcp14_ps (__m512 __W, __mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_rcp14_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rcp14ps512_mask ((__v16sf) __A, @@ -1723,7 +1724,7 @@ _mm512_maskz_rcp14_ps (__mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_rcp14_ss(__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A, @@ -1733,7 +1734,7 @@ _mm_rcp14_ss(__m128 __A, __m128 __B) (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_rcp14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A, @@ -1742,7 +1743,7 @@ _mm_mask_rcp14_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_rcp14_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A, @@ -1751,7 +1752,7 @@ _mm_maskz_rcp14_ss (__mmask8 __U, __m128 __A, __m128 __B) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_rcp14_sd(__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __A, @@ -1761,7 +1762,7 @@ _mm_rcp14_sd(__m128d __A, __m128d __B) (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_rcp14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rcp14sd_mask ( (__v2df) __A, @@ -1770,7 +1771,7 @@ _mm_mask_rcp14_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_rcp14_sd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_rcp14sd_mask ( (__v2df) __A, @@ -1779,7 +1780,7 @@ _mm_maskz_rcp14_sd (__mmask8 __U, __m128d __A, __m128d __B) (__mmask8) __U); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_floor_ps(__m512 __A) { return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, @@ -1788,7 +1789,7 @@ _mm512_floor_ps(__m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_floor_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, @@ -1797,7 +1798,7 @@ _mm512_mask_floor_ps (__m512 __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_floor_pd(__m512d __A) { return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, @@ -1806,7 +1807,7 @@ _mm512_floor_pd(__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_floor_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, @@ -1815,7 +1816,7 @@ _mm512_mask_floor_pd (__m512d __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_ceil_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, @@ -1824,7 +1825,7 @@ _mm512_mask_ceil_ps (__m512 __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_ceil_ps(__m512 __A) { return (__m512) __builtin_ia32_rndscaleps_mask ((__v16sf) __A, @@ -1833,7 +1834,7 @@ _mm512_ceil_ps(__m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_ceil_pd(__m512d __A) { return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, @@ -1842,7 +1843,7 @@ _mm512_ceil_pd(__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_ceil_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_rndscalepd_mask ((__v8df) __A, @@ -1851,13 +1852,13 @@ _mm512_mask_ceil_pd (__m512d __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_abs_epi64(__m512i __A) { return (__m512i)__builtin_ia32_pabsq512((__v8di)__A); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_abs_epi64 (__m512i __W, __mmask8 __U, __m512i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -1865,7 +1866,7 @@ _mm512_mask_abs_epi64 (__m512i __W, __mmask8 __U, __m512i __A) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_abs_epi64 (__mmask8 __U, __m512i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -1873,13 +1874,13 @@ _mm512_maskz_abs_epi64 (__mmask8 __U, __m512i __A) (__v8di)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_abs_epi32(__m512i __A) { return (__m512i)__builtin_ia32_pabsd512((__v16si) __A); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_abs_epi32 (__m512i __W, __mmask16 __U, __m512i __A) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -1887,7 +1888,7 @@ _mm512_mask_abs_epi32 (__m512i __W, __mmask16 __U, __m512i __A) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_abs_epi32 (__mmask16 __U, __m512i __A) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -1895,14 +1896,14 @@ _mm512_maskz_abs_epi32 (__mmask16 __U, __m512i __A) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -1927,14 +1928,14 @@ _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -1958,28 +1959,28 @@ _mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__v2df)_mm_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_add_pd(__A, __B), (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_add_pd(__A, __B), (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_add_ps(__A, __B), (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_add_ps(__A, __B), @@ -2014,14 +2015,14 @@ _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_add_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps()); -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -2045,14 +2046,14 @@ _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -2077,28 +2078,28 @@ _mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__v2df)_mm_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_sub_pd(__A, __B), (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_sub_pd(__A, __B), (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_sub_ps(__A, __B), (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_sub_ps(__A, __B), @@ -2133,14 +2134,14 @@ _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps()); -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -2164,14 +2165,14 @@ _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : __W[0]; return __A; } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); __A[0] = (__U & 1) ? __A[0] : 0; @@ -2196,28 +2197,28 @@ _mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__v2df)_mm_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_mul_pd(__A, __B), (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_mul_pd(__A, __B), (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_mul_ps(__A, __B), (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_mul_ps(__A, __B), @@ -2252,7 +2253,7 @@ _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps()); -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -2261,7 +2262,7 @@ _mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A, (__v4sf) __B, @@ -2288,7 +2289,7 @@ _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -2297,7 +2298,7 @@ _mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A, (__v2df) __B, @@ -2324,40 +2325,40 @@ _mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) { (__v2df)_mm_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_div_pd(__m512d __a, __m512d __b) { return (__m512d)((__v8df)__a/(__v8df)__b); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_div_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_div_pd(__A, __B), (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, (__v8df)_mm512_div_pd(__A, __B), (__v8df)_mm512_setzero_pd()); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_div_ps(__m512 __a, __m512 __b) { return (__m512)((__v16sf)__a/(__v16sf)__b); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_div_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_div_ps(__A, __B), (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, (__v16sf)_mm512_div_ps(__A, __B), @@ -2540,7 +2541,7 @@ _mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2550,7 +2551,7 @@ _mm512_fmadd_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2560,7 +2561,7 @@ _mm512_mask_fmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d) __builtin_ia32_vfmaddpd512_mask3 ((__v8df) __A, @@ -2570,7 +2571,7 @@ _mm512_mask3_fmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, @@ -2580,7 +2581,7 @@ _mm512_maskz_fmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2590,7 +2591,7 @@ _mm512_fmsub_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2600,7 +2601,7 @@ _mm512_mask_fmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_maskz ((__v8df) __A, @@ -2610,7 +2611,7 @@ _mm512_maskz_fmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2620,7 +2621,7 @@ _mm512_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d) __builtin_ia32_vfmaddpd512_mask3 (-(__v8df) __A, @@ -2630,7 +2631,7 @@ _mm512_mask3_fnmadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A, @@ -2640,7 +2641,7 @@ _mm512_maskz_fnmadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -2650,7 +2651,7 @@ _mm512_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_maskz (-(__v8df) __A, @@ -2744,7 +2745,7 @@ _mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2754,7 +2755,7 @@ _mm512_fmadd_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2764,7 +2765,7 @@ _mm512_mask_fmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512) __builtin_ia32_vfmaddps512_mask3 ((__v16sf) __A, @@ -2774,7 +2775,7 @@ _mm512_mask3_fmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, @@ -2784,7 +2785,7 @@ _mm512_maskz_fmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2794,7 +2795,7 @@ _mm512_fmsub_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2804,7 +2805,7 @@ _mm512_mask_fmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_maskz ((__v16sf) __A, @@ -2814,7 +2815,7 @@ _mm512_maskz_fmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2824,7 +2825,7 @@ _mm512_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512) __builtin_ia32_vfmaddps512_mask3 (-(__v16sf) __A, @@ -2834,7 +2835,7 @@ _mm512_mask3_fnmadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A, @@ -2844,7 +2845,7 @@ _mm512_maskz_fnmadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -2854,7 +2855,7 @@ _mm512_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_maskz (-(__v16sf) __A, @@ -2913,7 +2914,7 @@ _mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, @@ -2923,7 +2924,7 @@ _mm512_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, @@ -2933,7 +2934,7 @@ _mm512_mask_fmaddsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d) __builtin_ia32_vfmaddsubpd512_mask3 ((__v8df) __A, @@ -2943,7 +2944,7 @@ _mm512_mask3_fmaddsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, @@ -2953,7 +2954,7 @@ _mm512_maskz_fmaddsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, @@ -2963,7 +2964,7 @@ _mm512_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_mask ((__v8df) __A, @@ -2973,7 +2974,7 @@ _mm512_mask_fmsubadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddsubpd512_maskz ((__v8df) __A, @@ -3032,7 +3033,7 @@ _mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m512d __C) (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, @@ -3042,7 +3043,7 @@ _mm512_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, @@ -3052,7 +3053,7 @@ _mm512_mask_fmaddsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512) __builtin_ia32_vfmaddsubps512_mask3 ((__v16sf) __A, @@ -3062,7 +3063,7 @@ _mm512_mask3_fmaddsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, @@ -3072,7 +3073,7 @@ _mm512_maskz_fmaddsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, @@ -3082,7 +3083,7 @@ _mm512_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_mask ((__v16sf) __A, @@ -3092,7 +3093,7 @@ _mm512_mask_fmsubadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddsubps512_maskz ((__v16sf) __A, @@ -3109,7 +3110,7 @@ _mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512 __C) (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d)__builtin_ia32_vfmsubpd512_mask3 ((__v8df) __A, @@ -3125,7 +3126,7 @@ _mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) (__v16sf)(__m512)(C), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512)__builtin_ia32_vfmsubps512_mask3 ((__v16sf) __A, @@ -3142,7 +3143,7 @@ _mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d)__builtin_ia32_vfmsubaddpd512_mask3 ((__v8df) __A, @@ -3159,7 +3160,7 @@ _mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512)__builtin_ia32_vfmsubaddps512_mask3 ((__v16sf) __A, @@ -3176,7 +3177,7 @@ _mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -3193,7 +3194,7 @@ _mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -3217,7 +3218,7 @@ _mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) { return (__m512d) __builtin_ia32_vfmaddpd512_mask ((__v8df) __A, @@ -3227,7 +3228,7 @@ _mm512_mask_fnmsub_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512d __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) { return (__m512d) __builtin_ia32_vfmsubpd512_mask3 (-(__v8df) __A, @@ -3251,7 +3252,7 @@ _mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask8 __U) (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) { return (__m512) __builtin_ia32_vfmaddps512_mask ((__v16sf) __A, @@ -3261,7 +3262,7 @@ _mm512_mask_fnmsub_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 __C) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) { return (__m512) __builtin_ia32_vfmsubps512_mask3 (-(__v16sf) __A, @@ -3275,14 +3276,14 @@ _mm512_mask3_fnmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 __U) /* Vector permutations */ -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_permutex2var_epi32(__m512i __A, __m512i __I, __m512i __B) { return (__m512i)__builtin_ia32_vpermi2vard512((__v16si)__A, (__v16si) __I, (__v16si) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_permutex2var_epi32(__m512i __A, __mmask16 __U, __m512i __I, __m512i __B) { @@ -3291,7 +3292,7 @@ _mm512_mask_permutex2var_epi32(__m512i __A, __mmask16 __U, __m512i __I, (__v16si)__A); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask2_permutex2var_epi32(__m512i __A, __m512i __I, __mmask16 __U, __m512i __B) { @@ -3300,7 +3301,7 @@ _mm512_mask2_permutex2var_epi32(__m512i __A, __m512i __I, __mmask16 __U, (__v16si)__I); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_permutex2var_epi32(__mmask16 __U, __m512i __A, __m512i __I, __m512i __B) { @@ -3309,14 +3310,14 @@ _mm512_maskz_permutex2var_epi32(__mmask16 __U, __m512i __A, __m512i __I, (__v16si)_mm512_setzero_si512()); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_permutex2var_epi64(__m512i __A, __m512i __I, __m512i __B) { return (__m512i)__builtin_ia32_vpermi2varq512((__v8di)__A, (__v8di) __I, (__v8di) __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_permutex2var_epi64(__m512i __A, __mmask8 __U, __m512i __I, __m512i __B) { @@ -3325,7 +3326,7 @@ _mm512_mask_permutex2var_epi64(__m512i __A, __mmask8 __U, __m512i __I, (__v8di)__A); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask2_permutex2var_epi64(__m512i __A, __m512i __I, __mmask8 __U, __m512i __B) { @@ -3334,7 +3335,7 @@ _mm512_mask2_permutex2var_epi64(__m512i __A, __m512i __I, __mmask8 __U, (__v8di)__I); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, __m512i __B) { @@ -3404,7 +3405,7 @@ _mm512_maskz_permutex2var_epi64(__mmask8 __U, __m512i __A, __m512i __I, /* Vector Blend */ -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W) { return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U, @@ -3412,7 +3413,7 @@ _mm512_mask_blend_pd(__mmask8 __U, __m512d __A, __m512d __W) (__v8df) __A); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W) { return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U, @@ -3420,7 +3421,7 @@ _mm512_mask_blend_ps(__mmask16 __U, __m512 __A, __m512 __W) (__v16sf) __A); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W) { return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U, @@ -3428,7 +3429,7 @@ _mm512_mask_blend_epi64(__mmask8 __U, __m512i __A, __m512i __W) (__v8di) __A); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W) { return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U, @@ -3566,7 +3567,7 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W) (__mmask16)(U), (int)(R)) -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_cvttps_epu32(__m512 __A) { return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, @@ -3576,7 +3577,7 @@ _mm512_cvttps_epu32(__m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, @@ -3585,7 +3586,7 @@ _mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvttps2udq512_mask ((__v16sf) __A, @@ -3624,13 +3625,13 @@ _mm512_maskz_cvttps_epu32 (__mmask16 __U, __m512 __A) (__v16sf)_mm512_setzero_ps(), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_cvtepu32_ps (__m512i __A) { return (__m512)__builtin_convertvector((__v16su)__A, __v16sf); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu32_ps (__m512 __W, __mmask16 __U, __m512i __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -3638,7 +3639,7 @@ _mm512_mask_cvtepu32_ps (__m512 __W, __mmask16 __U, __m512i __A) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -3646,13 +3647,13 @@ _mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A) (__v16sf)_mm512_setzero_ps()); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtepi32_pd(__m256i __A) { return (__m512d)__builtin_convertvector((__v8si)__A, __v8df); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -3660,7 +3661,7 @@ _mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -3668,25 +3669,25 @@ _mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtepi32lo_pd(__m512i __A) { return (__m512d) _mm512_cvtepi32_pd(_mm512_castsi512_si256(__A)); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32lo_pd(__m512d __W, __mmask8 __U,__m512i __A) { return (__m512d) _mm512_mask_cvtepi32_pd(__W, __U, _mm512_castsi512_si256(__A)); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_cvtepi32_ps (__m512i __A) { return (__m512)__builtin_convertvector((__v16si)__A, __v16sf); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_ps (__m512 __W, __mmask16 __U, __m512i __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -3694,7 +3695,7 @@ _mm512_mask_cvtepi32_ps (__m512 __W, __mmask16 __U, __m512i __A) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -3702,13 +3703,13 @@ _mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A) (__v16sf)_mm512_setzero_ps()); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtepu32_pd(__m256i __A) { return (__m512d)__builtin_convertvector((__v8su)__A, __v8df); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -3716,7 +3717,7 @@ _mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -3724,13 +3725,13 @@ _mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtepu32lo_pd(__m512i __A) { return (__m512d) _mm512_cvtepu32_pd(_mm512_castsi512_si256(__A)); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu32lo_pd(__m512d __W, __mmask8 __U,__m512i __A) { return (__m512d) _mm512_mask_cvtepu32_pd(__W, __U, _mm512_castsi512_si256(__A)); @@ -3751,7 +3752,7 @@ _mm512_mask_cvtepu32lo_pd(__m512d __W, __mmask8 __U,__m512i __A) (__v8sf)_mm256_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS512 _mm512_cvtpd_ps (__m512d __A) { return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, @@ -3760,7 +3761,7 @@ _mm512_cvtpd_ps (__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS512 _mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A) { return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, @@ -3769,7 +3770,7 @@ _mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A) { return (__m256) __builtin_ia32_cvtpd2ps512_mask ((__v8df) __A, @@ -3778,7 +3779,7 @@ _mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_cvtpd_pslo (__m512d __A) { return (__m512) __builtin_shufflevector((__v8sf) _mm512_cvtpd_ps(__A), @@ -3786,7 +3787,7 @@ _mm512_cvtpd_pslo (__m512d __A) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_cvtpd_pslo (__m512 __W, __mmask8 __U,__m512d __A) { return (__m512) __builtin_shufflevector ( @@ -3842,7 +3843,7 @@ _mm512_mask_cvtpd_pslo (__m512 __W, __mmask8 __U,__m512d __A) (__mmask16)(U), (int)(R)) -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_cvtph_ps(__m256i __A) { return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, @@ -3852,7 +3853,7 @@ _mm512_cvtph_ps(__m256i __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_cvtph_ps (__m512 __W, __mmask16 __U, __m256i __A) { return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, @@ -3861,7 +3862,7 @@ _mm512_mask_cvtph_ps (__m512 __W, __mmask16 __U, __m256i __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtph_ps (__mmask16 __U, __m256i __A) { return (__m512) __builtin_ia32_vcvtph2ps512_mask ((__v16hi) __A, @@ -3885,7 +3886,7 @@ _mm512_maskz_cvtph_ps (__mmask16 __U, __m256i __A) (__v8si)_mm256_setzero_si256(), \ (__mmask8)(U), (int)(R)) -static __inline __m256i __DEFAULT_FN_ATTRS +static __inline __m256i __DEFAULT_FN_ATTRS512 _mm512_cvttpd_epi32(__m512d __a) { return (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df) __a, @@ -3894,7 +3895,7 @@ _mm512_cvttpd_epi32(__m512d __a) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvttpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, @@ -3903,7 +3904,7 @@ _mm512_mask_cvttpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvttpd_epi32 (__mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvttpd2dq512_mask ((__v8df) __A, @@ -3927,7 +3928,7 @@ _mm512_maskz_cvttpd_epi32 (__mmask8 __U, __m512d __A) (__v16si)_mm512_setzero_si512(), \ (__mmask16)(U), (int)(R)) -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_cvttps_epi32(__m512 __a) { return (__m512i) @@ -3936,7 +3937,7 @@ _mm512_cvttps_epi32(__m512 __a) (__mmask16) -1, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvttps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, @@ -3945,7 +3946,7 @@ _mm512_mask_cvttps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvttps_epi32 (__mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvttps2dq512_mask ((__v16sf) __A, @@ -3969,7 +3970,7 @@ _mm512_maskz_cvttps_epi32 (__mmask16 __U, __m512 __A) (__v16si)_mm512_setzero_si512(), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtps_epi32 (__m512 __A) { return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, @@ -3978,7 +3979,7 @@ _mm512_cvtps_epi32 (__m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, @@ -3987,7 +3988,7 @@ _mm512_mask_cvtps_epi32 (__m512i __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtps_epi32 (__mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvtps2dq512_mask ((__v16sf) __A, @@ -4012,7 +4013,7 @@ _mm512_maskz_cvtps_epi32 (__mmask16 __U, __m512 __A) (__v8si)_mm256_setzero_si256(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtpd_epi32 (__m512d __A) { return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, @@ -4022,7 +4023,7 @@ _mm512_cvtpd_epi32 (__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, @@ -4031,7 +4032,7 @@ _mm512_mask_cvtpd_epi32 (__m256i __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtpd_epi32 (__mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvtpd2dq512_mask ((__v8df) __A, @@ -4056,7 +4057,7 @@ _mm512_maskz_cvtpd_epi32 (__mmask8 __U, __m512d __A) (__v16si)_mm512_setzero_si512(), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtps_epu32 ( __m512 __A) { return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A,\ @@ -4066,7 +4067,7 @@ _mm512_cvtps_epu32 ( __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, @@ -4075,7 +4076,7 @@ _mm512_mask_cvtps_epu32 (__m512i __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtps_epu32 ( __mmask16 __U, __m512 __A) { return (__m512i) __builtin_ia32_cvtps2udq512_mask ((__v16sf) __A, @@ -4100,7 +4101,7 @@ _mm512_maskz_cvtps_epu32 ( __mmask16 __U, __m512 __A) (__v8si)_mm256_setzero_si256(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtpd_epu32 (__m512d __A) { return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, @@ -4110,7 +4111,7 @@ _mm512_cvtpd_epu32 (__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, @@ -4119,7 +4120,7 @@ _mm512_mask_cvtpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtpd_epu32 (__mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvtpd2udq512_mask ((__v8df) __A, @@ -4129,13 +4130,13 @@ _mm512_maskz_cvtpd_epu32 (__mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_cvtsd_f64(__m512d __a) { return __a[0]; } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_cvtss_f32(__m512 __a) { return __a[0]; @@ -4143,14 +4144,14 @@ _mm512_cvtss_f32(__m512 __a) /* Unpack and Interleave */ -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_unpackhi_pd(__m512d __a, __m512d __b) { return (__m512d)__builtin_shufflevector((__v8df)__a, (__v8df)__b, 1, 9, 1+2, 9+2, 1+4, 9+4, 1+6, 9+6); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_unpackhi_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -4158,7 +4159,7 @@ _mm512_mask_unpackhi_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_unpackhi_pd(__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -4166,14 +4167,14 @@ _mm512_maskz_unpackhi_pd(__mmask8 __U, __m512d __A, __m512d __B) (__v8df)_mm512_setzero_pd()); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_unpacklo_pd(__m512d __a, __m512d __b) { return (__m512d)__builtin_shufflevector((__v8df)__a, (__v8df)__b, 0, 8, 0+2, 8+2, 0+4, 8+4, 0+6, 8+6); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_unpacklo_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -4181,7 +4182,7 @@ _mm512_mask_unpacklo_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_unpacklo_pd (__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U, @@ -4189,7 +4190,7 @@ _mm512_maskz_unpacklo_pd (__mmask8 __U, __m512d __A, __m512d __B) (__v8df)_mm512_setzero_pd()); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_unpackhi_ps(__m512 __a, __m512 __b) { return (__m512)__builtin_shufflevector((__v16sf)__a, (__v16sf)__b, @@ -4199,7 +4200,7 @@ _mm512_unpackhi_ps(__m512 __a, __m512 __b) 2+12, 18+12, 3+12, 19+12); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_unpackhi_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16) __U, @@ -4207,7 +4208,7 @@ _mm512_mask_unpackhi_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_unpackhi_ps (__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16) __U, @@ -4215,7 +4216,7 @@ _mm512_maskz_unpackhi_ps (__mmask16 __U, __m512 __A, __m512 __B) (__v16sf)_mm512_setzero_ps()); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_unpacklo_ps(__m512 __a, __m512 __b) { return (__m512)__builtin_shufflevector((__v16sf)__a, (__v16sf)__b, @@ -4225,7 +4226,7 @@ _mm512_unpacklo_ps(__m512 __a, __m512 __b) 0+12, 16+12, 1+12, 17+12); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_unpacklo_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16) __U, @@ -4233,7 +4234,7 @@ _mm512_mask_unpacklo_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_unpacklo_ps (__mmask16 __U, __m512 __A, __m512 __B) { return (__m512)__builtin_ia32_selectps_512((__mmask16) __U, @@ -4241,7 +4242,7 @@ _mm512_maskz_unpacklo_ps (__mmask16 __U, __m512 __A, __m512 __B) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_unpackhi_epi32(__m512i __A, __m512i __B) { return (__m512i)__builtin_shufflevector((__v16si)__A, (__v16si)__B, @@ -4251,7 +4252,7 @@ _mm512_unpackhi_epi32(__m512i __A, __m512i __B) 2+12, 18+12, 3+12, 19+12); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_unpackhi_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U, @@ -4259,7 +4260,7 @@ _mm512_mask_unpackhi_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_unpackhi_epi32(__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U, @@ -4267,7 +4268,7 @@ _mm512_maskz_unpackhi_epi32(__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_unpacklo_epi32(__m512i __A, __m512i __B) { return (__m512i)__builtin_shufflevector((__v16si)__A, (__v16si)__B, @@ -4277,7 +4278,7 @@ _mm512_unpacklo_epi32(__m512i __A, __m512i __B) 0+12, 16+12, 1+12, 17+12); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_unpacklo_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U, @@ -4285,7 +4286,7 @@ _mm512_mask_unpacklo_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_unpacklo_epi32(__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16) __U, @@ -4293,14 +4294,14 @@ _mm512_maskz_unpacklo_epi32(__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_unpackhi_epi64(__m512i __A, __m512i __B) { return (__m512i)__builtin_shufflevector((__v8di)__A, (__v8di)__B, 1, 9, 1+2, 9+2, 1+4, 9+4, 1+6, 9+6); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_unpackhi_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U, @@ -4308,7 +4309,7 @@ _mm512_mask_unpackhi_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_unpackhi_epi64(__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U, @@ -4316,14 +4317,14 @@ _mm512_maskz_unpackhi_epi64(__mmask8 __U, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_unpacklo_epi64 (__m512i __A, __m512i __B) { return (__m512i)__builtin_shufflevector((__v8di)__A, (__v8di)__B, 0, 8, 0+2, 8+2, 0+4, 8+4, 0+6, 8+6); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_unpacklo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U, @@ -4331,7 +4332,7 @@ _mm512_mask_unpacklo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8) __U, @@ -4342,7 +4343,7 @@ _mm512_maskz_unpacklo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) /* SIMD load ops */ -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_loadu_si512 (void const *__P) { struct __loadu_si512 { @@ -4351,7 +4352,7 @@ _mm512_loadu_si512 (void const *__P) return ((struct __loadu_si512*)__P)->__v; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P, @@ -4360,7 +4361,7 @@ _mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P) } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *)__P, @@ -4369,7 +4370,7 @@ _mm512_maskz_loadu_epi32(__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P, @@ -4377,7 +4378,7 @@ _mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *)__P, @@ -4386,7 +4387,7 @@ _mm512_maskz_loadu_epi64(__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_loadu_ps (__m512 __W, __mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_loadups512_mask ((const float *) __P, @@ -4394,7 +4395,7 @@ _mm512_mask_loadu_ps (__m512 __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_loadu_ps(__mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_loadups512_mask ((const float *)__P, @@ -4403,7 +4404,7 @@ _mm512_maskz_loadu_ps(__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_loadu_pd (__m512d __W, __mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_loadupd512_mask ((const double *) __P, @@ -4411,7 +4412,7 @@ _mm512_mask_loadu_pd (__m512d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_loadu_pd(__mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_loadupd512_mask ((const double *)__P, @@ -4420,7 +4421,7 @@ _mm512_maskz_loadu_pd(__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_loadu_pd(void const *__p) { struct __loadu_pd { @@ -4429,7 +4430,7 @@ _mm512_loadu_pd(void const *__p) return ((struct __loadu_pd*)__p)->__v; } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_loadu_ps(void const *__p) { struct __loadu_ps { @@ -4438,13 +4439,13 @@ _mm512_loadu_ps(void const *__p) return ((struct __loadu_ps*)__p)->__v; } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_load_ps(void const *__p) { return *(__m512*)__p; } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_load_ps (__m512 __W, __mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *) __P, @@ -4452,7 +4453,7 @@ _mm512_mask_load_ps (__m512 __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_load_ps(__mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_loadaps512_mask ((const __v16sf *)__P, @@ -4461,13 +4462,13 @@ _mm512_maskz_load_ps(__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_load_pd(void const *__p) { return *(__m512d*)__p; } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_load_pd (__m512d __W, __mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *) __P, @@ -4475,7 +4476,7 @@ _mm512_mask_load_pd (__m512d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_load_pd(__mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_loadapd512_mask ((const __v8df *)__P, @@ -4484,19 +4485,19 @@ _mm512_maskz_load_pd(__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_load_si512 (void const *__P) { return *(__m512i *) __P; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_load_epi32 (void const *__P) { return *(__m512i *) __P; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_load_epi64 (void const *__P) { return *(__m512i *) __P; @@ -4504,14 +4505,14 @@ _mm512_load_epi64 (void const *__P) /* SIMD store ops */ -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A) { __builtin_ia32_storedqudi512_mask ((long long *)__P, (__v8di) __A, (__mmask8) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_storeu_si512 (void *__P, __m512i __A) { struct __storeu_si512 { @@ -4520,20 +4521,20 @@ _mm512_storeu_si512 (void *__P, __m512i __A) ((struct __storeu_si512*)__P)->__v = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A) { __builtin_ia32_storedqusi512_mask ((int *)__P, (__v16si) __A, (__mmask16) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_storeu_pd(void *__P, __mmask8 __U, __m512d __A) { __builtin_ia32_storeupd512_mask ((double *)__P, (__v8df) __A, (__mmask8) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_storeu_pd(void *__P, __m512d __A) { struct __storeu_pd { @@ -4542,14 +4543,14 @@ _mm512_storeu_pd(void *__P, __m512d __A) ((struct __storeu_pd*)__P)->__v = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_storeu_ps(void *__P, __mmask16 __U, __m512 __A) { __builtin_ia32_storeups512_mask ((float *)__P, (__v16sf) __A, (__mmask16) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_storeu_ps(void *__P, __m512 __A) { struct __storeu_ps { @@ -4558,44 +4559,44 @@ _mm512_storeu_ps(void *__P, __m512 __A) ((struct __storeu_ps*)__P)->__v = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_store_pd(void *__P, __mmask8 __U, __m512d __A) { __builtin_ia32_storeapd512_mask ((__v8df *)__P, (__v8df) __A, (__mmask8) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_store_pd(void *__P, __m512d __A) { *(__m512d*)__P = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_mask_store_ps(void *__P, __mmask16 __U, __m512 __A) { __builtin_ia32_storeaps512_mask ((__v16sf *)__P, (__v16sf) __A, (__mmask16) __U); } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_store_ps(void *__P, __m512 __A) { *(__m512*)__P = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_store_si512 (void *__P, __m512i __A) { *(__m512i *) __P = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_store_epi32 (void *__P, __m512i __A) { *(__m512i *) __P = __A; } -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS512 _mm512_store_epi64 (void *__P, __m512i __A) { *(__m512i *) __P = __A; @@ -4603,7 +4604,7 @@ _mm512_store_epi64 (void *__P, __m512i __A) /* Mask ops */ -static __inline __mmask16 __DEFAULT_FN_ATTRS +static __inline __mmask16 __DEFAULT_FN_ATTRS512 _mm512_knot(__mmask16 __M) { return __builtin_ia32_knothi(__M); @@ -4711,7 +4712,7 @@ _mm512_knot(__mmask16 __M) #define _mm512_mask_cmpneq_epu64_mask(k, A, B) \ _mm512_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepi8_epi32(__m128i __A) { /* This function always performs a signed extension, but __v16qi is a char @@ -4719,7 +4720,7 @@ _mm512_cvtepi8_epi32(__m128i __A) return (__m512i)__builtin_convertvector((__v16qs)__A, __v16si); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4727,7 +4728,7 @@ _mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4735,7 +4736,7 @@ _mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepi8_epi64(__m128i __A) { /* This function always performs a signed extension, but __v16qi is a char @@ -4743,7 +4744,7 @@ _mm512_cvtepi8_epi64(__m128i __A) return (__m512i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__A, (__v16qs)__A, 0, 1, 2, 3, 4, 5, 6, 7), __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4751,7 +4752,7 @@ _mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4759,13 +4760,13 @@ _mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) (__v8di)_mm512_setzero_si512 ()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepi32_epi64(__m256i __X) { return (__m512i)__builtin_convertvector((__v8si)__X, __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4773,7 +4774,7 @@ _mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4781,13 +4782,13 @@ _mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepi16_epi32(__m256i __A) { return (__m512i)__builtin_convertvector((__v16hi)__A, __v16si); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4795,7 +4796,7 @@ _mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4803,13 +4804,13 @@ _mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A) (__v16si)_mm512_setzero_si512 ()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepi16_epi64(__m128i __A) { return (__m512i)__builtin_convertvector((__v8hi)__A, __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4817,7 +4818,7 @@ _mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4825,13 +4826,13 @@ _mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepu8_epi32(__m128i __A) { return (__m512i)__builtin_convertvector((__v16qu)__A, __v16si); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4839,7 +4840,7 @@ _mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4847,13 +4848,13 @@ _mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepu8_epi64(__m128i __A) { return (__m512i)__builtin_convertvector(__builtin_shufflevector((__v16qu)__A, (__v16qu)__A, 0, 1, 2, 3, 4, 5, 6, 7), __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4861,7 +4862,7 @@ _mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4869,13 +4870,13 @@ _mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepu32_epi64(__m256i __X) { return (__m512i)__builtin_convertvector((__v8su)__X, __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4883,7 +4884,7 @@ _mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4891,13 +4892,13 @@ _mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepu16_epi32(__m256i __A) { return (__m512i)__builtin_convertvector((__v16hu)__A, __v16si); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4905,7 +4906,7 @@ _mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -4913,13 +4914,13 @@ _mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_cvtepu16_epi64(__m128i __A) { return (__m512i)__builtin_convertvector((__v8hu)__A, __v8di); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4927,7 +4928,7 @@ _mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -4935,13 +4936,13 @@ _mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_rorv_epi32 (__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_prorvd512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_rorv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -4949,7 +4950,7 @@ _mm512_mask_rorv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_rorv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -4957,13 +4958,13 @@ _mm512_maskz_rorv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_rorv_epi64 (__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_prorvq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_rorv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512(__U, @@ -4971,7 +4972,7 @@ _mm512_mask_rorv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512(__U, @@ -5047,13 +5048,13 @@ _mm512_maskz_rorv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) (__v8di)_mm512_rol_epi64((a), (b)), \ (__v8di)_mm512_setzero_si512()) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_rolv_epi32 (__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_prolvd512((__v16si)__A, (__v16si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_rolv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -5061,7 +5062,7 @@ _mm512_mask_rolv_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_rolv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectd_512(__U, @@ -5069,13 +5070,13 @@ _mm512_maskz_rolv_epi32 (__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_rolv_epi64 (__m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_prolvq512((__v8di)__A, (__v8di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_rolv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512(__U, @@ -5083,7 +5084,7 @@ _mm512_mask_rolv_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) { return (__m512i)__builtin_ia32_selectq_512(__U, @@ -5117,13 +5118,13 @@ _mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B) (__v8di)_mm512_ror_epi64((A), (B)), \ (__v8di)_mm512_setzero_si512()) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_slli_epi32(__m512i __A, int __B) { return (__m512i)__builtin_ia32_pslldi512((__v16si)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5131,20 +5132,20 @@ _mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_slli_epi32(__mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, (__v16si)_mm512_slli_epi32(__A, __B), (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_slli_epi64(__m512i __A, int __B) { return (__m512i)__builtin_ia32_psllqi512((__v8di)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5152,7 +5153,7 @@ _mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5160,13 +5161,13 @@ _mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A, int __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srli_epi32(__m512i __A, int __B) { return (__m512i)__builtin_ia32_psrldi512((__v16si)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5174,20 +5175,20 @@ _mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srli_epi32(__mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, (__v16si)_mm512_srli_epi32(__A, __B), (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srli_epi64(__m512i __A, int __B) { return (__m512i)__builtin_ia32_psrlqi512((__v8di)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5195,7 +5196,7 @@ _mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5203,7 +5204,7 @@ _mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A, int __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P, @@ -5211,7 +5212,7 @@ _mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_load_epi32 (__mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_movdqa32load512_mask ((const __v16si *) __P, @@ -5220,14 +5221,14 @@ _mm512_maskz_load_epi32 (__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_store_epi32 (void *__P, __mmask16 __U, __m512i __A) { __builtin_ia32_movdqa32store512_mask ((__v16si *) __P, (__v16si) __A, (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mov_epi32 (__m512i __W, __mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U, @@ -5235,7 +5236,7 @@ _mm512_mask_mov_epi32 (__m512i __W, __mmask16 __U, __m512i __A) (__v16si) __W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_mov_epi32 (__mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_selectd_512 ((__mmask16) __U, @@ -5243,7 +5244,7 @@ _mm512_maskz_mov_epi32 (__mmask16 __U, __m512i __A) (__v16si) _mm512_setzero_si512 ()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_mov_epi64 (__m512i __W, __mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U, @@ -5251,7 +5252,7 @@ _mm512_mask_mov_epi64 (__m512i __W, __mmask8 __U, __m512i __A) (__v8di) __W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_mov_epi64 (__mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_selectq_512 ((__mmask8) __U, @@ -5259,7 +5260,7 @@ _mm512_maskz_mov_epi64 (__mmask8 __U, __m512i __A) (__v8di) _mm512_setzero_si512 ()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_load_epi64 (__m512i __W, __mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P, @@ -5267,7 +5268,7 @@ _mm512_mask_load_epi64 (__m512i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_load_epi64 (__mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_movdqa64load512_mask ((const __v8di *) __P, @@ -5276,21 +5277,21 @@ _mm512_maskz_load_epi64 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_store_epi64 (void *__P, __mmask8 __U, __m512i __A) { __builtin_ia32_movdqa64store512_mask ((__v8di *) __P, (__v8di) __A, (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_movedup_pd (__m512d __A) { return (__m512d)__builtin_shufflevector((__v8df)__A, (__v8df)__A, 0, 0, 2, 2, 4, 4, 6, 6); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_movedup_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -5298,7 +5299,7 @@ _mm512_mask_movedup_pd (__m512d __W, __mmask8 __U, __m512d __A) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_movedup_pd (__mmask8 __U, __m512d __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -5471,14 +5472,14 @@ _mm512_maskz_movedup_pd (__mmask8 __U, __m512d __A) (__mmask8)-1, (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_getexp_sd (__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_getexpsd128_round_mask ((__v2df) __A, (__v2df) __B, (__v2df) _mm_setzero_pd(), (__mmask8) -1, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_getexpsd128_round_mask ( (__v2df) __A, @@ -5494,7 +5495,7 @@ _mm_mask_getexp_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)(__m128d)(W), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_getexpsd128_round_mask ( (__v2df) __A, @@ -5516,14 +5517,14 @@ _mm_maskz_getexp_sd (__mmask8 __U, __m128d __A, __m128d __B) (__v4sf)_mm_setzero_ps(), \ (__mmask8)-1, (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_getexp_ss (__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A, (__v4sf) __B, (__v4sf) _mm_setzero_ps(), (__mmask8) -1, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A, @@ -5539,7 +5540,7 @@ _mm_mask_getexp_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(W), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_getexpss128_round_mask ((__v4sf) __A, @@ -5645,7 +5646,7 @@ _mm_maskz_getexp_ss (__mmask8 __U, __m128 __A, __m128 __B) (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kmov (__mmask16 __A) { return __A; @@ -5664,13 +5665,13 @@ _mm512_kmov (__mmask16 __A) (long long)__builtin_ia32_vcvtsd2si64((__v2df)(__m128d)(A), (int)(R)) #endif -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sll_epi32(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_pslld512((__v16si) __A, (__v4si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5678,7 +5679,7 @@ _mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5686,13 +5687,13 @@ _mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sll_epi64(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_psllq512((__v8di)__A, (__v2di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5700,7 +5701,7 @@ _mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5708,13 +5709,13 @@ _mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sllv_epi32(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psllv16si((__v16si)__X, (__v16si)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5722,7 +5723,7 @@ _mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5730,13 +5731,13 @@ _mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sllv_epi64(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psllv8di((__v8di)__X, (__v8di)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5744,7 +5745,7 @@ _mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5752,13 +5753,13 @@ _mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sra_epi32(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_psrad512((__v16si) __A, (__v4si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5766,7 +5767,7 @@ _mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5774,13 +5775,13 @@ _mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_sra_epi64(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_psraq512((__v8di)__A, (__v2di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5788,7 +5789,7 @@ _mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5796,13 +5797,13 @@ _mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srav_epi32(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psrav16si((__v16si)__X, (__v16si)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5810,7 +5811,7 @@ _mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5818,13 +5819,13 @@ _mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srav_epi64(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psrav8di((__v8di)__X, (__v8di)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5832,7 +5833,7 @@ _mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5840,13 +5841,13 @@ _mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srl_epi32(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_psrld512((__v16si) __A, (__v4si)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5854,7 +5855,7 @@ _mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5862,13 +5863,13 @@ _mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srl_epi64(__m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_psrlq512((__v8di)__A, (__v2di)__B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5876,7 +5877,7 @@ _mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5884,13 +5885,13 @@ _mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srlv_epi32(__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psrlv16si((__v16si)__X, (__v16si)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5898,7 +5899,7 @@ _mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -5906,13 +5907,13 @@ _mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srlv_epi64 (__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_psrlv8di((__v8di)__X, (__v8di)__Y); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5920,7 +5921,7 @@ _mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -5978,7 +5979,7 @@ _mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) #define _mm_cvt_roundsd_u32(A, R) \ (unsigned int)__builtin_ia32_vcvtsd2usi32((__v2df)(__m128d)(A), (int)(R)) -static __inline__ unsigned __DEFAULT_FN_ATTRS +static __inline__ unsigned __DEFAULT_FN_ATTRS128 _mm_cvtsd_u32 (__m128d __A) { return (unsigned) __builtin_ia32_vcvtsd2usi32 ((__v2df) __A, @@ -5990,7 +5991,7 @@ _mm_cvtsd_u32 (__m128d __A) (unsigned long long)__builtin_ia32_vcvtsd2usi64((__v2df)(__m128d)(A), \ (int)(R)) -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS128 _mm_cvtsd_u64 (__m128d __A) { return (unsigned long long) __builtin_ia32_vcvtsd2usi64 ((__v2df) @@ -6016,7 +6017,7 @@ _mm_cvtsd_u64 (__m128d __A) #define _mm_cvt_roundss_u32(A, R) \ (unsigned int)__builtin_ia32_vcvtss2usi32((__v4sf)(__m128)(A), (int)(R)) -static __inline__ unsigned __DEFAULT_FN_ATTRS +static __inline__ unsigned __DEFAULT_FN_ATTRS128 _mm_cvtss_u32 (__m128 __A) { return (unsigned) __builtin_ia32_vcvtss2usi32 ((__v4sf) __A, @@ -6028,7 +6029,7 @@ _mm_cvtss_u32 (__m128 __A) (unsigned long long)__builtin_ia32_vcvtss2usi64((__v4sf)(__m128)(A), \ (int)(R)) -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS128 _mm_cvtss_u64 (__m128 __A) { return (unsigned long long) __builtin_ia32_vcvtss2usi64 ((__v4sf) @@ -6043,7 +6044,7 @@ _mm_cvtss_u64 (__m128 __A) #define _mm_cvtt_roundsd_si32(A, R) \ (int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R)) -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_cvttsd_i32 (__m128d __A) { return (int) __builtin_ia32_vcvttsd2si32 ((__v2df) __A, @@ -6057,7 +6058,7 @@ _mm_cvttsd_i32 (__m128d __A) #define _mm_cvtt_roundsd_i64(A, R) \ (long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R)) -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS128 _mm_cvttsd_i64 (__m128d __A) { return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A, @@ -6068,7 +6069,7 @@ _mm_cvttsd_i64 (__m128d __A) #define _mm_cvtt_roundsd_u32(A, R) \ (unsigned int)__builtin_ia32_vcvttsd2usi32((__v2df)(__m128d)(A), (int)(R)) -static __inline__ unsigned __DEFAULT_FN_ATTRS +static __inline__ unsigned __DEFAULT_FN_ATTRS128 _mm_cvttsd_u32 (__m128d __A) { return (unsigned) __builtin_ia32_vcvttsd2usi32 ((__v2df) __A, @@ -6080,7 +6081,7 @@ _mm_cvttsd_u32 (__m128d __A) (unsigned long long)__builtin_ia32_vcvttsd2usi64((__v2df)(__m128d)(A), \ (int)(R)) -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS128 _mm_cvttsd_u64 (__m128d __A) { return (unsigned long long) __builtin_ia32_vcvttsd2usi64 ((__v2df) @@ -6095,7 +6096,7 @@ _mm_cvttsd_u64 (__m128d __A) #define _mm_cvtt_roundss_si32(A, R) \ (int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R)) -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_cvttss_i32 (__m128 __A) { return (int) __builtin_ia32_vcvttss2si32 ((__v4sf) __A, @@ -6109,7 +6110,7 @@ _mm_cvttss_i32 (__m128 __A) #define _mm_cvtt_roundss_si64(A, R) \ (long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R)) -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS128 _mm_cvttss_i64 (__m128 __A) { return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A, @@ -6120,7 +6121,7 @@ _mm_cvttss_i64 (__m128 __A) #define _mm_cvtt_roundss_u32(A, R) \ (unsigned int)__builtin_ia32_vcvttss2usi32((__v4sf)(__m128)(A), (int)(R)) -static __inline__ unsigned __DEFAULT_FN_ATTRS +static __inline__ unsigned __DEFAULT_FN_ATTRS128 _mm_cvttss_u32 (__m128 __A) { return (unsigned) __builtin_ia32_vcvttss2usi32 ((__v4sf) __A, @@ -6132,7 +6133,7 @@ _mm_cvttss_u32 (__m128 __A) (unsigned long long)__builtin_ia32_vcvttss2usi64((__v4sf)(__m128)(A), \ (int)(R)) -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS128 _mm_cvttss_u64 (__m128 __A) { return (unsigned long long) __builtin_ia32_vcvttss2usi64 ((__v4sf) @@ -6167,13 +6168,13 @@ _mm_cvttss_u64 (__m128 __A) (__v16sf)_mm512_permute_ps((X), (C)), \ (__v16sf)_mm512_setzero_ps()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_permutevar_pd(__m512d __A, __m512i __C) { return (__m512d)__builtin_ia32_vpermilvarpd512((__v8df)__A, (__v8di)__C); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -6181,7 +6182,7 @@ _mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -6189,13 +6190,13 @@ _mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_permutevar_ps(__m512 __A, __m512i __C) { return (__m512)__builtin_ia32_vpermilvarps512((__v16sf)__A, (__v16si)__C); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -6203,7 +6204,7 @@ _mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -6211,14 +6212,14 @@ _mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C) (__v16sf)_mm512_setzero_ps()); } -static __inline __m512d __DEFAULT_FN_ATTRS +static __inline __m512d __DEFAULT_FN_ATTRS512 _mm512_permutex2var_pd(__m512d __A, __m512i __I, __m512d __B) { return (__m512d)__builtin_ia32_vpermi2varpd512((__v8df)__A, (__v8di)__I, (__v8df)__B); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_permutex2var_pd(__m512d __A, __mmask8 __U, __m512i __I, __m512d __B) { return (__m512d)__builtin_ia32_selectpd_512(__U, @@ -6226,7 +6227,7 @@ _mm512_mask_permutex2var_pd(__m512d __A, __mmask8 __U, __m512i __I, __m512d __B) (__v8df)__A); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask2_permutex2var_pd(__m512d __A, __m512i __I, __mmask8 __U, __m512d __B) { @@ -6235,7 +6236,7 @@ _mm512_mask2_permutex2var_pd(__m512d __A, __m512i __I, __mmask8 __U, (__v8df)(__m512d)__I); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_permutex2var_pd(__mmask8 __U, __m512d __A, __m512i __I, __m512d __B) { @@ -6244,14 +6245,14 @@ _mm512_maskz_permutex2var_pd(__mmask8 __U, __m512d __A, __m512i __I, (__v8df)_mm512_setzero_pd()); } -static __inline __m512 __DEFAULT_FN_ATTRS +static __inline __m512 __DEFAULT_FN_ATTRS512 _mm512_permutex2var_ps(__m512 __A, __m512i __I, __m512 __B) { return (__m512)__builtin_ia32_vpermi2varps512((__v16sf)__A, (__v16si)__I, (__v16sf) __B); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_permutex2var_ps(__m512 __A, __mmask16 __U, __m512i __I, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -6259,7 +6260,7 @@ _mm512_mask_permutex2var_ps(__m512 __A, __mmask16 __U, __m512i __I, __m512 __B) (__v16sf)__A); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask2_permutex2var_ps(__m512 __A, __m512i __I, __mmask16 __U, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -6267,7 +6268,7 @@ _mm512_mask2_permutex2var_ps(__m512 __A, __m512i __I, __mmask16 __U, __m512 __B) (__v16sf)(__m512)__I); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_permutex2var_ps(__mmask16 __U, __m512 __A, __m512i __I, __m512 __B) { return (__m512)__builtin_ia32_selectps_512(__U, @@ -6291,7 +6292,7 @@ _mm512_maskz_permutex2var_ps(__mmask16 __U, __m512 __A, __m512i __I, __m512 __B) (__v8si)_mm256_setzero_si256(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvttpd_epu32 (__m512d __A) { return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, @@ -6301,7 +6302,7 @@ _mm512_cvttpd_epu32 (__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvttpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, @@ -6310,7 +6311,7 @@ _mm512_mask_cvttpd_epu32 (__m256i __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvttpd_epu32 (__mmask8 __U, __m512d __A) { return (__m256i) __builtin_ia32_cvttpd2udq512_mask ((__v8df) __A, @@ -6422,7 +6423,7 @@ _mm512_maskz_cvttpd_epu32 (__mmask8 __U, __m512d __A) (__v8df)_mm512_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_scalef_pd (__m512d __A, __m512d __B) { return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, @@ -6433,7 +6434,7 @@ _mm512_scalef_pd (__m512d __A, __m512d __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_scalef_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, @@ -6443,7 +6444,7 @@ _mm512_mask_scalef_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_scalef_pd (__mmask8 __U, __m512d __A, __m512d __B) { return (__m512d) __builtin_ia32_scalefpd512_mask ((__v8df) __A, @@ -6472,7 +6473,7 @@ _mm512_maskz_scalef_pd (__mmask8 __U, __m512d __A, __m512d __B) (__v16sf)_mm512_setzero_ps(), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_scalef_ps (__m512 __A, __m512 __B) { return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, @@ -6483,7 +6484,7 @@ _mm512_scalef_ps (__m512 __A, __m512 __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_scalef_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, @@ -6493,7 +6494,7 @@ _mm512_mask_scalef_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_scalef_ps (__mmask16 __U, __m512 __A, __m512 __B) { return (__m512) __builtin_ia32_scalefps512_mask ((__v16sf) __A, @@ -6510,7 +6511,7 @@ _mm512_maskz_scalef_ps (__mmask16 __U, __m512 __A, __m512 __B) (__v2df)_mm_setzero_pd(), \ (__mmask8)-1, (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_scalef_sd (__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefsd_round_mask ((__v2df) __A, @@ -6519,7 +6520,7 @@ _mm_scalef_sd (__m128d __A, __m128d __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_scalef_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefsd_round_mask ( (__v2df) __A, @@ -6535,7 +6536,7 @@ _mm_mask_scalef_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)(__m128d)(W), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_scalef_sd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefsd_round_mask ( (__v2df) __A, @@ -6557,7 +6558,7 @@ _mm_maskz_scalef_sd (__mmask8 __U, __m128d __A, __m128d __B) (__v4sf)_mm_setzero_ps(), \ (__mmask8)-1, (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_scalef_ss (__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefss_round_mask ((__v4sf) __A, @@ -6566,7 +6567,7 @@ _mm_scalef_ss (__m128 __A, __m128 __B) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_scalef_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefss_round_mask ( (__v4sf) __A, @@ -6582,7 +6583,7 @@ _mm_mask_scalef_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(W), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefss_round_mask ( (__v4sf) __A, @@ -6599,13 +6600,13 @@ _mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B) (__mmask8)(U), \ (int)(R)) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srai_epi32(__m512i __A, int __B) { return (__m512i)__builtin_ia32_psradi512((__v16si)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, @@ -6613,20 +6614,20 @@ _mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B) (__v16si)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, (__v16si)_mm512_srai_epi32(__A, __B), (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_srai_epi64(__m512i __A, int __B) { return (__m512i)__builtin_ia32_psraqi512((__v8di)__A, __B); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -6634,7 +6635,7 @@ _mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B) (__v8di)__W); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U, @@ -6732,7 +6733,7 @@ _mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __B) (__v2df)_mm_setzero_pd(), \ (__mmask8)-1, (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_sqrt_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_sqrtsd_round_mask ( (__v2df) __A, @@ -6748,7 +6749,7 @@ _mm_mask_sqrt_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)(__m128d)(W), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_sqrt_sd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_sqrtsd_round_mask ( (__v2df) __A, @@ -6770,7 +6771,7 @@ _mm_maskz_sqrt_sd (__mmask8 __U, __m128d __A, __m128d __B) (__v4sf)_mm_setzero_ps(), \ (__mmask8)-1, (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_sqrt_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_sqrtss_round_mask ( (__v4sf) __A, @@ -6786,7 +6787,7 @@ _mm_mask_sqrt_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(W), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_sqrt_ss (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_sqrtss_round_mask ( (__v4sf) __A, @@ -6802,7 +6803,7 @@ _mm_maskz_sqrt_ss (__mmask8 __U, __m128 __A, __m128 __B) (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_broadcast_f32x4(__m128 __A) { return (__m512)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A, @@ -6810,7 +6811,7 @@ _mm512_broadcast_f32x4(__m128 __A) 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_broadcast_f32x4(__m512 __O, __mmask16 __M, __m128 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__M, @@ -6818,7 +6819,7 @@ _mm512_mask_broadcast_f32x4(__m512 __O, __mmask16 __M, __m128 __A) (__v16sf)__O); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcast_f32x4(__mmask16 __M, __m128 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__M, @@ -6826,14 +6827,14 @@ _mm512_maskz_broadcast_f32x4(__mmask16 __M, __m128 __A) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_broadcast_f64x4(__m256d __A) { return (__m512d)__builtin_shufflevector((__v4df)__A, (__v4df)__A, 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, __m256d __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M, @@ -6841,7 +6842,7 @@ _mm512_mask_broadcast_f64x4(__m512d __O, __mmask8 __M, __m256d __A) (__v8df)__O); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcast_f64x4(__mmask8 __M, __m256d __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__M, @@ -6849,7 +6850,7 @@ _mm512_maskz_broadcast_f64x4(__mmask8 __M, __m256d __A) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_broadcast_i32x4(__m128i __A) { return (__m512i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, @@ -6857,7 +6858,7 @@ _mm512_broadcast_i32x4(__m128i __A) 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_broadcast_i32x4(__m512i __O, __mmask16 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -6865,7 +6866,7 @@ _mm512_mask_broadcast_i32x4(__m512i __O, __mmask16 __M, __m128i __A) (__v16si)__O); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcast_i32x4(__mmask16 __M, __m128i __A) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -6873,14 +6874,14 @@ _mm512_maskz_broadcast_i32x4(__mmask16 __M, __m128i __A) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_broadcast_i64x4(__m256i __A) { return (__m512i)__builtin_shufflevector((__v4di)__A, (__v4di)__A, 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_broadcast_i64x4(__m512i __O, __mmask8 __M, __m256i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -6888,7 +6889,7 @@ _mm512_mask_broadcast_i64x4(__m512i __O, __mmask8 __M, __m256i __A) (__v8di)__O); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i __A) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -6896,7 +6897,7 @@ _mm512_maskz_broadcast_i64x4(__mmask8 __M, __m256i __A) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_broadcastsd_pd (__m512d __O, __mmask8 __M, __m128d __A) { return (__m512d)__builtin_ia32_selectpd_512(__M, @@ -6904,7 +6905,7 @@ _mm512_mask_broadcastsd_pd (__m512d __O, __mmask8 __M, __m128d __A) (__v8df) __O); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) { return (__m512d)__builtin_ia32_selectpd_512(__M, @@ -6912,7 +6913,7 @@ _mm512_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) (__v8df) _mm512_setzero_pd()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_broadcastss_ps (__m512 __O, __mmask16 __M, __m128 __A) { return (__m512)__builtin_ia32_selectps_512(__M, @@ -6920,7 +6921,7 @@ _mm512_mask_broadcastss_ps (__m512 __O, __mmask16 __M, __m128 __A) (__v16sf) __O); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_broadcastss_ps (__mmask16 __M, __m128 __A) { return (__m512)__builtin_ia32_selectps_512(__M, @@ -6928,7 +6929,7 @@ _mm512_maskz_broadcastss_ps (__mmask16 __M, __m128 __A) (__v16sf) _mm512_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtsepi32_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, @@ -6936,14 +6937,14 @@ _mm512_cvtsepi32_epi8 (__m512i __A) (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtsepi32_epi8 (__mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsdb512_mask ((__v16si) __A, @@ -6951,13 +6952,13 @@ _mm512_maskz_cvtsepi32_epi8 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovsdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtsepi32_epi16 (__m512i __A) { return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, @@ -6965,14 +6966,14 @@ _mm512_cvtsepi32_epi16 (__m512i __A) (__mmask16) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, (__v16hi) __O, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtsepi32_epi16 (__mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovsdw512_mask ((__v16si) __A, @@ -6980,13 +6981,13 @@ _mm512_maskz_cvtsepi32_epi16 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovsdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtsepi64_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, @@ -6994,14 +6995,14 @@ _mm512_cvtsepi64_epi8 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtsepi64_epi8 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsqb512_mask ((__v8di) __A, @@ -7009,13 +7010,13 @@ _mm512_maskz_cvtsepi64_epi8 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovsqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtsepi64_epi32 (__m512i __A) { return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, @@ -7023,14 +7024,14 @@ _mm512_cvtsepi64_epi32 (__m512i __A) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, (__v8si) __O, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtsepi64_epi32 (__mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovsqd512_mask ((__v8di) __A, @@ -7038,13 +7039,13 @@ _mm512_maskz_cvtsepi64_epi32 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_storeu_epi32 (void *__P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovsqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtsepi64_epi16 (__m512i __A) { return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, @@ -7052,14 +7053,14 @@ _mm512_cvtsepi64_epi16 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtsepi64_epi16 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovsqw512_mask ((__v8di) __A, @@ -7067,13 +7068,13 @@ _mm512_maskz_cvtsepi64_epi16 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovsqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtusepi32_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, @@ -7081,7 +7082,7 @@ _mm512_cvtusepi32_epi8 (__m512i __A) (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, @@ -7089,7 +7090,7 @@ _mm512_mask_cvtusepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtusepi32_epi8 (__mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusdb512_mask ((__v16si) __A, @@ -7097,13 +7098,13 @@ _mm512_maskz_cvtusepi32_epi8 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovusdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtusepi32_epi16 (__m512i __A) { return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, @@ -7111,7 +7112,7 @@ _mm512_cvtusepi32_epi16 (__m512i __A) (__mmask16) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, @@ -7119,7 +7120,7 @@ _mm512_mask_cvtusepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtusepi32_epi16 (__mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovusdw512_mask ((__v16si) __A, @@ -7127,13 +7128,13 @@ _mm512_maskz_cvtusepi32_epi16 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi32_storeu_epi16 (void *__P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovusdw512mem_mask ((__v16hi*) __P, (__v16si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtusepi64_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, @@ -7141,7 +7142,7 @@ _mm512_cvtusepi64_epi8 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, @@ -7149,7 +7150,7 @@ _mm512_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtusepi64_epi8 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusqb512_mask ((__v8di) __A, @@ -7157,13 +7158,13 @@ _mm512_maskz_cvtusepi64_epi8 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovusqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtusepi64_epi32 (__m512i __A) { return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, @@ -7171,14 +7172,14 @@ _mm512_cvtusepi64_epi32 (__m512i __A) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, (__v8si) __O, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtusepi64_epi32 (__mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovusqd512_mask ((__v8di) __A, @@ -7186,13 +7187,13 @@ _mm512_maskz_cvtusepi64_epi32 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovusqd512mem_mask ((__v8si*) __P, (__v8di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtusepi64_epi16 (__m512i __A) { return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, @@ -7200,14 +7201,14 @@ _mm512_cvtusepi64_epi16 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtusepi64_epi16 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovusqw512_mask ((__v8di) __A, @@ -7215,13 +7216,13 @@ _mm512_maskz_cvtusepi64_epi16 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtusepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovusqw512mem_mask ((__v8hi*) __P, (__v8di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtepi32_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, @@ -7229,14 +7230,14 @@ _mm512_cvtepi32_epi8 (__m512i __A) (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_epi8 (__m128i __O, __mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi32_epi8 (__mmask16 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovdb512_mask ((__v16si) __A, @@ -7244,13 +7245,13 @@ _mm512_maskz_cvtepi32_epi8 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_storeu_epi8 (void * __P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovdb512mem_mask ((__v16qi *) __P, (__v16si) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtepi32_epi16 (__m512i __A) { return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, @@ -7258,14 +7259,14 @@ _mm512_cvtepi32_epi16 (__m512i __A) (__mmask16) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_epi16 (__m256i __O, __mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, (__v16hi) __O, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi32_epi16 (__mmask16 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovdw512_mask ((__v16si) __A, @@ -7273,13 +7274,13 @@ _mm512_maskz_cvtepi32_epi16 (__mmask16 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi32_storeu_epi16 (void * __P, __mmask16 __M, __m512i __A) { __builtin_ia32_pmovdw512mem_mask ((__v16hi *) __P, (__v16si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtepi64_epi8 (__m512i __A) { return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, @@ -7287,14 +7288,14 @@ _mm512_cvtepi64_epi8 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi64_epi8 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovqb512_mask ((__v8di) __A, @@ -7302,13 +7303,13 @@ _mm512_maskz_cvtepi64_epi8 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovqb512mem_mask ((__v16qi *) __P, (__v8di) __A, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_cvtepi64_epi32 (__m512i __A) { return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, @@ -7316,14 +7317,14 @@ _mm512_cvtepi64_epi32 (__m512i __A) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_epi32 (__m256i __O, __mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, (__v8si) __O, __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A) { return (__m256i) __builtin_ia32_pmovqd512_mask ((__v8di) __A, @@ -7331,13 +7332,13 @@ _mm512_maskz_cvtepi64_epi32 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_storeu_epi32 (void* __P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovqd512mem_mask ((__v8si *) __P, (__v8di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_cvtepi64_epi16 (__m512i __A) { return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, @@ -7345,14 +7346,14 @@ _mm512_cvtepi64_epi16 (__m512i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtepi64_epi16 (__mmask8 __M, __m512i __A) { return (__m128i) __builtin_ia32_pmovqw512_mask ((__v8di) __A, @@ -7360,7 +7361,7 @@ _mm512_maskz_cvtepi64_epi16 (__mmask8 __M, __m512i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) { __builtin_ia32_pmovqw512mem_mask ((__v8hi *) __P, (__v8di) __A, __M); @@ -7545,7 +7546,7 @@ _mm512_mask_cvtepi64_storeu_epi16 (void *__P, __mmask8 __M, __m512i __A) (__v8df)_mm512_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_getexp_pd (__m512d __A) { return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, @@ -7554,7 +7555,7 @@ _mm512_getexp_pd (__m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_getexp_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, @@ -7563,7 +7564,7 @@ _mm512_mask_getexp_pd (__m512d __W, __mmask8 __U, __m512d __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_getexp_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_getexppd512_mask ((__v8df) __A, @@ -7587,7 +7588,7 @@ _mm512_maskz_getexp_pd (__mmask8 __U, __m512d __A) (__v16sf)_mm512_setzero_ps(), \ (__mmask16)(U), (int)(R)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_getexp_ps (__m512 __A) { return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, @@ -7596,7 +7597,7 @@ _mm512_getexp_ps (__m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_getexp_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, @@ -7605,7 +7606,7 @@ _mm512_mask_getexp_ps (__m512 __W, __mmask16 __U, __m512 __A) _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_getexpps512_mask ((__v16sf) __A, @@ -7790,7 +7791,7 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) (__v8si)(__m256i)(index), \ (__v8di)(__m512i)(v1), (int)(scale)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7812,7 +7813,7 @@ _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, @@ -7828,7 +7829,7 @@ _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)(__m128)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7844,7 +7845,7 @@ _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) (__v4sf)(__m128)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7866,7 +7867,7 @@ _mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) -(__v4sf)(__m128)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, @@ -7882,7 +7883,7 @@ _mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) -(__v4sf)(__m128)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7898,7 +7899,7 @@ _mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) (__v4sf)(__m128)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7920,7 +7921,7 @@ _mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)(__m128)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, @@ -7936,7 +7937,7 @@ _mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)(__m128)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7952,7 +7953,7 @@ _mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) (__v4sf)(__m128)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -7974,7 +7975,7 @@ _mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) -(__v4sf)(__m128)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, @@ -7990,7 +7991,7 @@ _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) -(__v4sf)(__m128)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, @@ -8006,7 +8007,7 @@ _mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) (__v4sf)(__m128)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8028,7 +8029,7 @@ _mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)(__m128d)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, @@ -8044,7 +8045,7 @@ _mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)(__m128d)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8060,7 +8061,7 @@ _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__v2df)(__m128d)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8082,7 +8083,7 @@ _mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) -(__v2df)(__m128d)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, @@ -8098,7 +8099,7 @@ _mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) -(__v2df)(__m128d)(C), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8114,7 +8115,7 @@ _mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__v2df)(__m128d)(Y), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8136,7 +8137,7 @@ _mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)(__m128d)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, @@ -8152,7 +8153,7 @@ _mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)(__m128d)(C), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8168,7 +8169,7 @@ _mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__v2df)(__m128d)(Y), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8190,7 +8191,7 @@ _mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) -(__v2df)(__m128d)(B), (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, @@ -8207,7 +8208,7 @@ _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__mmask8)(U), \ (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, @@ -8249,13 +8250,13 @@ _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) (__v8di)_mm512_permutex_epi64((X), (C)), \ (__v8di)_mm512_setzero_si512()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_permutexvar_pd (__m512i __X, __m512d __Y) { return (__m512d)__builtin_ia32_permvardf512((__v8df) __Y, (__v8di) __X); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_permutexvar_pd (__m512d __W, __mmask8 __U, __m512i __X, __m512d __Y) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -8263,7 +8264,7 @@ _mm512_mask_permutexvar_pd (__m512d __W, __mmask8 __U, __m512i __X, __m512d __Y) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_permutexvar_pd (__mmask8 __U, __m512i __X, __m512d __Y) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -8271,13 +8272,13 @@ _mm512_maskz_permutexvar_pd (__mmask8 __U, __m512i __X, __m512d __Y) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_permutexvar_epi64 (__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_permvardi512((__v8di)__Y, (__v8di)__X); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_permutexvar_epi64 (__mmask8 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M, @@ -8285,7 +8286,7 @@ _mm512_maskz_permutexvar_epi64 (__mmask8 __M, __m512i __X, __m512i __Y) (__v8di)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_permutexvar_epi64 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) { @@ -8294,13 +8295,13 @@ _mm512_mask_permutexvar_epi64 (__m512i __W, __mmask8 __M, __m512i __X, (__v8di)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_permutexvar_ps (__m512i __X, __m512 __Y) { return (__m512)__builtin_ia32_permvarsf512((__v16sf)__Y, (__v16si)__X); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_permutexvar_ps (__m512 __W, __mmask16 __U, __m512i __X, __m512 __Y) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8308,7 +8309,7 @@ _mm512_mask_permutexvar_ps (__m512 __W, __mmask16 __U, __m512i __X, __m512 __Y) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_permutexvar_ps (__mmask16 __U, __m512i __X, __m512 __Y) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8316,7 +8317,7 @@ _mm512_maskz_permutexvar_ps (__mmask16 __U, __m512i __X, __m512 __Y) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_permutexvar_epi32 (__m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_permvarsi512((__v16si)__Y, (__v16si)__X); @@ -8324,7 +8325,7 @@ _mm512_permutexvar_epi32 (__m512i __X, __m512i __Y) #define _mm512_permutevar_epi32 _mm512_permutexvar_epi32 -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_permutexvar_epi32 (__mmask16 __M, __m512i __X, __m512i __Y) { return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M, @@ -8332,7 +8333,7 @@ _mm512_maskz_permutexvar_epi32 (__mmask16 __M, __m512i __X, __m512i __Y) (__v16si)_mm512_setzero_si512()); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_permutexvar_epi32 (__m512i __W, __mmask16 __M, __m512i __X, __m512i __Y) { @@ -8343,83 +8344,83 @@ _mm512_mask_permutexvar_epi32 (__m512i __W, __mmask16 __M, __m512i __X, #define _mm512_mask_permutevar_epi32 _mm512_mask_permutexvar_epi32 -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kand (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_kandhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kandn (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_kandnhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kor (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_korhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_kortestc (__mmask16 __A, __mmask16 __B) { return __builtin_ia32_kortestchi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_kortestz (__mmask16 __A, __mmask16 __B) { return __builtin_ia32_kortestzhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kunpackb (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kxnor (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_kxnorhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_kxor (__mmask16 __A, __mmask16 __B) { return (__mmask16) __builtin_ia32_kxorhi ((__mmask16) __A, (__mmask16) __B); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_stream_si512 (__m512i * __P, __m512i __A) { typedef __v8di __v8di_aligned __attribute__((aligned(64))); __builtin_nontemporal_store((__v8di_aligned)__A, (__v8di_aligned*)__P); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_stream_load_si512 (void const *__P) { typedef __v8di __v8di_aligned __attribute__((aligned(64))); return (__m512i) __builtin_nontemporal_load((const __v8di_aligned *)__P); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_stream_pd (double *__P, __m512d __A) { typedef __v8df __v8df_aligned __attribute__((aligned(64))); __builtin_nontemporal_store((__v8df_aligned)__A, (__v8df_aligned*)__P); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_stream_ps (float *__P, __m512 __A) { typedef __v16sf __v16sf_aligned __attribute__((aligned(64))); __builtin_nontemporal_store((__v16sf_aligned)__A, (__v16sf_aligned*)__P); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_compress_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A, @@ -8427,7 +8428,7 @@ _mm512_mask_compress_pd (__m512d __W, __mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_compress_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_compressdf512_mask ((__v8df) __A, @@ -8436,7 +8437,7 @@ _mm512_maskz_compress_pd (__mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_compress_epi64 (__m512i __W, __mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A, @@ -8444,7 +8445,7 @@ _mm512_mask_compress_epi64 (__m512i __W, __mmask8 __U, __m512i __A) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_compress_epi64 (__mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_compressdi512_mask ((__v8di) __A, @@ -8453,7 +8454,7 @@ _mm512_maskz_compress_epi64 (__mmask8 __U, __m512i __A) (__mmask8) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_compress_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A, @@ -8461,7 +8462,7 @@ _mm512_mask_compress_ps (__m512 __W, __mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_compress_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_compresssf512_mask ((__v16sf) __A, @@ -8470,7 +8471,7 @@ _mm512_maskz_compress_ps (__mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_compress_epi32 (__m512i __W, __mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A, @@ -8478,7 +8479,7 @@ _mm512_mask_compress_epi32 (__m512i __W, __mmask16 __U, __m512i __A) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_compresssi512_mask ((__v16si) __A, @@ -8533,70 +8534,70 @@ _mm512_maskz_compress_epi32 (__mmask16 __U, __m512i __A) /* Bit Test */ -static __inline __mmask16 __DEFAULT_FN_ATTRS +static __inline __mmask16 __DEFAULT_FN_ATTRS512 _mm512_test_epi32_mask (__m512i __A, __m512i __B) { return _mm512_cmpneq_epi32_mask (_mm512_and_epi32(__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_mask_test_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) { return _mm512_mask_cmpneq_epi32_mask (__U, _mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline __mmask8 __DEFAULT_FN_ATTRS +static __inline __mmask8 __DEFAULT_FN_ATTRS512 _mm512_test_epi64_mask (__m512i __A, __m512i __B) { return _mm512_cmpneq_epi64_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS512 _mm512_mask_test_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) { return _mm512_mask_cmpneq_epi64_mask (__U, _mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_testn_epi32_mask (__m512i __A, __m512i __B) { return _mm512_cmpeq_epi32_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS512 _mm512_mask_testn_epi32_mask (__mmask16 __U, __m512i __A, __m512i __B) { return _mm512_mask_cmpeq_epi32_mask (__U, _mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS512 _mm512_testn_epi64_mask (__m512i __A, __m512i __B) { return _mm512_cmpeq_epi64_mask (_mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS512 _mm512_mask_testn_epi64_mask (__mmask8 __U, __m512i __A, __m512i __B) { return _mm512_mask_cmpeq_epi64_mask (__U, _mm512_and_epi32 (__A, __B), _mm512_setzero_si512()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_movehdup_ps (__m512 __A) { return (__m512)__builtin_shufflevector((__v16sf)__A, (__v16sf)__A, 1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_movehdup_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8604,7 +8605,7 @@ _mm512_mask_movehdup_ps (__m512 __W, __mmask16 __U, __m512 __A) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_movehdup_ps (__mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8612,14 +8613,14 @@ _mm512_maskz_movehdup_ps (__mmask16 __U, __m512 __A) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_moveldup_ps (__m512 __A) { return (__m512)__builtin_shufflevector((__v16sf)__A, (__v16sf)__A, 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_moveldup_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8627,7 +8628,7 @@ _mm512_mask_moveldup_ps (__m512 __W, __mmask16 __U, __m512 __A) (__v16sf)__W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A) { return (__m512)__builtin_ia32_selectps_512((__mmask16)__U, @@ -8635,7 +8636,7 @@ _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A) (__v16sf)_mm512_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __m128 res = __A; @@ -8643,7 +8644,7 @@ _mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) return res; } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) { __m128 res = __A; @@ -8651,7 +8652,7 @@ _mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) return res; } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __m128d res = __A; @@ -8659,7 +8660,7 @@ _mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) return res; } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) { __m128d res = __A; @@ -8667,19 +8668,19 @@ _mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) return res; } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_ss (float * __W, __mmask8 __U, __m128 __A) { __builtin_ia32_storess128_mask ((__v4sf *)__W, __A, __U & 1); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_sd (double * __W, __mmask8 __U, __m128d __A) { __builtin_ia32_storesd128_mask ((__v2df *)__W, __A, __U & 1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_load_ss (__m128 __W, __mmask8 __U, const float* __A) { __m128 src = (__v4sf) __builtin_shufflevector((__v4sf) __W, @@ -8689,7 +8690,7 @@ _mm_mask_load_ss (__m128 __W, __mmask8 __U, const float* __A) return (__m128) __builtin_ia32_loadss128_mask ((__v4sf *) __A, src, __U & 1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_load_ss (__mmask8 __U, const float* __A) { return (__m128)__builtin_ia32_loadss128_mask ((__v4sf *) __A, @@ -8697,7 +8698,7 @@ _mm_maskz_load_ss (__mmask8 __U, const float* __A) __U & 1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_load_sd (__m128d __W, __mmask8 __U, const double* __A) { __m128d src = (__v2df) __builtin_shufflevector((__v2df) __W, @@ -8707,7 +8708,7 @@ _mm_mask_load_sd (__m128d __W, __mmask8 __U, const double* __A) return (__m128d) __builtin_ia32_loadsd128_mask ((__v2df *) __A, src, __U & 1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_load_sd (__mmask8 __U, const double* __A) { return (__m128d) __builtin_ia32_loadsd128_mask ((__v2df *) __A, @@ -8728,7 +8729,7 @@ _mm_maskz_load_sd (__mmask8 __U, const double* __A) (__v16si)_mm512_shuffle_epi32((A), (I)), \ (__v16si)_mm512_setzero_si512()) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_expand_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_expanddf512_mask ((__v8df) __A, @@ -8736,7 +8737,7 @@ _mm512_mask_expand_pd (__m512d __W, __mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_expand_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_expanddf512_mask ((__v8df) __A, @@ -8744,7 +8745,7 @@ _mm512_maskz_expand_pd (__mmask8 __U, __m512d __A) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_expand_epi64 (__m512i __W, __mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A, @@ -8752,7 +8753,7 @@ _mm512_mask_expand_epi64 (__m512i __W, __mmask8 __U, __m512i __A) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_expand_epi64 ( __mmask8 __U, __m512i __A) { return (__m512i) __builtin_ia32_expanddi512_mask ((__v8di) __A, @@ -8760,7 +8761,7 @@ _mm512_maskz_expand_epi64 ( __mmask8 __U, __m512i __A) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_expandloaddf512_mask ((const __v8df *)__P, @@ -8768,7 +8769,7 @@ _mm512_mask_expandloadu_pd(__m512d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P) { return (__m512d) __builtin_ia32_expandloaddf512_mask ((const __v8df *)__P, @@ -8776,7 +8777,7 @@ _mm512_maskz_expandloadu_pd(__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *)__P, @@ -8784,7 +8785,7 @@ _mm512_mask_expandloadu_epi64(__m512i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloaddi512_mask ((const __v8di *)__P, @@ -8792,7 +8793,7 @@ _mm512_maskz_expandloadu_epi64(__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_expandloadsf512_mask ((const __v16sf *)__P, @@ -8800,7 +8801,7 @@ _mm512_mask_expandloadu_ps(__m512 __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P) { return (__m512) __builtin_ia32_expandloadsf512_mask ((const __v16sf *)__P, @@ -8808,7 +8809,7 @@ _mm512_maskz_expandloadu_ps(__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *)__P, @@ -8816,7 +8817,7 @@ _mm512_mask_expandloadu_epi32(__m512i __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_expandloadsi512_mask ((const __v16si *)__P, @@ -8824,7 +8825,7 @@ _mm512_maskz_expandloadu_epi32(__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_expand_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_expandsf512_mask ((__v16sf) __A, @@ -8832,7 +8833,7 @@ _mm512_mask_expand_ps (__m512 __W, __mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_expand_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_expandsf512_mask ((__v16sf) __A, @@ -8840,7 +8841,7 @@ _mm512_maskz_expand_ps (__mmask16 __U, __m512 __A) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_expand_epi32 (__m512i __W, __mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A, @@ -8848,7 +8849,7 @@ _mm512_mask_expand_epi32 (__m512i __W, __mmask16 __U, __m512i __A) (__mmask16) __U); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_maskz_expand_epi32 (__mmask16 __U, __m512i __A) { return (__m512i) __builtin_ia32_expandsi512_mask ((__v16si) __A, @@ -8871,13 +8872,13 @@ _mm512_maskz_expand_epi32 (__mmask16 __U, __m512i __A) (__v8df)_mm512_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtps_pd (__m256 __A) { return (__m512d) __builtin_convertvector((__v8sf)__A, __v8df); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtps_pd (__m512d __W, __mmask8 __U, __m256 __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -8885,7 +8886,7 @@ _mm512_mask_cvtps_pd (__m512d __W, __mmask8 __U, __m256 __A) (__v8df)__W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A) { return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U, @@ -8893,19 +8894,19 @@ _mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A) (__v8df)_mm512_setzero_pd()); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_cvtpslo_pd (__m512 __A) { return (__m512d) _mm512_cvtps_pd(_mm512_castps512_ps256(__A)); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A) { return (__m512d) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A)); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U, @@ -8913,7 +8914,7 @@ _mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A) (__v8df) __W); } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_maskz_mov_pd (__mmask8 __U, __m512d __A) { return (__m512d) __builtin_ia32_selectpd_512 ((__mmask8) __U, @@ -8921,7 +8922,7 @@ _mm512_maskz_mov_pd (__mmask8 __U, __m512d __A) (__v8df) _mm512_setzero_pd ()); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U, @@ -8929,7 +8930,7 @@ _mm512_mask_mov_ps (__m512 __W, __mmask16 __U, __m512 __A) (__v16sf) __W); } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_maskz_mov_ps (__mmask16 __U, __m512 __A) { return (__m512) __builtin_ia32_selectps_512 ((__mmask16) __U, @@ -8937,28 +8938,28 @@ _mm512_maskz_mov_ps (__mmask16 __U, __m512 __A) (__v16sf) _mm512_setzero_ps ()); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m512d __A) { __builtin_ia32_compressstoredf512_mask ((__v8df *) __P, (__v8df) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m512i __A) { __builtin_ia32_compressstoredi512_mask ((__v8di *) __P, (__v8di) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_compressstoreu_ps (void *__P, __mmask16 __U, __m512 __A) { __builtin_ia32_compressstoresf512_mask ((__v16sf *) __P, (__v16sf) __A, (__mmask16) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS512 _mm512_mask_compressstoreu_epi32 (void *__P, __mmask16 __U, __m512i __A) { __builtin_ia32_compressstoresi512_mask ((__v16si *) __P, (__v16si) __A, @@ -8983,7 +8984,7 @@ _mm512_mask_compressstoreu_epi32 (void *__P, __mmask16 __U, __m512i __A) (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtsd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128d __B) { return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)__A, @@ -8992,7 +8993,7 @@ _mm_mask_cvtsd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128d __B) (__mmask8)__U, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B) { return __builtin_ia32_cvtsd2ss_round_mask ((__v4sf)__A, @@ -9056,7 +9057,7 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B) (__v2df)_mm_setzero_pd(), \ (__mmask8)(U), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtss_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128 __B) { return __builtin_ia32_cvtss2sd_round_mask((__v2df)__A, @@ -9065,7 +9066,7 @@ _mm_mask_cvtss_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128 __B) (__mmask8)__U, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtss_sd (__mmask8 __U, __m128d __A, __m128 __B) { return __builtin_ia32_cvtss2sd_round_mask((__v2df)__A, @@ -9074,7 +9075,7 @@ _mm_maskz_cvtss_sd (__mmask8 __U, __m128d __A, __m128 __B) (__mmask8)__U, _MM_FROUND_CUR_DIRECTION); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_cvtu32_sd (__m128d __A, unsigned __B) { __A[0] = __B; @@ -9086,7 +9087,7 @@ _mm_cvtu32_sd (__m128d __A, unsigned __B) (__m128d)__builtin_ia32_cvtusi2sd64((__v2df)(__m128d)(A), \ (unsigned long long)(B), (int)(R)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_cvtu64_sd (__m128d __A, unsigned long long __B) { __A[0] = __B; @@ -9098,7 +9099,7 @@ _mm_cvtu64_sd (__m128d __A, unsigned long long __B) (__m128)__builtin_ia32_cvtusi2ss32((__v4sf)(__m128)(A), (unsigned int)(B), \ (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_cvtu32_ss (__m128 __A, unsigned __B) { __A[0] = __B; @@ -9110,7 +9111,7 @@ _mm_cvtu32_ss (__m128 __A, unsigned __B) (__m128)__builtin_ia32_cvtusi2ss64((__v4sf)(__m128)(A), \ (unsigned long long)(B), (int)(R)) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_cvtu64_ss (__m128 __A, unsigned long long __B) { __A[0] = __B; @@ -9118,7 +9119,7 @@ _mm_cvtu64_ss (__m128 __A, unsigned long long __B) } #endif -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A) { return (__m512i) __builtin_ia32_selectd_512(__M, @@ -9126,7 +9127,7 @@ _mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A) (__v16si) __O); } -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A) { return (__m512i) __builtin_ia32_selectq_512(__M, @@ -9134,7 +9135,7 @@ _mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A) (__v8di) __O); } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set_epi8 (char __e63, char __e62, char __e61, char __e60, char __e59, char __e58, char __e57, char __e56, char __e55, char __e54, char __e53, char __e52, char __e51, char __e50, char __e49, char __e48, char __e47, @@ -9158,7 +9159,7 @@ _mm512_set_epi8 (char __e63, char __e62, char __e61, char __e60, char __e59, __e56, __e57, __e58, __e59, __e60, __e61, __e62, __e63}; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set_epi16(short __e31, short __e30, short __e29, short __e28, short __e27, short __e26, short __e25, short __e24, short __e23, short __e22, short __e21, short __e20, short __e19, short __e18, @@ -9173,7 +9174,7 @@ _mm512_set_epi16(short __e31, short __e30, short __e29, short __e28, __e24, __e25, __e26, __e27, __e28, __e29, __e30, __e31 }; } -static __inline __m512i __DEFAULT_FN_ATTRS +static __inline __m512i __DEFAULT_FN_ATTRS512 _mm512_set_epi32 (int __A, int __B, int __C, int __D, int __E, int __F, int __G, int __H, int __I, int __J, int __K, int __L, @@ -9189,7 +9190,7 @@ _mm512_set_epi32 (int __A, int __B, int __C, int __D, _mm512_set_epi32((e15),(e14),(e13),(e12),(e11),(e10),(e9),(e8),(e7),(e6), \ (e5),(e4),(e3),(e2),(e1),(e0)) -static __inline__ __m512i __DEFAULT_FN_ATTRS +static __inline__ __m512i __DEFAULT_FN_ATTRS512 _mm512_set_epi64 (long long __A, long long __B, long long __C, long long __D, long long __E, long long __F, long long __G, long long __H) @@ -9201,7 +9202,7 @@ _mm512_set_epi64 (long long __A, long long __B, long long __C, #define _mm512_setr_epi64(e0,e1,e2,e3,e4,e5,e6,e7) \ _mm512_set_epi64((e7),(e6),(e5),(e4),(e3),(e2),(e1),(e0)) -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_set_pd (double __A, double __B, double __C, double __D, double __E, double __F, double __G, double __H) { @@ -9212,7 +9213,7 @@ _mm512_set_pd (double __A, double __B, double __C, double __D, #define _mm512_setr_pd(e0,e1,e2,e3,e4,e5,e6,e7) \ _mm512_set_pd((e7),(e6),(e5),(e4),(e3),(e2),(e1),(e0)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_set_ps (float __A, float __B, float __C, float __D, float __E, float __F, float __G, float __H, float __I, float __J, float __K, float __L, @@ -9227,25 +9228,25 @@ _mm512_set_ps (float __A, float __B, float __C, float __D, _mm512_set_ps((e15),(e14),(e13),(e12),(e11),(e10),(e9),(e8),(e7),(e6),(e5), \ (e4),(e3),(e2),(e1),(e0)) -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_abs_ps(__m512 __A) { return (__m512)_mm512_and_epi32(_mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ; } -static __inline__ __m512 __DEFAULT_FN_ATTRS +static __inline__ __m512 __DEFAULT_FN_ATTRS512 _mm512_mask_abs_ps(__m512 __W, __mmask16 __K, __m512 __A) { return (__m512)_mm512_mask_and_epi32((__m512i)__W, __K, _mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ; } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_abs_pd(__m512d __A) { return (__m512d)_mm512_and_epi64(_mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)__A) ; } -static __inline__ __m512d __DEFAULT_FN_ATTRS +static __inline__ __m512d __DEFAULT_FN_ATTRS512 _mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A) { return (__m512d)_mm512_mask_and_epi64((__v8di)__W, __K, _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)__A); @@ -9272,41 +9273,41 @@ _mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A) __v2du __t8 = __t6 op __t7; \ return __t8[0]; -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_add_epi64(__m512i __W) { +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_add_epi64(__m512i __W) { _mm512_mask_reduce_operator(+); } -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_mul_epi64(__m512i __W) { +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_epi64(__m512i __W) { _mm512_mask_reduce_operator(*); } -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_and_epi64(__m512i __W) { +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_and_epi64(__m512i __W) { _mm512_mask_reduce_operator(&); } -static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_or_epi64(__m512i __W) { +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_or_epi64(__m512i __W) { _mm512_mask_reduce_operator(|); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W) { __W = _mm512_maskz_mov_epi64(__M, __W); _mm512_mask_reduce_operator(+); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W) { __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(1), __M, __W); _mm512_mask_reduce_operator(*); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W) { __W = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __W); _mm512_mask_reduce_operator(&); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { __W = _mm512_maskz_mov_epi64(__M, __W); _mm512_mask_reduce_operator(|); @@ -9324,21 +9325,21 @@ _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { __m128d __t8 = __t6 op __t7; \ return __t8[0]; -static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_add_pd(__m512d __W) { +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_add_pd(__m512d __W) { _mm512_mask_reduce_operator(+); } -static __inline__ double __DEFAULT_FN_ATTRS _mm512_reduce_mul_pd(__m512d __W) { +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) { _mm512_mask_reduce_operator(*); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) { __W = _mm512_maskz_mov_pd(__M, __W); _mm512_mask_reduce_operator(+); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W) { __W = _mm512_mask_mov_pd(_mm512_set1_pd(1.0), __M, __W); _mm512_mask_reduce_operator(*); @@ -9358,45 +9359,45 @@ _mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W) { __v4su __t10 = __t8 op __t9; \ return __t10[0]; -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_add_epi32(__m512i __W) { _mm512_mask_reduce_operator(+); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_epi32(__m512i __W) { _mm512_mask_reduce_operator(*); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_and_epi32(__m512i __W) { _mm512_mask_reduce_operator(&); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_or_epi32(__m512i __W) { _mm512_mask_reduce_operator(|); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_epi32( __mmask16 __M, __m512i __W) { __W = _mm512_maskz_mov_epi32(__M, __W); _mm512_mask_reduce_operator(+); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_mul_epi32( __mmask16 __M, __m512i __W) { __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(1), __M, __W); _mm512_mask_reduce_operator(*); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_and_epi32( __mmask16 __M, __m512i __W) { __W = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __W); _mm512_mask_reduce_operator(&); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) { __W = _mm512_maskz_mov_epi32(__M, __W); _mm512_mask_reduce_operator(|); @@ -9416,23 +9417,23 @@ _mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) { __m128 __t10 = __t8 op __t9; \ return __t10[0]; -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_add_ps(__m512 __W) { _mm512_mask_reduce_operator(+); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_ps(__m512 __W) { _mm512_mask_reduce_operator(*); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) { __W = _mm512_maskz_mov_ps(__M, __W); _mm512_mask_reduce_operator(+); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { __W = _mm512_mask_mov_ps(_mm512_set1_ps(1.0f), __M, __W); _mm512_mask_reduce_operator(*); @@ -9448,45 +9449,45 @@ _mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W) { __v8di __t6 = (__v8di)_mm512_##op(__t4, __t5); \ return __t6[0]; -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_max_epi64(__m512i __V) { _mm512_mask_reduce_operator(max_epi64); } -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS512 _mm512_reduce_max_epu64(__m512i __V) { _mm512_mask_reduce_operator(max_epu64); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_reduce_min_epi64(__m512i __V) { _mm512_mask_reduce_operator(min_epi64); } -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS512 _mm512_reduce_min_epu64(__m512i __V) { _mm512_mask_reduce_operator(min_epu64); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __V) { __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(-__LONG_LONG_MAX__ - 1LL), __M, __V); _mm512_mask_reduce_operator(max_epi64); } -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __V) { __V = _mm512_maskz_mov_epi64(__M, __V); _mm512_mask_reduce_operator(max_epu64); } -static __inline__ long long __DEFAULT_FN_ATTRS +static __inline__ long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __V) { __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(__LONG_LONG_MAX__), __M, __V); _mm512_mask_reduce_operator(min_epi64); } -static __inline__ unsigned long long __DEFAULT_FN_ATTRS +static __inline__ unsigned long long __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) { __V = _mm512_mask_mov_epi64(_mm512_set1_epi64(~0ULL), __M, __V); _mm512_mask_reduce_operator(min_epu64); @@ -9506,45 +9507,45 @@ _mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __V) { __v4si __t10 = (__v4si)_mm_##op(__t8, __t9); \ return __t10[0]; -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_max_epi32(__m512i __V) { _mm512_mask_reduce_operator(max_epi32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS +static __inline__ unsigned int __DEFAULT_FN_ATTRS512 _mm512_reduce_max_epu32(__m512i __V) { _mm512_mask_reduce_operator(max_epu32); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_reduce_min_epi32(__m512i __V) { _mm512_mask_reduce_operator(min_epi32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS +static __inline__ unsigned int __DEFAULT_FN_ATTRS512 _mm512_reduce_min_epu32(__m512i __V) { _mm512_mask_reduce_operator(min_epu32); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __V) { __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(-__INT_MAX__ - 1), __M, __V); _mm512_mask_reduce_operator(max_epi32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS +static __inline__ unsigned int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __V) { __V = _mm512_maskz_mov_epi32(__M, __V); _mm512_mask_reduce_operator(max_epu32); } -static __inline__ int __DEFAULT_FN_ATTRS +static __inline__ int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __V) { __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(__INT_MAX__), __M, __V); _mm512_mask_reduce_operator(min_epi32); } -static __inline__ unsigned int __DEFAULT_FN_ATTRS +static __inline__ unsigned int __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { __V = _mm512_mask_mov_epi32(_mm512_set1_epi32(~0U), __M, __V); _mm512_mask_reduce_operator(min_epu32); @@ -9562,23 +9563,23 @@ _mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __V) { __m128d __t8 = _mm_##op(__t6, __t7); \ return __t8[0]; -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_max_pd(__m512d __V) { _mm512_mask_reduce_operator(max_pd); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_min_pd(__m512d __V) { _mm512_mask_reduce_operator(min_pd); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) { __V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V); _mm512_mask_reduce_operator(max_pd); } -static __inline__ double __DEFAULT_FN_ATTRS +static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { __V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V); _mm512_mask_reduce_operator(min_pd); @@ -9598,29 +9599,30 @@ _mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) { __m128 __t10 = _mm_##op(__t8, __t9); \ return __t10[0]; -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_max_ps(__m512 __V) { _mm512_mask_reduce_operator(max_ps); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_min_ps(__m512 __V) { _mm512_mask_reduce_operator(min_ps); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) { __V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V); _mm512_mask_reduce_operator(max_ps); } -static __inline__ float __DEFAULT_FN_ATTRS +static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) { __V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V); _mm512_mask_reduce_operator(min_ps); } #undef _mm512_mask_reduce_operator -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS512 +#undef __DEFAULT_FN_ATTRS128 #endif /* __AVX512FINTRIN_H */ diff --git a/lib/Headers/avx512ifmaintrin.h b/lib/Headers/avx512ifmaintrin.h index 0018ef5de9..159713049c 100644 --- a/lib/Headers/avx512ifmaintrin.h +++ b/lib/Headers/avx512ifmaintrin.h @@ -29,7 +29,7 @@ #define __IFMAINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_madd52hi_epu64 (__m512i __X, __m512i __Y, __m512i __Z) diff --git a/lib/Headers/avx512ifmavlintrin.h b/lib/Headers/avx512ifmavlintrin.h index 934cfb433f..afdea888c5 100644 --- a/lib/Headers/avx512ifmavlintrin.h +++ b/lib/Headers/avx512ifmavlintrin.h @@ -29,18 +29,19 @@ #define __IFMAVLINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512ifma,avx512vl"), __min_vector_width__(256))) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_madd52hi_epu64 (__m128i __X, __m128i __Y, __m128i __Z) { return (__m128i)__builtin_ia32_vpmadd52huq128((__v2di) __X, (__v2di) __Y, (__v2di) __Z); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -48,7 +49,7 @@ _mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -56,14 +57,14 @@ _mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_madd52hi_epu64 (__m256i __X, __m256i __Y, __m256i __Z) { return (__m256i)__builtin_ia32_vpmadd52huq256((__v4di)__X, (__v4di)__Y, (__v4di)__Z); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -71,7 +72,7 @@ _mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -79,14 +80,14 @@ _mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_madd52lo_epu64 (__m128i __X, __m128i __Y, __m128i __Z) { return (__m128i)__builtin_ia32_vpmadd52luq128((__v2di)__X, (__v2di)__Y, (__v2di)__Z); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -94,7 +95,7 @@ _mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -102,14 +103,14 @@ _mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_madd52lo_epu64 (__m256i __X, __m256i __Y, __m256i __Z) { return (__m256i)__builtin_ia32_vpmadd52luq256((__v4di)__X, (__v4di)__Y, (__v4di)__Z); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -117,7 +118,7 @@ _mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -126,6 +127,7 @@ _mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vbmi2intrin.h b/lib/Headers/avx512vbmi2intrin.h index 01a75a70bb..d2a58094fd 100644 --- a/lib/Headers/avx512vbmi2intrin.h +++ b/lib/Headers/avx512vbmi2intrin.h @@ -29,7 +29,7 @@ #define __AVX512VBMI2INTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi2"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi2"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512vbmiintrin.h b/lib/Headers/avx512vbmiintrin.h index dd6593e7b4..b6e93c2858 100644 --- a/lib/Headers/avx512vbmiintrin.h +++ b/lib/Headers/avx512vbmiintrin.h @@ -29,7 +29,7 @@ #define __VBMIINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512vbmivlintrin.h b/lib/Headers/avx512vbmivlintrin.h index 34b8d76365..9a0400b2b5 100644 --- a/lib/Headers/avx512vbmivlintrin.h +++ b/lib/Headers/avx512vbmivlintrin.h @@ -29,10 +29,11 @@ #define __VBMIVLINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vbmi,avx512vl"), __min_vector_width__(256))) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutex2var_epi8(__m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_vpermi2varqi128((__v16qi)__A, @@ -40,7 +41,7 @@ _mm_permutex2var_epi8(__m128i __A, __m128i __I, __m128i __B) (__v16qi)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_epi8(__m128i __A, __mmask16 __U, __m128i __I, __m128i __B) { @@ -49,7 +50,7 @@ _mm_mask_permutex2var_epi8(__m128i __A, __mmask16 __U, __m128i __I, (__v16qi)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_epi8(__m128i __A, __m128i __I, __mmask16 __U, __m128i __B) { @@ -58,7 +59,7 @@ _mm_mask2_permutex2var_epi8(__m128i __A, __m128i __I, __mmask16 __U, (__v16qi)__I); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_epi8(__mmask16 __U, __m128i __A, __m128i __I, __m128i __B) { @@ -67,14 +68,14 @@ _mm_maskz_permutex2var_epi8(__mmask16 __U, __m128i __A, __m128i __I, (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutex2var_epi8(__m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_vpermi2varqi256((__v32qi)__A, (__v32qi)__I, (__v32qi)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_epi8(__m256i __A, __mmask32 __U, __m256i __I, __m256i __B) { @@ -83,7 +84,7 @@ _mm256_mask_permutex2var_epi8(__m256i __A, __mmask32 __U, __m256i __I, (__v32qi)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_epi8(__m256i __A, __m256i __I, __mmask32 __U, __m256i __B) { @@ -92,7 +93,7 @@ _mm256_mask2_permutex2var_epi8(__m256i __A, __m256i __I, __mmask32 __U, (__v32qi)__I); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_epi8(__mmask32 __U, __m256i __A, __m256i __I, __m256i __B) { @@ -101,13 +102,13 @@ _mm256_maskz_permutex2var_epi8(__mmask32 __U, __m256i __A, __m256i __I, (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutexvar_epi8 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_permvarqi128((__v16qi)__B, (__v16qi)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -115,7 +116,7 @@ _mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { @@ -124,13 +125,13 @@ _mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A, (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutexvar_epi8 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_permvarqi256((__v32qi) __B, (__v32qi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A, __m256i __B) { @@ -139,7 +140,7 @@ _mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A, (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { @@ -148,7 +149,7 @@ _mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A, (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y) { return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, @@ -157,7 +158,7 @@ _mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i (__mmask16) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y) { return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, @@ -167,7 +168,7 @@ _mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y) (__mmask16) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y) { return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X, @@ -177,7 +178,7 @@ _mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y) (__mmask16) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y) { return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, @@ -186,7 +187,7 @@ _mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m2 (__mmask32) __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y) { return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, @@ -196,7 +197,7 @@ _mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y) (__mmask32) __M); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y) { return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X, @@ -207,6 +208,7 @@ _mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y) } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vlbitalgintrin.h b/lib/Headers/avx512vlbitalgintrin.h index a5ed93c088..64860b2925 100644 --- a/lib/Headers/avx512vlbitalgintrin.h +++ b/lib/Headers/avx512vlbitalgintrin.h @@ -29,15 +29,16 @@ #define __AVX512VLBITALGINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bitalg"), __min_vector_width__(256))) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_popcnt_epi16(__m256i __A) { return (__m256i) __builtin_ia32_vpopcntw_256((__v16hi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) { return (__m256i) __builtin_ia32_selectw_256((__mmask16) __U, @@ -45,7 +46,7 @@ _mm256_mask_popcnt_epi16(__m256i __A, __mmask16 __U, __m256i __B) (__v16hi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) { return _mm256_mask_popcnt_epi16((__m256i) _mm256_setzero_si256(), @@ -53,13 +54,13 @@ _mm256_maskz_popcnt_epi16(__mmask16 __U, __m256i __B) __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi16(__m128i __A) { return (__m128i) __builtin_ia32_vpopcntw_128((__v8hi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) { return (__m128i) __builtin_ia32_selectw_128((__mmask8) __U, @@ -67,7 +68,7 @@ _mm_mask_popcnt_epi16(__m128i __A, __mmask8 __U, __m128i __B) (__v8hi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) { return _mm_mask_popcnt_epi16((__m128i) _mm_setzero_si128(), @@ -75,13 +76,13 @@ _mm_maskz_popcnt_epi16(__mmask8 __U, __m128i __B) __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_popcnt_epi8(__m256i __A) { return (__m256i) __builtin_ia32_vpopcntb_256((__v32qi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) { return (__m256i) __builtin_ia32_selectb_256((__mmask32) __U, @@ -89,7 +90,7 @@ _mm256_mask_popcnt_epi8(__m256i __A, __mmask32 __U, __m256i __B) (__v32qi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) { return _mm256_mask_popcnt_epi8((__m256i) _mm256_setzero_si256(), @@ -97,13 +98,13 @@ _mm256_maskz_popcnt_epi8(__mmask32 __U, __m256i __B) __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_popcnt_epi8(__m128i __A) { return (__m128i) __builtin_ia32_vpopcntb_128((__v16qi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) { return (__m128i) __builtin_ia32_selectb_128((__mmask16) __U, @@ -111,7 +112,7 @@ _mm_mask_popcnt_epi8(__m128i __A, __mmask16 __U, __m128i __B) (__v16qi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) { return _mm_mask_popcnt_epi8((__m128i) _mm_setzero_si128(), @@ -119,7 +120,7 @@ _mm_maskz_popcnt_epi8(__mmask16 __U, __m128i __B) __B); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) { return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask((__v32qi) __A, @@ -127,7 +128,7 @@ _mm256_mask_bitshuffle_epi64_mask(__mmask32 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B) { return _mm256_mask_bitshuffle_epi64_mask((__mmask32) -1, @@ -135,7 +136,7 @@ _mm256_bitshuffle_epi64_mask(__m256i __A, __m256i __B) __B); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B) { return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask((__v16qi) __A, @@ -143,7 +144,7 @@ _mm_mask_bitshuffle_epi64_mask(__mmask16 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B) { return _mm_mask_bitshuffle_epi64_mask((__mmask16) -1, @@ -152,6 +153,7 @@ _mm_bitshuffle_epi64_mask(__m128i __A, __m128i __B) } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h index 1c0cb49a57..72e07d0541 100644 --- a/lib/Headers/avx512vlbwintrin.h +++ b/lib/Headers/avx512vlbwintrin.h @@ -29,7 +29,8 @@ #define __AVX512VLBWINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw"), __min_vector_width__(256))) /* Integer compare */ @@ -313,147 +314,147 @@ #define _mm256_mask_cmpneq_epu16_mask(k, A, B) \ _mm256_mask_cmp_epu16_mask((k), (A), (B), _MM_CMPINT_NE) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_add_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_add_epi8(__A, __B), (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_add_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_add_epi8(__A, __B), (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_add_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_add_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_add_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_add_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sub_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_sub_epi8(__A, __B), (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_sub_epi8(__A, __B), (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sub_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_sub_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_sub_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_add_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_add_epi8(__A, __B), (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_add_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_add_epi8(__A, __B), (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_add_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_add_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_add_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_add_epi16(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sub_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_sub_epi8(__A, __B), (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sub_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_sub_epi8(__A, __B), (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sub_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_sub_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sub_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_sub_epi16(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mullo_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mullo_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mullo_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mullo_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mullo_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mullo_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mullo_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mullo_epi16(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W) { return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U, @@ -461,7 +462,7 @@ _mm_mask_blend_epi8 (__mmask16 __U, __m128i __A, __m128i __W) (__v16qi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W) { return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U, @@ -469,7 +470,7 @@ _mm256_mask_blend_epi8 (__mmask32 __U, __m256i __A, __m256i __W) (__v32qi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W) { return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U, @@ -477,7 +478,7 @@ _mm_mask_blend_epi16 (__mmask8 __U, __m128i __A, __m128i __W) (__v8hi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W) { return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U, @@ -485,7 +486,7 @@ _mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W) (__v16hi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -493,7 +494,7 @@ _mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_abs_epi8(__mmask16 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -501,7 +502,7 @@ _mm_maskz_abs_epi8(__mmask16 __U, __m128i __A) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -509,7 +510,7 @@ _mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -517,7 +518,7 @@ _mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -525,7 +526,7 @@ _mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_abs_epi16(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -533,7 +534,7 @@ _mm_maskz_abs_epi16(__mmask8 __U, __m128i __A) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -541,7 +542,7 @@ _mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -549,14 +550,14 @@ _mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, (__v8hi)_mm_packs_epi32(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -564,7 +565,7 @@ _mm_mask_packs_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -572,7 +573,7 @@ _mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -580,7 +581,7 @@ _mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -588,7 +589,7 @@ _mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -596,7 +597,7 @@ _mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -604,7 +605,7 @@ _mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -612,7 +613,7 @@ _mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -620,7 +621,7 @@ _mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -628,7 +629,7 @@ _mm_mask_packus_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -636,7 +637,7 @@ _mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -644,7 +645,7 @@ _mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -652,7 +653,7 @@ _mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -660,7 +661,7 @@ _mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -668,7 +669,7 @@ _mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -676,7 +677,7 @@ _mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -684,7 +685,7 @@ _mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -692,7 +693,7 @@ _mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -700,7 +701,7 @@ _mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -708,7 +709,7 @@ _mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -716,7 +717,7 @@ _mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -724,7 +725,7 @@ _mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -732,7 +733,7 @@ _mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -740,7 +741,7 @@ _mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -748,7 +749,7 @@ _mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -756,7 +757,7 @@ _mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -764,7 +765,7 @@ _mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -772,7 +773,7 @@ _mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -780,7 +781,7 @@ _mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -788,7 +789,7 @@ _mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -796,7 +797,7 @@ _mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -804,7 +805,7 @@ _mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -812,7 +813,7 @@ _mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -820,7 +821,7 @@ _mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -828,7 +829,7 @@ _mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -836,7 +837,7 @@ _mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -844,7 +845,7 @@ _mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -852,7 +853,7 @@ _mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -860,7 +861,7 @@ _mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -868,7 +869,7 @@ _mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -876,7 +877,7 @@ _mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -884,7 +885,7 @@ _mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -892,7 +893,7 @@ _mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -900,7 +901,7 @@ _mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -908,7 +909,7 @@ _mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -916,7 +917,7 @@ _mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -924,7 +925,7 @@ _mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -932,7 +933,7 @@ _mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -940,7 +941,7 @@ _mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -948,7 +949,7 @@ _mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -956,7 +957,7 @@ _mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -964,7 +965,7 @@ _mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -972,7 +973,7 @@ _mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -980,7 +981,7 @@ _mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -988,7 +989,7 @@ _mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -996,7 +997,7 @@ _mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -1004,7 +1005,7 @@ _mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -1012,7 +1013,7 @@ _mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -1020,7 +1021,7 @@ _mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -1028,7 +1029,7 @@ _mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -1036,7 +1037,7 @@ _mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -1044,7 +1045,7 @@ _mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -1052,7 +1053,7 @@ _mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -1060,7 +1061,7 @@ _mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -1068,7 +1069,7 @@ _mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, @@ -1076,7 +1077,7 @@ _mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -1084,7 +1085,7 @@ _mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M, @@ -1092,7 +1093,7 @@ _mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -1100,7 +1101,7 @@ _mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -1108,7 +1109,7 @@ _mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -1116,7 +1117,7 @@ _mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M, @@ -1124,7 +1125,7 @@ _mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1132,7 +1133,7 @@ _mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1140,7 +1141,7 @@ _mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1148,7 +1149,7 @@ _mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1156,7 +1157,7 @@ _mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1164,7 +1165,7 @@ _mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1172,7 +1173,7 @@ _mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1180,7 +1181,7 @@ _mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1188,7 +1189,7 @@ _mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1196,7 +1197,7 @@ _mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1204,7 +1205,7 @@ _mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1212,7 +1213,7 @@ _mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1220,7 +1221,7 @@ _mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1228,7 +1229,7 @@ _mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, @@ -1236,7 +1237,7 @@ _mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1244,7 +1245,7 @@ _mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, @@ -1252,7 +1253,7 @@ _mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1260,7 +1261,7 @@ _mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1268,7 +1269,7 @@ _mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1276,7 +1277,7 @@ _mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A, (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1284,14 +1285,14 @@ _mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutex2var_epi16(__m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_vpermi2varhi128((__v8hi)__A, (__v8hi)__I, (__v8hi) __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) { @@ -1300,7 +1301,7 @@ _mm_mask_permutex2var_epi16(__m128i __A, __mmask8 __U, __m128i __I, (__v8hi)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) { @@ -1309,7 +1310,7 @@ _mm_mask2_permutex2var_epi16(__m128i __A, __m128i __I, __mmask8 __U, (__v8hi)__I); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) { @@ -1318,14 +1319,14 @@ _mm_maskz_permutex2var_epi16 (__mmask8 __U, __m128i __A, __m128i __I, (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutex2var_epi16(__m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_vpermi2varhi256((__v16hi)__A, (__v16hi)__I, (__v16hi)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, __m256i __B) { @@ -1334,7 +1335,7 @@ _mm256_mask_permutex2var_epi16(__m256i __A, __mmask16 __U, __m256i __I, (__v16hi)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, __m256i __B) { @@ -1343,7 +1344,7 @@ _mm256_mask2_permutex2var_epi16(__m256i __A, __m256i __I, __mmask16 __U, (__v16hi)__I); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A, __m256i __I, __m256i __B) { @@ -1352,21 +1353,21 @@ _mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A, __m256i __I, (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_maddubs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_maddubs_epi16(__X, __Y), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_maddubs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_maddubs_epi16(__X, __Y), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1374,126 +1375,126 @@ _mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X, (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_maddubs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_maddubs_epi16(__X, __Y), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_madd_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_madd_epi16(__A, __B), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_madd_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_madd_epi16(__A, __B), (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_madd_epi16(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_madd_epi16(__A, __B), (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_madd_epi16(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_madd_epi16(__A, __B), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi16_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, (__v16qi) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi16_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A, (__v16qi) _mm_setzero_si128(), __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtsepi16_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, (__v16qi) _mm_setzero_si128(), (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi16_epi8 (__mmask16 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A, (__v16qi) _mm_setzero_si128(), __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi16_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, (__v16qi) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi16_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A, (__v16qi) _mm_setzero_si128(), __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi16_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, (__v16qi) _mm_setzero_si128(), (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi16_epi8 (__mmask16 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A, (__v16qi) _mm_setzero_si128(), __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi16_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, @@ -1501,273 +1502,273 @@ _mm_cvtepi16_epi8 (__m128i __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi16_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, (__v16qi) _mm_setzero_si128(), __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovwb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovswb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovuswb128mem_mask ((__v16qi *) __P, (__v8hi) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi16_epi8 (__m256i __A) { return (__m128i)__builtin_convertvector((__v16hi) __A, __v16qi); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, (__v16qi)_mm256_cvtepi16_epi8(__A), (__v16qi)__O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi16_epi8 (__mmask16 __M, __m256i __A) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M, (__v16qi)_mm256_cvtepi16_epi8(__A), (__v16qi)_mm_setzero_si128()); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A) { __builtin_ia32_pmovwb256mem_mask ((__v16qi *) __P, (__v16hi) __A, __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A) { __builtin_ia32_pmovswb256mem_mask ((__v16qi *) __P, (__v16hi) __A, __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask16 __M, __m256i __A) { __builtin_ia32_pmovuswb256mem_mask ((__v16qi*) __P, (__v16hi) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mulhrs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhrs_epi16(__X, __Y), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mulhrs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhrs_epi16(__X, __Y), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mulhrs_epi16(__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhrs_epi16(__X, __Y), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mulhrs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhrs_epi16(__X, __Y), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mulhi_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhi_epu16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mulhi_epu16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhi_epu16(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mulhi_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhi_epu16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mulhi_epu16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhi_epu16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mulhi_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhi_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mulhi_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_mulhi_epi16(__A, __B), (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mulhi_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhi_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mulhi_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_mulhi_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_unpackhi_epi8(__A, __B), (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_unpackhi_epi8(__A, __B), (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_unpackhi_epi8(__A, __B), (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_unpackhi_epi8(__A, __B), (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_unpackhi_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_unpackhi_epi16(__A, __B), (__v8hi) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_unpackhi_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_unpackhi_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_unpacklo_epi8(__A, __B), (__v16qi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U, (__v16qi)_mm_unpacklo_epi8(__A, __B), (__v16qi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_unpacklo_epi8(__A, __B), (__v32qi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U, (__v32qi)_mm256_unpacklo_epi8(__A, __B), (__v32qi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_unpacklo_epi16(__A, __B), (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, (__v8hi)_mm_unpacklo_epi16(__A, __B), (__v8hi) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_unpacklo_epi16(__A, __B), (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, (__v16hi)_mm256_unpacklo_epi16(__A, __B), (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1775,7 +1776,7 @@ _mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1783,7 +1784,7 @@ _mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1791,7 +1792,7 @@ _mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1800,7 +1801,7 @@ _mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A) } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1808,7 +1809,7 @@ _mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1816,7 +1817,7 @@ _mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1824,7 +1825,7 @@ _mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1875,13 +1876,13 @@ _mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A) (imm)), \ (__v16hi)_mm256_setzero_si256()) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sllv_epi16(__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_psllv16hi((__v16hi)__A, (__v16hi)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1889,7 +1890,7 @@ _mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1897,13 +1898,13 @@ _mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_sllv_epi16(__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_psllv8hi((__v8hi)__A, (__v8hi)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1911,7 +1912,7 @@ _mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1919,7 +1920,7 @@ _mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1927,7 +1928,7 @@ _mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1935,7 +1936,7 @@ _mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1943,7 +1944,7 @@ _mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1951,7 +1952,7 @@ _mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1959,7 +1960,7 @@ _mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -1967,7 +1968,7 @@ _mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1975,7 +1976,7 @@ _mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1983,13 +1984,13 @@ _mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A, int __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srlv_epi16(__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_psrlv16hi((__v16hi)__A, (__v16hi)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -1997,7 +1998,7 @@ _mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2005,13 +2006,13 @@ _mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srlv_epi16(__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_psrlv8hi((__v8hi)__A, (__v8hi)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2019,7 +2020,7 @@ _mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2027,13 +2028,13 @@ _mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srav_epi16(__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_psrav16hi((__v16hi)__A, (__v16hi)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2041,7 +2042,7 @@ _mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2049,13 +2050,13 @@ _mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srav_epi16(__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_psrav8hi((__v8hi)__A, (__v8hi)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2063,7 +2064,7 @@ _mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2071,7 +2072,7 @@ _mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2079,7 +2080,7 @@ _mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2087,7 +2088,7 @@ _mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2095,7 +2096,7 @@ _mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2103,7 +2104,7 @@ _mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2111,7 +2112,7 @@ _mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srai_epi16(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2119,7 +2120,7 @@ _mm_maskz_srai_epi16(__mmask8 __U, __m128i __A, int __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2127,7 +2128,7 @@ _mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2135,7 +2136,7 @@ _mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A, int __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2143,7 +2144,7 @@ _mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2151,7 +2152,7 @@ _mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2159,7 +2160,7 @@ _mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2167,7 +2168,7 @@ _mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2175,7 +2176,7 @@ _mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v8hi)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U, @@ -2183,7 +2184,7 @@ _mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, int __B) (__v8hi)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2191,7 +2192,7 @@ _mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B) (__v16hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U, @@ -2199,7 +2200,7 @@ _mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A, int __B) (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U, @@ -2207,7 +2208,7 @@ _mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A) (__v8hi) __W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mov_epi16 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectw_128 ((__mmask8) __U, @@ -2215,7 +2216,7 @@ _mm_maskz_mov_epi16 (__mmask8 __U, __m128i __A) (__v8hi) _mm_setzero_si128 ()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mov_epi16 (__m256i __W, __mmask16 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U, @@ -2223,7 +2224,7 @@ _mm256_mask_mov_epi16 (__m256i __W, __mmask16 __U, __m256i __A) (__v16hi) __W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_epi16 (__mmask16 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectw_256 ((__mmask16) __U, @@ -2231,7 +2232,7 @@ _mm256_maskz_mov_epi16 (__mmask16 __U, __m256i __A) (__v16hi) _mm256_setzero_si256 ()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mov_epi8 (__m128i __W, __mmask16 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U, @@ -2239,7 +2240,7 @@ _mm_mask_mov_epi8 (__m128i __W, __mmask16 __U, __m128i __A) (__v16qi) __W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mov_epi8 (__mmask16 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectb_128 ((__mmask16) __U, @@ -2247,7 +2248,7 @@ _mm_maskz_mov_epi8 (__mmask16 __U, __m128i __A) (__v16qi) _mm_setzero_si128 ()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mov_epi8 (__m256i __W, __mmask32 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U, @@ -2255,7 +2256,7 @@ _mm256_mask_mov_epi8 (__m256i __W, __mmask32 __U, __m256i __A) (__v32qi) __W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectb_256 ((__mmask32) __U, @@ -2264,7 +2265,7 @@ _mm256_maskz_mov_epi8 (__mmask32 __U, __m256i __A) } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A) { return (__m128i) __builtin_ia32_selectb_128(__M, @@ -2272,7 +2273,7 @@ _mm_mask_set1_epi8 (__m128i __O, __mmask16 __M, char __A) (__v16qi) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_set1_epi8 (__mmask16 __M, char __A) { return (__m128i) __builtin_ia32_selectb_128(__M, @@ -2280,7 +2281,7 @@ _mm_maskz_set1_epi8 (__mmask16 __M, char __A) (__v16qi) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A) { return (__m256i) __builtin_ia32_selectb_256(__M, @@ -2288,7 +2289,7 @@ _mm256_mask_set1_epi8 (__m256i __O, __mmask32 __M, char __A) (__v32qi) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_set1_epi8 (__mmask32 __M, char __A) { return (__m256i) __builtin_ia32_selectb_256(__M, @@ -2296,7 +2297,7 @@ _mm256_maskz_set1_epi8 (__mmask32 __M, char __A) (__v32qi) _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddquhi128_mask ((__v8hi *) __P, @@ -2304,7 +2305,7 @@ _mm_mask_loadu_epi16 (__m128i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_epi16 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddquhi128_mask ((__v8hi *) __P, @@ -2313,7 +2314,7 @@ _mm_maskz_loadu_epi16 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddquhi256_mask ((__v16hi *) __P, @@ -2321,7 +2322,7 @@ _mm256_mask_loadu_epi16 (__m256i __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddquhi256_mask ((__v16hi *) __P, @@ -2330,7 +2331,7 @@ _mm256_maskz_loadu_epi16 (__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddquqi128_mask ((__v16qi *) __P, @@ -2338,7 +2339,7 @@ _mm_mask_loadu_epi8 (__m128i __W, __mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddquqi128_mask ((__v16qi *) __P, @@ -2347,7 +2348,7 @@ _mm_maskz_loadu_epi8 (__mmask16 __U, void const *__P) (__mmask16) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddquqi256_mask ((__v32qi *) __P, @@ -2355,7 +2356,7 @@ _mm256_mask_loadu_epi8 (__m256i __W, __mmask32 __U, void const *__P) (__mmask32) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddquqi256_mask ((__v32qi *) __P, @@ -2363,7 +2364,7 @@ _mm256_maskz_loadu_epi8 (__mmask32 __U, void const *__P) _mm256_setzero_si256 (), (__mmask32) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_storedquhi128_mask ((__v8hi *) __P, @@ -2371,7 +2372,7 @@ _mm_mask_storeu_epi16 (void *__P, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A) { __builtin_ia32_storedquhi256_mask ((__v16hi *) __P, @@ -2379,7 +2380,7 @@ _mm256_mask_storeu_epi16 (void *__P, __mmask16 __U, __m256i __A) (__mmask16) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A) { __builtin_ia32_storedquqi128_mask ((__v16qi *) __P, @@ -2387,7 +2388,7 @@ _mm_mask_storeu_epi8 (void *__P, __mmask16 __U, __m128i __A) (__mmask16) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A) { __builtin_ia32_storedquqi256_mask ((__v32qi *) __P, @@ -2395,162 +2396,162 @@ _mm256_mask_storeu_epi8 (void *__P, __mmask32 __U, __m256i __A) (__mmask32) __U); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_test_epi8_mask (__m128i __A, __m128i __B) { return _mm_cmpneq_epi8_mask (_mm_and_si128(__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_mask_test_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpneq_epi8_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_test_epi8_mask (__m256i __A, __m256i __B) { return _mm256_cmpneq_epi8_mask (_mm256_and_si256(__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_mask_test_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpneq_epi8_mask (__U, _mm256_and_si256(__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_test_epi16_mask (__m128i __A, __m128i __B) { return _mm_cmpneq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_test_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpneq_epi16_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS256 _mm256_test_epi16_mask (__m256i __A, __m256i __B) { return _mm256_cmpneq_epi16_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256 ()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS256 _mm256_mask_test_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpneq_epi16_mask (__U, _mm256_and_si256(__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_testn_epi8_mask (__m128i __A, __m128i __B) { return _mm_cmpeq_epi8_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_mask_testn_epi8_mask (__mmask16 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpeq_epi8_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_testn_epi8_mask (__m256i __A, __m256i __B) { return _mm256_cmpeq_epi8_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_mask_testn_epi8_mask (__mmask32 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpeq_epi8_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_testn_epi16_mask (__m128i __A, __m128i __B) { return _mm_cmpeq_epi16_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_testn_epi16_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpeq_epi16_mask (__U, _mm_and_si128(__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS256 _mm256_testn_epi16_mask (__m256i __A, __m256i __B) { return _mm256_cmpeq_epi16_mask (_mm256_and_si256(__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS256 _mm256_mask_testn_epi16_mask (__mmask16 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpeq_epi16_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS128 _mm_movepi8_mask (__m128i __A) { return (__mmask16) __builtin_ia32_cvtb2mask128 ((__v16qi) __A); } -static __inline__ __mmask32 __DEFAULT_FN_ATTRS +static __inline__ __mmask32 __DEFAULT_FN_ATTRS256 _mm256_movepi8_mask (__m256i __A) { return (__mmask32) __builtin_ia32_cvtb2mask256 ((__v32qi) __A); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_movepi16_mask (__m128i __A) { return (__mmask8) __builtin_ia32_cvtw2mask128 ((__v8hi) __A); } -static __inline__ __mmask16 __DEFAULT_FN_ATTRS +static __inline__ __mmask16 __DEFAULT_FN_ATTRS256 _mm256_movepi16_mask (__m256i __A) { return (__mmask16) __builtin_ia32_cvtw2mask256 ((__v16hi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_movm_epi8 (__mmask16 __A) { return (__m128i) __builtin_ia32_cvtmask2b128 (__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_movm_epi8 (__mmask32 __A) { return (__m256i) __builtin_ia32_cvtmask2b256 (__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_movm_epi16 (__mmask8 __A) { return (__m128i) __builtin_ia32_cvtmask2w128 (__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_movm_epi16 (__mmask16 __A) { return (__m256i) __builtin_ia32_cvtmask2w256 (__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_broadcastb_epi8 (__m128i __O, __mmask16 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectb_128(__M, @@ -2558,7 +2559,7 @@ _mm_mask_broadcastb_epi8 (__m128i __O, __mmask16 __M, __m128i __A) (__v16qi) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_broadcastb_epi8 (__mmask16 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectb_128(__M, @@ -2566,7 +2567,7 @@ _mm_maskz_broadcastb_epi8 (__mmask16 __M, __m128i __A) (__v16qi) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastb_epi8 (__m256i __O, __mmask32 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectb_256(__M, @@ -2574,7 +2575,7 @@ _mm256_mask_broadcastb_epi8 (__m256i __O, __mmask32 __M, __m128i __A) (__v32qi) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastb_epi8 (__mmask32 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectb_256(__M, @@ -2582,7 +2583,7 @@ _mm256_maskz_broadcastb_epi8 (__mmask32 __M, __m128i __A) (__v32qi) _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_broadcastw_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128(__M, @@ -2590,7 +2591,7 @@ _mm_mask_broadcastw_epi16 (__m128i __O, __mmask8 __M, __m128i __A) (__v8hi) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_broadcastw_epi16 (__mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectw_128(__M, @@ -2598,7 +2599,7 @@ _mm_maskz_broadcastw_epi16 (__mmask8 __M, __m128i __A) (__v8hi) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastw_epi16 (__m256i __O, __mmask16 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256(__M, @@ -2606,7 +2607,7 @@ _mm256_mask_broadcastw_epi16 (__m256i __O, __mmask16 __M, __m128i __A) (__v16hi) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectw_256(__M, @@ -2614,7 +2615,7 @@ _mm256_maskz_broadcastw_epi16 (__mmask16 __M, __m128i __A) (__v16hi) _mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A) { return (__m256i) __builtin_ia32_selectw_256 (__M, @@ -2622,7 +2623,7 @@ _mm256_mask_set1_epi16 (__m256i __O, __mmask16 __M, short __A) (__v16hi) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_set1_epi16 (__mmask16 __M, short __A) { return (__m256i) __builtin_ia32_selectw_256(__M, @@ -2630,7 +2631,7 @@ _mm256_maskz_set1_epi16 (__mmask16 __M, short __A) (__v16hi) _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A) { return (__m128i) __builtin_ia32_selectw_128(__M, @@ -2638,7 +2639,7 @@ _mm_mask_set1_epi16 (__m128i __O, __mmask8 __M, short __A) (__v8hi) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_set1_epi16 (__mmask8 __M, short __A) { return (__m128i) __builtin_ia32_selectw_128(__M, @@ -2646,13 +2647,13 @@ _mm_maskz_set1_epi16 (__mmask8 __M, short __A) (__v8hi) _mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutexvar_epi16 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_permvarhi128((__v8hi) __B, (__v8hi) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutexvar_epi16 (__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M, @@ -2660,7 +2661,7 @@ _mm_maskz_permutexvar_epi16 (__mmask8 __M, __m128i __A, __m128i __B) (__v8hi) _mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutexvar_epi16 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { @@ -2669,13 +2670,13 @@ _mm_mask_permutexvar_epi16 (__m128i __W, __mmask8 __M, __m128i __A, (__v8hi)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutexvar_epi16 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_permvarhi256((__v16hi) __B, (__v16hi) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_epi16 (__mmask16 __M, __m256i __A, __m256i __B) { @@ -2684,7 +2685,7 @@ _mm256_maskz_permutexvar_epi16 (__mmask16 __M, __m256i __A, (__v16hi)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) { @@ -2741,6 +2742,7 @@ _mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A, (__v16hi)_mm256_dbsad_epu8((A), (B), (imm)), \ (__v16hi)_mm256_setzero_si256()) -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __AVX512VLBWINTRIN_H */ diff --git a/lib/Headers/avx512vlcdintrin.h b/lib/Headers/avx512vlcdintrin.h index d3b6da256d..127c5b132a 100644 --- a/lib/Headers/avx512vlcdintrin.h +++ b/lib/Headers/avx512vlcdintrin.h @@ -28,35 +28,36 @@ #define __AVX512VLCDINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512cd"), __min_vector_width__(256))) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastmb_epi64 (__mmask8 __A) { return (__m128i) _mm_set1_epi64x((long long) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastmb_epi64 (__mmask8 __A) { return (__m256i) _mm256_set1_epi64x((long long)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcastmw_epi32 (__mmask16 __A) { return (__m128i) _mm_set1_epi32((int)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcastmw_epi32 (__mmask16 __A) { return (__m256i) _mm256_set1_epi32((int)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_conflict_epi64 (__m128i __A) { return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, @@ -64,7 +65,7 @@ _mm_conflict_epi64 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_conflict_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, @@ -72,7 +73,7 @@ _mm_mask_conflict_epi64 (__m128i __W, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_conflict_epi64 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_vpconflictdi_128_mask ((__v2di) __A, @@ -81,7 +82,7 @@ _mm_maskz_conflict_epi64 (__mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_conflict_epi64 (__m256i __A) { return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, @@ -89,7 +90,7 @@ _mm256_conflict_epi64 (__m256i __A) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_conflict_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, @@ -97,7 +98,7 @@ _mm256_mask_conflict_epi64 (__m256i __W, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_conflict_epi64 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_vpconflictdi_256_mask ((__v4di) __A, @@ -105,7 +106,7 @@ _mm256_maskz_conflict_epi64 (__mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_conflict_epi32 (__m128i __A) { return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, @@ -113,7 +114,7 @@ _mm_conflict_epi32 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_conflict_epi32 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, @@ -121,7 +122,7 @@ _mm_mask_conflict_epi32 (__m128i __W, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_conflict_epi32 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_vpconflictsi_128_mask ((__v4si) __A, @@ -129,7 +130,7 @@ _mm_maskz_conflict_epi32 (__mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_conflict_epi32 (__m256i __A) { return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, @@ -137,7 +138,7 @@ _mm256_conflict_epi32 (__m256i __A) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_conflict_epi32 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, @@ -145,7 +146,7 @@ _mm256_mask_conflict_epi32 (__m256i __W, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_conflict_epi32 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_vpconflictsi_256_mask ((__v8si) __A, @@ -154,13 +155,13 @@ _mm256_maskz_conflict_epi32 (__mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_lzcnt_epi32 (__m128i __A) { return (__m128i) __builtin_ia32_vplzcntd_128 ((__v4si) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_lzcnt_epi32 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -168,7 +169,7 @@ _mm_mask_lzcnt_epi32 (__m128i __W, __mmask8 __U, __m128i __A) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_lzcnt_epi32 (__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -176,13 +177,13 @@ _mm_maskz_lzcnt_epi32 (__mmask8 __U, __m128i __A) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_lzcnt_epi32 (__m256i __A) { return (__m256i) __builtin_ia32_vplzcntd_256 ((__v8si) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_lzcnt_epi32 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -190,7 +191,7 @@ _mm256_mask_lzcnt_epi32 (__m256i __W, __mmask8 __U, __m256i __A) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_lzcnt_epi32 (__mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -198,13 +199,13 @@ _mm256_maskz_lzcnt_epi32 (__mmask8 __U, __m256i __A) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_lzcnt_epi64 (__m128i __A) { return (__m128i) __builtin_ia32_vplzcntq_128 ((__v2di) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_lzcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -212,7 +213,7 @@ _mm_mask_lzcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_lzcnt_epi64 (__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -220,13 +221,13 @@ _mm_maskz_lzcnt_epi64 (__mmask8 __U, __m128i __A) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_lzcnt_epi64 (__m256i __A) { return (__m256i) __builtin_ia32_vplzcntq_256 ((__v4di) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_lzcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -234,7 +235,7 @@ _mm256_mask_lzcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_lzcnt_epi64 (__mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -242,6 +243,7 @@ _mm256_maskz_lzcnt_epi64 (__mmask8 __U, __m256i __A) (__v4di)_mm256_setzero_si256()); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __AVX512VLCDINTRIN_H */ diff --git a/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h index 62c0fd7bd1..9d13846e89 100644 --- a/lib/Headers/avx512vldqintrin.h +++ b/lib/Headers/avx512vldqintrin.h @@ -29,760 +29,761 @@ #define __AVX512VLDQINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq"), __min_vector_width__(256))) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mullo_epi64 (__m256i __A, __m256i __B) { return (__m256i) ((__v4du) __A * (__v4du) __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mullo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, (__v4di)_mm256_mullo_epi64(__A, __B), (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mullo_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, (__v4di)_mm256_mullo_epi64(__A, __B), (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mullo_epi64 (__m128i __A, __m128i __B) { return (__m128i) ((__v2du) __A * (__v2du) __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mullo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, (__v2di)_mm_mullo_epi64(__A, __B), (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mullo_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, (__v2di)_mm_mullo_epi64(__A, __B), (__v2di)_mm_setzero_si128()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_andnot_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_andnot_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_andnot_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_andnot_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_andnot_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_andnot_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_andnot_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_andnot_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_andnot_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_andnot_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_andnot_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_andnot_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_andnot_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_andnot_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_andnot_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_andnot_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_and_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_and_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_and_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_and_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_and_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_and_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_and_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_and_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_and_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_and_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_and_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_and_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_and_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_and_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_and_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_and_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_xor_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_xor_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_xor_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_xor_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_xor_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_xor_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_xor_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_xor_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_xor_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_xor_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_xor_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_xor_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_xor_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_xor_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_xor_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_or_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_or_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_or_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_or_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_or_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_or_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_or_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_or_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_or_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_or_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_or_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_or_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_or_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_or_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_or_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_or_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtpd_epi64 (__m128d __A) { return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtpd_epi64 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtpd_epi64 (__m256d __A) { return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtpd_epi64 (__mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtpd_epu64 (__m128d __A) { return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtpd_epu64 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtpd_epu64 (__m256d __A) { return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtpd_epu64 (__mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtps_epi64 (__m128 __A) { return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtps_epi64 (__m128 __A) { return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtps_epu64 (__m128 __A) { return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtps_epu64 (__m128 __A) { return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_cvtepi64_pd (__m128i __A) { return (__m128d)__builtin_convertvector((__v2di)__A, __v2df); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_pd (__m128d __W, __mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtepi64_pd(__A), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi64_pd (__mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtepi64_pd(__A), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_pd (__m256i __A) { return (__m256d)__builtin_convertvector((__v4di)__A, __v4df); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_pd (__m256d __W, __mmask8 __U, __m256i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtepi64_pd(__A), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi64_pd (__mmask8 __U, __m256i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtepi64_pd(__A), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_cvtepi64_ps (__m128i __A) { return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi64_ps (__mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_ps (__m256i __A) { return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m256i __A) { return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi64_ps (__mmask8 __U, __m256i __A) { return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttpd_epi64 (__m128d __A) { return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttpd_epi64 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvttpd_epi64 (__m256d __A) { return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttpd_epi64 (__mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttpd_epu64 (__m128d __A) { return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttpd_epu64 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvttpd_epu64 (__m256d __A) { return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttpd_epu64 (__mmask8 __U, __m256d __A) { return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttps_epi64 (__m128 __A) { return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvttps_epi64 (__m128 __A) { return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttps_epu64 (__m128 __A) { return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A, (__v2di) _mm_setzero_si128(), (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvttps_epu64 (__m128 __A) { return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) { return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A, (__v4di) _mm256_setzero_si256(), (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_cvtepu64_pd (__m128i __A) { return (__m128d)__builtin_convertvector((__v2du)__A, __v2df); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu64_pd (__m128d __W, __mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtepu64_pd(__A), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu64_pd (__mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtepu64_pd(__A), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_cvtepu64_pd (__m256i __A) { return (__m256d)__builtin_convertvector((__v4du)__A, __v4df); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu64_pd (__m256d __W, __mmask8 __U, __m256i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtepu64_pd(__A), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu64_pd (__mmask8 __U, __m256i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtepu64_pd(__A), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_cvtepu64_ps (__m128i __A) { return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu64_ps (__mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_cvtepu64_ps (__m256i __A) { return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, (__v4sf) _mm_setzero_ps(), (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m256i __A) { return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu64_ps (__mmask8 __U, __m256i __A) { return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A, (__v4sf) _mm_setzero_ps(), @@ -919,62 +920,62 @@ _mm256_maskz_cvtepu64_ps (__mmask8 __U, __m256i __A) { (__v8sf)_mm256_setzero_ps(), \ (__mmask8)(U)) -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_movepi32_mask (__m128i __A) { return (__mmask8) __builtin_ia32_cvtd2mask128 ((__v4si) __A); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_movepi32_mask (__m256i __A) { return (__mmask8) __builtin_ia32_cvtd2mask256 ((__v8si) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_movm_epi32 (__mmask8 __A) { return (__m128i) __builtin_ia32_cvtmask2d128 (__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_movm_epi32 (__mmask8 __A) { return (__m256i) __builtin_ia32_cvtmask2d256 (__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_movm_epi64 (__mmask8 __A) { return (__m128i) __builtin_ia32_cvtmask2q128 (__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_movm_epi64 (__mmask8 __A) { return (__m256i) __builtin_ia32_cvtmask2q256 (__A); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_movepi64_mask (__m128i __A) { return (__mmask8) __builtin_ia32_cvtq2mask128 ((__v2di) __A); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_movepi64_mask (__m256i __A) { return (__mmask8) __builtin_ia32_cvtq2mask256 ((__v4di) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_broadcast_f32x2 (__m128 __A) { return (__m256)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A, 0, 1, 0, 1, 0, 1, 0, 1); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__M, @@ -982,7 +983,7 @@ _mm256_mask_broadcast_f32x2 (__m256 __O, __mmask8 __M, __m128 __A) (__v8sf)__O); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__M, @@ -990,14 +991,14 @@ _mm256_maskz_broadcast_f32x2 (__mmask8 __M, __m128 __A) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_broadcast_f64x2(__m128d __A) { return (__m256d)__builtin_shufflevector((__v2df)__A, (__v2df)__A, 0, 1, 0, 1); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_f64x2(__m256d __O, __mmask8 __M, __m128d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__M, @@ -1005,7 +1006,7 @@ _mm256_mask_broadcast_f64x2(__m256d __O, __mmask8 __M, __m128d __A) (__v4df)__O); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__M, @@ -1013,14 +1014,14 @@ _mm256_maskz_broadcast_f64x2 (__mmask8 __M, __m128d __A) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_broadcast_i32x2 (__m128i __A) { return (__m128i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 0, 1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -1028,7 +1029,7 @@ _mm_mask_broadcast_i32x2 (__m128i __O, __mmask8 __M, __m128i __A) (__v4si)__O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -1036,14 +1037,14 @@ _mm_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcast_i32x2 (__m128i __A) { return (__m256i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 0, 1, 0, 1, 0, 1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -1051,7 +1052,7 @@ _mm256_mask_broadcast_i32x2 (__m256i __O, __mmask8 __M, __m128i __A) (__v8si)__O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -1059,14 +1060,14 @@ _mm256_maskz_broadcast_i32x2 (__mmask8 __M, __m128i __A) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcast_i64x2(__m128i __A) { return (__m256i)__builtin_shufflevector((__v2di)__A, (__v2di)__A, 0, 1, 0, 1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_i64x2(__m256i __O, __mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -1074,7 +1075,7 @@ _mm256_mask_broadcast_i64x2(__m256i __O, __mmask8 __M, __m128i __A) (__v4di)__O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -1178,6 +1179,7 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A) (__mmask8)__builtin_ia32_fpclassps256_mask((__v8sf)(__m256)(A), (int)(imm), \ (__mmask8)-1) -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index 66f92abcb0..de898845ce 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -28,7 +28,8 @@ #ifndef __AVX512VLINTRIN_H #define __AVX512VLINTRIN_H -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(256))) /* Integer compare */ @@ -232,7 +233,7 @@ #define _mm256_mask_cmpneq_epu64_mask(k, A, B) \ _mm256_mask_cmp_epu64_mask((k), (A), (B), _MM_CMPINT_NE) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -240,7 +241,7 @@ _mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_add_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -248,7 +249,7 @@ _mm256_maskz_add_epi32(__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_add_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -256,7 +257,7 @@ _mm256_mask_add_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_add_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -264,7 +265,7 @@ _mm256_maskz_add_epi64(__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sub_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -272,7 +273,7 @@ _mm256_mask_sub_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -280,7 +281,7 @@ _mm256_maskz_sub_epi32(__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sub_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -288,7 +289,7 @@ _mm256_mask_sub_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -296,7 +297,7 @@ _mm256_maskz_sub_epi64(__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_add_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -304,7 +305,7 @@ _mm_mask_add_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_add_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -312,7 +313,7 @@ _mm_maskz_add_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_add_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -320,7 +321,7 @@ _mm_mask_add_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_add_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -328,7 +329,7 @@ _mm_maskz_add_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sub_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -336,7 +337,7 @@ _mm_mask_sub_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sub_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -344,7 +345,7 @@ _mm_maskz_sub_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sub_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -352,7 +353,7 @@ _mm_mask_sub_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sub_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -360,7 +361,7 @@ _mm_maskz_sub_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mul_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -368,7 +369,7 @@ _mm256_mask_mul_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mul_epi32(__mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -376,7 +377,7 @@ _mm256_maskz_mul_epi32(__mmask8 __M, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mul_epi32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, @@ -384,7 +385,7 @@ _mm_mask_mul_epi32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mul_epi32(__mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, @@ -392,7 +393,7 @@ _mm_maskz_mul_epi32(__mmask8 __M, __m128i __X, __m128i __Y) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mul_epu32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -400,7 +401,7 @@ _mm256_mask_mul_epu32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mul_epu32(__mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -408,7 +409,7 @@ _mm256_maskz_mul_epu32(__mmask8 __M, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mul_epu32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, @@ -416,7 +417,7 @@ _mm_mask_mul_epu32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mul_epu32(__mmask8 __M, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, @@ -424,7 +425,7 @@ _mm_maskz_mul_epu32(__mmask8 __M, __m128i __X, __m128i __Y) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mullo_epi32(__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -432,7 +433,7 @@ _mm256_maskz_mullo_epi32(__mmask8 __M, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mullo_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -440,7 +441,7 @@ _mm256_mask_mullo_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mullo_epi32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -448,7 +449,7 @@ _mm_maskz_mullo_epi32(__mmask8 __M, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -456,7 +457,7 @@ _mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_and_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -464,13 +465,13 @@ _mm256_mask_and_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_and_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_and_epi32(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_and_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -478,13 +479,13 @@ _mm_mask_and_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_and_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_and_epi32(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_andnot_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -492,14 +493,14 @@ _mm256_mask_andnot_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_andnot_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_andnot_epi32(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_andnot_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -507,13 +508,13 @@ _mm_mask_andnot_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_andnot_epi32 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_andnot_epi32(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -521,13 +522,13 @@ _mm256_mask_or_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_or_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_or_epi32(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_or_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -535,13 +536,13 @@ _mm_mask_or_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_or_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_or_epi32(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_xor_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -549,13 +550,13 @@ _mm256_mask_xor_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_xor_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_xor_epi32(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { @@ -564,13 +565,13 @@ _mm_mask_xor_epi32(__m128i __W, __mmask8 __U, __m128i __A, (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_xor_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_xor_epi32(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_and_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -578,13 +579,13 @@ _mm256_mask_and_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_and_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_and_epi64(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_and_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -592,13 +593,13 @@ _mm_mask_and_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_and_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_and_epi64(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_andnot_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -606,14 +607,14 @@ _mm256_mask_andnot_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_andnot_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_andnot_epi64(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_andnot_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -621,13 +622,13 @@ _mm_mask_andnot_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_andnot_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_andnot_epi64(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_or_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -635,13 +636,13 @@ _mm256_mask_or_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_or_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_or_epi64(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_or_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -649,13 +650,13 @@ _mm_mask_or_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_or_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_or_epi64(_mm_setzero_si128(), __U, __A, __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_xor_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -663,13 +664,13 @@ _mm256_mask_xor_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_xor_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)_mm256_mask_xor_epi64(_mm256_setzero_si256(), __U, __A, __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_xor_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { @@ -678,7 +679,7 @@ _mm_mask_xor_epi64(__m128i __W, __mmask8 __U, __m128i __A, (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_xor_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)_mm_mask_xor_epi64(_mm_setzero_si128(), __U, __A, __B); @@ -804,7 +805,7 @@ _mm_maskz_xor_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2df)(__m128d)(b), (int)(p), \ (__mmask8)(m)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -814,7 +815,7 @@ _mm_mask_fmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -824,7 +825,7 @@ _mm_mask3_fmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -834,7 +835,7 @@ _mm_maskz_fmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -844,7 +845,7 @@ _mm_mask_fmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -854,7 +855,7 @@ _mm_maskz_fmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -864,7 +865,7 @@ _mm_mask3_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -874,7 +875,7 @@ _mm_maskz_fnmadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -884,7 +885,7 @@ _mm_maskz_fnmsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -894,7 +895,7 @@ _mm256_mask_fmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -904,7 +905,7 @@ _mm256_mask3_fmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -914,7 +915,7 @@ _mm256_maskz_fmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -924,7 +925,7 @@ _mm256_mask_fmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -934,7 +935,7 @@ _mm256_maskz_fmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -944,7 +945,7 @@ _mm256_mask3_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fnmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -954,7 +955,7 @@ _mm256_maskz_fnmadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fnmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -964,7 +965,7 @@ _mm256_maskz_fnmsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -974,7 +975,7 @@ _mm_mask_fmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -984,7 +985,7 @@ _mm_mask3_fmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -994,7 +995,7 @@ _mm_maskz_fmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1004,7 +1005,7 @@ _mm_mask_fmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1014,7 +1015,7 @@ _mm_maskz_fmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1024,7 +1025,7 @@ _mm_mask3_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1034,7 +1035,7 @@ _mm_maskz_fnmadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1044,7 +1045,7 @@ _mm_maskz_fnmsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1054,7 +1055,7 @@ _mm256_mask_fmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) (__v8sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1064,7 +1065,7 @@ _mm256_mask3_fmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1074,7 +1075,7 @@ _mm256_maskz_fmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1084,7 +1085,7 @@ _mm256_mask_fmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) (__v8sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1094,7 +1095,7 @@ _mm256_maskz_fmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1104,7 +1105,7 @@ _mm256_mask3_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fnmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1114,7 +1115,7 @@ _mm256_maskz_fnmadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1124,7 +1125,7 @@ _mm256_maskz_fnmsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1134,7 +1135,7 @@ _mm_mask_fmaddsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1144,7 +1145,7 @@ _mm_mask3_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1154,7 +1155,7 @@ _mm_maskz_fmaddsub_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1164,7 +1165,7 @@ _mm_mask_fmsubadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1174,7 +1175,7 @@ _mm_maskz_fmsubadd_pd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1184,7 +1185,7 @@ _mm256_mask_fmaddsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1194,7 +1195,7 @@ _mm256_mask3_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1204,7 +1205,7 @@ _mm256_maskz_fmaddsub_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1214,7 +1215,7 @@ _mm256_mask_fmsubadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1224,7 +1225,7 @@ _mm256_maskz_fmsubadd_pd(__mmask8 __U, __m256d __A, __m256d __B, __m256d __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1234,7 +1235,7 @@ _mm_mask_fmaddsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1244,7 +1245,7 @@ _mm_mask3_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1254,7 +1255,7 @@ _mm_maskz_fmaddsub_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1264,7 +1265,7 @@ _mm_mask_fmsubadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1274,7 +1275,7 @@ _mm_maskz_fmsubadd_ps(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { @@ -1285,7 +1286,7 @@ _mm256_mask_fmaddsub_ps(__m256 __A, __mmask8 __U, __m256 __B, (__v8sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1295,7 +1296,7 @@ _mm256_mask3_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1305,7 +1306,7 @@ _mm256_maskz_fmaddsub_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1315,7 +1316,7 @@ _mm256_mask_fmsubadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) (__v8sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1325,7 +1326,7 @@ _mm256_maskz_fmsubadd_ps(__mmask8 __U, __m256 __A, __m256 __B, __m256 __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1335,7 +1336,7 @@ _mm_mask3_fmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1345,7 +1346,7 @@ _mm256_mask3_fmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1355,7 +1356,7 @@ _mm_mask3_fmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1365,7 +1366,7 @@ _mm256_mask3_fmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1375,7 +1376,7 @@ _mm_mask3_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1385,7 +1386,7 @@ _mm256_mask3_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1395,7 +1396,7 @@ _mm_mask3_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1405,7 +1406,7 @@ _mm256_mask3_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1415,7 +1416,7 @@ _mm_mask_fnmadd_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fnmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1425,7 +1426,7 @@ _mm256_mask_fnmadd_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1435,7 +1436,7 @@ _mm_mask_fnmadd_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fnmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1445,7 +1446,7 @@ _mm256_mask_fnmadd_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) (__v8sf) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1455,7 +1456,7 @@ _mm_mask_fnmsub_pd(__m128d __A, __mmask8 __U, __m128d __B, __m128d __C) (__v2df) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) { return (__m128d) __builtin_ia32_selectpd_128((__mmask8) __U, @@ -1465,7 +1466,7 @@ _mm_mask3_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C, __mmask8 __U) (__v2df) __C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_fnmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1475,7 +1476,7 @@ _mm256_mask_fnmsub_pd(__m256d __A, __mmask8 __U, __m256d __B, __m256d __C) (__v4df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask3_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) { return (__m256d) __builtin_ia32_selectpd_256((__mmask8) __U, @@ -1485,7 +1486,7 @@ _mm256_mask3_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C, __mmask8 __U) (__v4df) __C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1495,7 +1496,7 @@ _mm_mask_fnmsub_ps(__m128 __A, __mmask8 __U, __m128 __B, __m128 __C) (__v4sf) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) { return (__m128) __builtin_ia32_selectps_128((__mmask8) __U, @@ -1505,7 +1506,7 @@ _mm_mask3_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C, __mmask8 __U) (__v4sf) __C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_fnmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1515,7 +1516,7 @@ _mm256_mask_fnmsub_ps(__m256 __A, __mmask8 __U, __m256 __B, __m256 __C) (__v8sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) { return (__m256) __builtin_ia32_selectps_256((__mmask8) __U, @@ -1525,126 +1526,126 @@ _mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U) (__v8sf) __C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_add_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_add_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_add_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_add_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_add_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_add_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_add_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_add_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_add_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_add_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_add_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_add_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_add_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_add_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_add_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_add_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_blend_epi32 (__mmask8 __U, __m128i __A, __m128i __W) { return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U, (__v4si) __W, (__v4si) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_blend_epi32 (__mmask8 __U, __m256i __A, __m256i __W) { return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U, (__v8si) __W, (__v8si) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_blend_pd (__mmask8 __U, __m128d __A, __m128d __W) { return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U, (__v2df) __W, (__v2df) __A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_blend_pd (__mmask8 __U, __m256d __A, __m256d __W) { return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U, (__v4df) __W, (__v4df) __A); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_blend_ps (__mmask8 __U, __m128 __A, __m128 __W) { return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U, (__v4sf) __W, (__v4sf) __A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_blend_ps (__mmask8 __U, __m256 __A, __m256 __W) { return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U, (__v8sf) __W, (__v8sf) __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_blend_epi64 (__mmask8 __U, __m128i __A, __m128i __W) { return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U, (__v2di) __W, (__v2di) __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_blend_epi64 (__mmask8 __U, __m256i __A, __m256i __W) { return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U, (__v4di) __W, (__v4di) __A); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_compress_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A, (__v2df) __W, (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_compress_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A, (__v2df) @@ -1652,14 +1653,14 @@ _mm_maskz_compress_pd (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_compress_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A, (__v4df) __W, (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A, (__v4df) @@ -1667,14 +1668,14 @@ _mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_compress_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A, (__v2di) @@ -1682,14 +1683,14 @@ _mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_compress_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A, (__v4di) @@ -1697,14 +1698,14 @@ _mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) { (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_compress_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_compress_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A, (__v4sf) @@ -1712,14 +1713,14 @@ _mm_maskz_compress_ps (__mmask8 __U, __m128 __A) { (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_compress_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A, (__v8sf) __W, (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A, (__v8sf) @@ -1727,14 +1728,14 @@ _mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_compress_epi32 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A, (__v4si) @@ -1742,14 +1743,14 @@ _mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_compress_epi32 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A, (__v8si) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A, (__v8si) @@ -1757,126 +1758,126 @@ _mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) { (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m128d __A) { __builtin_ia32_compressstoredf128_mask ((__v2df *) __P, (__v2df) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m256d __A) { __builtin_ia32_compressstoredf256_mask ((__v4df *) __P, (__v4df) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_compressstoredi128_mask ((__v2di *) __P, (__v2di) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_compressstoredi256_mask ((__v4di *) __P, (__v4di) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m128 __A) { __builtin_ia32_compressstoresf128_mask ((__v4sf *) __P, (__v4sf) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m256 __A) { __builtin_ia32_compressstoresf256_mask ((__v8sf *) __P, (__v8sf) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_compressstoresi128_mask ((__v4si *) __P, (__v4si) __A, (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_compressstoresi256_mask ((__v8si *) __P, (__v8si) __A, (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_pd (__m128d __W, __mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U, (__v2df)_mm_cvtepi32_pd(__A), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U, (__v2df)_mm_cvtepi32_pd(__A), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_pd (__m256d __W, __mmask8 __U, __m128i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U, (__v4df)_mm256_cvtepi32_pd(__A), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U, (__v4df)_mm256_cvtepi32_pd(__A), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_ps (__m128 __W, __mmask8 __U, __m128i __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_cvtepi32_ps(__A), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi32_ps (__mmask8 __U, __m128i __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_cvtepi32_ps(__A), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_ps (__m256 __W, __mmask8 __U, __m256i __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_cvtepi32_ps(__A), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi32_ps (__mmask8 __U, __m256i __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_cvtepi32_ps(__A), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A, (__v4si) @@ -1884,28 +1885,28 @@ _mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm256_cvtpd_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtpd_epi32 (__mmask8 __U, __m256d __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm256_cvtpd_epi32(__A), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m128d __A) { return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) { return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A, (__v4sf) @@ -1913,21 +1914,21 @@ _mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m256d __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm256_cvtpd_ps(__A), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtpd_ps (__mmask8 __U, __m256d __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm256_cvtpd_ps(__A), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtpd_epu32 (__m128d __A) { return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, (__v4si) @@ -1935,14 +1936,14 @@ _mm_cvtpd_epu32 (__m128d __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A, (__v4si) @@ -1950,7 +1951,7 @@ _mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtpd_epu32 (__m256d __A) { return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, (__v4si) @@ -1958,14 +1959,14 @@ _mm256_cvtpd_epu32 (__m256d __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) { return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) { return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A, (__v4si) @@ -1973,63 +1974,63 @@ _mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_cvtps_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_epi32 (__mmask8 __U, __m128 __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_cvtps_epi32(__A), (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_cvtps_epi32(__A), (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_epi32 (__mmask8 __U, __m256 __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_cvtps_epi32(__A), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_pd (__m128d __W, __mmask8 __U, __m128 __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtps_pd(__A), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_pd (__mmask8 __U, __m128 __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_cvtps_pd(__A), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_pd (__m256d __W, __mmask8 __U, __m128 __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtps_pd(__A), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_pd (__mmask8 __U, __m128 __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_cvtps_pd(__A), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtps_epu32 (__m128 __A) { return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, (__v4si) @@ -2037,14 +2038,14 @@ _mm_cvtps_epu32 (__m128 __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A, (__v4si) @@ -2052,7 +2053,7 @@ _mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvtps_epu32 (__m256 __A) { return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, (__v8si) @@ -2060,14 +2061,14 @@ _mm256_cvtps_epu32 (__m256 __A) { (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) { return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, (__v8si) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) { return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A, (__v8si) @@ -2075,14 +2076,14 @@ _mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A, (__v4si) @@ -2090,21 +2091,21 @@ _mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm256_cvttpd_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttpd_epi32 (__mmask8 __U, __m256d __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm256_cvttpd_epi32(__A), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttpd_epu32 (__m128d __A) { return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, (__v4si) @@ -2112,14 +2113,14 @@ _mm_cvttpd_epu32 (__m128d __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) { return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A, (__v4si) @@ -2127,7 +2128,7 @@ _mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvttpd_epu32 (__m256d __A) { return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, (__v4si) @@ -2135,14 +2136,14 @@ _mm256_cvttpd_epu32 (__m256d __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) { return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) { return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A, (__v4si) @@ -2150,35 +2151,35 @@ _mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_cvttps_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttps_epi32 (__mmask8 __U, __m128 __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_cvttps_epi32(__A), (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_cvttps_epi32(__A), (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttps_epi32 (__mmask8 __U, __m256 __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_cvttps_epi32(__A), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvttps_epu32 (__m128 __A) { return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, (__v4si) @@ -2186,14 +2187,14 @@ _mm_cvttps_epu32 (__m128 __A) { (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvttps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A, (__v4si) @@ -2201,7 +2202,7 @@ _mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cvttps_epu32 (__m256 __A) { return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, (__v8si) @@ -2209,14 +2210,14 @@ _mm256_cvttps_epu32 (__m256 __A) { (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvttps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) { return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, (__v8si) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) { return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A, (__v8si) @@ -2224,147 +2225,147 @@ _mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) { (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_cvtepu32_pd (__m128i __A) { return (__m128d) __builtin_convertvector( __builtin_shufflevector((__v4su)__A, (__v4su)__A, 0, 1), __v2df); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu32_pd (__m128d __W, __mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U, (__v2df)_mm_cvtepu32_pd(__A), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U, (__v2df)_mm_cvtepu32_pd(__A), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_cvtepu32_pd (__m128i __A) { return (__m256d)__builtin_convertvector((__v4su)__A, __v4df); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu32_pd (__m256d __W, __mmask8 __U, __m128i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U, (__v4df)_mm256_cvtepu32_pd(__A), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U, (__v4df)_mm256_cvtepu32_pd(__A), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_cvtepu32_ps (__m128i __A) { return (__m128)__builtin_convertvector((__v4su)__A, __v4sf); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu32_ps (__m128 __W, __mmask8 __U, __m128i __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_cvtepu32_ps(__A), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu32_ps (__mmask8 __U, __m128i __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_cvtepu32_ps(__A), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_cvtepu32_ps (__m256i __A) { return (__m256)__builtin_convertvector((__v8su)__A, __v8sf); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu32_ps (__m256 __W, __mmask8 __U, __m256i __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_cvtepu32_ps(__A), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu32_ps (__mmask8 __U, __m256i __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_cvtepu32_ps(__A), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_div_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_div_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_div_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_div_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_div_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_div_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_div_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_div_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_div_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_div_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_div_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_div_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_div_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_div_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_div_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_div_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_expand_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A, (__v2df) __W, (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_expand_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A, (__v2df) @@ -2372,14 +2373,14 @@ _mm_maskz_expand_pd (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_expand_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A, (__v4df) __W, (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A, (__v4df) @@ -2387,14 +2388,14 @@ _mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expand_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A, (__v2di) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A, (__v2di) @@ -2402,14 +2403,14 @@ _mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expand_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A, (__v4di) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A, (__v4di) @@ -2417,7 +2418,7 @@ _mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) { (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P, (__v2df) __W, @@ -2425,7 +2426,7 @@ _mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) { __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P, (__v2df) @@ -2434,7 +2435,7 @@ _mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P, (__v4df) __W, @@ -2442,7 +2443,7 @@ _mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) { __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P, (__v4df) @@ -2451,7 +2452,7 @@ _mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P, (__v2di) __W, @@ -2459,7 +2460,7 @@ _mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) { __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P, (__v2di) @@ -2468,7 +2469,7 @@ _mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P, @@ -2477,7 +2478,7 @@ _mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U, __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P, (__v4di) @@ -2486,14 +2487,14 @@ _mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_ps (__m128 __W, __mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P, (__v4sf) @@ -2502,14 +2503,14 @@ _mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_ps (__m256 __W, __mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P, (__v8sf) __W, (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P, (__v8sf) @@ -2518,7 +2519,7 @@ _mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P, (__v4si) __W, @@ -2526,7 +2527,7 @@ _mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) { __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P, (__v4si) @@ -2534,7 +2535,7 @@ _mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P, @@ -2543,7 +2544,7 @@ _mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U, __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P, (__v8si) @@ -2552,14 +2553,14 @@ _mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) { __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_expand_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_expand_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A, (__v4sf) @@ -2567,14 +2568,14 @@ _mm_maskz_expand_ps (__mmask8 __U, __m128 __A) { (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_expand_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A, (__v8sf) __W, (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A, (__v8sf) @@ -2582,14 +2583,14 @@ _mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) { (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expand_epi32 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A, (__v4si) __W, (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A, (__v4si) @@ -2597,14 +2598,14 @@ _mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) { (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expand_epi32 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A, (__v8si) __W, (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A, (__v8si) @@ -2612,7 +2613,7 @@ _mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) { (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_getexp_pd (__m128d __A) { return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, (__v2df) @@ -2620,14 +2621,14 @@ _mm_getexp_pd (__m128d __A) { (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_getexp_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, (__v2df) __W, (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A, (__v2df) @@ -2635,7 +2636,7 @@ _mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) { (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_getexp_pd (__m256d __A) { return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, (__v4df) @@ -2643,14 +2644,14 @@ _mm256_getexp_pd (__m256d __A) { (__mmask8) -1); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_getexp_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, (__v4df) __W, (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A, (__v4df) @@ -2658,7 +2659,7 @@ _mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) { (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_getexp_ps (__m128 __A) { return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, (__v4sf) @@ -2666,14 +2667,14 @@ _mm_getexp_ps (__m128 __A) { (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_getexp_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, (__v4sf) __W, (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A, (__v4sf) @@ -2681,7 +2682,7 @@ _mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) { (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_getexp_ps (__m256 __A) { return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, (__v8sf) @@ -2689,14 +2690,14 @@ _mm256_getexp_ps (__m256 __A) { (__mmask8) -1); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_getexp_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, (__v8sf) __W, (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A, (__v8sf) @@ -2704,498 +2705,498 @@ _mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) { (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_max_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_max_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_max_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_max_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_max_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_max_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_max_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_max_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_max_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_max_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_max_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_max_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_max_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_max_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_max_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_max_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_min_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_min_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_min_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_min_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_min_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_min_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_min_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_min_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_min_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_min_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_min_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_min_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_min_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_min_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_min_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_min_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_mul_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_mul_pd(__A, __B), (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_mul_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_mul_pd(__A, __B), (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_mul_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_mul_pd(__A, __B), (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_mul_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_mul_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_mul_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_mul_ps(__A, __B), (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_mul_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_mul_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_mul_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_mul_ps(__A, __B), (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_mul_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_mul_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_abs_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_abs_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_abs_epi32(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, (__v4si)_mm_abs_epi32(__A), (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_abs_epi32(__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_abs_epi32(__A), (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_abs_epi32(__mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, (__v8si)_mm256_abs_epi32(__A), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_abs_epi64 (__m128i __A) { return (__m128i)__builtin_ia32_pabsq128((__v2di)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_abs_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, (__v2di)_mm_abs_epi64(__A), (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_abs_epi64 (__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, (__v2di)_mm_abs_epi64(__A), (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_abs_epi64 (__m256i __A) { return (__m256i)__builtin_ia32_pabsq256 ((__v4di)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_abs_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, (__v4di)_mm256_abs_epi64(__A), (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_abs_epi64 (__mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, (__v4di)_mm256_abs_epi64(__A), (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epi32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_max_epi32(__A, __B), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_max_epi32(__A, __B), (__v4si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epi32(__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_max_epi32(__A, __B), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_max_epi32(__A, __B), (__v8si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_max_epi64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_pmaxsq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epi64 (__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_max_epi64(__A, __B), (__v2di)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epi64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_max_epi64(__A, __B), (__v2di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epi64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_pmaxsq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epi64 (__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_max_epi64(__A, __B), (__v4di)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epi64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_max_epi64(__A, __B), (__v4di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epu32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_max_epu32(__A, __B), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_max_epu32(__A, __B), (__v4si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epu32(__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_max_epu32(__A, __B), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_max_epu32(__A, __B), (__v8si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_max_epu64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_pmaxuq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_max_epu64 (__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_max_epu64(__A, __B), (__v2di)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_max_epu64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_max_epu64(__A, __B), (__v2di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_max_epu64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_pmaxuq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_max_epu64 (__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_max_epu64(__A, __B), (__v4di)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_max_epu64(__A, __B), (__v4di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epi32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_min_epi32(__A, __B), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_min_epi32(__A, __B), (__v4si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epi32(__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_min_epi32(__A, __B), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_min_epi32(__A, __B), (__v8si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_min_epi64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_pminsq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epi64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_min_epi64(__A, __B), (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epi64 (__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_min_epi64(__A, __B), (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epi64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_pminsq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epi64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_min_epi64(__A, __B), (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epi64 (__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_min_epi64(__A, __B), (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epu32(__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_min_epu32(__A, __B), (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, (__v4si)_mm_min_epu32(__A, __B), (__v4si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epu32(__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_min_epu32(__A, __B), (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, (__v8si)_mm256_min_epu32(__A, __B), (__v8si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_min_epu64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_pminuq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_min_epu64 (__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_min_epu64(__A, __B), (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_min_epu64 (__mmask8 __M, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M, (__v2di)_mm_min_epu64(__A, __B), (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_min_epu64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_pminuq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_min_epu64 (__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_min_epu64(__A, __B), (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_min_epu64 (__mmask8 __M, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, (__v4di)_mm256_min_epu64(__A, __B), @@ -3276,7 +3277,7 @@ _mm256_maskz_min_epu64 (__mmask8 __M, __m256i __A, __m256i __B) { (__v8sf)_mm256_setzero_ps(), \ (__mmask8)(U)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_scalef_pd (__m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, (__v2df) __B, @@ -3285,7 +3286,7 @@ _mm_scalef_pd (__m128d __A, __m128d __B) { (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, @@ -3294,7 +3295,7 @@ _mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A, (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A, (__v2df) __B, @@ -3303,7 +3304,7 @@ _mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) { (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_scalef_pd (__m256d __A, __m256d __B) { return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, (__v4df) __B, @@ -3312,7 +3313,7 @@ _mm256_scalef_pd (__m256d __A, __m256d __B) { (__mmask8) -1); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, @@ -3321,7 +3322,7 @@ _mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A, (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A, (__v4df) __B, @@ -3330,7 +3331,7 @@ _mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) { (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_scalef_ps (__m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, (__v4sf) __B, @@ -3339,7 +3340,7 @@ _mm_scalef_ps (__m128 __A, __m128 __B) { (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, (__v4sf) __B, @@ -3347,7 +3348,7 @@ _mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) { return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A, (__v4sf) __B, @@ -3356,7 +3357,7 @@ _mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) { (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_scalef_ps (__m256 __A, __m256 __B) { return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, (__v8sf) __B, @@ -3365,7 +3366,7 @@ _mm256_scalef_ps (__m256 __A, __m256 __B) { (__mmask8) -1); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, @@ -3374,7 +3375,7 @@ _mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A, (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A, (__v8sf) __B, @@ -3543,125 +3544,125 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)(__m256i)(index), \ (__v8si)(__m256i)(v1), (int)(scale)) - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_sqrt_pd(__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_sqrt_pd(__A), (__v2df)__W); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_sqrt_pd(__mmask8 __U, __m128d __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_sqrt_pd(__A), (__v2df)_mm_setzero_pd()); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_sqrt_pd(__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_sqrt_pd(__A), (__v4df)__W); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_sqrt_pd(__mmask8 __U, __m256d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_sqrt_pd(__A), (__v4df)_mm256_setzero_pd()); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_sqrt_ps(__m128 __W, __mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_sqrt_ps(__A), (__v4sf)__W); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_sqrt_ps(__mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_sqrt_ps(__A), (__v4sf)_mm_setzero_ps()); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_sqrt_ps(__m256 __W, __mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_sqrt_ps(__A), (__v8sf)__W); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_sqrt_ps(__mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_sqrt_ps(__A), (__v8sf)_mm256_setzero_ps()); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_sub_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_sub_pd(__A, __B), (__v2df)__W); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_sub_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, (__v2df)_mm_sub_pd(__A, __B), (__v2df)_mm_setzero_pd()); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_sub_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_sub_pd(__A, __B), (__v4df)__W); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, (__v4df)_mm256_sub_pd(__A, __B), (__v4df)_mm256_setzero_pd()); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_sub_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_sub_ps(__A, __B), (__v4sf)__W); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_sub_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, (__v4sf)_mm_sub_ps(__A, __B), (__v4sf)_mm_setzero_ps()); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_sub_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_sub_ps(__A, __B), (__v8sf)__W); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_sub_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, (__v8sf)_mm256_sub_ps(__A, __B), (__v8sf)_mm256_setzero_ps()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutex2var_epi32(__m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_vpermi2vard128((__v4si) __A, (__v4si)__I, (__v4si)__B); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_epi32(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -3669,7 +3670,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__A); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_epi32(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -3677,7 +3678,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__I); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_epi32(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -3685,13 +3686,13 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutex2var_epi32(__m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_vpermi2vard256((__v8si)__A, (__v8si) __I, (__v8si) __B); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_epi32(__m256i __A, __mmask8 __U, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -3699,7 +3700,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__A); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_epi32(__m256i __A, __m256i __I, __mmask8 __U, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -3707,7 +3708,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__I); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_epi32(__mmask8 __U, __m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -3715,40 +3716,40 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)_mm256_setzero_si256()); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_permutex2var_pd(__m128d __A, __m128i __I, __m128d __B) { return (__m128d)__builtin_ia32_vpermi2varpd128((__v2df)__A, (__v2di)__I, (__v2df)__B); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_pd(__m128d __A, __mmask8 __U, __m128i __I, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128(__U, (__v2df)_mm_permutex2var_pd(__A, __I, __B), (__v2df)__A); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_pd(__m128d __A, __m128i __I, __mmask8 __U, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128(__U, (__v2df)_mm_permutex2var_pd(__A, __I, __B), (__v2df)(__m128d)__I); } - static __inline__ __m128d __DEFAULT_FN_ATTRS + static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_pd(__mmask8 __U, __m128d __A, __m128i __I, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128(__U, (__v2df)_mm_permutex2var_pd(__A, __I, __B), (__v2df)_mm_setzero_pd()); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_permutex2var_pd(__m256d __A, __m256i __I, __m256d __B) { return (__m256d)__builtin_ia32_vpermi2varpd256((__v4df)__A, (__v4di)__I, (__v4df)__B); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_pd(__m256d __A, __mmask8 __U, __m256i __I, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256(__U, @@ -3756,7 +3757,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4df)__A); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_pd(__m256d __A, __m256i __I, __mmask8 __U, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256(__U, @@ -3764,7 +3765,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4df)(__m256d)__I); } - static __inline__ __m256d __DEFAULT_FN_ATTRS + static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_pd(__mmask8 __U, __m256d __A, __m256i __I, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256(__U, @@ -3772,47 +3773,47 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4df)_mm256_setzero_pd()); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_permutex2var_ps(__m128 __A, __m128i __I, __m128 __B) { return (__m128)__builtin_ia32_vpermi2varps128((__v4sf)__A, (__v4si)__I, (__v4sf)__B); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_ps(__m128 __A, __mmask8 __U, __m128i __I, __m128 __B) { return (__m128)__builtin_ia32_selectps_128(__U, (__v4sf)_mm_permutex2var_ps(__A, __I, __B), (__v4sf)__A); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_ps(__m128 __A, __m128i __I, __mmask8 __U, __m128 __B) { return (__m128)__builtin_ia32_selectps_128(__U, (__v4sf)_mm_permutex2var_ps(__A, __I, __B), (__v4sf)(__m128)__I); } - static __inline__ __m128 __DEFAULT_FN_ATTRS + static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_ps(__mmask8 __U, __m128 __A, __m128i __I, __m128 __B) { return (__m128)__builtin_ia32_selectps_128(__U, (__v4sf)_mm_permutex2var_ps(__A, __I, __B), (__v4sf)_mm_setzero_ps()); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_permutex2var_ps(__m256 __A, __m256i __I, __m256 __B) { return (__m256)__builtin_ia32_vpermi2varps256((__v8sf)__A, (__v8si)__I, (__v8sf) __B); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_ps(__m256 __A, __mmask8 __U, __m256i __I, __m256 __B) { return (__m256)__builtin_ia32_selectps_256(__U, (__v8sf)_mm256_permutex2var_ps(__A, __I, __B), (__v8sf)__A); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_ps(__m256 __A, __m256i __I, __mmask8 __U, __m256 __B) { return (__m256)__builtin_ia32_selectps_256(__U, @@ -3820,7 +3821,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8sf)(__m256)__I); } - static __inline__ __m256 __DEFAULT_FN_ATTRS + static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_ps(__mmask8 __U, __m256 __A, __m256i __I, __m256 __B) { return (__m256)__builtin_ia32_selectps_256(__U, @@ -3828,13 +3829,13 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8sf)_mm256_setzero_ps()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_permutex2var_epi64(__m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_vpermi2varq128((__v2di)__A, (__v2di)__I, (__v2di)__B); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_permutex2var_epi64(__m128i __A, __mmask8 __U, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -3842,7 +3843,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__A); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask2_permutex2var_epi64(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -3850,7 +3851,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__I); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_permutex2var_epi64(__mmask8 __U, __m128i __A, __m128i __I, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -3859,13 +3860,13 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutex2var_epi64(__m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_vpermi2varq256((__v4di)__A, (__v4di) __I, (__v4di) __B); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutex2var_epi64(__m256i __A, __mmask8 __U, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -3873,7 +3874,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__A); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask2_permutex2var_epi64(__m256i __A, __m256i __I, __mmask8 __U, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -3881,7 +3882,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__I); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutex2var_epi64(__mmask8 __U, __m256i __A, __m256i __I, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -3889,7 +3890,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi8_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -3897,7 +3898,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -3905,7 +3906,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi8_epi32 (__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -3913,7 +3914,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi8_epi32 (__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -3921,7 +3922,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi8_epi64(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -3929,7 +3930,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -3937,7 +3938,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi8_epi64(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -3945,7 +3946,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -3953,7 +3954,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_epi64(__m128i __W, __mmask8 __U, __m128i __X) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -3961,7 +3962,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -3969,7 +3970,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_epi64(__m256i __W, __mmask8 __U, __m128i __X) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -3977,7 +3978,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -3985,7 +3986,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi16_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -3993,7 +3994,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4001,7 +4002,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi16_epi32(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4009,7 +4010,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi16_epi32 (__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4017,7 +4018,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi16_epi64(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4025,7 +4026,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4033,7 +4034,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi16_epi64(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4041,7 +4042,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4050,7 +4051,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4058,7 +4059,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4066,7 +4067,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4074,7 +4075,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4082,7 +4083,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4090,7 +4091,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4098,7 +4099,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4106,7 +4107,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4114,7 +4115,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4122,7 +4123,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4130,7 +4131,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4138,7 +4139,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4146,7 +4147,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4154,7 +4155,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4162,7 +4163,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4si)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4170,7 +4171,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4178,7 +4179,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v8si)_mm256_setzero_si256()); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4186,7 +4187,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)__W); } - static __inline__ __m128i __DEFAULT_FN_ATTRS + static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4194,7 +4195,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v2di)_mm_setzero_si128()); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4202,7 +4203,7 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)__W); } - static __inline__ __m256i __DEFAULT_FN_ATTRS + static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4263,13 +4264,13 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) { (__v4di)_mm256_rol_epi64((a), (b)), \ (__v4di)_mm256_setzero_si256()) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_rolv_epi32 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_prolvd128((__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -4277,7 +4278,7 @@ _mm_mask_rolv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_rolv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -4285,13 +4286,13 @@ _mm_maskz_rolv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_rolv_epi32 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_prolvd256((__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -4299,7 +4300,7 @@ _mm256_mask_rolv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_rolv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -4307,13 +4308,13 @@ _mm256_maskz_rolv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_rolv_epi64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_prolvq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -4321,7 +4322,7 @@ _mm_mask_rolv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_rolv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -4329,13 +4330,13 @@ _mm_maskz_rolv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_rolv_epi64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_prolvq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -4343,7 +4344,7 @@ _mm256_mask_rolv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -4403,7 +4404,7 @@ _mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_ror_epi64((a), (b)), \ (__v4di)_mm256_setzero_si256()) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4411,7 +4412,7 @@ _mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4419,7 +4420,7 @@ _mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4427,7 +4428,7 @@ _mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4435,7 +4436,7 @@ _mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4443,7 +4444,7 @@ _mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_slli_epi32(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4451,7 +4452,7 @@ _mm_maskz_slli_epi32(__mmask8 __U, __m128i __A, int __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4459,7 +4460,7 @@ _mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4467,7 +4468,7 @@ _mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A, int __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4475,7 +4476,7 @@ _mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sll_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4483,7 +4484,7 @@ _mm_maskz_sll_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4491,7 +4492,7 @@ _mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4499,7 +4500,7 @@ _mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4507,7 +4508,7 @@ _mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_slli_epi64(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4515,7 +4516,7 @@ _mm_maskz_slli_epi64(__mmask8 __U, __m128i __A, int __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4523,7 +4524,7 @@ _mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4531,13 +4532,13 @@ _mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_rorv_epi32 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_prorvd128((__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -4545,7 +4546,7 @@ _mm_mask_rorv_epi32 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_rorv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -4553,13 +4554,13 @@ _mm_maskz_rorv_epi32 (__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_rorv_epi32 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_prorvd256((__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -4567,7 +4568,7 @@ _mm256_mask_rorv_epi32 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_rorv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -4575,13 +4576,13 @@ _mm256_maskz_rorv_epi32 (__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_rorv_epi64 (__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_prorvq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -4589,7 +4590,7 @@ _mm_mask_rorv_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_rorv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128(__U, @@ -4597,13 +4598,13 @@ _mm_maskz_rorv_epi64 (__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_rorv_epi64 (__m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_prorvq256((__v4di)__A, (__v4di)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -4611,7 +4612,7 @@ _mm256_mask_rorv_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256(__U, @@ -4619,7 +4620,7 @@ _mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4627,7 +4628,7 @@ _mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sllv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4635,7 +4636,7 @@ _mm_maskz_sllv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4643,7 +4644,7 @@ _mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4651,7 +4652,7 @@ _mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4659,7 +4660,7 @@ _mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4667,7 +4668,7 @@ _mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4675,7 +4676,7 @@ _mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4683,7 +4684,7 @@ _mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4691,7 +4692,7 @@ _mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srlv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4699,7 +4700,7 @@ _mm_maskz_srlv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4707,7 +4708,7 @@ _mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4715,7 +4716,7 @@ _mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4723,7 +4724,7 @@ _mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4731,7 +4732,7 @@ _mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4739,7 +4740,7 @@ _mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4747,7 +4748,7 @@ _mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4755,7 +4756,7 @@ _mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4763,7 +4764,7 @@ _mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4771,7 +4772,7 @@ _mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4779,7 +4780,7 @@ _mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4787,7 +4788,7 @@ _mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srli_epi32(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4795,7 +4796,7 @@ _mm_maskz_srli_epi32(__mmask8 __U, __m128i __A, int __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4803,7 +4804,7 @@ _mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4811,7 +4812,7 @@ _mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A, int __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4819,7 +4820,7 @@ _mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srl_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4827,7 +4828,7 @@ _mm_maskz_srl_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4835,7 +4836,7 @@ _mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4843,7 +4844,7 @@ _mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4851,7 +4852,7 @@ _mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srli_epi64(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4859,7 +4860,7 @@ _mm_maskz_srli_epi64(__mmask8 __U, __m128i __A, int __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4867,7 +4868,7 @@ _mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4875,7 +4876,7 @@ _mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A, int __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4883,7 +4884,7 @@ _mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -4891,7 +4892,7 @@ _mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4899,7 +4900,7 @@ _mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -4907,13 +4908,13 @@ _mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srav_epi64(__m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_psravq128((__v2di)__X, (__v2di)__Y); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4921,7 +4922,7 @@ _mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srav_epi64(__mmask8 __U, __m128i __X, __m128i __Y) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -4929,13 +4930,13 @@ _mm_maskz_srav_epi64(__mmask8 __U, __m128i __X, __m128i __Y) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srav_epi64(__m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_psravq256((__v4di)__X, (__v4di) __Y); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4943,7 +4944,7 @@ _mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -4951,7 +4952,7 @@ _mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mov_epi32 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U, @@ -4959,7 +4960,7 @@ _mm_mask_mov_epi32 (__m128i __W, __mmask8 __U, __m128i __A) (__v4si) __W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mov_epi32 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectd_128 ((__mmask8) __U, @@ -4968,7 +4969,7 @@ _mm_maskz_mov_epi32 (__mmask8 __U, __m128i __A) } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mov_epi32 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U, @@ -4976,7 +4977,7 @@ _mm256_mask_mov_epi32 (__m256i __W, __mmask8 __U, __m256i __A) (__v8si) __W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectd_256 ((__mmask8) __U, @@ -4984,7 +4985,7 @@ _mm256_maskz_mov_epi32 (__mmask8 __U, __m256i __A) (__v8si) _mm256_setzero_si256 ()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P, @@ -4993,7 +4994,7 @@ _mm_mask_load_epi32 (__m128i __W, __mmask8 __U, void const *__P) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_load_epi32 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_movdqa32load128_mask ((__v4si *) __P, @@ -5003,7 +5004,7 @@ _mm_maskz_load_epi32 (__mmask8 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P, @@ -5012,7 +5013,7 @@ _mm256_mask_load_epi32 (__m256i __W, __mmask8 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_load_epi32 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_movdqa32load256_mask ((__v8si *) __P, @@ -5022,7 +5023,7 @@ _mm256_maskz_load_epi32 (__mmask8 __U, void const *__P) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_movdqa32store128_mask ((__v4si *) __P, @@ -5030,7 +5031,7 @@ _mm_mask_store_epi32 (void *__P, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_movdqa32store256_mask ((__v8si *) __P, @@ -5038,7 +5039,7 @@ _mm256_mask_store_epi32 (void *__P, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_mov_epi64 (__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U, @@ -5046,7 +5047,7 @@ _mm_mask_mov_epi64 (__m128i __W, __mmask8 __U, __m128i __A) (__v2di) __W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_mov_epi64 (__mmask8 __U, __m128i __A) { return (__m128i) __builtin_ia32_selectq_128 ((__mmask8) __U, @@ -5054,7 +5055,7 @@ _mm_maskz_mov_epi64 (__mmask8 __U, __m128i __A) (__v2di) _mm_setzero_si128 ()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_mov_epi64 (__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U, @@ -5062,7 +5063,7 @@ _mm256_mask_mov_epi64 (__m256i __W, __mmask8 __U, __m256i __A) (__v4di) __W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A) { return (__m256i) __builtin_ia32_selectq_256 ((__mmask8) __U, @@ -5070,7 +5071,7 @@ _mm256_maskz_mov_epi64 (__mmask8 __U, __m256i __A) (__v4di) _mm256_setzero_si256 ()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P, @@ -5079,7 +5080,7 @@ _mm_mask_load_epi64 (__m128i __W, __mmask8 __U, void const *__P) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_load_epi64 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_movdqa64load128_mask ((__v2di *) __P, @@ -5089,7 +5090,7 @@ _mm_maskz_load_epi64 (__mmask8 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P, @@ -5098,7 +5099,7 @@ _mm256_mask_load_epi64 (__m256i __W, __mmask8 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_load_epi64 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_movdqa64load256_mask ((__v4di *) __P, @@ -5108,7 +5109,7 @@ _mm256_maskz_load_epi64 (__mmask8 __U, void const *__P) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_movdqa64store128_mask ((__v2di *) __P, @@ -5116,7 +5117,7 @@ _mm_mask_store_epi64 (void *__P, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_movdqa64store256_mask ((__v4di *) __P, @@ -5124,7 +5125,7 @@ _mm256_mask_store_epi64 (void *__P, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_movedup_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5132,7 +5133,7 @@ _mm_mask_movedup_pd (__m128d __W, __mmask8 __U, __m128d __A) (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_movedup_pd (__mmask8 __U, __m128d __A) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5140,7 +5141,7 @@ _mm_maskz_movedup_pd (__mmask8 __U, __m128d __A) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_movedup_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5148,7 +5149,7 @@ _mm256_mask_movedup_pd (__m256d __W, __mmask8 __U, __m256d __A) (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5156,7 +5157,7 @@ _mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_set1_epi32(__m128i __O, __mmask8 __M, int __A) { return (__m128i)__builtin_ia32_selectd_128(__M, @@ -5164,7 +5165,7 @@ _mm_mask_set1_epi32(__m128i __O, __mmask8 __M, int __A) (__v4si)__O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_set1_epi32( __mmask8 __M, int __A) { return (__m128i)__builtin_ia32_selectd_128(__M, @@ -5172,7 +5173,7 @@ _mm_maskz_set1_epi32( __mmask8 __M, int __A) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_set1_epi32(__m256i __O, __mmask8 __M, int __A) { return (__m256i)__builtin_ia32_selectd_256(__M, @@ -5180,7 +5181,7 @@ _mm256_mask_set1_epi32(__m256i __O, __mmask8 __M, int __A) (__v8si)__O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_set1_epi32( __mmask8 __M, int __A) { return (__m256i)__builtin_ia32_selectd_256(__M, @@ -5189,7 +5190,7 @@ _mm256_maskz_set1_epi32( __mmask8 __M, int __A) } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A) { return (__m128i) __builtin_ia32_selectq_128(__M, @@ -5197,7 +5198,7 @@ _mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A) (__v2di) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_set1_epi64 (__mmask8 __M, long long __A) { return (__m128i) __builtin_ia32_selectq_128(__M, @@ -5205,7 +5206,7 @@ _mm_maskz_set1_epi64 (__mmask8 __M, long long __A) (__v2di) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A) { return (__m256i) __builtin_ia32_selectq_256(__M, @@ -5213,7 +5214,7 @@ _mm256_mask_set1_epi64 (__m256i __O, __mmask8 __M, long long __A) (__v4di) __O) ; } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_set1_epi64 (__mmask8 __M, long long __A) { return (__m256i) __builtin_ia32_selectq_256(__M, @@ -5293,7 +5294,7 @@ _mm256_maskz_set1_epi64 (__mmask8 __M, long long __A) (__v8si)(__m256i)(C), (int)(imm), \ (__mmask8)(U)) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_load_pd (__m128d __W, __mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P, @@ -5301,7 +5302,7 @@ _mm_mask_load_pd (__m128d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_load_pd (__mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_loadapd128_mask ((__v2df *) __P, @@ -5310,7 +5311,7 @@ _mm_maskz_load_pd (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_load_pd (__m256d __W, __mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P, @@ -5318,7 +5319,7 @@ _mm256_mask_load_pd (__m256d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_load_pd (__mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_loadapd256_mask ((__v4df *) __P, @@ -5327,7 +5328,7 @@ _mm256_maskz_load_pd (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_load_ps (__m128 __W, __mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P, @@ -5335,7 +5336,7 @@ _mm_mask_load_ps (__m128 __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_load_ps (__mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_loadaps128_mask ((__v4sf *) __P, @@ -5344,7 +5345,7 @@ _mm_maskz_load_ps (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_load_ps (__m256 __W, __mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P, @@ -5352,7 +5353,7 @@ _mm256_mask_load_ps (__m256 __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_load_ps (__mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_loadaps256_mask ((__v8sf *) __P, @@ -5361,7 +5362,7 @@ _mm256_maskz_load_ps (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddqudi128_mask ((__v2di *) __P, @@ -5369,7 +5370,7 @@ _mm_mask_loadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddqudi128_mask ((__v2di *) __P, @@ -5378,7 +5379,7 @@ _mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddqudi256_mask ((__v4di *) __P, @@ -5386,7 +5387,7 @@ _mm256_mask_loadu_epi64 (__m256i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddqudi256_mask ((__v4di *) __P, @@ -5395,7 +5396,7 @@ _mm256_maskz_loadu_epi64 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddqusi128_mask ((__v4si *) __P, @@ -5403,7 +5404,7 @@ _mm_mask_loadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_loaddqusi128_mask ((__v4si *) __P, @@ -5412,7 +5413,7 @@ _mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddqusi256_mask ((__v8si *) __P, @@ -5420,7 +5421,7 @@ _mm256_mask_loadu_epi32 (__m256i __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_epi32 (__mmask8 __U, void const *__P) { return (__m256i) __builtin_ia32_loaddqusi256_mask ((__v8si *) __P, @@ -5429,7 +5430,7 @@ _mm256_maskz_loadu_epi32 (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_loadu_pd (__m128d __W, __mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_loadupd128_mask ((__v2df *) __P, @@ -5437,7 +5438,7 @@ _mm_mask_loadu_pd (__m128d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_pd (__mmask8 __U, void const *__P) { return (__m128d) __builtin_ia32_loadupd128_mask ((__v2df *) __P, @@ -5446,7 +5447,7 @@ _mm_maskz_loadu_pd (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_loadupd256_mask ((__v4df *) __P, @@ -5454,7 +5455,7 @@ _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_pd (__mmask8 __U, void const *__P) { return (__m256d) __builtin_ia32_loadupd256_mask ((__v4df *) __P, @@ -5463,7 +5464,7 @@ _mm256_maskz_loadu_pd (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_loadu_ps (__m128 __W, __mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_loadups128_mask ((__v4sf *) __P, @@ -5471,7 +5472,7 @@ _mm_mask_loadu_ps (__m128 __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_loadu_ps (__mmask8 __U, void const *__P) { return (__m128) __builtin_ia32_loadups128_mask ((__v4sf *) __P, @@ -5480,7 +5481,7 @@ _mm_maskz_loadu_ps (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_loadu_ps (__m256 __W, __mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_loadups256_mask ((__v8sf *) __P, @@ -5488,7 +5489,7 @@ _mm256_mask_loadu_ps (__m256 __W, __mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_loadu_ps (__mmask8 __U, void const *__P) { return (__m256) __builtin_ia32_loadups256_mask ((__v8sf *) __P, @@ -5497,7 +5498,7 @@ _mm256_maskz_loadu_ps (__mmask8 __U, void const *__P) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_pd (void *__P, __mmask8 __U, __m128d __A) { __builtin_ia32_storeapd128_mask ((__v2df *) __P, @@ -5505,7 +5506,7 @@ _mm_mask_store_pd (void *__P, __mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_store_pd (void *__P, __mmask8 __U, __m256d __A) { __builtin_ia32_storeapd256_mask ((__v4df *) __P, @@ -5513,7 +5514,7 @@ _mm256_mask_store_pd (void *__P, __mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_store_ps (void *__P, __mmask8 __U, __m128 __A) { __builtin_ia32_storeaps128_mask ((__v4sf *) __P, @@ -5521,7 +5522,7 @@ _mm_mask_store_ps (void *__P, __mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A) { __builtin_ia32_storeaps256_mask ((__v8sf *) __P, @@ -5529,7 +5530,7 @@ _mm256_mask_store_ps (void *__P, __mmask8 __U, __m256 __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_storedqudi128_mask ((__v2di *) __P, @@ -5537,7 +5538,7 @@ _mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_storedqudi256_mask ((__v4di *) __P, @@ -5545,7 +5546,7 @@ _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_storedqusi128_mask ((__v4si *) __P, @@ -5553,7 +5554,7 @@ _mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_storedqusi256_mask ((__v8si *) __P, @@ -5561,7 +5562,7 @@ _mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_storeu_pd (void *__P, __mmask8 __U, __m128d __A) { __builtin_ia32_storeupd128_mask ((__v2df *) __P, @@ -5569,7 +5570,7 @@ _mm_mask_storeu_pd (void *__P, __mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_pd (void *__P, __mmask8 __U, __m256d __A) { __builtin_ia32_storeupd256_mask ((__v4df *) __P, @@ -5577,7 +5578,7 @@ _mm256_mask_storeu_pd (void *__P, __mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_storeu_ps (void *__P, __mmask8 __U, __m128 __A) { __builtin_ia32_storeups128_mask ((__v4sf *) __P, @@ -5585,7 +5586,7 @@ _mm_mask_storeu_ps (void *__P, __mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_storeu_ps (void *__P, __mmask8 __U, __m256 __A) { __builtin_ia32_storeups256_mask ((__v8sf *) __P, @@ -5594,7 +5595,7 @@ _mm256_mask_storeu_ps (void *__P, __mmask8 __U, __m256 __A) } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5602,7 +5603,7 @@ _mm_mask_unpackhi_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5610,7 +5611,7 @@ _mm_maskz_unpackhi_pd(__mmask8 __U, __m128d __A, __m128d __B) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5618,7 +5619,7 @@ _mm256_mask_unpackhi_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5626,7 +5627,7 @@ _mm256_maskz_unpackhi_pd(__mmask8 __U, __m256d __A, __m256d __B) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5634,7 +5635,7 @@ _mm_mask_unpackhi_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5642,7 +5643,7 @@ _mm_maskz_unpackhi_ps(__mmask8 __U, __m128 __A, __m128 __B) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5650,7 +5651,7 @@ _mm256_mask_unpackhi_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5658,7 +5659,7 @@ _mm256_maskz_unpackhi_ps(__mmask8 __U, __m256 __A, __m256 __B) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5666,7 +5667,7 @@ _mm_mask_unpacklo_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_pd(__mmask8 __U, __m128d __A, __m128d __B) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5674,7 +5675,7 @@ _mm_maskz_unpacklo_pd(__mmask8 __U, __m128d __A, __m128d __B) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5682,7 +5683,7 @@ _mm256_mask_unpacklo_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_pd(__mmask8 __U, __m256d __A, __m256d __B) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5690,7 +5691,7 @@ _mm256_maskz_unpacklo_pd(__mmask8 __U, __m256d __A, __m256d __B) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5698,7 +5699,7 @@ _mm_mask_unpacklo_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_ps(__mmask8 __U, __m128 __A, __m128 __B) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5706,7 +5707,7 @@ _mm_maskz_unpacklo_ps(__mmask8 __U, __m128 __A, __m128 __B) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5714,7 +5715,7 @@ _mm256_mask_unpacklo_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_ps(__mmask8 __U, __m256 __A, __m256 __B) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5722,7 +5723,7 @@ _mm256_maskz_unpacklo_ps(__mmask8 __U, __m256 __A, __m256 __B) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_rcp14_pd (__m128d __A) { return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, @@ -5731,7 +5732,7 @@ _mm_rcp14_pd (__m128d __A) (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_rcp14_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, @@ -5739,7 +5740,7 @@ _mm_mask_rcp14_pd (__m128d __W, __mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_rcp14_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_rcp14pd128_mask ((__v2df) __A, @@ -5748,7 +5749,7 @@ _mm_maskz_rcp14_pd (__mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_rcp14_pd (__m256d __A) { return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, @@ -5757,7 +5758,7 @@ _mm256_rcp14_pd (__m256d __A) (__mmask8) -1); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_rcp14_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, @@ -5765,7 +5766,7 @@ _mm256_mask_rcp14_pd (__m256d __W, __mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_rcp14_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_rcp14pd256_mask ((__v4df) __A, @@ -5774,7 +5775,7 @@ _mm256_maskz_rcp14_pd (__mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_rcp14_ps (__m128 __A) { return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, @@ -5783,7 +5784,7 @@ _mm_rcp14_ps (__m128 __A) (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_rcp14_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, @@ -5791,7 +5792,7 @@ _mm_mask_rcp14_ps (__m128 __W, __mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_rcp14_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_rcp14ps128_mask ((__v4sf) __A, @@ -5800,7 +5801,7 @@ _mm_maskz_rcp14_ps (__mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_rcp14_ps (__m256 __A) { return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, @@ -5809,7 +5810,7 @@ _mm256_rcp14_ps (__m256 __A) (__mmask8) -1); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_rcp14_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, @@ -5817,7 +5818,7 @@ _mm256_mask_rcp14_ps (__m256 __W, __mmask8 __U, __m256 __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_rcp14ps256_mask ((__v8sf) __A, @@ -5866,7 +5867,7 @@ _mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A) (__v8sf)_mm256_permute_ps((X), (C)), \ (__v8sf)_mm256_setzero_ps()) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5874,7 +5875,7 @@ _mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C) (__v2df)__W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C) { return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U, @@ -5882,7 +5883,7 @@ _mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C) (__v2df)_mm_setzero_pd()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5890,7 +5891,7 @@ _mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C) (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -5898,7 +5899,7 @@ _mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5906,7 +5907,7 @@ _mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C) (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -5914,7 +5915,7 @@ _mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5922,7 +5923,7 @@ _mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -5930,115 +5931,115 @@ _mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_test_epi32_mask (__m128i __A, __m128i __B) { return _mm_cmpneq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_test_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpneq_epi32_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_test_epi32_mask (__m256i __A, __m256i __B) { return _mm256_cmpneq_epi32_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_mask_test_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpneq_epi32_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_test_epi64_mask (__m128i __A, __m128i __B) { return _mm_cmpneq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_test_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpneq_epi64_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_test_epi64_mask (__m256i __A, __m256i __B) { return _mm256_cmpneq_epi64_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_mask_test_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpneq_epi64_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_testn_epi32_mask (__m128i __A, __m128i __B) { return _mm_cmpeq_epi32_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_testn_epi32_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpeq_epi32_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_testn_epi32_mask (__m256i __A, __m256i __B) { return _mm256_cmpeq_epi32_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_mask_testn_epi32_mask (__mmask8 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpeq_epi32_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_testn_epi64_mask (__m128i __A, __m128i __B) { return _mm_cmpeq_epi64_mask (_mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS128 _mm_mask_testn_epi64_mask (__mmask8 __U, __m128i __A, __m128i __B) { return _mm_mask_cmpeq_epi64_mask (__U, _mm_and_si128 (__A, __B), _mm_setzero_si128()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_testn_epi64_mask (__m256i __A, __m256i __B) { return _mm256_cmpeq_epi64_mask (_mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __mmask8 __DEFAULT_FN_ATTRS +static __inline__ __mmask8 __DEFAULT_FN_ATTRS256 _mm256_mask_testn_epi64_mask (__mmask8 __U, __m256i __A, __m256i __B) { return _mm256_mask_cmpeq_epi64_mask (__U, _mm256_and_si256 (__A, __B), _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6046,7 +6047,7 @@ _mm_mask_unpackhi_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6054,7 +6055,7 @@ _mm_maskz_unpackhi_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6062,7 +6063,7 @@ _mm256_mask_unpackhi_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6070,7 +6071,7 @@ _mm256_maskz_unpackhi_epi32(__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpackhi_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -6078,7 +6079,7 @@ _mm_mask_unpackhi_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpackhi_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -6086,7 +6087,7 @@ _mm_maskz_unpackhi_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpackhi_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -6094,7 +6095,7 @@ _mm256_mask_unpackhi_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpackhi_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -6102,7 +6103,7 @@ _mm256_maskz_unpackhi_epi64(__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6110,7 +6111,7 @@ _mm_mask_unpacklo_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6118,7 +6119,7 @@ _mm_maskz_unpacklo_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6126,7 +6127,7 @@ _mm256_mask_unpacklo_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_epi32(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6134,7 +6135,7 @@ _mm256_maskz_unpacklo_epi32(__mmask8 __U, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_unpacklo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -6142,7 +6143,7 @@ _mm_mask_unpacklo_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_unpacklo_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, @@ -6150,7 +6151,7 @@ _mm_maskz_unpacklo_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_unpacklo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -6158,7 +6159,7 @@ _mm256_mask_unpacklo_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, @@ -6166,7 +6167,7 @@ _mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6174,7 +6175,7 @@ _mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6182,7 +6183,7 @@ _mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6190,7 +6191,7 @@ _mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6198,7 +6199,7 @@ _mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6206,7 +6207,7 @@ _mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B) (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srai_epi32(__mmask8 __U, __m128i __A, int __B) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U, @@ -6214,7 +6215,7 @@ _mm_maskz_srai_epi32(__mmask8 __U, __m128i __A, int __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6222,7 +6223,7 @@ _mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B) (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A, int __B) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U, @@ -6230,13 +6231,13 @@ _mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A, int __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_sra_epi64(__m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_psraq128((__v2di)__A, (__v2di)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \ @@ -6244,7 +6245,7 @@ _mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_sra_epi64(__mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \ @@ -6252,13 +6253,13 @@ _mm_maskz_sra_epi64(__mmask8 __U, __m128i __A, __m128i __B) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_sra_epi64(__m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_psraq256((__v4di) __A, (__v2di) __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \ @@ -6266,7 +6267,7 @@ _mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \ @@ -6274,13 +6275,13 @@ _mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_srai_epi64(__m128i __A, int __imm) { return (__m128i)__builtin_ia32_psraqi128((__v2di)__A, __imm); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __imm) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \ @@ -6288,7 +6289,7 @@ _mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __imm) (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_srai_epi64(__mmask8 __U, __m128i __A, int __imm) { return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \ @@ -6296,13 +6297,13 @@ _mm_maskz_srai_epi64(__mmask8 __U, __m128i __A, int __imm) (__v2di)_mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_srai_epi64(__m256i __A, int __imm) { return (__m256i)__builtin_ia32_psraqi256((__v4di)__A, __imm); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __imm) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \ @@ -6310,7 +6311,7 @@ _mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __imm) (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \ @@ -6489,7 +6490,7 @@ _mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm) (__v8sf)_mm256_shuffle_ps((A), (B), (M)), \ (__v8sf)_mm256_setzero_ps()) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_rsqrt14_pd (__m128d __A) { return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, @@ -6498,7 +6499,7 @@ _mm_rsqrt14_pd (__m128d __A) (__mmask8) -1); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_rsqrt14_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, @@ -6506,7 +6507,7 @@ _mm_mask_rsqrt14_pd (__m128d __W, __mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_rsqrt14_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_rsqrt14pd128_mask ((__v2df) __A, @@ -6515,7 +6516,7 @@ _mm_maskz_rsqrt14_pd (__mmask8 __U, __m128d __A) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_rsqrt14_pd (__m256d __A) { return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, @@ -6524,7 +6525,7 @@ _mm256_rsqrt14_pd (__m256d __A) (__mmask8) -1); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_rsqrt14_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, @@ -6532,7 +6533,7 @@ _mm256_mask_rsqrt14_pd (__m256d __W, __mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_rsqrt14_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_rsqrt14pd256_mask ((__v4df) __A, @@ -6541,7 +6542,7 @@ _mm256_maskz_rsqrt14_pd (__mmask8 __U, __m256d __A) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_rsqrt14_ps (__m128 __A) { return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, @@ -6550,7 +6551,7 @@ _mm_rsqrt14_ps (__m128 __A) (__mmask8) -1); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_rsqrt14_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, @@ -6558,7 +6559,7 @@ _mm_mask_rsqrt14_ps (__m128 __W, __mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_rsqrt14_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_rsqrt14ps128_mask ((__v4sf) __A, @@ -6567,7 +6568,7 @@ _mm_maskz_rsqrt14_ps (__mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_rsqrt14_ps (__m256 __A) { return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, @@ -6576,7 +6577,7 @@ _mm256_rsqrt14_ps (__m256 __A) (__mmask8) -1); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_rsqrt14_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, @@ -6584,7 +6585,7 @@ _mm256_mask_rsqrt14_ps (__m256 __W, __mmask8 __U, __m256 __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_rsqrt14_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_rsqrt14ps256_mask ((__v8sf) __A, @@ -6593,14 +6594,14 @@ _mm256_maskz_rsqrt14_ps (__mmask8 __U, __m256 __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_broadcast_f32x4(__m128 __A) { return (__m256)__builtin_shufflevector((__v4sf)__A, (__v4sf)__A, 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_f32x4(__m256 __O, __mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__M, @@ -6608,7 +6609,7 @@ _mm256_mask_broadcast_f32x4(__m256 __O, __mmask8 __M, __m128 __A) (__v8sf)__O); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_f32x4 (__mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__M, @@ -6616,14 +6617,14 @@ _mm256_maskz_broadcast_f32x4 (__mmask8 __M, __m128 __A) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_broadcast_i32x4(__m128i __A) { return (__m256i)__builtin_shufflevector((__v4si)__A, (__v4si)__A, 0, 1, 2, 3, 0, 1, 2, 3); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcast_i32x4(__m256i __O, __mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -6631,7 +6632,7 @@ _mm256_mask_broadcast_i32x4(__m256i __O, __mmask8 __M, __m128i __A) (__v8si)__O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcast_i32x4(__mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -6639,7 +6640,7 @@ _mm256_maskz_broadcast_i32x4(__mmask8 __M, __m128i __A) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastsd_pd (__m256d __O, __mmask8 __M, __m128d __A) { return (__m256d)__builtin_ia32_selectpd_256(__M, @@ -6647,7 +6648,7 @@ _mm256_mask_broadcastsd_pd (__m256d __O, __mmask8 __M, __m128d __A) (__v4df) __O); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) { return (__m256d)__builtin_ia32_selectpd_256(__M, @@ -6655,7 +6656,7 @@ _mm256_maskz_broadcastsd_pd (__mmask8 __M, __m128d __A) (__v4df) _mm256_setzero_pd()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_broadcastss_ps (__m128 __O, __mmask8 __M, __m128 __A) { return (__m128)__builtin_ia32_selectps_128(__M, @@ -6663,7 +6664,7 @@ _mm_mask_broadcastss_ps (__m128 __O, __mmask8 __M, __m128 __A) (__v4sf) __O); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) { return (__m128)__builtin_ia32_selectps_128(__M, @@ -6671,7 +6672,7 @@ _mm_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) (__v4sf) _mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastss_ps (__m256 __O, __mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256(__M, @@ -6679,7 +6680,7 @@ _mm256_mask_broadcastss_ps (__m256 __O, __mmask8 __M, __m128 __A) (__v8sf) __O); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) { return (__m256)__builtin_ia32_selectps_256(__M, @@ -6687,7 +6688,7 @@ _mm256_maskz_broadcastss_ps (__mmask8 __M, __m128 __A) (__v8sf) _mm256_setzero_ps()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_broadcastd_epi32 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128(__M, @@ -6695,7 +6696,7 @@ _mm_mask_broadcastd_epi32 (__m128i __O, __mmask8 __M, __m128i __A) (__v4si) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128(__M, @@ -6703,7 +6704,7 @@ _mm_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) (__v4si) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastd_epi32 (__m256i __O, __mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256(__M, @@ -6711,7 +6712,7 @@ _mm256_mask_broadcastd_epi32 (__m256i __O, __mmask8 __M, __m128i __A) (__v8si) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectd_256(__M, @@ -6719,7 +6720,7 @@ _mm256_maskz_broadcastd_epi32 (__mmask8 __M, __m128i __A) (__v8si) _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_broadcastq_epi64 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -6727,7 +6728,7 @@ _mm_mask_broadcastq_epi64 (__m128i __O, __mmask8 __M, __m128i __A) (__v2di) __O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128(__M, @@ -6735,7 +6736,7 @@ _mm_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) (__v2di) _mm_setzero_si128()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_broadcastq_epi64 (__m256i __O, __mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -6743,7 +6744,7 @@ _mm256_mask_broadcastq_epi64 (__m256i __O, __mmask8 __M, __m128i __A) (__v4di) __O); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) { return (__m256i)__builtin_ia32_selectq_256(__M, @@ -6751,7 +6752,7 @@ _mm256_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A) (__v4di) _mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi32_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, @@ -6759,14 +6760,14 @@ _mm_cvtsepi32_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi32_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsdb128_mask ((__v4si) __A, @@ -6774,13 +6775,13 @@ _mm_maskz_cvtsepi32_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovsdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm256_cvtsepi32_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, @@ -6788,14 +6789,14 @@ _mm256_cvtsepi32_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi32_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsdb256_mask ((__v8si) __A, @@ -6803,13 +6804,13 @@ _mm256_maskz_cvtsepi32_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm256_mask_cvtsepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovsdb256mem_mask ((__v16qi *) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi32_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, @@ -6817,7 +6818,7 @@ _mm_cvtsepi32_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, @@ -6825,7 +6826,7 @@ _mm_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi32_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsdw128_mask ((__v4si) __A, @@ -6833,13 +6834,13 @@ _mm_maskz_cvtsepi32_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovsdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtsepi32_epi16 (__m256i __A) { return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, @@ -6847,14 +6848,14 @@ _mm256_cvtsepi32_epi16 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi32_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsdw256_mask ((__v8si) __A, @@ -6862,13 +6863,13 @@ _mm256_maskz_cvtsepi32_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovsdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi64_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, @@ -6876,14 +6877,14 @@ _mm_cvtsepi64_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi64_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqb128_mask ((__v2di) __A, @@ -6891,13 +6892,13 @@ _mm_maskz_cvtsepi64_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovsqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtsepi64_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, @@ -6905,14 +6906,14 @@ _mm256_cvtsepi64_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi64_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqb256_mask ((__v4di) __A, @@ -6920,13 +6921,13 @@ _mm256_maskz_cvtsepi64_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovsqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi64_epi32 (__m128i __A) { return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, @@ -6934,14 +6935,14 @@ _mm_cvtsepi64_epi32 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, (__v4si) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi64_epi32 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqd128_mask ((__v2di) __A, @@ -6949,13 +6950,13 @@ _mm_maskz_cvtsepi64_epi32 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovsqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtsepi64_epi32 (__m256i __A) { return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, @@ -6963,7 +6964,7 @@ _mm256_cvtsepi64_epi32 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, @@ -6971,7 +6972,7 @@ _mm256_mask_cvtsepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi64_epi32 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqd256_mask ((__v4di) __A, @@ -6979,13 +6980,13 @@ _mm256_maskz_cvtsepi64_epi32 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovsqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtsepi64_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, @@ -6993,14 +6994,14 @@ _mm_cvtsepi64_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtsepi64_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovsqw128_mask ((__v2di) __A, @@ -7008,13 +7009,13 @@ _mm_maskz_cvtsepi64_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovsqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtsepi64_epi16 (__m256i __A) { return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, @@ -7022,14 +7023,14 @@ _mm256_cvtsepi64_epi16 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtsepi64_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovsqw256_mask ((__v4di) __A, @@ -7037,13 +7038,13 @@ _mm256_maskz_cvtsepi64_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtsepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovsqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi32_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, @@ -7051,7 +7052,7 @@ _mm_cvtusepi32_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, @@ -7059,7 +7060,7 @@ _mm_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi32_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusdb128_mask ((__v4si) __A, @@ -7067,13 +7068,13 @@ _mm_maskz_cvtusepi32_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovusdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi32_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, @@ -7081,7 +7082,7 @@ _mm256_cvtusepi32_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, @@ -7089,7 +7090,7 @@ _mm256_mask_cvtusepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi32_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusdb256_mask ((__v8si) __A, @@ -7097,13 +7098,13 @@ _mm256_maskz_cvtusepi32_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovusdb256mem_mask ((__v16qi*) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi32_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, @@ -7111,14 +7112,14 @@ _mm_cvtusepi32_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi32_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusdw128_mask ((__v4si) __A, @@ -7126,13 +7127,13 @@ _mm_maskz_cvtusepi32_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovusdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi32_epi16 (__m256i __A) { return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, @@ -7140,14 +7141,14 @@ _mm256_cvtusepi32_epi16 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi32_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusdw256_mask ((__v8si) __A, @@ -7155,13 +7156,13 @@ _mm256_maskz_cvtusepi32_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovusdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi64_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, @@ -7169,7 +7170,7 @@ _mm_cvtusepi64_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, @@ -7177,7 +7178,7 @@ _mm_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi64_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqb128_mask ((__v2di) __A, @@ -7185,13 +7186,13 @@ _mm_maskz_cvtusepi64_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovusqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi64_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, @@ -7199,7 +7200,7 @@ _mm256_cvtusepi64_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, @@ -7207,7 +7208,7 @@ _mm256_mask_cvtusepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi64_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqb256_mask ((__v4di) __A, @@ -7215,13 +7216,13 @@ _mm256_maskz_cvtusepi64_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovusqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi64_epi32 (__m128i __A) { return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, @@ -7229,14 +7230,14 @@ _mm_cvtusepi64_epi32 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, (__v4si) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi64_epi32 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqd128_mask ((__v2di) __A, @@ -7244,13 +7245,13 @@ _mm_maskz_cvtusepi64_epi32 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovusqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi64_epi32 (__m256i __A) { return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, @@ -7258,14 +7259,14 @@ _mm256_cvtusepi64_epi32 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, (__v4si) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi64_epi32 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqd256_mask ((__v4di) __A, @@ -7273,13 +7274,13 @@ _mm256_maskz_cvtusepi64_epi32 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovusqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtusepi64_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, @@ -7287,14 +7288,14 @@ _mm_cvtusepi64_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtusepi64_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovusqw128_mask ((__v2di) __A, @@ -7302,13 +7303,13 @@ _mm_maskz_cvtusepi64_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovusqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtusepi64_epi16 (__m256i __A) { return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, @@ -7316,14 +7317,14 @@ _mm256_cvtusepi64_epi16 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtusepi64_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovusqw256_mask ((__v4di) __A, @@ -7331,13 +7332,13 @@ _mm256_maskz_cvtusepi64_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovusqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi32_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, @@ -7345,14 +7346,14 @@ _mm_cvtepi32_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi32_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, @@ -7361,13 +7362,13 @@ _mm_maskz_cvtepi32_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovdb128mem_mask ((__v16qi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi32_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, @@ -7375,14 +7376,14 @@ _mm256_cvtepi32_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi32_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, @@ -7390,13 +7391,13 @@ _mm256_maskz_cvtepi32_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovdb256mem_mask ((__v16qi *) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi32_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, @@ -7404,14 +7405,14 @@ _mm_cvtepi32_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi32_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, @@ -7419,26 +7420,26 @@ _mm_maskz_cvtepi32_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovdw128mem_mask ((__v8hi *) __P, (__v4si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi32_epi16 (__m256i __A) { return (__m128i)__builtin_convertvector((__v8si)__A, __v8hi); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi32_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovdw256_mask ((__v8si) __A, @@ -7446,13 +7447,13 @@ _mm256_maskz_cvtepi32_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovdw256mem_mask ((__v8hi *) __P, (__v8si) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi8 (__m128i __A) { return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, @@ -7460,14 +7461,14 @@ _mm_cvtepi64_epi8 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi64_epi8 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, @@ -7475,13 +7476,13 @@ _mm_maskz_cvtepi64_epi8 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovqb128mem_mask ((__v16qi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_epi8 (__m256i __A) { return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, @@ -7489,14 +7490,14 @@ _mm256_cvtepi64_epi8 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_epi8 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, (__v16qi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi64_epi8 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, @@ -7504,13 +7505,13 @@ _mm256_maskz_cvtepi64_epi8 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovqb256mem_mask ((__v16qi *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi32 (__m128i __A) { return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, @@ -7518,14 +7519,14 @@ _mm_cvtepi64_epi32 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, (__v4si) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi64_epi32 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, @@ -7533,19 +7534,19 @@ _mm_maskz_cvtepi64_epi32 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovqd128mem_mask ((__v4si *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_epi32 (__m256i __A) { return (__m128i)__builtin_convertvector((__v4di)__A, __v4si); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -7553,7 +7554,7 @@ _mm256_mask_cvtepi64_epi32 (__m128i __O, __mmask8 __M, __m256i __A) (__v4si)__O); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi64_epi32 (__mmask8 __M, __m256i __A) { return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M, @@ -7561,13 +7562,13 @@ _mm256_maskz_cvtepi64_epi32 (__mmask8 __M, __m256i __A) (__v4si)_mm_setzero_si128()); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovqd256mem_mask ((__v4si *) __P, (__v4di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi16 (__m128i __A) { return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, @@ -7575,7 +7576,7 @@ _mm_cvtepi64_epi16 (__m128i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, @@ -7583,7 +7584,7 @@ _mm_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m128i __A) __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtepi64_epi16 (__mmask8 __M, __m128i __A) { return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, @@ -7591,13 +7592,13 @@ _mm_maskz_cvtepi64_epi16 (__mmask8 __M, __m128i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) { __builtin_ia32_pmovqw128mem_mask ((__v8hi *) __P, (__v2di) __A, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_epi16 (__m256i __A) { return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, @@ -7605,14 +7606,14 @@ _mm256_cvtepi64_epi16 (__m256i __A) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_epi16 (__m128i __O, __mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, (__v8hi) __O, __M); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtepi64_epi16 (__mmask8 __M, __m256i __A) { return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, @@ -7620,7 +7621,7 @@ _mm256_maskz_cvtepi64_epi16 (__mmask8 __M, __m256i __A) __M); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) { __builtin_ia32_pmovqw256mem_mask ((__v8hi *) __P, (__v4di) __A, __M); @@ -7884,13 +7885,13 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) (__v4di)_mm256_permutex_epi64((X), (C)), \ (__v4di)_mm256_setzero_si256()) -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_permutexvar_pd (__m256i __X, __m256d __Y) { return (__m256d)__builtin_ia32_permvardf256((__v4df)__Y, (__v4di)__X); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_pd (__m256d __W, __mmask8 __U, __m256i __X, __m256d __Y) { @@ -7899,7 +7900,7 @@ _mm256_mask_permutexvar_pd (__m256d __W, __mmask8 __U, __m256i __X, (__v4df)__W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_pd (__mmask8 __U, __m256i __X, __m256d __Y) { return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U, @@ -7907,13 +7908,13 @@ _mm256_maskz_permutexvar_pd (__mmask8 __U, __m256i __X, __m256d __Y) (__v4df)_mm256_setzero_pd()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_permutexvar_epi64 ( __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_permvardi256((__v4di) __Y, (__v4di) __X); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_epi64 (__mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M, @@ -7921,7 +7922,7 @@ _mm256_maskz_permutexvar_epi64 (__mmask8 __M, __m256i __X, __m256i __Y) (__v4di)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_epi64 (__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { @@ -7932,7 +7933,7 @@ _mm256_mask_permutexvar_epi64 (__m256i __W, __mmask8 __M, __m256i __X, #define _mm256_permutexvar_ps(A, B) _mm256_permutevar8x32_ps((B), (A)) -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_ps(__m256 __W, __mmask8 __U, __m256i __X, __m256 __Y) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -7940,7 +7941,7 @@ _mm256_mask_permutexvar_ps(__m256 __W, __mmask8 __U, __m256i __X, __m256 __Y) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_ps(__mmask8 __U, __m256i __X, __m256 __Y) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -7950,7 +7951,7 @@ _mm256_maskz_permutexvar_ps(__mmask8 __U, __m256i __X, __m256 __Y) #define _mm256_permutexvar_epi32(A, B) _mm256_permutevar8x32_epi32((B), (A)) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_permutexvar_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) { @@ -7959,7 +7960,7 @@ _mm256_mask_permutexvar_epi32(__m256i __W, __mmask8 __M, __m256i __X, (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) { return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M, @@ -8023,7 +8024,7 @@ _mm256_maskz_permutexvar_epi32(__mmask8 __M, __m256i __X, __m256i __Y) (__v4di)_mm256_alignr_epi64((A), (B), (imm)), \ (__v4di)_mm256_setzero_si256()) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -8031,7 +8032,7 @@ _mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A) (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_movehdup_ps (__mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -8039,7 +8040,7 @@ _mm_maskz_movehdup_ps (__mmask8 __U, __m128 __A) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_movehdup_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -8047,7 +8048,7 @@ _mm256_mask_movehdup_ps (__m256 __W, __mmask8 __U, __m256 __A) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_movehdup_ps (__mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -8055,7 +8056,7 @@ _mm256_maskz_movehdup_ps (__mmask8 __U, __m256 __A) (__v8sf)_mm256_setzero_ps()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_moveldup_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -8063,7 +8064,7 @@ _mm_mask_moveldup_ps (__m128 __W, __mmask8 __U, __m128 __A) (__v4sf)__W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_moveldup_ps (__mmask8 __U, __m128 __A) { return (__m128)__builtin_ia32_selectps_128((__mmask8)__U, @@ -8071,7 +8072,7 @@ _mm_maskz_moveldup_ps (__mmask8 __U, __m128 __A) (__v4sf)_mm_setzero_ps()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_moveldup_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -8079,7 +8080,7 @@ _mm256_mask_moveldup_ps (__m256 __W, __mmask8 __U, __m256 __A) (__v8sf)__W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A) { return (__m256)__builtin_ia32_selectps_256((__mmask8)__U, @@ -8107,7 +8108,7 @@ _mm256_maskz_moveldup_ps (__mmask8 __U, __m256 __A) (__v4si)_mm_shuffle_epi32((A), (I)), \ (__v4si)_mm_setzero_si128()) -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U, @@ -8115,7 +8116,7 @@ _mm_mask_mov_pd (__m128d __W, __mmask8 __U, __m128d __A) (__v2df) __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_mov_pd (__mmask8 __U, __m128d __A) { return (__m128d) __builtin_ia32_selectpd_128 ((__mmask8) __U, @@ -8123,7 +8124,7 @@ _mm_maskz_mov_pd (__mmask8 __U, __m128d __A) (__v2df) _mm_setzero_pd ()); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U, @@ -8131,7 +8132,7 @@ _mm256_mask_mov_pd (__m256d __W, __mmask8 __U, __m256d __A) (__v4df) __W); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_pd (__mmask8 __U, __m256d __A) { return (__m256d) __builtin_ia32_selectpd_256 ((__mmask8) __U, @@ -8139,7 +8140,7 @@ _mm256_maskz_mov_pd (__mmask8 __U, __m256d __A) (__v4df) _mm256_setzero_pd ()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U, @@ -8147,7 +8148,7 @@ _mm_mask_mov_ps (__m128 __W, __mmask8 __U, __m128 __A) (__v4sf) __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_mov_ps (__mmask8 __U, __m128 __A) { return (__m128) __builtin_ia32_selectps_128 ((__mmask8) __U, @@ -8155,7 +8156,7 @@ _mm_maskz_mov_ps (__mmask8 __U, __m128 __A) (__v4sf) _mm_setzero_ps ()); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U, @@ -8163,7 +8164,7 @@ _mm256_mask_mov_ps (__m256 __W, __mmask8 __U, __m256 __A) (__v8sf) __W); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_mov_ps (__mmask8 __U, __m256 __A) { return (__m256) __builtin_ia32_selectps_256 ((__mmask8) __U, @@ -8171,7 +8172,7 @@ _mm256_maskz_mov_ps (__mmask8 __U, __m256 __A) (__v8sf) _mm256_setzero_ps ()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_cvtph_ps (__m128 __W, __mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A, @@ -8179,7 +8180,7 @@ _mm_mask_cvtph_ps (__m128 __W, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_cvtph_ps (__mmask8 __U, __m128i __A) { return (__m128) __builtin_ia32_vcvtph2ps_mask ((__v8hi) __A, @@ -8188,7 +8189,7 @@ _mm_maskz_cvtph_ps (__mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_mask_cvtph_ps (__m256 __W, __mmask8 __U, __m128i __A) { return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A, @@ -8196,7 +8197,7 @@ _mm256_mask_cvtph_ps (__m256 __W, __mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A) { return (__m256) __builtin_ia32_vcvtph2ps256_mask ((__v8hi) __A, @@ -8205,7 +8206,7 @@ _mm256_maskz_cvtph_ps (__mmask8 __U, __m128i __A) (__mmask8) __U); } -static __inline __m128i __DEFAULT_FN_ATTRS +static __inline __m128i __DEFAULT_FN_ATTRS128 _mm_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, _MM_FROUND_CUR_DIRECTION, @@ -8213,7 +8214,7 @@ _mm_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m128 __A) (__mmask8) __U); } -static __inline __m128i __DEFAULT_FN_ATTRS +static __inline __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_cvtps_ph (__mmask8 __U, __m128 __A) { return (__m128i) __builtin_ia32_vcvtps2ph_mask ((__v4sf) __A, _MM_FROUND_CUR_DIRECTION, @@ -8231,7 +8232,7 @@ _mm_maskz_cvtps_ph (__mmask8 __U, __m128 __A) (__v8hi)_mm_setzero_si128(), \ (__mmask8)(U)) -static __inline __m128i __DEFAULT_FN_ATTRS +static __inline __m128i __DEFAULT_FN_ATTRS256 _mm256_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m256 __A) { return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, _MM_FROUND_CUR_DIRECTION, @@ -8239,7 +8240,7 @@ _mm256_mask_cvtps_ph (__m128i __W, __mmask8 __U, __m256 __A) (__mmask8) __U); } -static __inline __m128i __DEFAULT_FN_ATTRS +static __inline __m128i __DEFAULT_FN_ATTRS256 _mm256_maskz_cvtps_ph ( __mmask8 __U, __m256 __A) { return (__m128i) __builtin_ia32_vcvtps2ph256_mask ((__v8sf) __A, _MM_FROUND_CUR_DIRECTION, @@ -8257,6 +8258,7 @@ _mm256_maskz_cvtps_ph ( __mmask8 __U, __m256 __A) (__mmask8)(U)) -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __AVX512VLINTRIN_H */ diff --git a/lib/Headers/avx512vlvbmi2intrin.h b/lib/Headers/avx512vlvbmi2intrin.h index 38ef9b0f84..baaf565463 100644 --- a/lib/Headers/avx512vlvbmi2intrin.h +++ b/lib/Headers/avx512vlvbmi2intrin.h @@ -29,9 +29,10 @@ #define __AVX512VLVBMI2INTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vbmi2"), __min_vector_width__(256))) -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D) { return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D, @@ -39,7 +40,7 @@ _mm_mask_compress_epi16(__m128i __S, __mmask8 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_compress_epi16(__mmask8 __U, __m128i __D) { return (__m128i) __builtin_ia32_compresshi128_mask ((__v8hi) __D, @@ -47,7 +48,7 @@ _mm_maskz_compress_epi16(__mmask8 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D) { return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D, @@ -55,7 +56,7 @@ _mm_mask_compress_epi8(__m128i __S, __mmask16 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_compress_epi8(__mmask16 __U, __m128i __D) { return (__m128i) __builtin_ia32_compressqi128_mask ((__v16qi) __D, @@ -63,21 +64,21 @@ _mm_maskz_compress_epi8(__mmask16 __U, __m128i __D) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_epi16(void *__P, __mmask8 __U, __m128i __D) { __builtin_ia32_compressstorehi128_mask ((__v8hi *) __P, (__v8hi) __D, __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS128 _mm_mask_compressstoreu_epi8(void *__P, __mmask16 __U, __m128i __D) { __builtin_ia32_compressstoreqi128_mask ((__v16qi *) __P, (__v16qi) __D, __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D) { return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D, @@ -85,7 +86,7 @@ _mm_mask_expand_epi16(__m128i __S, __mmask8 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expand_epi16(__mmask8 __U, __m128i __D) { return (__m128i) __builtin_ia32_expandhi128_mask ((__v8hi) __D, @@ -93,7 +94,7 @@ _mm_maskz_expand_epi16(__mmask8 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D) { return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D, @@ -101,7 +102,7 @@ _mm_mask_expand_epi8(__m128i __S, __mmask16 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expand_epi8(__mmask16 __U, __m128i __D) { return (__m128i) __builtin_ia32_expandqi128_mask ((__v16qi) __D, @@ -109,7 +110,7 @@ _mm_maskz_expand_epi8(__mmask16 __U, __m128i __D) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *)__P, @@ -117,7 +118,7 @@ _mm_mask_expandloadu_epi16(__m128i __S, __mmask8 __U, void const *__P) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_epi16(__mmask8 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadhi128_mask ((const __v8hi *)__P, @@ -125,7 +126,7 @@ _mm_maskz_expandloadu_epi16(__mmask8 __U, void const *__P) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *)__P, @@ -133,7 +134,7 @@ _mm_mask_expandloadu_epi8(__m128i __S, __mmask16 __U, void const *__P) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_expandloadu_epi8(__mmask16 __U, void const *__P) { return (__m128i) __builtin_ia32_expandloadqi128_mask ((const __v16qi *)__P, @@ -141,7 +142,7 @@ _mm_maskz_expandloadu_epi8(__mmask16 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D) { return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __D, @@ -149,7 +150,7 @@ _mm256_mask_compress_epi16(__m256i __S, __mmask16 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_epi16(__mmask16 __U, __m256i __D) { return (__m256i) __builtin_ia32_compresshi256_mask ((__v16hi) __D, @@ -157,7 +158,7 @@ _mm256_maskz_compress_epi16(__mmask16 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_compress_epi8(__m256i __S, __mmask32 __U, __m256i __D) { return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi) __D, @@ -165,7 +166,7 @@ _mm256_mask_compress_epi8(__m256i __S, __mmask32 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D) { return (__m256i) __builtin_ia32_compressqi256_mask ((__v32qi) __D, @@ -173,21 +174,21 @@ _mm256_maskz_compress_epi8(__mmask32 __U, __m256i __D) __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_epi16(void *__P, __mmask16 __U, __m256i __D) { __builtin_ia32_compressstorehi256_mask ((__v16hi *) __P, (__v16hi) __D, __U); } -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __DEFAULT_FN_ATTRS256 _mm256_mask_compressstoreu_epi8(void *__P, __mmask32 __U, __m256i __D) { __builtin_ia32_compressstoreqi256_mask ((__v32qi *) __P, (__v32qi) __D, __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expand_epi16(__m256i __S, __mmask16 __U, __m256i __D) { return (__m256i) __builtin_ia32_expandhi256_mask ((__v16hi) __D, @@ -195,7 +196,7 @@ _mm256_mask_expand_epi16(__m256i __S, __mmask16 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_epi16(__mmask16 __U, __m256i __D) { return (__m256i) __builtin_ia32_expandhi256_mask ((__v16hi) __D, @@ -203,7 +204,7 @@ _mm256_maskz_expand_epi16(__mmask16 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expand_epi8(__m256i __S, __mmask32 __U, __m256i __D) { return (__m256i) __builtin_ia32_expandqi256_mask ((__v32qi) __D, @@ -211,7 +212,7 @@ _mm256_mask_expand_epi8(__m256i __S, __mmask32 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D) { return (__m256i) __builtin_ia32_expandqi256_mask ((__v32qi) __D, @@ -219,7 +220,7 @@ _mm256_maskz_expand_epi8(__mmask32 __U, __m256i __D) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadhi256_mask ((const __v16hi *)__P, @@ -227,7 +228,7 @@ _mm256_mask_expandloadu_epi16(__m256i __S, __mmask16 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_epi16(__mmask16 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadhi256_mask ((const __v16hi *)__P, @@ -235,7 +236,7 @@ _mm256_maskz_expandloadu_epi16(__mmask16 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadqi256_mask ((const __v32qi *)__P, @@ -243,7 +244,7 @@ _mm256_mask_expandloadu_epi8(__m256i __S, __mmask32 __U, void const *__P) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P) { return (__m256i) __builtin_ia32_expandloadqi256_mask ((const __v32qi *)__P, @@ -419,7 +420,7 @@ _mm256_maskz_expandloadu_epi8(__mmask32 __U, void const *__P) (__v8hi)_mm_shrdi_epi16((A), (B), (I)), \ (__v8hi)_mm_setzero_si128()) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S, @@ -428,7 +429,7 @@ _mm256_mask_shldv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvq256_maskz ((__v4di) __S, @@ -437,7 +438,7 @@ _mm256_maskz_shldv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvq256_mask ((__v4di) __S, @@ -446,7 +447,7 @@ _mm256_shldv_epi64(__m256i __S, __m256i __A, __m256i __B) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S, @@ -455,7 +456,7 @@ _mm_mask_shldv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvq128_maskz ((__v2di) __S, @@ -464,7 +465,7 @@ _mm_maskz_shldv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvq128_mask ((__v2di) __S, @@ -473,7 +474,7 @@ _mm_shldv_epi64(__m128i __S, __m128i __A, __m128i __B) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S, @@ -482,7 +483,7 @@ _mm256_mask_shldv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvd256_maskz ((__v8si) __S, @@ -491,7 +492,7 @@ _mm256_maskz_shldv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvd256_mask ((__v8si) __S, @@ -500,7 +501,7 @@ _mm256_shldv_epi32(__m256i __S, __m256i __A, __m256i __B) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S, @@ -509,7 +510,7 @@ _mm_mask_shldv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvd128_maskz ((__v4si) __S, @@ -518,7 +519,7 @@ _mm_maskz_shldv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvd128_mask ((__v4si) __S, @@ -527,7 +528,7 @@ _mm_shldv_epi32(__m128i __S, __m128i __A, __m128i __B) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S, @@ -536,7 +537,7 @@ _mm256_mask_shldv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvw256_maskz ((__v16hi) __S, @@ -545,7 +546,7 @@ _mm256_maskz_shldv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshldvw256_mask ((__v16hi) __S, @@ -554,7 +555,7 @@ _mm256_shldv_epi16(__m256i __S, __m256i __A, __m256i __B) (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S, @@ -563,7 +564,7 @@ _mm_mask_shldv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvw128_maskz ((__v8hi) __S, @@ -572,7 +573,7 @@ _mm_maskz_shldv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshldvw128_mask ((__v8hi) __S, @@ -581,7 +582,7 @@ _mm_shldv_epi16(__m128i __S, __m128i __A, __m128i __B) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S, @@ -590,7 +591,7 @@ _mm256_mask_shrdv_epi64(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvq256_maskz ((__v4di) __S, @@ -599,7 +600,7 @@ _mm256_maskz_shrdv_epi64(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvq256_mask ((__v4di) __S, @@ -608,7 +609,7 @@ _mm256_shrdv_epi64(__m256i __S, __m256i __A, __m256i __B) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S, @@ -617,7 +618,7 @@ _mm_mask_shrdv_epi64(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvq128_maskz ((__v2di) __S, @@ -626,7 +627,7 @@ _mm_maskz_shrdv_epi64(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvq128_mask ((__v2di) __S, @@ -635,7 +636,7 @@ _mm_shrdv_epi64(__m128i __S, __m128i __A, __m128i __B) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S, @@ -644,7 +645,7 @@ _mm256_mask_shrdv_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvd256_maskz ((__v8si) __S, @@ -653,7 +654,7 @@ _mm256_maskz_shrdv_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvd256_mask ((__v8si) __S, @@ -662,7 +663,7 @@ _mm256_shrdv_epi32(__m256i __S, __m256i __A, __m256i __B) (__mmask8) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S, @@ -671,7 +672,7 @@ _mm_mask_shrdv_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvd128_maskz ((__v4si) __S, @@ -680,7 +681,7 @@ _mm_maskz_shrdv_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvd128_mask ((__v4si) __S, @@ -689,7 +690,7 @@ _mm_shrdv_epi32(__m128i __S, __m128i __A, __m128i __B) (__mmask8) -1); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S, @@ -698,7 +699,7 @@ _mm256_mask_shrdv_epi16(__m256i __S, __mmask16 __U, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvw256_maskz ((__v16hi) __S, @@ -707,7 +708,7 @@ _mm256_maskz_shrdv_epi16(__mmask16 __U, __m256i __S, __m256i __A, __m256i __B) __U); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_vpshrdvw256_mask ((__v16hi) __S, @@ -716,7 +717,7 @@ _mm256_shrdv_epi16(__m256i __S, __m256i __A, __m256i __B) (__mmask16) -1); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S, @@ -725,7 +726,7 @@ _mm_mask_shrdv_epi16(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvw128_maskz ((__v8hi) __S, @@ -734,7 +735,7 @@ _mm_maskz_shrdv_epi16(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) __U); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_vpshrdvw128_mask ((__v8hi) __S, @@ -744,6 +745,7 @@ _mm_shrdv_epi16(__m128i __S, __m128i __A, __m128i __B) } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vlvnniintrin.h b/lib/Headers/avx512vlvnniintrin.h index fd901f11a8..62382268ec 100644 --- a/lib/Headers/avx512vlvnniintrin.h +++ b/lib/Headers/avx512vlvnniintrin.h @@ -29,17 +29,18 @@ #define __AVX512VLVNNIINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512vnni"), __min_vector_width__(256))) -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_dpbusd_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_vpdpbusd256((__v8si)__S, (__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_dpbusd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -47,7 +48,7 @@ _mm256_mask_dpbusd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__S); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpbusd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -55,14 +56,14 @@ _mm256_maskz_dpbusd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_dpbusds_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_vpdpbusds256((__v8si)__S, (__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_dpbusds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -70,7 +71,7 @@ _mm256_mask_dpbusds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__S); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpbusds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -78,14 +79,14 @@ _mm256_maskz_dpbusds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_dpwssd_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_vpdpwssd256((__v8si)__S, (__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_dpwssd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -93,7 +94,7 @@ _mm256_mask_dpwssd_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__S); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwssd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -101,14 +102,14 @@ _mm256_maskz_dpwssd_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_dpwssds_epi32(__m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_vpdpwssds256((__v8si)__S, (__v8si)__A, (__v8si)__B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_dpwssds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -116,7 +117,7 @@ _mm256_mask_dpwssds_epi32(__m256i __S, __mmask8 __U, __m256i __A, __m256i __B) (__v8si)__S); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwssds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) { return (__m256i)__builtin_ia32_selectd_256(__U, @@ -124,14 +125,14 @@ _mm256_maskz_dpwssds_epi32(__mmask8 __U, __m256i __S, __m256i __A, __m256i __B) (__v8si)_mm256_setzero_si256()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_dpbusd_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_vpdpbusd128((__v4si)__S, (__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -139,7 +140,7 @@ _mm_mask_dpbusd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__S); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -147,14 +148,14 @@ _mm_maskz_dpbusd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_dpbusds_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_vpdpbusds128((__v4si)__S, (__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -162,7 +163,7 @@ _mm_mask_dpbusds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__S); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -170,14 +171,14 @@ _mm_maskz_dpbusds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_dpwssd_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_vpdpwssd128((__v4si)__S, (__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -185,7 +186,7 @@ _mm_mask_dpwssd_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__S); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -193,14 +194,14 @@ _mm_maskz_dpwssd_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_dpwssds_epi32(__m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_vpdpwssds128((__v4si)__S, (__v4si)__A, (__v4si)__B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -208,7 +209,7 @@ _mm_mask_dpwssds_epi32(__m128i __S, __mmask8 __U, __m128i __A, __m128i __B) (__v4si)__S); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) { return (__m128i)__builtin_ia32_selectd_128(__U, @@ -216,6 +217,7 @@ _mm_maskz_dpwssds_epi32(__mmask8 __U, __m128i __S, __m128i __A, __m128i __B) (__v4si)_mm_setzero_si128()); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avx512vnniintrin.h b/lib/Headers/avx512vnniintrin.h index 410e1ee59e..620ef5a789 100644 --- a/lib/Headers/avx512vnniintrin.h +++ b/lib/Headers/avx512vnniintrin.h @@ -29,7 +29,7 @@ #define __AVX512VNNIINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vnni"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS diff --git a/lib/Headers/avx512vpopcntdqintrin.h b/lib/Headers/avx512vpopcntdqintrin.h index 21ffed145c..c99f594569 100644 --- a/lib/Headers/avx512vpopcntdqintrin.h +++ b/lib/Headers/avx512vpopcntdqintrin.h @@ -31,8 +31,7 @@ /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS \ - __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntd" \ - "q"))) + __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq"), __min_vector_width__(512))) static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_popcnt_epi64(__m512i __A) { return (__m512i)__builtin_ia32_vpopcntq_512((__v8di)__A); diff --git a/lib/Headers/avx512vpopcntdqvlintrin.h b/lib/Headers/avx512vpopcntdqvlintrin.h index a7460509a0..681a75fa07 100644 --- a/lib/Headers/avx512vpopcntdqvlintrin.h +++ b/lib/Headers/avx512vpopcntdqvlintrin.h @@ -30,69 +30,76 @@ #define __AVX512VPOPCNTDQVLINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS \ - __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl"))) +#define __DEFAULT_FN_ATTRS128 \ + __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 \ + __attribute__((__always_inline__, __nodebug__, __target__("avx512vpopcntdq,avx512vl"), __min_vector_width__(256))) -static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_popcnt_epi64(__m128i __A) { +static __inline__ __m128i __DEFAULT_FN_ATTRS128 +_mm_popcnt_epi64(__m128i __A) { return (__m128i)__builtin_ia32_vpopcntq_128((__v2di)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_popcnt_epi64(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectq_128( (__mmask8)__U, (__v2di)_mm_popcnt_epi64(__A), (__v2di)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_popcnt_epi64(__mmask8 __U, __m128i __A) { return _mm_mask_popcnt_epi64((__m128i)_mm_setzero_si128(), __U, __A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_popcnt_epi32(__m128i __A) { +static __inline__ __m128i __DEFAULT_FN_ATTRS128 +_mm_popcnt_epi32(__m128i __A) { return (__m128i)__builtin_ia32_vpopcntd_128((__v4si)__A); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_mask_popcnt_epi32(__m128i __W, __mmask8 __U, __m128i __A) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_popcnt_epi32(__A), (__v4si)__W); } -static __inline__ __m128i __DEFAULT_FN_ATTRS +static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_maskz_popcnt_epi32(__mmask8 __U, __m128i __A) { return _mm_mask_popcnt_epi32((__m128i)_mm_setzero_si128(), __U, __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_popcnt_epi64(__m256i __A) { +static __inline__ __m256i __DEFAULT_FN_ATTRS256 +_mm256_popcnt_epi64(__m256i __A) { return (__m256i)__builtin_ia32_vpopcntq_256((__v4di)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_popcnt_epi64(__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectq_256( (__mmask8)__U, (__v4di)_mm256_popcnt_epi64(__A), (__v4di)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_popcnt_epi64(__mmask8 __U, __m256i __A) { return _mm256_mask_popcnt_epi64((__m256i)_mm256_setzero_si256(), __U, __A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS _mm256_popcnt_epi32(__m256i __A) { +static __inline__ __m256i __DEFAULT_FN_ATTRS256 +_mm256_popcnt_epi32(__m256i __A) { return (__m256i)__builtin_ia32_vpopcntd_256((__v8si)__A); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_mask_popcnt_epi32(__m256i __W, __mmask8 __U, __m256i __A) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_popcnt_epi32(__A), (__v8si)__W); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_popcnt_epi32(__mmask8 __U, __m256i __A) { return _mm256_mask_popcnt_epi32((__m256i)_mm256_setzero_si256(), __U, __A); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h index 3ba6c95604..cb15396b3f 100644 --- a/lib/Headers/avxintrin.h +++ b/lib/Headers/avxintrin.h @@ -50,7 +50,8 @@ typedef double __m256d __attribute__((__vector_size__(32))); typedef long long __m256i __attribute__((__vector_size__(32))); /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx"), __min_vector_width__(256))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx"), __min_vector_width__(128))) /* Arithmetic */ /// Adds two 256-bit vectors of [4 x double]. @@ -780,7 +781,7 @@ _mm256_hsub_ps(__m256 __a, __m256 __b) /// 1: Bits [127:64] of the source are copied to bits [127:64] of the /// returned vector. /// \returns A 128-bit vector of [2 x double] containing the copied values. -static __inline __m128d __DEFAULT_FN_ATTRS +static __inline __m128d __DEFAULT_FN_ATTRS128 _mm_permutevar_pd(__m128d __a, __m128i __c) { return (__m128d)__builtin_ia32_vpermilvarpd((__v2df)__a, (__v2di)__c); @@ -873,7 +874,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c) /// 11: Bits [127:96] of the source are copied to bits [127:96] of the /// returned vector. /// \returns A 128-bit vector of [4 x float] containing the copied values. -static __inline __m128 __DEFAULT_FN_ATTRS +static __inline __m128 __DEFAULT_FN_ATTRS128 _mm_permutevar_ps(__m128 __a, __m128i __c) { return (__m128)__builtin_ia32_vpermilvarps((__v4sf)__a, (__v4si)__c); @@ -2497,7 +2498,7 @@ _mm256_unpacklo_ps(__m256 __a, __m256 __b) /// \param __b /// A 128-bit vector of [2 x double]. /// \returns the ZF flag in the EFLAGS register. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testz_pd(__m128d __a, __m128d __b) { return __builtin_ia32_vtestzpd((__v2df)__a, (__v2df)__b); @@ -2526,7 +2527,7 @@ _mm_testz_pd(__m128d __a, __m128d __b) /// \param __b /// A 128-bit vector of [2 x double]. /// \returns the CF flag in the EFLAGS register. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testc_pd(__m128d __a, __m128d __b) { return __builtin_ia32_vtestcpd((__v2df)__a, (__v2df)__b); @@ -2556,7 +2557,7 @@ _mm_testc_pd(__m128d __a, __m128d __b) /// \param __b /// A 128-bit vector of [2 x double]. /// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testnzc_pd(__m128d __a, __m128d __b) { return __builtin_ia32_vtestnzcpd((__v2df)__a, (__v2df)__b); @@ -2585,7 +2586,7 @@ _mm_testnzc_pd(__m128d __a, __m128d __b) /// \param __b /// A 128-bit vector of [4 x float]. /// \returns the ZF flag. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testz_ps(__m128 __a, __m128 __b) { return __builtin_ia32_vtestzps((__v4sf)__a, (__v4sf)__b); @@ -2614,7 +2615,7 @@ _mm_testz_ps(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. /// \returns the CF flag. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testc_ps(__m128 __a, __m128 __b) { return __builtin_ia32_vtestcps((__v4sf)__a, (__v4sf)__b); @@ -2644,7 +2645,7 @@ _mm_testc_ps(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. /// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0. -static __inline int __DEFAULT_FN_ATTRS +static __inline int __DEFAULT_FN_ATTRS128 _mm_testnzc_ps(__m128 __a, __m128 __b) { return __builtin_ia32_vtestnzcps((__v4sf)__a, (__v4sf)__b); @@ -2948,7 +2949,7 @@ _mm256_movemask_ps(__m256 __a) /// \headerfile /// /// This intrinsic corresponds to the VZEROALL instruction. -static __inline void __DEFAULT_FN_ATTRS +static __inline void __attribute__((__always_inline__, __nodebug__, __target__("avx"))) _mm256_zeroall(void) { __builtin_ia32_vzeroall(); @@ -2959,7 +2960,7 @@ _mm256_zeroall(void) /// \headerfile /// /// This intrinsic corresponds to the VZEROUPPER instruction. -static __inline void __DEFAULT_FN_ATTRS +static __inline void __attribute__((__always_inline__, __nodebug__, __target__("avx"))) _mm256_zeroupper(void) { __builtin_ia32_vzeroupper(); @@ -2978,7 +2979,7 @@ _mm256_zeroupper(void) /// The single-precision floating point value to be broadcast. /// \returns A 128-bit vector of [4 x float] whose 32-bit elements are set /// equal to the broadcast value. -static __inline __m128 __DEFAULT_FN_ATTRS +static __inline __m128 __DEFAULT_FN_ATTRS128 _mm_broadcast_ss(float const *__a) { float __f = *__a; @@ -3327,7 +3328,7 @@ _mm256_storeu_si256(__m256i *__p, __m256i __a) /// corresponding value in the memory location is not loaded and the /// corresponding field in the return value is set to zero. /// \returns A 128-bit vector of [2 x double] containing the loaded values. -static __inline __m128d __DEFAULT_FN_ATTRS +static __inline __m128d __DEFAULT_FN_ATTRS128 _mm_maskload_pd(double const *__p, __m128i __m) { return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)__p, (__v2di)__m); @@ -3376,7 +3377,7 @@ _mm256_maskload_pd(double const *__p, __m256i __m) /// corresponding value in the memory location is not loaded and the /// corresponding field in the return value is set to zero. /// \returns A 128-bit vector of [4 x float] containing the loaded values. -static __inline __m128 __DEFAULT_FN_ATTRS +static __inline __m128 __DEFAULT_FN_ATTRS128 _mm_maskload_ps(float const *__p, __m128i __m) { return (__m128)__builtin_ia32_maskloadps((const __v4sf *)__p, (__v4si)__m); @@ -3449,7 +3450,7 @@ _mm256_maskstore_ps(float *__p, __m256i __m, __m256 __a) /// changed. /// \param __a /// A 128-bit vector of [2 x double] containing the values to be stored. -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS128 _mm_maskstore_pd(double *__p, __m128i __m, __m128d __a) { __builtin_ia32_maskstorepd((__v2df *)__p, (__v2di)__m, (__v2df)__a); @@ -3497,7 +3498,7 @@ _mm256_maskstore_pd(double *__p, __m256i __m, __m256d __a) /// changed. /// \param __a /// A 128-bit vector of [4 x float] containing the values to be stored. -static __inline void __DEFAULT_FN_ATTRS +static __inline void __DEFAULT_FN_ATTRS128 _mm_maskstore_ps(float *__p, __m128i __m, __m128 __a) { __builtin_ia32_maskstoreps((__v4sf *)__p, (__v4si)__m, (__v4sf)__a); @@ -5057,5 +5058,6 @@ _mm256_setr_m128i (__m128i __lo, __m128i __hi) } #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 #endif /* __AVXINTRIN_H */ diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index df98a81d05..be88c65843 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -45,8 +45,8 @@ typedef unsigned char __v16qu __attribute__((__vector_size__(16))); typedef signed char __v16qs __attribute__((__vector_size__(16))); /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2"))) -#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse2"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse2"), __min_vector_width__(64))) /// Adds lower double-precision values in both operands and returns the /// sum in the lower 64 bits of the result. The upper 64 bits of the result @@ -4093,7 +4093,7 @@ _mm_stream_si128(__m128i *__p, __m128i __a) /// A pointer to the 32-bit memory location used to store the value. /// \param __a /// A 32-bit integer containing the value to be stored. -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("sse2"))) _mm_stream_si32(int *__p, int __a) { __builtin_ia32_movnti(__p, __a); @@ -4113,7 +4113,7 @@ _mm_stream_si32(int *__p, int __a) /// A pointer to the 64-bit memory location used to store the value. /// \param __a /// A 64-bit integer containing the value to be stored. -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("sse2"))) _mm_stream_si64(long long *__p, long long __a) { __builtin_ia32_movnti64(__p, __a); diff --git a/lib/Headers/f16cintrin.h b/lib/Headers/f16cintrin.h index 47700a5ee9..3d35f28eb3 100644 --- a/lib/Headers/f16cintrin.h +++ b/lib/Headers/f16cintrin.h @@ -29,8 +29,10 @@ #define __F16CINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS \ - __attribute__((__always_inline__, __nodebug__, __target__("f16c"))) +#define __DEFAULT_FN_ATTRS128 \ + __attribute__((__always_inline__, __nodebug__, __target__("f16c"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 \ + __attribute__((__always_inline__, __nodebug__, __target__("f16c"), __min_vector_width__(256))) /* NOTE: Intel documents the 128-bit versions of these as being in emmintrin.h, * but that's because icc can emulate these without f16c using a library call. @@ -47,7 +49,7 @@ /// \param __a /// A 16-bit half-precision float value. /// \returns The converted 32-bit float value. -static __inline float __DEFAULT_FN_ATTRS +static __inline float __DEFAULT_FN_ATTRS128 _cvtsh_ss(unsigned short __a) { __v8hi v = {(short)__a, 0, 0, 0, 0, 0, 0, 0}; @@ -118,7 +120,7 @@ _cvtsh_ss(unsigned short __a) /// A 128-bit vector containing 16-bit half-precision float values. The lower /// 64 bits are used in the conversion. /// \returns A 128-bit vector of [4 x float] containing converted float values. -static __inline __m128 __DEFAULT_FN_ATTRS +static __inline __m128 __DEFAULT_FN_ATTRS128 _mm_cvtph_ps(__m128i __a) { return (__m128)__builtin_ia32_vcvtph2ps((__v8hi)__a); @@ -162,12 +164,13 @@ _mm_cvtph_ps(__m128i __a) /// converted to 32-bit single-precision float values. /// \returns A vector of [8 x float] containing the converted 32-bit /// single-precision float values. -static __inline __m256 __attribute__((__always_inline__, __nodebug__, __target__("f16c"))) +static __inline __m256 __DEFAULT_FN_ATTRS256 _mm256_cvtph_ps(__m128i __a) { return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __F16CINTRIN_H */ diff --git a/lib/Headers/fma4intrin.h b/lib/Headers/fma4intrin.h index 962b1a60a2..7bae2f4a31 100644 --- a/lib/Headers/fma4intrin.h +++ b/lib/Headers/fma4intrin.h @@ -31,200 +31,202 @@ #include /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma4"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("fma4"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("fma4"), __min_vector_width__(256))) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_macc_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_macc_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_macc_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_macc_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_msub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_msub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_msub_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_msub_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_nmacc_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_nmacc_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_nmacc_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_nmacc_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_nmsub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_nmsub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_nmsub_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_nmsub_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maddsub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maddsub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_msubadd_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_msubadd_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_macc_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_macc_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_msub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_msub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_nmacc_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_nmacc_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_nmsub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_nmsub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_maddsub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_maddsub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_msubadd_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_msubadd_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __FMA4INTRIN_H */ diff --git a/lib/Headers/fmaintrin.h b/lib/Headers/fmaintrin.h index d0dc66fe85..094d13afea 100644 --- a/lib/Headers/fmaintrin.h +++ b/lib/Headers/fmaintrin.h @@ -29,200 +29,202 @@ #define __FMAINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma"))) +#define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("fma"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("fma"), __min_vector_width__(256))) -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmadd_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmadd_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmadd_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmadd_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmsub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmsub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmsub_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmsub_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fnmadd_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fnmadd_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fnmadd_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fnmsub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddps(-(__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddpd(-(__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fnmsub_ss(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddss3((__v4sf)__A, -(__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fnmsub_sd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsd3((__v2df)__A, -(__v2df)__B, -(__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, (__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, (__v2df)__C); } -static __inline__ __m128 __DEFAULT_FN_ATTRS +static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C) { return (__m128)__builtin_ia32_vfmaddsubps((__v4sf)__A, (__v4sf)__B, -(__v4sf)__C); } -static __inline__ __m128d __DEFAULT_FN_ATTRS +static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_fmsubadd_pd(__m128d __A, __m128d __B, __m128d __C) { return (__m128d)__builtin_ia32_vfmaddsubpd((__v2df)__A, (__v2df)__B, -(__v2df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fmadd_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fmadd_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fmsub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fmsub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fnmadd_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fnmadd_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddps256(-(__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddpd256(-(__v4df)__A, (__v4df)__B, -(__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, (__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, (__v4df)__C); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C) { return (__m256)__builtin_ia32_vfmaddsubps256((__v8sf)__A, (__v8sf)__B, -(__v8sf)__C); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C) { return (__m256d)__builtin_ia32_vfmaddsubpd256((__v4df)__A, (__v4df)__B, -(__v4df)__C); } -#undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS128 +#undef __DEFAULT_FN_ATTRS256 #endif /* __FMAINTRIN_H */ diff --git a/lib/Headers/gfniintrin.h b/lib/Headers/gfniintrin.h index 99dc4b90d0..804d4f3d06 100644 --- a/lib/Headers/gfniintrin.h +++ b/lib/Headers/gfniintrin.h @@ -120,16 +120,17 @@ U, A, B, I) /* Default attributes for simple form (no masking). */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("gfni"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("gfni"), __min_vector_width__(128))) /* Default attributes for YMM unmasked form. */ -#define __DEFAULT_FN_ATTRS_Y __attribute__((__always_inline__, __nodebug__, __target__("avx,gfni"))) +#define __DEFAULT_FN_ATTRS_Y __attribute__((__always_inline__, __nodebug__, __target__("avx,gfni"), __min_vector_width__(256))) /* Default attributes for ZMM forms. */ -#define __DEFAULT_FN_ATTRS_Z __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,gfni"))) +#define __DEFAULT_FN_ATTRS_Z __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,gfni"), __min_vector_width__(512))) /* Default attributes for VLX forms. */ -#define __DEFAULT_FN_ATTRS_VL __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni"))) +#define __DEFAULT_FN_ATTRS_VL128 __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS_VL256 __attribute__((__always_inline__, __nodebug__, __target__("avx512bw,avx512vl,gfni"), __min_vector_width__(256))) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_gf2p8mul_epi8(__m128i __A, __m128i __B) @@ -138,7 +139,7 @@ _mm_gf2p8mul_epi8(__m128i __A, __m128i __B) (__v16qi) __B); } -static __inline__ __m128i __DEFAULT_FN_ATTRS_VL +static __inline__ __m128i __DEFAULT_FN_ATTRS_VL128 _mm_mask_gf2p8mul_epi8(__m128i __S, __mmask16 __U, __m128i __A, __m128i __B) { return (__m128i) __builtin_ia32_selectb_128(__U, @@ -146,7 +147,7 @@ _mm_mask_gf2p8mul_epi8(__m128i __S, __mmask16 __U, __m128i __A, __m128i __B) (__v16qi) __S); } -static __inline__ __m128i __DEFAULT_FN_ATTRS_VL +static __inline__ __m128i __DEFAULT_FN_ATTRS_VL128 _mm_maskz_gf2p8mul_epi8(__mmask16 __U, __m128i __A, __m128i __B) { return _mm_mask_gf2p8mul_epi8((__m128i)_mm_setzero_si128(), @@ -160,7 +161,7 @@ _mm256_gf2p8mul_epi8(__m256i __A, __m256i __B) (__v32qi) __B); } -static __inline__ __m256i __DEFAULT_FN_ATTRS_VL +static __inline__ __m256i __DEFAULT_FN_ATTRS_VL256 _mm256_mask_gf2p8mul_epi8(__m256i __S, __mmask32 __U, __m256i __A, __m256i __B) { return (__m256i) __builtin_ia32_selectb_256(__U, @@ -168,7 +169,7 @@ _mm256_mask_gf2p8mul_epi8(__m256i __S, __mmask32 __U, __m256i __A, __m256i __B) (__v32qi) __S); } -static __inline__ __m256i __DEFAULT_FN_ATTRS_VL +static __inline__ __m256i __DEFAULT_FN_ATTRS_VL256 _mm256_maskz_gf2p8mul_epi8(__mmask32 __U, __m256i __A, __m256i __B) { return _mm256_mask_gf2p8mul_epi8((__m256i)_mm256_setzero_si256(), @@ -200,7 +201,8 @@ _mm512_maskz_gf2p8mul_epi8(__mmask64 __U, __m512i __A, __m512i __B) #undef __DEFAULT_FN_ATTRS #undef __DEFAULT_FN_ATTRS_Y #undef __DEFAULT_FN_ATTRS_Z -#undef __DEFAULT_FN_ATTRS_VL +#undef __DEFAULT_FN_ATTRS_VL128 +#undef __DEFAULT_FN_ATTRS_VL256 #endif /* __GFNIINTRIN_H */ diff --git a/lib/Headers/mm3dnow.h b/lib/Headers/mm3dnow.h index 294866c1dc..b0288757a3 100644 --- a/lib/Headers/mm3dnow.h +++ b/lib/Headers/mm3dnow.h @@ -30,9 +30,9 @@ typedef float __v2sf __attribute__((__vector_size__(8))); /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnow"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnow"), __min_vector_width__(64))) -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("3dnow"))) _m_femms(void) { __builtin_ia32_femms(); } @@ -134,7 +134,7 @@ _m_pmulhrw(__m64 __m1, __m64 __m2) { /* Handle the 3dnowa instructions here. */ #undef __DEFAULT_FN_ATTRS -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnowa"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnowa"), __min_vector_width__(64))) static __inline__ __m64 __DEFAULT_FN_ATTRS _m_pf2iw(__m64 __m) { diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h index 56b44a23db..a73539942a 100644 --- a/lib/Headers/mmintrin.h +++ b/lib/Headers/mmintrin.h @@ -32,7 +32,7 @@ typedef short __v4hi __attribute__((__vector_size__(8))); typedef char __v8qi __attribute__((__vector_size__(8))); /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mmx"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mmx"), __min_vector_width__(64))) /// Clears the MMX state by setting the state of the x87 stack registers /// to empty. @@ -41,7 +41,7 @@ typedef char __v8qi __attribute__((__vector_size__(8))); /// /// This intrinsic corresponds to the EMMS instruction. /// -static __inline__ void __DEFAULT_FN_ATTRS +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("mmx"))) _mm_empty(void) { __builtin_ia32_emms(); diff --git a/lib/Headers/pmmintrin.h b/lib/Headers/pmmintrin.h index fc27d7cda0..7e1a9eae59 100644 --- a/lib/Headers/pmmintrin.h +++ b/lib/Headers/pmmintrin.h @@ -28,7 +28,7 @@ /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS \ - __attribute__((__always_inline__, __nodebug__, __target__("sse3"))) + __attribute__((__always_inline__, __nodebug__, __target__("sse3"), __min_vector_width__(128))) /// Loads data from an unaligned memory location to elements in a 128-bit /// vector. diff --git a/lib/Headers/shaintrin.h b/lib/Headers/shaintrin.h index 6056165d7f..3df4718ced 100644 --- a/lib/Headers/shaintrin.h +++ b/lib/Headers/shaintrin.h @@ -29,7 +29,7 @@ #define __SHAINTRIN_H /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sha"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sha"), __min_vector_width__(128))) #define _mm_sha1rnds4_epu32(V1, V2, M) \ __builtin_ia32_sha1rnds4((__v4si)(__m128i)(V1), (__v4si)(__m128i)(V2), (M)) diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h index 7ccb1a37f5..4806b3e4e1 100644 --- a/lib/Headers/smmintrin.h +++ b/lib/Headers/smmintrin.h @@ -27,7 +27,7 @@ #include /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1"), __min_vector_width__(128))) /* SSE4 Rounding macros. */ #define _MM_FROUND_TO_NEAREST_INT 0x00 diff --git a/lib/Headers/tmmintrin.h b/lib/Headers/tmmintrin.h index a3d11b90a4..734cd391be 100644 --- a/lib/Headers/tmmintrin.h +++ b/lib/Headers/tmmintrin.h @@ -27,8 +27,8 @@ #include /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3"))) -#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,ssse3"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3"), __min_vector_width__(64))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,ssse3"), __min_vector_width__(64))) /// Computes the absolute value of each of the packed 8-bit signed /// integers in the source operand and stores the 8-bit unsigned integer diff --git a/lib/Headers/vaesintrin.h b/lib/Headers/vaesintrin.h index efbb8a5652..e4174bb82f 100644 --- a/lib/Headers/vaesintrin.h +++ b/lib/Headers/vaesintrin.h @@ -29,10 +29,10 @@ #define __VAESINTRIN_H /* Default attributes for YMM forms. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("vaes"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("vaes"), __min_vector_width__(256))) /* Default attributes for ZMM forms. */ -#define __DEFAULT_FN_ATTRS_F __attribute__((__always_inline__, __nodebug__, __target__("avx512f,vaes"))) +#define __DEFAULT_FN_ATTRS_F __attribute__((__always_inline__, __nodebug__, __target__("avx512f,vaes"), __min_vector_width__(512))) static __inline__ __m256i __DEFAULT_FN_ATTRS diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 8d82da3ce5..0bc765073b 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -40,8 +40,8 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16))); #endif /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse"))) -#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS_MMX __attribute__((__always_inline__, __nodebug__, __target__("mmx,sse"), __min_vector_width__(64))) /// Adds the 32-bit float values in the low-order bits of the operands. /// diff --git a/lib/Headers/xopintrin.h b/lib/Headers/xopintrin.h index 34887dc79f..9d540a2abd 100644 --- a/lib/Headers/xopintrin.h +++ b/lib/Headers/xopintrin.h @@ -31,7 +31,8 @@ #include /* Define the default attributes for the functions in this file. */ -#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xop"))) +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xop"), __min_vector_width__(128))) +#define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("xop"), __min_vector_width__(256))) static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C) @@ -201,7 +202,7 @@ _mm_cmov_si128(__m128i __A, __m128i __B, __m128i __C) return (__m128i)(((__v2du)__A & (__v2du)__C) | ((__v2du)__B & ~(__v2du)__C)); } -static __inline__ __m256i __DEFAULT_FN_ATTRS +static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_cmov_si256(__m256i __A, __m256i __B, __m256i __C) { return (__m256i)(((__v4du)__A & (__v4du)__C) | ((__v4du)__B & ~(__v4du)__C)); @@ -765,18 +766,19 @@ _mm_frcz_pd(__m128d __A) return (__m128d)__builtin_ia32_vfrczpd((__v2df)__A); } -static __inline__ __m256 __DEFAULT_FN_ATTRS +static __inline__ __m256 __DEFAULT_FN_ATTRS256 _mm256_frcz_ps(__m256 __A) { return (__m256)__builtin_ia32_vfrczps256((__v8sf)__A); } -static __inline__ __m256d __DEFAULT_FN_ATTRS +static __inline__ __m256d __DEFAULT_FN_ATTRS256 _mm256_frcz_pd(__m256d __A) { return (__m256d)__builtin_ia32_vfrczpd256((__v4df)__A); } #undef __DEFAULT_FN_ATTRS +#undef __DEFAULT_FN_ATTRS256 #endif /* __XOPINTRIN_H */ diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 614432b0e2..022d9fe8b8 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2942,6 +2942,25 @@ static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &AL) { D->addAttr(NewAttr); } +static void handleMinVectorWidthAttr(Sema &S, Decl *D, const AttributeList &AL) { + Expr *E = AL.getArgAsExpr(0); + uint32_t VecWidth; + if (!checkUInt32Argument(S, AL, E, VecWidth)) { + AL.setInvalid(); + return; + } + + MinVectorWidthAttr *Existing = D->getAttr(); + if (Existing && Existing->getVectorWidth() != VecWidth) { + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getName(); + return; + } + + D->addAttr(::new (S.Context) + MinVectorWidthAttr(AL.getRange(), S.Context, VecWidth, + AL.getAttributeSpellingListIndex())); +} + static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &AL) { Expr *E = AL.getArgAsExpr(0); SourceLocation Loc = E->getExprLoc(); @@ -6130,6 +6149,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Target: handleTargetAttr(S, D, AL); break; + case AttributeList::AT_MinVectorWidth: + handleMinVectorWidthAttr(S, D, AL); + break; case AttributeList::AT_Unavailable: handleAttrWithMessage(S, D, AL); break; diff --git a/test/CodeGen/function-min-vector-width.c b/test/CodeGen/function-min-vector-width.c new file mode 100644 index 0000000000..fb22a4fce6 --- /dev/null +++ b/test/CodeGen/function-min-vector-width.c @@ -0,0 +1,7 @@ +// This test verifies that we produce min-legal-vector-width attributes + +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +void __attribute((__min_vector_width__(128))) foo() {} + +// CHECK: "min-legal-vector-width"="128" diff --git a/test/CodeGen/x86-builtins-vector-width.c b/test/CodeGen/x86-builtins-vector-width.c new file mode 100644 index 0000000000..62f5929e4f --- /dev/null +++ b/test/CodeGen/x86-builtins-vector-width.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu i686 -emit-llvm %s -o - | FileCheck %s + +typedef signed long long V2LLi __attribute__((vector_size(16))); +typedef signed long long V4LLi __attribute__((vector_size(32))); + +// Make sure builtin forces a min-legal-width attribute +void foo(void) { + V2LLi tmp_V2LLi; + + tmp_V2LLi = __builtin_ia32_undef128(); +} + +// Make sure explicit attribute larger than builtin wins. +void goo(void) __attribute__((__min_vector_width__(256))) { + V2LLi tmp_V2LLi; + + tmp_V2LLi = __builtin_ia32_undef128(); +} + +// Make sure builtin larger than explicit attribute wins. +void hoo(void) __attribute__((__min_vector_width__(128))) { + V4LLi tmp_V4LLi; + + tmp_V4LLi = __builtin_ia32_undef256(); +} + +// CHECK: foo{{.*}} #0 +// CHECK: goo{{.*}} #1 +// CHECK: hoo{{.*}} #1 + +// CHECK: #0 = {{.*}}"min-legal-vector-width"="128" +// CHECK: #1 = {{.*}}"min-legal-vector-width"="256" diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test index dd8d09e061..675a178d31 100644 --- a/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/test/Misc/pragma-attribute-supported-attributes-list.test @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 69 attributes: +// CHECK: #pragma clang attribute supports 70 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -32,6 +32,7 @@ // CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record) // CHECK-NEXT: MicroMips (SubjectMatchRule_function) +// CHECK-NEXT: MinVectorWidth (SubjectMatchRule_function) // CHECK-NEXT: MipsLongCall (SubjectMatchRule_function) // CHECK-NEXT: MipsShortCall (SubjectMatchRule_function) // CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter) diff --git a/test/Sema/attr-min-vector-width.c b/test/Sema/attr-min-vector-width.c new file mode 100644 index 0000000000..0e6f84a672 --- /dev/null +++ b/test/Sema/attr-min-vector-width.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s + +int i; +void f(void) __attribute__((__min_vector_width__(i))); /* expected-error {{'__min_vector_width__' attribute requires an integer constant}} */ + +void f2(void) __attribute__((__min_vector_width__(128))); + +void f3(void) __attribute__((__min_vector_width__(128), __min_vector_width__(256))); /* expected-warning {{attribute '__min_vector_width__' is already applied with different parameters}} */ + +void f4(void) __attribute__((__min_vector_width__())); /* expected-error {{'__min_vector_width__' attribute takes one argument}} */ + +void f5(void) __attribute__((__min_vector_width__(128, 256))); /* expected-error {{'__min_vector_width__' attribute takes one argument}} */ + +void f6(void) { + int x __attribute__((__min_vector_width__(128))) = 0; /* expected-error {{'__min_vector_width__' attribute only applies to functions}} */ +} -- GitLab From f983ca81222092615a93802c6820e9a46b5b9ac2 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Mon, 9 Jul 2018 19:02:41 +0000 Subject: [PATCH 0456/1023] [Index] Ignore noop #undef's when handling macro occurrences. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336584 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Index/IndexingAction.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Index/IndexingAction.cpp b/lib/Index/IndexingAction.cpp index b8faf7075e..16f6c21745 100644 --- a/lib/Index/IndexingAction.cpp +++ b/lib/Index/IndexingAction.cpp @@ -98,6 +98,8 @@ public: void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, const MacroDirective *Undef) override { + if (!MD.getMacroInfo()) // Ignore noop #undef. + return; IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(), MacroNameTok.getLocation(), *MD.getMacroInfo()); -- GitLab From 0b6fe1495ec1565f554715b650e7e13b391e0ab1 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 9 Jul 2018 19:41:28 +0000 Subject: [PATCH 0457/1023] [libclang] evalute compound statement cursors before trying to evaluate the cursor like a declaration This change fixes a bug in libclang in which it tries to evaluate a statement cursor as a declaration cursor, because that statement still has a pointer to the declaration parent. rdar://38888477 Differential Revision: https://reviews.llvm.org/D49051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336590 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndex.cpp | 26 +++++++++--------- unittests/libclang/LibclangTest.cpp | 41 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index b61dff3238..a4698830d9 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3890,6 +3890,19 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { } CXEvalResult clang_Cursor_Evaluate(CXCursor C) { + if (clang_getCursorKind(C) == CXCursor_CompoundStmt) { + const CompoundStmt *compoundStmt = cast(getCursorStmt(C)); + Expr *expr = nullptr; + for (auto *bodyIterator : compoundStmt->body()) { + if ((expr = dyn_cast(bodyIterator))) { + break; + } + } + if (expr) + return const_cast( + reinterpret_cast(evaluateExpr(expr, C))); + } + const Decl *D = getCursorDecl(C); if (D) { const Expr *expr = nullptr; @@ -3903,19 +3916,6 @@ CXEvalResult clang_Cursor_Evaluate(CXCursor C) { evaluateExpr(const_cast(expr), C))); return nullptr; } - - const CompoundStmt *compoundStmt = dyn_cast_or_null(getCursorStmt(C)); - if (compoundStmt) { - Expr *expr = nullptr; - for (auto *bodyIterator : compoundStmt->body()) { - if ((expr = dyn_cast(bodyIterator))) { - break; - } - } - if (expr) - return const_cast( - reinterpret_cast(evaluateExpr(expr, C))); - } return nullptr; } diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp index 6fddcb2cbf..9629b62475 100644 --- a/unittests/libclang/LibclangTest.cpp +++ b/unittests/libclang/LibclangTest.cpp @@ -461,6 +461,47 @@ TEST_F(LibclangParseTest, AllSkippedRanges) { clang_disposeSourceRangeList(Ranges); } +TEST_F(LibclangParseTest, EvaluateChildExpression) { + std::string Main = "main.m"; + WriteFile(Main, "#define kFOO @\"foo\"\n" + "void foobar(void) {\n" + " {kFOO;}\n" + "}\n"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + CXCursor C = clang_getTranslationUnitCursor(ClangTU); + clang_visitChildren( + C, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) { + int numberedStmt = 0; + clang_visitChildren( + cursor, + [](CXCursor cursor, CXCursor parent, + CXClientData client_data) -> CXChildVisitResult { + int &numberedStmt = *((int *)client_data); + if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) { + if (numberedStmt) { + CXEvalResult RE = clang_Cursor_Evaluate(cursor); + EXPECT_NE(RE, nullptr); + EXPECT_EQ(clang_EvalResult_getKind(RE), + CXEval_ObjCStrLiteral); + return CXChildVisit_Break; + } + numberedStmt++; + } + return CXChildVisit_Recurse; + }, + &numberedStmt); + EXPECT_EQ(numberedStmt, 1); + } + return CXChildVisit_Continue; + }, + nullptr); +} + class LibclangReparseTest : public LibclangParseTest { public: void DisplayDiagnostics() { -- GitLab From 7a9552d9f1a0e003326fa99215e050e75556127b Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 9 Jul 2018 19:56:45 +0000 Subject: [PATCH 0458/1023] [libclang] NFC, simplify clang_Cursor_Evaluate Take advantage of early returns as suggested by Duncan in https://reviews.llvm.org/D49051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336591 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndex.cpp | 49 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a4698830d9..ab606ec92f 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3889,36 +3889,35 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { return nullptr; } -CXEvalResult clang_Cursor_Evaluate(CXCursor C) { - if (clang_getCursorKind(C) == CXCursor_CompoundStmt) { - const CompoundStmt *compoundStmt = cast(getCursorStmt(C)); - Expr *expr = nullptr; - for (auto *bodyIterator : compoundStmt->body()) { - if ((expr = dyn_cast(bodyIterator))) { - break; - } - } - if (expr) - return const_cast( - reinterpret_cast(evaluateExpr(expr, C))); - } - - const Decl *D = getCursorDecl(C); - if (D) { - const Expr *expr = nullptr; - if (auto *Var = dyn_cast(D)) { - expr = Var->getInit(); - } else if (auto *Field = dyn_cast(D)) { - expr = Field->getInClassInitializer(); - } - if (expr) - return const_cast(reinterpret_cast( - evaluateExpr(const_cast(expr), C))); +static const Expr *evaluateDeclExpr(const Decl *D) { + if (!D) return nullptr; + if (auto *Var = dyn_cast(D)) + return Var->getInit(); + else if (auto *Field = dyn_cast(D)) + return Field->getInClassInitializer(); + return nullptr; +} + +static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) { + assert(CS && "invalid compound statement"); + for (auto *bodyIterator : CS->body()) { + if (const auto *E = dyn_cast(bodyIterator)) + return E; } return nullptr; } +CXEvalResult clang_Cursor_Evaluate(CXCursor C) { + if (const Expr *E = + clang_getCursorKind(C) == CXCursor_CompoundStmt + ? evaluateCompoundStmtExpr(cast(getCursorStmt(C))) + : evaluateDeclExpr(getCursorDecl(C))) + return const_cast( + reinterpret_cast(evaluateExpr(const_cast(E), C))); + return nullptr; +} + unsigned clang_Cursor_hasAttrs(CXCursor C) { const Decl *D = getCursorDecl(C); if (!D) { -- GitLab From 500eccb77e6a768d61ce43490a3e1842466d75df Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 9 Jul 2018 19:58:08 +0000 Subject: [PATCH 0459/1023] [OPENMP] Do not mark local variables as declare target. When the parsing of the functions happens inside of the declare target region, we may erroneously mark local variables as declare target thought they are not. This attribute can be applied only to global variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336592 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 6 +++++- test/OpenMP/dump.cpp | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 6fb0125e6e..f5a1d0b222 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -13012,8 +13012,12 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, return; SourceRange SR = E ? E->getSourceRange() : D->getSourceRange(); SourceLocation SL = E ? E->getLocStart() : D->getLocation(); - // 2.10.6: threadprivate variable cannot appear in a declare target directive. if (auto *VD = dyn_cast(D)) { + // Only global variables can be marked as declare target. + if (VD->isLocalVarDeclOrParm()) + return; + // 2.10.6: threadprivate variable cannot appear in a declare target + // directive. if (DSAStack->isThreadPrivate(VD)) { Diag(SL, diag::err_omp_threadprivate_in_target); reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false)); diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp index f54d25f197..28da82b3b8 100644 --- a/test/OpenMP/dump.cpp +++ b/test/OpenMP/dump.cpp @@ -63,7 +63,22 @@ struct S { #pragma omp declare simd inbranch void foo(); -// CHECK: `-FunctionDecl {{.+}} col:6 foo 'void ()' +// CHECK: |-FunctionDecl {{.+}} col:6 foo 'void ()' // CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} Implicit BS_Inbranch // CHECK: `-OMPDeclareSimdDeclAttr {{.+}} Implicit BS_Undefined +#pragma omp declare target +int bar() { + int f; + return f; +} +#pragma omp end declare target + +// CHECK: `-FunctionDecl {{.+}} line:71:5 bar 'int ()' +// CHECK-NEXT: |-CompoundStmt {{.+}} +// CHECK-NEXT: | |-DeclStmt {{.+}} +// CHECK-NEXT: | | `-VarDecl {{.+}} col:7 used f 'int' +// CHECK-NEXT: | `-ReturnStmt {{.+}} +// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} 'int' +// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'int' lvalue Var {{.+}} 'f' 'int' +// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <> Implicit MT_To -- GitLab From 2098bf010ac1d68a9378edc1a04fda31812158d9 Mon Sep 17 00:00:00 2001 From: Stefan Pintilie Date: Mon, 9 Jul 2018 20:09:52 +0000 Subject: [PATCH 0460/1023] [Power9] [CLANG] Add __float128 support for trunc to double round to odd Add support for this builtin: double builtin_truncf128_round_to_odd(float128) Differential Revision: https://reviews.llvm.org/D48482 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336596 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsPPC.def | 1 + test/CodeGen/builtins-ppc-p9-f128.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index e3d71385eb..8cd8a2be20 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -430,6 +430,7 @@ BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "") BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "") BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "") BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "") +BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "") // HTM builtins BUILTIN(__builtin_tbegin, "UiUIi", "") diff --git a/test/CodeGen/builtins-ppc-p9-f128.c b/test/CodeGen/builtins-ppc-p9-f128.c index c0e8f6485c..c43915ad24 100644 --- a/test/CodeGen/builtins-ppc-p9-f128.c +++ b/test/CodeGen/builtins-ppc-p9-f128.c @@ -42,4 +42,9 @@ __float128 testDivOdd() { // CHECK-NEXT: ret fp128 } +double testTruncOdd() { + return __builtin_truncf128_round_to_odd(A); +// CHECK: @llvm.ppc.truncf128.round.to.odd(fp128 +// CHECK-NEXT: ret double +} -- GitLab From 15685126aca86d46c25fcc0964173377adc1cc3d Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Mon, 9 Jul 2018 21:07:20 +0000 Subject: [PATCH 0461/1023] Added -fcrash-diagnostics-dir flag Summary: New flag causes crash reports to be written in the specified directory rather than the temp directory. Patch by Chijioke Kamanu. Reviewers: hans, inglorion, rnk Reviewed By: hans Subscribers: zturner, hiraditya, llvm-commits, cfe-commits Differential Revision: https://reviews.llvm.org/D48601 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336604 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 1 + lib/Driver/Driver.cpp | 25 ++++++++++++++++++++----- test/Driver/crash-diagnostics-dir.c | 6 ++++++ 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 test/Driver/crash-diagnostics-dir.c diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 496cc12aa3..f958999f1c 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -798,6 +798,7 @@ def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit="> Group; def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group, Flags<[NoArgumentUnused]>, HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">; +def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<["-"], "fcreate-profile">, Group; def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1fd7a6d718..9e92f64f66 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1291,12 +1291,13 @@ void Driver::generateCompilationDiagnostics( // Assume associated files are based off of the first temporary file. CrashReportInfo CrashInfo(TempFiles[0], VFS); - std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; + llvm::SmallString<128> Script(CrashInfo.Filename); + llvm::sys::path::replace_extension(Script, "sh"); std::error_code EC; llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew); if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating run script: " + Script + " " + EC.message(); + << "Error generating run script: " << Script << " " << EC.message(); } else { ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" << "# Driver args: "; @@ -1308,7 +1309,7 @@ void Driver::generateCompilationDiagnostics( ScriptOS << "\n# Additional information: " << AdditionalInformation << "\n"; if (Report) - Report->TemporaryFiles.push_back(Script); + Report->TemporaryFiles.push_back(Script.str()); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } @@ -4018,8 +4019,22 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); std::pair Split = Name.split('.'); - std::string TmpName = GetTemporaryPath( - Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode())); + SmallString<128> TmpName; + const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); + Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir); + if (CCGenDiagnostics && A) { + SmallString<128> CrashDirectory(A->getValue()); + llvm::sys::path::append(CrashDirectory, Split.first); + const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%"; + std::error_code EC = + llvm::sys::fs::createUniqueFile(CrashDirectory + Middle + Suffix, TmpName); + if (EC) { + Diag(clang::diag::err_unable_to_make_temp) << EC.message(); + return ""; + } + } else { + TmpName = GetTemporaryPath(Split.first, Suffix); + } return C.addTempFile(C.getArgs().MakeArgString(TmpName)); } diff --git a/test/Driver/crash-diagnostics-dir.c b/test/Driver/crash-diagnostics-dir.c new file mode 100644 index 0000000000..e922eac4be --- /dev/null +++ b/test/Driver/crash-diagnostics-dir.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s 2>&1 | FileCheck %s +#pragma clang __debug parser_crash +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK: diagnostic msg: {{.*}}Output{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c -- GitLab From 2a527c0d94c929757ffc59f03009e1b3c67dba25 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 9 Jul 2018 21:31:20 +0000 Subject: [PATCH 0462/1023] [AST] Rename some Redeclarable functions to reduce confusion Reviewers: rsmith, akyrtzi Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48894 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336605 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Redeclarable.h | 66 +++++++++++++++----------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index ab1ab3ff38..c2bd6e6fd1 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -36,7 +36,7 @@ class Decl; // DeclLink that may point to one of 3 possible states: // - the "previous" (temporal) element in the chain // - the "latest" (temporal) element in the chain -// - the an "uninitialized-latest" value (when newly-constructed) +// - the "uninitialized-latest" value (when newly-constructed) // // - The first element is also often called the canonical element. Every // element has a pointer to it so that "getCanonical" can be fast. @@ -48,10 +48,8 @@ class Decl; // "most-recent" when referring to temporal order: order of addition // to the chain. // -// - To make matters confusing, the DeclLink type uses the term "next" -// for its pointer-storage internally (thus functions like -// NextIsPrevious). It's easiest to just ignore the implementation of -// DeclLink when making sense of the redeclaration chain. +// - It's easiest to just ignore the implementation of DeclLink when making +// sense of the redeclaration chain. // // - There's also a "definition" link for several types of // redeclarable, where only one definition should exist at any given @@ -105,66 +103,64 @@ protected: /// previous declaration. using NotKnownLatest = llvm::PointerUnion; - mutable llvm::PointerUnion Next; + mutable llvm::PointerUnion Link; public: enum PreviousTag { PreviousLink }; enum LatestTag { LatestLink }; DeclLink(LatestTag, const ASTContext &Ctx) - : Next(NotKnownLatest(reinterpret_cast(&Ctx))) {} - DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {} + : Link(NotKnownLatest(reinterpret_cast(&Ctx))) {} + DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {} - bool NextIsPrevious() const { - return Next.is() && + bool isFirst() const { + return Link.is() || // FIXME: 'template' is required on the next line due to an // apparent clang bug. - Next.get().template is(); + Link.get().template is(); } - bool NextIsLatest() const { return !NextIsPrevious(); } - - decl_type *getNext(const decl_type *D) const { - if (Next.is()) { - NotKnownLatest NKL = Next.get(); + decl_type *getPrevious(const decl_type *D) const { + if (Link.is()) { + NotKnownLatest NKL = Link.get(); if (NKL.is()) return static_cast(NKL.get()); // Allocate the generational 'most recent' cache now, if needed. - Next = KnownLatest(*reinterpret_cast( + Link = KnownLatest(*reinterpret_cast( NKL.get()), const_cast(D)); } - return static_cast(Next.get().get(D)); + return static_cast(Link.get().get(D)); } void setPrevious(decl_type *D) { - assert(NextIsPrevious() && "decl became non-canonical unexpectedly"); - Next = Previous(D); + assert(!isFirst() && "decl became non-canonical unexpectedly"); + Link = Previous(D); } void setLatest(decl_type *D) { - assert(NextIsLatest() && "decl became canonical unexpectedly"); - if (Next.is()) { - NotKnownLatest NKL = Next.get(); - Next = KnownLatest(*reinterpret_cast( + assert(isFirst() && "decl became canonical unexpectedly"); + if (Link.is()) { + NotKnownLatest NKL = Link.get(); + Link = KnownLatest(*reinterpret_cast( NKL.get()), D); } else { - auto Latest = Next.get(); + auto Latest = Link.get(); Latest.set(D); - Next = Latest; + Link = Latest; } } - void markIncomplete() { Next.get().markIncomplete(); } + void markIncomplete() { Link.get().markIncomplete(); } Decl *getLatestNotUpdated() const { - assert(NextIsLatest() && "expected a canonical decl"); - if (Next.is()) + assert(isFirst() && "expected a canonical decl"); + if (Link.is()) return nullptr; - return Next.get().getNotUpdated(); + return Link.get().getNotUpdated(); } }; @@ -178,8 +174,8 @@ protected: /// Points to the next redeclaration in the chain. /// - /// If NextIsPrevious() is true, this is a link to the previous declaration - /// of this same Decl. If NextIsLatest() is true, this is the first + /// If isFirst() is false, this is a link to the previous declaration + /// of this same Decl. If isFirst() is true, this is the first /// declaration and Link points to the latest declaration. For example: /// /// #1 int f(int x, int y = 1); // @@ -192,7 +188,7 @@ protected: decl_type *First; decl_type *getNextRedeclaration() const { - return RedeclLink.getNext(static_cast(this)); + return RedeclLink.getPrevious(static_cast(this)); } public: @@ -206,7 +202,7 @@ public: /// Return the previous declaration of this declaration or NULL if this /// is the first declaration. decl_type *getPreviousDecl() { - if (RedeclLink.NextIsPrevious()) + if (!RedeclLink.isFirst()) return getNextRedeclaration(); return nullptr; } @@ -224,7 +220,7 @@ public: const decl_type *getFirstDecl() const { return First; } /// True if this is the first declaration in its redeclaration chain. - bool isFirstDecl() const { return RedeclLink.NextIsLatest(); } + bool isFirstDecl() const { return RedeclLink.isFirst(); } /// Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDecl() { -- GitLab From b1e72a63c203cd48dba8b1a3b3b260dd325a1472 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 9 Jul 2018 21:49:06 +0000 Subject: [PATCH 0463/1023] [Index] Add index::IndexingOptions::IndexImplicitInstantiation Summary: With IndexImplicitInstantiation=true, the following case records an occurrence of B::bar in A::foo, which will benefit cross reference tools. template struct B { void bar() {}}; template struct A { void foo(B *x) { x->bar(); }}; int main() { A a; a.foo(0); } Reviewers: akyrtzi, arphaman, rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49002 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336606 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Index/IndexingAction.h | 1 + lib/Index/IndexDecl.cpp | 2 +- lib/Index/IndexTypeSourceInfo.cpp | 2 +- lib/Index/IndexingContext.cpp | 4 ++++ lib/Index/IndexingContext.h | 4 +--- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h index 48385b396f..64496a21ec 100644 --- a/include/clang/Index/IndexingAction.h +++ b/include/clang/Index/IndexingAction.h @@ -39,6 +39,7 @@ struct IndexingOptions { SystemSymbolFilterKind SystemSymbolFilter = SystemSymbolFilterKind::DeclarationsOnly; bool IndexFunctionLocals = false; + bool IndexImplicitInstantiation = false; }; /// Creates a frontend action that indexes all symbols (macros and AST decls). diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index 01608d2b77..01ad3a2772 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -726,7 +726,7 @@ bool IndexingContext::indexDecl(const Decl *D) { if (D->isImplicit() && shouldIgnoreIfImplicit(D)) return true; - if (isTemplateImplicitInstantiation(D)) + if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) return true; IndexingDeclVisitor Visitor(*this); diff --git a/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp index c8ff3d72d4..7a7a156478 100644 --- a/lib/Index/IndexTypeSourceInfo.cpp +++ b/lib/Index/IndexTypeSourceInfo.cpp @@ -129,7 +129,7 @@ public: template bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) { if (const auto *T = TL.getTypePtr()) { - if (IndexCtx.shouldIndexImplicitTemplateInsts()) { + if (IndexCtx.shouldIndexImplicitInstantiation()) { if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), Parent, ParentDC, SymbolRoleSet(), Relations); diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index 71b92bc6bf..6c09ac7c09 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -37,6 +37,10 @@ bool IndexingContext::shouldIndexFunctionLocalSymbols() const { return IndexOpts.IndexFunctionLocals; } +bool IndexingContext::shouldIndexImplicitInstantiation() const { + return IndexOpts.IndexImplicitInstantiation; +} + bool IndexingContext::handleDecl(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations) { diff --git a/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h index f05eaae696..04960086d0 100644 --- a/lib/Index/IndexingContext.h +++ b/lib/Index/IndexingContext.h @@ -60,9 +60,7 @@ public: bool shouldIndexFunctionLocalSymbols() const; - bool shouldIndexImplicitTemplateInsts() const { - return false; - } + bool shouldIndexImplicitInstantiation() const; static bool isTemplateImplicitInstantiation(const Decl *D); -- GitLab From 48ab15fabbe6c74f02f5d6717960161877b0e588 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Mon, 9 Jul 2018 22:09:33 +0000 Subject: [PATCH 0464/1023] Rename function calls missed in r336605 NextIsLatest -> isFirst git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336610 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index c10ca9e967..ed0725d036 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -4260,7 +4260,7 @@ template void Redeclarable::setPreviousDecl(decl_type *PrevDecl) { // Note: This routine is implemented here because we need both NamedDecl // and Redeclarable to be defined. - assert(RedeclLink.NextIsLatest() && + assert(RedeclLink.isFirst() && "setPreviousDecl on a decl already in a redeclaration chain"); if (PrevDecl) { @@ -4268,7 +4268,7 @@ void Redeclarable::setPreviousDecl(decl_type *PrevDecl) { // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. First = PrevDecl->getFirstDecl(); - assert(First->RedeclLink.NextIsLatest() && "Expected first"); + assert(First->RedeclLink.isFirst() && "Expected first"); decl_type *MostRecent = First->getNextRedeclaration(); RedeclLink = PreviousDeclLink(cast(MostRecent)); -- GitLab From 8ccbbcf85598e60c728f171857f3e82681860dc6 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 10 Jul 2018 00:37:25 +0000 Subject: [PATCH 0465/1023] [X86] Add __builtin_ia32_selectss_128 and __builtin_ia32_selectsd_128 that is suitable for use in scalar mask intrinsics. This will convert the i8 mask argument to <8 x i1> and extract an i1 and then emit a select instruction. This replaces the '(__U & 1)" and ternary operator used in some of intrinsics. The old sequence was lowered to a scalar and and compare. The new sequence uses an i1 vector that will interoperate better with other mask intrinsics. This removes the need to handle div_ss/sd specially in CGBuiltin.cpp. A follow up patch will add the GCCBuiltin name back in llvm and remove the custom handling. I made some adjustments to legacy move_ss/sd intrinsics which we reused here to do a simpler extract and insert instead of 2 extracts and two inserts or a shuffle. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336622 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 2 + lib/CodeGen/CGBuiltin.cpp | 7 + lib/Headers/avx512fintrin.h | 82 ++++-------- lib/Headers/emmintrin.h | 3 +- lib/Headers/xmmintrin.h | 3 +- test/CodeGen/avx512f-builtins.c | 196 +++++++++++++++++----------- test/CodeGen/sse-builtins.c | 3 +- test/CodeGen/sse2-builtins.c | 4 +- 8 files changed, 162 insertions(+), 138 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 0b08e03764..e98f7d612c 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -1809,6 +1809,8 @@ TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "ncV:512:", "avx51 TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "ncV:128:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "ncV:256:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectss_128, "V4fUcV4fV4f", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectsd_128, "V2dUcV2dV2d", "ncV:128:", "avx512f") // MONITORX/MWAITX TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 6b1198d64e..ba0519b355 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -9832,6 +9832,13 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_selectpd_256: case X86::BI__builtin_ia32_selectpd_512: return EmitX86Select(*this, Ops[0], Ops[1], Ops[2]); + case X86::BI__builtin_ia32_selectss_128: + case X86::BI__builtin_ia32_selectsd_128: { + Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0); + Value *B = Builder.CreateExtractElement(Ops[2], (uint64_t)0); + A = EmitX86ScalarSelect(*this, Ops[0], A, B); + return Builder.CreateInsertElement(Ops[1], A, (uint64_t)0); + } case X86::BI__builtin_ia32_cmpb128_mask: case X86::BI__builtin_ia32_cmpb256_mask: case X86::BI__builtin_ia32_cmpb512_mask: diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 9024168483..f69620bbca 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -1899,15 +1899,13 @@ _mm512_maskz_abs_epi32 (__mmask16 __U, __m512i __A) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectss_128(__U, __A, __W); } static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } #define _mm_add_round_ss(A, B, R) \ @@ -1931,15 +1929,13 @@ _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, __W); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } #define _mm_add_round_sd(A, B, R) \ (__m128d)__builtin_ia32_addsd_round_mask((__v2df)(__m128d)(A), \ @@ -2018,15 +2014,13 @@ _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectss_128(__U, __A, __W); } static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } #define _mm_sub_round_ss(A, B, R) \ (__m128)__builtin_ia32_subss_round_mask((__v4sf)(__m128)(A), \ @@ -2049,15 +2043,13 @@ _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, __W); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } #define _mm_sub_round_sd(A, B, R) \ @@ -2137,15 +2129,13 @@ _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectss_128(__U, __A, __W); } static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } #define _mm_mul_round_ss(A, B, R) \ (__m128)__builtin_ia32_mulss_round_mask((__v4sf)(__m128)(A), \ @@ -2168,15 +2158,13 @@ _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : __W[0]; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, __W); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); - __A[0] = (__U & 1) ? __A[0] : 0; - return __A; + return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } #define _mm_mul_round_sd(A, B, R) \ @@ -2255,20 +2243,14 @@ _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { - return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A, - (__v4sf) __B, - (__v4sf) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + __A = _mm_div_ss(__A, __B); + return __builtin_ia32_selectss_128(__U, __A, __W); } static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { - return (__m128) __builtin_ia32_divss_round_mask ((__v4sf) __A, - (__v4sf) __B, - (__v4sf) _mm_setzero_ps (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + __A = _mm_div_ss(__A, __B); + return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } #define _mm_div_round_ss(A, B, R) \ @@ -2291,20 +2273,14 @@ _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { - return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A, - (__v2df) __B, - (__v2df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + __A = _mm_div_sd(__A, __B); + return __builtin_ia32_selectsd_128(__U, __A, __W); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) { - return (__m128d) __builtin_ia32_divsd_round_mask ((__v2df) __A, - (__v2df) __B, - (__v2df) _mm_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + __A = _mm_div_sd(__A, __B); + return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } #define _mm_div_round_sd(A, B, R) \ @@ -8639,33 +8615,27 @@ _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 res = __A; - res[0] = (__U & 1) ? __B[0] : __W[0]; - return res; + return __builtin_ia32_selectss_128(__U, _mm_move_ss(__A, __B), __W); } static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) { - __m128 res = __A; - res[0] = (__U & 1) ? __B[0] : 0; - return res; + return __builtin_ia32_selectss_128(__U, _mm_move_ss(__A, __B), + _mm_setzero_ps()); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d res = __A; - res[0] = (__U & 1) ? __B[0] : __W[0]; - return res; + return __builtin_ia32_selectsd_128(__U, _mm_move_sd(__A, __B), __W); } static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) { - __m128d res = __A; - res[0] = (__U & 1) ? __B[0] : 0; - return res; + return __builtin_ia32_selectsd_128(__U, _mm_move_sd(__A, __B), + _mm_setzero_pd()); } static __inline__ void __DEFAULT_FN_ATTRS128 diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h index be88c65843..f0ea7cd05c 100644 --- a/lib/Headers/emmintrin.h +++ b/lib/Headers/emmintrin.h @@ -1900,7 +1900,8 @@ _mm_setzero_pd(void) static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_move_sd(__m128d __a, __m128d __b) { - return __extension__ (__m128d){ __b[0], __a[1] }; + __a[0] = __b[0]; + return __a; } /// Stores the lower 64 bits of a 128-bit vector of [2 x double] to a diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h index 0bc765073b..17af17267c 100644 --- a/lib/Headers/xmmintrin.h +++ b/lib/Headers/xmmintrin.h @@ -2671,7 +2671,8 @@ _mm_unpacklo_ps(__m128 __a, __m128 __b) static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_move_ss(__m128 __a, __m128 __b) { - return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 4, 1, 2, 3); + __a[0] = __b[0]; + return __a; } /// Constructs a 128-bit floating-point vector of [4 x float]. The lower diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index be5fcb207c..2beae24e45 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -3150,11 +3150,12 @@ __m128 test_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fadd float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> %{{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_add_ss(__W,__U,__A,__B); } __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { @@ -3164,10 +3165,12 @@ __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fadd float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> %{{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_add_ss(__U,__A,__B); } __m128d test_mm_add_round_sd(__m128d __A, __m128d __B) { @@ -3192,11 +3195,12 @@ __m128d test_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fadd double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_add_sd(__W,__U,__A,__B); } __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { @@ -3206,10 +3210,12 @@ __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fadd double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_add_sd(__U,__A,__B); } __m512d test_mm512_sub_round_pd(__m512d __A, __m512d __B) { @@ -3292,11 +3298,12 @@ __m128 test_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fsub float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_sub_ss(__W,__U,__A,__B); } __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { @@ -3306,10 +3313,12 @@ __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fsub float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_sub_ss(__U,__A,__B); } __m128d test_mm_sub_round_sd(__m128d __A, __m128d __B) { @@ -3334,11 +3343,12 @@ __m128d test_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fsub double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_sub_sd(__W,__U,__A,__B); } __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { @@ -3348,10 +3358,12 @@ __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fsub double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_sub_sd(__U,__A,__B); } __m512d test_mm512_mul_round_pd(__m512d __A, __m512d __B) { @@ -3434,11 +3446,12 @@ __m128 test_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fmul float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_mul_ss(__W,__U,__A,__B); } __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { @@ -3448,10 +3461,12 @@ __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK: extractelement <4 x float> %{{.*}}, i32 0 // CHECK: fmul float %{{.*}}, %{{.*}} // CHECK: insertelement <4 x float> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} + // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_mul_ss(__U,__A,__B); } __m128d test_mm_mul_round_sd(__m128d __A, __m128d __B) { @@ -3476,11 +3491,12 @@ __m128d test_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fmul double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_mul_sd(__W,__U,__A,__B); } __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { @@ -3490,10 +3506,12 @@ __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK: extractelement <2 x double> %{{.*}}, i32 0 // CHECK: fmul double %{{.*}}, %{{.*}} // CHECK: insertelement <2 x double> {{.*}}, i32 0 - // CHECK: and i32 {{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br {{.*}}, {{.*}}, {{.*}} - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} + // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_mul_sd(__U,__A,__B); } __m512d test_mm512_div_round_pd(__m512d __A, __m512d __B) { @@ -3581,10 +3599,12 @@ __m128 test_mm_maskz_div_round_ss(__mmask8 __U, __m128 __A, __m128 __B) { } __m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_div_ss + // CHECK: extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: fdiv float %{{.*}}, %{{.*}} + // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 // CHECK: extractelement <4 x float> %{{.*}}, i64 0 // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: fdiv float %{{.*}}, %{{.*}} // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} @@ -3593,10 +3613,12 @@ __m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { } __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_maskz_div_ss + // CHECK: extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: fdiv float %{{.*}}, %{{.*}} + // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 // CHECK: extractelement <4 x float> %{{.*}}, i64 0 // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: fdiv float %{{.*}}, %{{.*}} // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 // CHECK-NEXT: select i1 %{{.*}}, float %{{.*}}, float %{{.*}} @@ -3620,10 +3642,12 @@ __m128d test_mm_maskz_div_round_sd(__mmask8 __U, __m128d __A, __m128d __B) { } __m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_mask_div_sd + // CHECK: extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: fdiv double %{{.*}}, %{{.*}} + // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 // CHECK: extractelement <2 x double> %{{.*}}, i64 0 // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: fdiv double %{{.*}}, %{{.*}} // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} @@ -3632,10 +3656,12 @@ __m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) } __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_maskz_div_sd + // CHECK: extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: fdiv double %{{.*}}, %{{.*}} + // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 // CHECK: extractelement <2 x double> %{{.*}}, i64 0 // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: fdiv double %{{.*}}, %{{.*}} // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 // CHECK-NEXT: select i1 %{{.*}}, double %{{.*}}, double %{{.*}} @@ -10531,38 +10557,56 @@ int test_mm512_mask2int(__mmask16 __a) __m128 test_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_mask_move_ss - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: phi float [ %{{.*}}, %{{.*}} ], [ %{{.*}}, %{{.*}} ] - // CHECK: insertelement <4 x float> %{{.*}}, float %cond.i, i32 0 + // CHECK: [[EXT:%.*]] = extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: insertelement <4 x float> %{{.*}}, float [[EXT]], i32 0 + // CHECK: [[A:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0 + // CHECK-NEXT: [[B:%.*]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, float [[A]], float [[B]] + // CHECK-NEXT: insertelement <4 x float> [[VEC]], float [[SEL]], i64 0 return _mm_mask_move_ss ( __W, __U, __A, __B); } __m128 test_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_maskz_move_ss - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: phi float [ %{{.*}}, %{{.*}} ], [ 0.000000e+00, %{{.*}} ] - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[EXT:%.*]] = extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: insertelement <4 x float> %{{.*}}, float [[EXT]], i32 0 + // CHECK: [[A:%.*]] = extractelement <4 x float> [[VEC:%.*]], i64 0 + // CHECK-NEXT: [[B:%.*]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, float [[A]], float [[B]] + // CHECK-NEXT: insertelement <4 x float> [[VEC]], float [[SEL]], i64 0 return _mm_maskz_move_ss (__U, __A, __B); } __m128d test_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_mask_move_sd - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: phi double [ %{{.*}}, %{{.*}} ], [ %{{.*}}, %{{.*}} ] - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[EXT:%.*]] = extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: insertelement <2 x double> %{{.*}}, double [[EXT]], i32 0 + // CHECK: [[A:%.*]] = extractelement <2 x double> [[VEC:%.*]], i64 0 + // CHECK-NEXT: [[B:%.*]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.*]] = select i1 %{{.*}}, double [[A]], double [[B]] + // CHECK-NEXT: insertelement <2 x double> [[VEC]], double [[SEL]], i64 0 return _mm_mask_move_sd ( __W, __U, __A, __B); } __m128d test_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_maskz_move_sd - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: phi double [ %{{.*}}, %{{.*}} ], [ 0.000000e+00, %{{.*}} ] - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[EXT:%.*]] = extractelement <2 x double> %{{.*}}, i32 0 + // CHECK: insertelement <2 x double> %{{.*}}, double [[EXT]], i32 0 + // CHECK: [[A:%.*]] = extractelement <2 x double> [[VEC:%.*]], i64 0 + // CHECK-NEXT: [[B:%.*]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.*]] = select i1 %13, double [[A]], double [[B]] + // CHECK-NEXT: insertelement <2 x double> [[VEC]], double [[SEL]], i64 0 return _mm_maskz_move_sd (__U, __A, __B); } diff --git a/test/CodeGen/sse-builtins.c b/test/CodeGen/sse-builtins.c index b7c7a7fc7e..e9801487be 100644 --- a/test/CodeGen/sse-builtins.c +++ b/test/CodeGen/sse-builtins.c @@ -450,7 +450,8 @@ __m128 test_mm_min_ss(__m128 A, __m128 B) { __m128 test_mm_move_ss(__m128 A, __m128 B) { // CHECK-LABEL: test_mm_move_ss - // CHECK: shufflevector <4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x i32> + // CHECK: extractelement <4 x float> %{{.*}}, i32 0 + // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 return _mm_move_ss(A, B); } diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c index dbf79c4736..fe7f7ccf83 100644 --- a/test/CodeGen/sse2-builtins.c +++ b/test/CodeGen/sse2-builtins.c @@ -794,9 +794,7 @@ __m128i test_mm_move_epi64(__m128i A) { __m128d test_mm_move_sd(__m128d A, __m128d B) { // CHECK-LABEL: test_mm_move_sd // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: insertelement <2 x double> undef, double %{{.*}}, i32 0 - // CHECK: extractelement <2 x double> %{{.*}}, i32 1 - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 1 + // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 return _mm_move_sd(A, B); } -- GitLab From ba066d5d857128bff3ea63ff9cd504945c23ef26 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 10 Jul 2018 00:50:03 +0000 Subject: [PATCH 0466/1023] [X86] Remove custom handling for __builtin_ia32_divss_round_mask and __builtin_ia32_divsd_round_mask. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336628 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index ba0519b355..ad983372df 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10068,30 +10068,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_pternlogq256_maskz: return EmitX86Ternlog(*this, /*ZeroMask*/true, Ops); - case X86::BI__builtin_ia32_divss_round_mask: - case X86::BI__builtin_ia32_divsd_round_mask: { - Intrinsic::ID ID; - switch (BuiltinID) { - default: llvm_unreachable("Unsupported intrinsic!"); - case X86::BI__builtin_ia32_divss_round_mask: - ID = Intrinsic::x86_avx512_mask_div_ss_round; break; - case X86::BI__builtin_ia32_divsd_round_mask: - ID = Intrinsic::x86_avx512_mask_div_sd_round; break; - } - Function *Intr = CGM.getIntrinsic(ID); - - // If round parameter is not _MM_FROUND_CUR_DIRECTION, don't lower. - if (cast(Ops[4])->getZExtValue() != (uint64_t)4) - return Builder.CreateCall(Intr, Ops); - - Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0); - Value *B = Builder.CreateExtractElement(Ops[1], (uint64_t)0); - Value *C = Builder.CreateExtractElement(Ops[2], (uint64_t)0); - Value *Div = Builder.CreateFDiv(A, B); - Div = EmitX86ScalarSelect(*this, Ops[3], Div, C); - return Builder.CreateInsertElement(Ops[0], Div, (uint64_t)0); - } - // 3DNow! case X86::BI__builtin_ia32_pswapdsf: case X86::BI__builtin_ia32_pswapdsi: { -- GitLab From c6a6cc59273c246d9e578e7d6a9b56be87c232bc Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 10 Jul 2018 00:50:25 +0000 Subject: [PATCH 0467/1023] Fix parsing of privacy annotations in os_log format strings. Privacy annotations shouldn't have to appear in the first comma-delimited string in order to be recognized. Also, they should be ignored if they are preceded or followed by non-whitespace characters. rdar://problem/40706280 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336629 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/PrintfFormatString.cpp | 78 ++++++++++++++++++----------- test/CodeGen/builtins.c | 24 ++++++++- 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 688b2031a3..2e5841ecae 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Analysis/Analyses/OSLog.h" #include "FormatStringParsing.h" #include "clang/Basic/TargetInfo.h" @@ -119,36 +120,55 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, return true; } - const char *OSLogVisibilityFlagsStart = nullptr, - *OSLogVisibilityFlagsEnd = nullptr; if (*I == '{') { - OSLogVisibilityFlagsStart = I++; - // Find the end of the modifier. - while (I != E && *I != '}') { - I++; - } - if (I == E) { - if (Warn) - H.HandleIncompleteSpecifier(Start, E - Start); - return true; - } - assert(*I == '}'); - OSLogVisibilityFlagsEnd = I++; - - // Just see if 'private' or 'public' is the first word. os_log itself will - // do any further parsing. - const char *P = OSLogVisibilityFlagsStart + 1; - while (P < OSLogVisibilityFlagsEnd && isspace(*P)) - P++; - const char *WordStart = P; - while (P < OSLogVisibilityFlagsEnd && (isalnum(*P) || *P == '_')) - P++; - const char *WordEnd = P; - StringRef Word(WordStart, WordEnd - WordStart); - if (Word == "private") { - FS.setIsPrivate(WordStart); - } else if (Word == "public") { - FS.setIsPublic(WordStart); + ++I; + unsigned char PrivacyFlags = 0; + StringRef MatchedStr; + + do { + StringRef Str(I, E - I); + std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})"; + llvm::Regex R(Match); + SmallVector Matches; + + if (R.match(Str, &Matches)) { + MatchedStr = Matches[1]; + I += Matches[0].size(); + + // Set the privacy flag if there is a privacy annotation in the + // comma-delimited segment. This overrides any privacy annotations that + // appeared in previous comma-delimited segments. + if (MatchedStr.equals("private")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; + else if (MatchedStr.equals("public")) + PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; + } else { + size_t CommaOrBracePos = + Str.find_if([](char c) { return c == ',' || c == '}'; }); + I += CommaOrBracePos + 1; + + if (CommaOrBracePos == StringRef::npos) { + // Neither a comma nor the closing brace was found. + if (Warn) + H.HandleIncompleteSpecifier(Start, E - Start); + return true; + } + } + // Continue until the closing brace is found. + } while (*(I - 1) == ','); + + // Set the privacy flag. + switch (PrivacyFlags) { + case 0: + break; + case clang::analyze_os_log::OSLogBufferItem::IsPrivate: + FS.setIsPrivate(MatchedStr.data()); + break; + case clang::analyze_os_log::OSLogBufferItem::IsPublic: + FS.setIsPublic(MatchedStr.data()); + break; + default: + llvm_unreachable("Unexpected privacy flag value"); } } diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 4f84db00cb..4059f16fbf 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -421,7 +421,29 @@ void test_builtin_os_log(void *buf, int i, const char *data) { // CHECK: %[[V5:.*]] = load i8*, i8** %[[DATA_ADDR]] // CHECK: %[[V6:.*]] = ptrtoint i8* %[[V5]] to i64 // CHECK: call void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49(i8* %[[V1]], i32 %[[V2]], i64 %[[V4]], i32 16, i64 %[[V6]]) - __builtin_os_log_format(buf, "%d %{public}s %{private}.16P", i, data, data); + __builtin_os_log_format(buf, "%d %{private,public}s %{public,private}.16P", i, data, data); + + // privacy annotations aren't recognized when they are preceded or followed + // by non-whitespace characters. + + // CHECK: call void @__os_log_helper_1_2_1_8_32( + __builtin_os_log_format(buf, "%{xyz public}s", data); + + // CHECK: call void @__os_log_helper_1_2_1_8_32( + __builtin_os_log_format(buf, "%{ public xyz}s", data); + + // CHECK: call void @__os_log_helper_1_2_1_8_32( + __builtin_os_log_format(buf, "%{ public1}s", data); + + // Privacy annotations do not have to be in the first comma-delimited string. + + // CHECK: call void @__os_log_helper_1_2_1_8_34( + __builtin_os_log_format(buf, "%{ xyz, public }s", "abc"); + + // The last privacy annotation in the string wins. + + // CHECK: call void @__os_log_helper_1_3_1_8_33( + __builtin_os_log_format(buf, "%{ public, private, public, private}s", "abc"); } // CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49 -- GitLab From a758e727e602b5e05058271c990063baeeea3ccd Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Tue, 10 Jul 2018 01:01:38 +0000 Subject: [PATCH 0468/1023] Update crash diagnostics test to avoid attempting to write into various directories if possible and to not require %t to have "Output" in the name. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336630 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-diagnostics-dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Driver/crash-diagnostics-dir.c b/test/Driver/crash-diagnostics-dir.c index e922eac4be..c8faf497b5 100644 --- a/test/Driver/crash-diagnostics-dir.c +++ b/test/Driver/crash-diagnostics-dir.c @@ -1,6 +1,6 @@ // RUN: rm -rf %t // RUN: mkdir -p %t -// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s 2>&1 | FileCheck %s +// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s #pragma clang __debug parser_crash // CHECK: Preprocessed source(s) and associated run script(s) are located at: -// CHECK: diagnostic msg: {{.*}}Output{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c +// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c -- GitLab From 2e63a7ebe45201946297edd903d3b30d91f9d273 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Tue, 10 Jul 2018 01:40:50 +0000 Subject: [PATCH 0469/1023] [ODRHash] Merge the two function hashes into one. Functions that are a sub-Decl of a record were hashed differently than other functions. This change keeps the AddFunctionDecl function and the hash of records now calls this function. In addition, AddFunctionDecl has an option to perform a hash as if the body was absent, which is required for some checks after loading modules. Additional logic prevents multiple error message from being printed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336632 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 4 + include/clang/AST/ODRHash.h | 5 +- .../Basic/DiagnosticSerializationKinds.td | 12 + lib/AST/Decl.cpp | 13 +- lib/AST/ODRHash.cpp | 93 +++++--- lib/Serialization/ASTReader.cpp | 69 +++++- test/Modules/odr_hash.cpp | 222 ++++++++++++++++++ 7 files changed, 368 insertions(+), 50 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ed0725d036..e419ded280 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2504,6 +2504,10 @@ public: /// stored on first call, then the stored value returned on the other calls. unsigned getODRHash(); + /// Returns cached ODRHash of the function. This must have been previously + /// computed and stored. + unsigned getODRHash() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h index d4cddb8dfd..6a66ba1dad 100644 --- a/include/clang/AST/ODRHash.h +++ b/include/clang/AST/ODRHash.h @@ -54,8 +54,9 @@ public: void AddCXXRecordDecl(const CXXRecordDecl *Record); // Use this for ODR checking functions between modules. This method compares - // more information than the AddDecl class. - void AddFunctionDecl(const FunctionDecl *Function); + // more information than the AddDecl class. SkipBody will process the + // hash as if the function has no body. + void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody = false); // Process SubDecls of the main Decl. This method calls the DeclVisitor // while AddDecl does not. diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 4f8f27cca4..a70e48a788 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -191,6 +191,8 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "%select{method %5|constructor|destructor}4|" "%select{method %5|constructor|destructor}4 " "is %select{not deleted|deleted}6|" + "%select{method %5|constructor|destructor}4 " + "is %select{not defaulted|defaulted}6|" "%select{method %5|constructor|destructor}4 " "is %select{|pure }6%select{not virtual|virtual}7|" "%select{method %5|constructor|destructor}4 " @@ -217,6 +219,10 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "with %6 template argument%s6|" "%select{method %5|constructor|destructor}4 " "with %6 for %ordinal7 template argument|" + "%select{method %5|constructor|destructor}4 " + "with %select{no body|body}6|" + "%select{method %5|constructor|destructor}4 " + "with body|" "%select{typedef|type alias}4 name %5|" "%select{typedef|type alias}4 %5 with underlying type %6|" "data member with name %4|" @@ -256,6 +262,8 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "%select{method %3|constructor|destructor}2|" "%select{method %3|constructor|destructor}2 " "is %select{not deleted|deleted}4|" + "%select{method %3|constructor|destructor}2 " + "is %select{not defaulted|defaulted}4|" "%select{method %3|constructor|destructor}2 " "is %select{|pure }4%select{not virtual|virtual}5|" "%select{method %3|constructor|destructor}2 " @@ -282,6 +290,10 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "with %4 template argument%s4|" "%select{method %3|constructor|destructor}2 " "with %4 for %ordinal5 template argument|" + "%select{method %3|constructor|destructor}2 " + "with %select{no body|body}4|" + "%select{method %3|constructor|destructor}2 " + "with different body|" "%select{typedef|type alias}2 name %3|" "%select{typedef|type alias}2 %3 with different underlying type %4|" "data member with name %2|" diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 08718e0a9e..7db105eded 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3658,18 +3658,15 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return 0; } +unsigned FunctionDecl::getODRHash() const { + assert(HasODRHash); + return ODRHash; +} + unsigned FunctionDecl::getODRHash() { if (HasODRHash) return ODRHash; - if (FunctionDecl *Definition = getDefinition()) { - if (Definition != this) { - HasODRHash = true; - ODRHash = Definition->getODRHash(); - return ODRHash; - } - } - if (auto *FT = getInstantiatedFromMemberFunction()) { HasODRHash = true; ODRHash = FT->getODRHash(); diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index ef1235e1d8..45b8ee61ad 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -317,35 +317,14 @@ public: } void VisitFunctionDecl(const FunctionDecl *D) { - ID.AddInteger(D->getStorageClass()); - Hash.AddBoolean(D->isInlineSpecified()); - Hash.AddBoolean(D->isVirtualAsWritten()); - Hash.AddBoolean(D->isPure()); - Hash.AddBoolean(D->isDeletedAsWritten()); - - ID.AddInteger(D->param_size()); - - for (auto *Param : D->parameters()) { - Hash.AddSubDecl(Param); - } - - AddQualType(D->getReturnType()); - - const auto* SpecializationArgs = D->getTemplateSpecializationArgs(); - Hash.AddBoolean(SpecializationArgs); - if (SpecializationArgs) { - ID.AddInteger(SpecializationArgs->size()); - for (const TemplateArgument &TA : SpecializationArgs->asArray()) { - Hash.AddTemplateArgument(TA); - } - } + // Handled by the ODRHash for FunctionDecl + ID.AddInteger(D->getODRHash()); Inherited::VisitFunctionDecl(D); } void VisitCXXMethodDecl(const CXXMethodDecl *D) { - Hash.AddBoolean(D->isConst()); - Hash.AddBoolean(D->isVolatile()); + // Handled by the ODRHash for FunctionDecl Inherited::VisitCXXMethodDecl(D); } @@ -425,7 +404,6 @@ public: } void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - Visit(D->getTemplatedDecl()); AddDecl(D->getTemplatedDecl()); Inherited::VisitFunctionTemplateDecl(D); } @@ -479,9 +457,13 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { // Filter out sub-Decls which will not be processed in order to get an // accurate count of Decl's. llvm::SmallVector Decls; - for (const Decl *SubDecl : Record->decls()) { + for (Decl *SubDecl : Record->decls()) { if (isWhitelistedDecl(SubDecl, Record)) { Decls.push_back(SubDecl); + if (auto *Function = dyn_cast(SubDecl)) { + // Compute/Preload ODRHash into FunctionDecl. + Function->getODRHash(); + } } } @@ -505,25 +487,48 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { } } -void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { +void ODRHash::AddFunctionDecl(const FunctionDecl *Function, + bool SkipBody) { assert(Function && "Expecting non-null pointer."); - // Skip hashing these kinds of function. - if (Function->isImplicit()) return; - if (Function->isDefaulted()) return; - if (Function->isDeleted()) return; - if (!Function->hasBody()) return; - if (!Function->getBody()) return; - // Skip functions that are specializations or in specialization context. const DeclContext *DC = Function; while (DC) { if (isa(DC)) return; - if (auto *F = dyn_cast(DC)) - if (F->isFunctionTemplateSpecialization()) return; + if (auto *F = dyn_cast(DC)) { + if (F->isFunctionTemplateSpecialization()) { + if (!isa(DC)) return; + if (DC->getLexicalParent()->isFileContext()) return; + // Inline method specializations are the only supported + // specialization for now. + } + } DC = DC->getParent(); } + ID.AddInteger(Function->getDeclKind()); + + const auto *SpecializationArgs = Function->getTemplateSpecializationArgs(); + AddBoolean(SpecializationArgs); + if (SpecializationArgs) { + ID.AddInteger(SpecializationArgs->size()); + for (const TemplateArgument &TA : SpecializationArgs->asArray()) { + AddTemplateArgument(TA); + } + } + + if (const auto *Method = dyn_cast(Function)) { + AddBoolean(Method->isConst()); + AddBoolean(Method->isVolatile()); + } + + ID.AddInteger(Function->getStorageClass()); + AddBoolean(Function->isInlineSpecified()); + AddBoolean(Function->isVirtualAsWritten()); + AddBoolean(Function->isPure()); + AddBoolean(Function->isDeletedAsWritten()); + AddBoolean(Function->isExplicitlyDefaulted()); + AddDecl(Function); AddQualType(Function->getReturnType()); @@ -532,7 +537,21 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { for (auto Param : Function->parameters()) AddSubDecl(Param); - AddStmt(Function->getBody()); + if (SkipBody) { + AddBoolean(false); + return; + } + + const bool HasBody = Function->isThisDeclarationADefinition() && + !Function->isDefaulted() && !Function->isDeleted() && + !Function->isLateTemplateParsed(); + AddBoolean(HasBody); + if (HasBody) { + auto *Body = Function->getBody(); + AddBoolean(Body); + if (Body) + AddStmt(Body); + } } void ODRHash::AddDecl(const Decl *D) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 84286ca380..3277243667 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9397,7 +9397,15 @@ void ASTReader::finishPendingActions() { if (!FD->isLateTemplateParsed() && !NonConstDefn->isLateTemplateParsed() && FD->getODRHash() != NonConstDefn->getODRHash()) { - PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + if (!isa(FD)) { + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } else if (FD->getLexicalParent()->isFileContext() && + NonConstDefn->getLexicalParent()->isFileContext()) { + // Only diagnose out-of-line method definitions. If they are + // in class definitions, then an error will be generated when + // processing the class bodies. + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } } } continue; @@ -10069,6 +10077,7 @@ void ASTReader::diagnoseOdrViolations() { FieldDifferentInitializers, MethodName, MethodDeleted, + MethodDefaulted, MethodVirtual, MethodStatic, MethodVolatile, @@ -10082,6 +10091,8 @@ void ASTReader::diagnoseOdrViolations() { MethodNoTemplateArguments, MethodDifferentNumberTemplateArguments, MethodDifferentTemplateArgument, + MethodSingleBody, + MethodDifferentBody, TypedefName, TypedefType, VarName, @@ -10315,8 +10326,8 @@ void ASTReader::diagnoseOdrViolations() { break; } - const bool FirstDeleted = FirstMethod->isDeleted(); - const bool SecondDeleted = SecondMethod->isDeleted(); + const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); + const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); if (FirstDeleted != SecondDeleted) { ODRDiagError(FirstMethod->getLocation(), FirstMethod->getSourceRange(), MethodDeleted) @@ -10329,6 +10340,20 @@ void ASTReader::diagnoseOdrViolations() { break; } + const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); + const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); + if (FirstDefaulted != SecondDefaulted) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDefaulted) + << FirstMethodType << FirstName << FirstDefaulted; + + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDefaulted) + << SecondMethodType << SecondName << SecondDefaulted; + Diagnosed = true; + break; + } + const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); const bool FirstPure = FirstMethod->isPure(); @@ -10594,6 +10619,44 @@ void ASTReader::diagnoseOdrViolations() { break; } } + + // Compute the hash of the method as if it has no body. + auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) { + Hash.clear(); + Hash.AddFunctionDecl(D, true /*SkipBody*/); + return Hash.CalculateHash(); + }; + + // Compare the hash generated to the hash stored. A difference means + // that a body was present in the original source. Due to merging, + // the stardard way of detecting a body will not work. + const bool HasFirstBody = + ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); + const bool HasSecondBody = + ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); + + if (HasFirstBody != HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodSingleBody) + << FirstMethodType << FirstName << HasFirstBody; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodSingleBody) + << SecondMethodType << SecondName << HasSecondBody; + Diagnosed = true; + break; + } + + if (HasFirstBody && HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDifferentBody) + << FirstMethodType << FirstName; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDifferentBody) + << SecondMethodType << SecondName; + Diagnosed = true; + break; + } + break; } case TypeAlias: diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 9cb177fbfc..28ee423c74 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -660,6 +660,202 @@ Invalid1* i1; #undef DECLS } // namespace Method +namespace MethodBody { +#if defined(FIRST) +struct S1 { + int A() { return 0; } +}; +#elif defined(SECOND) +struct S1 { + int A() { return 0; } +}; +#else +S1 s1; +#endif + +#if defined(FIRST) +struct S2 { + int BothBodies() { return 0; } +}; +#elif defined(SECOND) +struct S2 { + int BothBodies() { return 1; } +}; +#else +S2 s2; +// expected-error@first.h:* {{'MethodBody::S2' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'BothBodies' with body}} +// expected-note@second.h:* {{but in 'SecondModule' found method 'BothBodies' with different body}} +#endif + +#if defined(FIRST) +struct S3 { + int FirstBody() { return 0; } +}; +#elif defined(SECOND) +struct S3 { + int FirstBody(); +}; +#else +S3 s3; +// expected-error@first.h:* {{'MethodBody::S3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstBody' with body}} +// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstBody' with no body}} +#endif + +#if defined(FIRST) +struct S4 { + int SecondBody(); +}; +#elif defined(SECOND) +struct S4 { + int SecondBody() { return 0; } +}; +#else +S4 s4; +// expected-error@first.h:* {{'MethodBody::S4' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'SecondBody' with no body}} +// expected-note@second.h:* {{but in 'SecondModule' found method 'SecondBody' with body}} +#endif + +#if defined(FIRST) +struct S5 { + int FirstBodySecondOutOfLine() { return 0; } +}; +#elif defined(SECOND) +struct S5 { + int FirstBodySecondOutOfLine(); +}; +int S5::FirstBodySecondOutOfLine() { return 0; } +#else +S5 s5; +// expected-error@second.h:* {{'MethodBody::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}} +#endif + +#if defined(FIRST) +struct S6 { + int FirstOutOfLineSecondBody(); +}; +int S6::FirstOutOfLineSecondBody() { return 0; } +#elif defined(SECOND) +struct S6 { + int FirstOutOfLineSecondBody() { return 0; } +}; +#else +S6 s6; +// expected-error@first.h:* {{'MethodBody::S6' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}} +// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}} +#endif + +#if defined(FIRST) +struct S7 { + int BothOutOfLine(); +}; +int S7::BothOutOfLine() { return 1; } +#elif defined(SECOND) +struct S7 { + int BothOutOfLine(); +}; +int S7::BothOutOfLine() { return 0; } +#else +S7 s7; +// expected-error@second.h:* {{'MethodBody::S7::BothOutOfLine' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}} +// expected-note@first.h:* {{but in 'FirstModule' found a different body}} +#endif + +#if defined(FIRST) +struct S8 { + int FirstBodySecondOutOfLine() { return 0; } +}; +#elif defined(SECOND) +struct S8 { + int FirstBodySecondOutOfLine(); +}; +int S8::FirstBodySecondOutOfLine() { return 1; } +#else +S8 s8; +// expected-error@second.h:* {{'MethodBody::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}} +// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}} +#endif + +#if defined(FIRST) +struct S9 { + int FirstOutOfLineSecondBody(); +}; +int S9::FirstOutOfLineSecondBody() { return 1; } +#elif defined(SECOND) +struct S9 { + int FirstOutOfLineSecondBody() { return 0; } +}; +#else +S9 s9; +// expected-error@first.h:* {{'MethodBody::S9' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}} +// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}} +#endif + +#if defined(FIRST) +struct S10 { + S10(int); + S10() = delete; +}; +#elif defined(SECOND) +struct S10 { + S10(int); + S10(); +}; +#else +S10 s10(10); +// expected-error@first.h:* {{'MethodBody::S10' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is deleted}} +// expected-note@second.h:* {{but in 'SecondModule' found constructor is not deleted}} +#endif + +#if defined(FIRST) +struct S11 { + S11() = default; +}; +#elif defined(SECOND) +struct S11 { + S11(); +}; +#else +S11 s11; +// expected-error@first.h:* {{'MethodBody::S11' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is defaulted}} +// expected-note@second.h:* {{but in 'SecondModule' found constructor is not defaulted}} +#endif + +#define DECLS(CLASSNAME) \ + CLASSNAME() = default; \ + ~CLASSNAME() = delete; \ + void A(); \ + void B() { return; }; \ + void C(); \ + void D(); + +#define OUTOFLINEDEFS(CLASSNAME) \ + void CLASSNAME::C() {} \ + void CLASSNAME::D() { return; } + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS(Valid1) +}; +OUTOFLINEDEFS(Valid1) +#else +Valid1* v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS(Invalid1) + ACCESS +}; +OUTOFLINEDEFS(Invalid1) +#else +Invalid1* i1; +// expected-error@first.h:* {{'MethodBody::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found public access specifier}} +// expected-note@second.h:* {{but in 'SecondModule' found private access specifier}} +#endif +#undef DECLS +} // namespace MethodBody + namespace Constructor { #if defined(FIRST) struct S1 { @@ -3631,6 +3827,32 @@ template void S11::foo() {} S11 s11; #endif +#if defined(FIRST) +struct S12 { + void foo(int x); +}; +#elif defined(SECOND) +struct S12 { + void foo(int x); +}; +void S12::foo(int y) {} +#else +S12 s12; +#endif + +#if defined(FIRST) +struct S13 { + void foo(int x); +}; +void S13::foo(int y) {} +#elif defined(SECOND) +struct S13 { + void foo(int x); +}; +void S13::foo(int y) {} +#else +S13 s13; +#endif } // namespace FunctionDecl namespace DeclTemplateArguments { -- GitLab From c5845b4c8c168b6a9c41029b51573b6e7019c9fe Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Tue, 10 Jul 2018 02:15:07 +0000 Subject: [PATCH 0470/1023] [Sema] Fix a structured binding typo correction bug BindingDecls have null type until their initializer is processed, so we can't assume that a correction candidate has non-null type. rdar://41559582 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336634 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaLookup.cpp | 2 ++ test/SemaCXX/typo-correction-cxx17.cpp | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 test/SemaCXX/typo-correction-cxx17.cpp diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 984247bacc..4545bf9d85 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -4990,6 +4990,8 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { // determine if it is a pointer or reference to a function. If so, // check against the number of arguments expected for the pointee. QualType ValType = cast(ND)->getType(); + if (ValType.isNull()) + continue; if (ValType->isAnyPointerType() || ValType->isReferenceType()) ValType = ValType->getPointeeType(); if (const FunctionProtoType *FPT = ValType->getAs()) diff --git a/test/SemaCXX/typo-correction-cxx17.cpp b/test/SemaCXX/typo-correction-cxx17.cpp new file mode 100644 index 0000000000..f137499753 --- /dev/null +++ b/test/SemaCXX/typo-correction-cxx17.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s + +namespace decomp_decl { +void f() { + auto [this_is_a_typo] = this_is_a_typp(); // expected-error{{use of undeclared identifier 'this_is_a_typp'}} +} +} -- GitLab From 3d47eea1c6cffcd7a7307e31876c172a5c04bd0c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 10 Jul 2018 04:38:29 +0000 Subject: [PATCH 0471/1023] [X86] Use masked the masked scalar fma builtins to implement the default rounding version of the fma intrinsics. The rounding mode is checked in CGBuiltin.cpp to generate the correct intrinsic call. Making this switch switchs the masking to use the i8 bitcast to <8 x i1> and extract i1 version of the IR for the mask. Previously we ended up with a scalar 'and' plus an icmp. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336637 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512fintrin.h | 240 ++++++------ test/CodeGen/avx512f-builtins.c | 668 +++++++++++--------------------- 2 files changed, 340 insertions(+), 568 deletions(-) diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index f69620bbca..81696953b7 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -7770,11 +7770,11 @@ _mm512_maskz_getexp_ps (__mmask16 __U, __m512 __A) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - (__v4sf) __A, - (__v4sf) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddss3_mask((__v4sf)__W, + (__v4sf)__A, + (__v4sf)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fmadd_round_ss(A, B, C, R) \ @@ -7792,11 +7792,11 @@ _mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, - (__v4sf) __B, - (__v4sf) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A, + (__v4sf)__B, + (__v4sf)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fmadd_round_ss(U, A, B, C, R) \ @@ -7808,11 +7808,11 @@ _mm_maskz_fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - (__v4sf) __X, - (__v4sf) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmaddss3_mask3((__v4sf)__W, + (__v4sf)__X, + (__v4sf)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fmadd_round_ss(W, X, Y, U, R) \ @@ -7824,11 +7824,11 @@ _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - (__v4sf) __A, - -(__v4sf) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddss3_mask((__v4sf)__W, + (__v4sf)__A, + -(__v4sf)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fmsub_round_ss(A, B, C, R) \ @@ -7846,11 +7846,11 @@ _mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, - (__v4sf) __B, - -(__v4sf) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A, + (__v4sf)__B, + -(__v4sf)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fmsub_round_ss(U, A, B, C, R) \ @@ -7862,11 +7862,11 @@ _mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - (__v4sf) __X, - -(__v4sf) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmsubss3_mask3((__v4sf)__W, + (__v4sf)__X, + (__v4sf)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fmsub_round_ss(W, X, Y, U, R) \ @@ -7878,11 +7878,11 @@ _mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - -(__v4sf) __A, - (__v4sf) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddss3_mask((__v4sf)__W, + -(__v4sf)__A, + (__v4sf)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fnmadd_round_ss(A, B, C, R) \ @@ -7900,11 +7900,11 @@ _mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, - -(__v4sf) __B, - (__v4sf) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A, + -(__v4sf)__B, + (__v4sf)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fnmadd_round_ss(U, A, B, C, R) \ @@ -7916,11 +7916,11 @@ _mm_maskz_fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - -(__v4sf) __X, - (__v4sf) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmaddss3_mask3((__v4sf)__W, + -(__v4sf)__X, + (__v4sf)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fnmadd_round_ss(W, X, Y, U, R) \ @@ -7932,11 +7932,11 @@ _mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - -(__v4sf) __A, - -(__v4sf) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddss3_mask((__v4sf)__W, + -(__v4sf)__A, + -(__v4sf)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fnmsub_round_ss(A, B, C, R) \ @@ -7954,11 +7954,11 @@ _mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __A, - -(__v4sf) __B, - -(__v4sf) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddss3_maskz((__v4sf)__A, + -(__v4sf)__B, + -(__v4sf)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fnmsub_round_ss(U, A, B, C, R) \ @@ -7970,11 +7970,11 @@ _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C) static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) { - __m128 __Z = __builtin_ia32_vfmaddss3((__v4sf) __W, - -(__v4sf) __X, - -(__v4sf) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmsubss3_mask3((__v4sf)__W, + -(__v4sf)__X, + (__v4sf)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fnmsub_round_ss(W, X, Y, U, R) \ @@ -7986,11 +7986,11 @@ _mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - (__v2df) __A, - (__v2df) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddsd3_mask((__v2df)__W, + (__v2df)__A, + (__v2df)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fmadd_round_sd(A, B, C, R) \ @@ -8008,11 +8008,11 @@ _mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, - (__v2df) __B, - (__v2df) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A, + (__v2df)__B, + (__v2df)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fmadd_round_sd(U, A, B, C, R) \ @@ -8024,11 +8024,11 @@ _mm_maskz_fmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - (__v2df) __X, - (__v2df) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmaddsd3_mask3((__v2df)__W, + (__v2df)__X, + (__v2df)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fmadd_round_sd(W, X, Y, U, R) \ @@ -8040,11 +8040,11 @@ _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - (__v2df) __A, - -(__v2df) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddsd3_mask((__v2df)__W, + (__v2df)__A, + -(__v2df)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fmsub_round_sd(A, B, C, R) \ @@ -8062,11 +8062,11 @@ _mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, - (__v2df) __B, - -(__v2df) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A, + (__v2df)__B, + -(__v2df)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fmsub_round_sd(U, A, B, C, R) \ @@ -8078,11 +8078,11 @@ _mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - (__v2df) __X, - -(__v2df) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmsubsd3_mask3((__v2df)__W, + (__v2df)__X, + (__v2df)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fmsub_round_sd(W, X, Y, U, R) \ @@ -8094,11 +8094,11 @@ _mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - -(__v2df) __A, - (__v2df) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddsd3_mask((__v2df)__W, + -(__v2df)__A, + (__v2df)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fnmadd_round_sd(A, B, C, R) \ @@ -8116,11 +8116,11 @@ _mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, - -(__v2df) __B, - (__v2df) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A, + -(__v2df)__B, + (__v2df)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fnmadd_round_sd(U, A, B, C, R) \ @@ -8132,11 +8132,11 @@ _mm_maskz_fnmadd_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - -(__v2df) __X, - (__v2df) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmaddsd3_mask3((__v2df)__W, + -(__v2df)__X, + (__v2df)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fnmadd_round_sd(W, X, Y, U, R) \ @@ -8148,11 +8148,11 @@ _mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - -(__v2df) __A, - -(__v2df) __B); - __W[0] = (__U & 1) ? __Z[0] : __W[0]; - return __W; + return __builtin_ia32_vfmaddsd3_mask((__v2df)__W, + -(__v2df)__A, + -(__v2df)__B, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_fnmsub_round_sd(A, B, C, R) \ @@ -8170,11 +8170,11 @@ _mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __A, - -(__v2df) __B, - -(__v2df) __C); - __A[0] = (__U & 1) ? __Z[0] : 0; - return __A; + return __builtin_ia32_vfmaddsd3_maskz((__v2df)__A, + -(__v2df)__B, + -(__v2df)__C, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_maskz_fnmsub_round_sd(U, A, B, C, R) \ @@ -8187,11 +8187,11 @@ _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C) static __inline__ __m128d __DEFAULT_FN_ATTRS128 _mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U) { - __m128d __Z = __builtin_ia32_vfmaddsd3((__v2df) __W, - -(__v2df) __X, - -(__v2df) __Y); - __Y[0] = (__U & 1) ? __Z[0] : __Y[0]; - return __Y; + return __builtin_ia32_vfmsubsd3_mask3((__v2df)__W, + -(__v2df)__X, + (__v2df)__Y, + (__mmask8)__U, + _MM_FROUND_CUR_DIRECTION); } #define _mm_mask3_fnmsub_round_sd(W, X, Y, U, R) \ diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 2beae24e45..b13e6bbbbf 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -7235,24 +7235,14 @@ __m128 test_mm_maskz_getmant_round_ss(__mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_mask_fmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmadd_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fmadd_ss(__W, __U, __A, __B); } @@ -7281,23 +7271,14 @@ __m128 test_mm_mask_fmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __m128 test_mm_maskz_fmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fmadd_ss(__U, __A, __B, __C); } @@ -7316,24 +7297,14 @@ __m128 test_mm_maskz_fmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __m128 test_mm_mask3_fmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fmadd_ss(__W, __X, __Y, __U); } @@ -7352,25 +7323,15 @@ __m128 test_mm_mask3_fmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __m128 test_mm_mask_fmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fmsub_ss(__W, __U, __A, __B); } @@ -7401,24 +7362,15 @@ __m128 test_mm_mask_fmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __m128 test_mm_maskz_fmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fmsub_ss(__U, __A, __B, __C); } @@ -7438,25 +7390,16 @@ __m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __m128 test_mm_mask3_fmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fmsub_ss(__W, __X, __Y, __U); } @@ -7477,25 +7420,15 @@ __m128 test_mm_mask3_fmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __m128 test_mm_mask_fnmadd_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fnmadd_ss(__W, __U, __A, __B); } @@ -7526,24 +7459,15 @@ __m128 test_mm_mask_fnmadd_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __m128 test_mm_maskz_fnmadd_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fnmadd_ss(__U, __A, __B, __C); } @@ -7563,25 +7487,15 @@ __m128 test_mm_maskz_fnmadd_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m12 __m128 test_mm_mask3_fnmadd_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fnmadd_ss(__W, __X, __Y, __U); } @@ -7601,26 +7515,16 @@ __m128 test_mm_mask3_fnmadd_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask __m128 test_mm_mask_fnmsub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[A]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_mask_fnmsub_ss(__W, __U, __A, __B); } @@ -7653,25 +7557,16 @@ __m128 test_mm_mask_fnmsub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __m128 test_mm_maskz_fnmsub_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128 __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <4 x float> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float 0.000000e+00 + // CHECK-NEXT: insertelement <4 x float> [[ORIGA]], float [[SEL]], i64 0 return _mm_maskz_fnmsub_ss(__U, __A, __B, __C); } @@ -7692,26 +7587,17 @@ __m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m12 __m128 test_mm_mask3_fnmsub_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_ss - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: fsub <4 x float> , %{{.*}} - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK: call float @llvm.fma.f32(float %{{.*}}, float %{{.*}}, float %{{.*}}) - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <4 x float> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi float - // CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <4 x float> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <4 x float> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <4 x float> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <4 x float> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <4 x float> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call float @llvm.fma.f32(float [[A]], float [[B]], float [[C]]) + // CHECK-NEXT: [[C2:%.+]] = extractelement <4 x float> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, float [[FMA]], float [[C2]] + // CHECK-NEXT: insertelement <4 x float> [[ORIGC]], float [[SEL]], i64 0 return _mm_mask3_fnmsub_ss(__W, __X, __Y, __U); } @@ -7733,24 +7619,14 @@ __m128 test_mm_mask3_fnmsub_round_ss(__m128 __W, __m128 __X, __m128 __Y, __mmask __m128d test_mm_mask_fmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmadd_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fmadd_sd(__W, __U, __A, __B); } @@ -7779,23 +7655,14 @@ __m128d test_mm_mask_fmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m1 __m128d test_mm_maskz_fmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmadd_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fmadd_sd(__U, __A, __B, __C); } @@ -7814,24 +7681,14 @@ __m128d test_mm_maskz_fmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m __m128d test_mm_mask3_fmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmadd_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fmadd_sd(__W, __X, __Y, __U); } @@ -7850,25 +7707,15 @@ __m128d test_mm_mask3_fmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mm __m128d test_mm_mask_fmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fmsub_sd(__W, __U, __A, __B); } @@ -7899,24 +7746,15 @@ __m128d test_mm_mask_fmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m1 __m128d test_mm_maskz_fmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fmsub_sd(__U, __A, __B, __C); } @@ -7936,25 +7774,16 @@ __m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m __m128d test_mm_mask3_fmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fmsub_sd(__W, __X, __Y, __U); } @@ -7975,25 +7804,15 @@ __m128d test_mm_mask3_fmsub_round_sd(__m128d __W, __m128d __X, __m128d __Y, __mm __m128d test_mm_mask_fnmadd_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmadd_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fnmadd_sd(__W, __U, __A, __B); } @@ -8024,24 +7843,15 @@ __m128d test_mm_mask_fnmadd_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m __m128d test_mm_maskz_fnmadd_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmadd_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.+]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fnmadd_sd(__U, __A, __B, __C); } @@ -8061,25 +7871,15 @@ __m128d test_mm_maskz_fnmadd_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __ __m128d test_mm_mask3_fnmadd_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmadd_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[ORIGC:%.+]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fnmadd_sd(__W, __X, __Y, __U); } @@ -8099,26 +7899,16 @@ __m128d test_mm_mask3_fnmadd_round_sd(__m128d __W, __m128d __X, __m128d __Y, __m __m128d test_mm_mask_fnmsub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_fnmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[A]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_mask_fnmsub_sd(__W, __U, __A, __B); } @@ -8151,25 +7941,16 @@ __m128d test_mm_mask_fnmsub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m __m128d test_mm_maskz_fnmsub_sd(__mmask8 __U, __m128d __A, __m128d __B, __m128d __C){ // CHECK-LABEL: @test_mm_maskz_fnmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[A:%.+]] = extractelement <2 x double> [[ORIGA:%.]], i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double 0.000000e+00 + // CHECK-NEXT: insertelement <2 x double> [[ORIGA]], double [[SEL]], i64 0 return _mm_maskz_fnmsub_sd(__U, __A, __B, __C); } @@ -8190,26 +7971,17 @@ __m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __ __m128d test_mm_mask3_fnmsub_sd(__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U){ // CHECK-LABEL: @test_mm_mask3_fnmsub_sd - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: fsub <2 x double> , %{{.*}} - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK: call double @llvm.fma.f64(double %{{.*}}, double %{{.*}}, double %{{.*}}) - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 - // CHECK: zext i8 %{{.*}} to i32 - // CHECK: and i32 %{{.*}}, 1 - // CHECK: icmp ne i32 %{{.*}}, 0 - // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: extractelement <2 x double> %{{.*}}, i32 0 - // CHECK: br label %{{.*}} - - // CHECK: phi double - // CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0 + // CHECK: [[NEG:%.+]] = fsub <2 x double> , %{{.*}} + // CHECK: [[NEG2:%.+]] = fsub <2 x double> , [[ORIGC:%.+]] + // CHECK: [[A:%.+]] = extractelement <2 x double> %{{.*}}, i64 0 + // CHECK-NEXT: [[B:%.+]] = extractelement <2 x double> [[NEG]], i64 0 + // CHECK-NEXT: [[C:%.+]] = extractelement <2 x double> [[NEG2]], i64 0 + // CHECK-NEXT: [[FMA:%.+]] = call double @llvm.fma.f64(double [[A]], double [[B]], double [[C]]) + // CHECK-NEXT: [[C2:%.+]] = extractelement <2 x double> [[ORIGC]], i64 0 + // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> + // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 + // CHECK-NEXT: [[SEL:%.+]] = select i1 %{{.*}}, double [[FMA]], double [[C2]] + // CHECK-NEXT: insertelement <2 x double> [[ORIGC]], double [[SEL]], i64 0 return _mm_mask3_fnmsub_sd(__W, __X, __Y, __U); } -- GitLab From 5734eced0745f4cf3d04c6b07d5d048d8a785537 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 10 Jul 2018 06:55:12 +0000 Subject: [PATCH 0472/1023] Test commit Add redundant doc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336640 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 1c4cd9b3a6..8206a26b2c 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -619,6 +619,7 @@ public: return SubExpr->getLocEnd(); } + /// Retrieve the source range of the expression. SourceRange getSourceRange() const LLVM_READONLY { return SubExpr->getSourceRange(); } -- GitLab From b4d2cac846d91bba7f952a0ce7651425fb56d585 Mon Sep 17 00:00:00 2001 From: Mikhail Dvoretckii Date: Tue, 10 Jul 2018 08:22:44 +0000 Subject: [PATCH 0473/1023] [X86] Lowering integer truncation intrinsics to native IR This patch lowers the _mm[256|512]_cvtepi{64|32|16}_epi{32|16|8} intrinsics to native IR in cases where the result's length is less than 128 bits. The resulting IR for 256-bit inputs is folded into VPMOV instructions, while for 128-bit inputs the vpshufb (or, in the 64-to-32-bit case, vinsertps) instructions are generated instead Differential Revision: https://reviews.llvm.org/D48712 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336643 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/avx512vlbwintrin.h | 8 ++--- lib/Headers/avx512vlintrin.h | 52 ++++++++++++++++-------------- test/CodeGen/avx512vl-builtins.c | 24 +++++++++----- test/CodeGen/avx512vlbw-builtins.c | 3 +- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h index 72e07d0541..1b038dd04d 100644 --- a/lib/Headers/avx512vlbwintrin.h +++ b/lib/Headers/avx512vlbwintrin.h @@ -1496,10 +1496,10 @@ _mm256_maskz_cvtusepi16_epi8 (__mmask16 __M, __m256i __A) { static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi16_epi8 (__m128i __A) { - - return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A, - (__v16qi) _mm_setzero_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v8hi)__A, __v8qi), + (__v8qi){0, 0, 0, 0, 0, 0, 0, 0}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h index de898845ce..0ee1d00ef4 100644 --- a/lib/Headers/avx512vlintrin.h +++ b/lib/Headers/avx512vlintrin.h @@ -31,6 +31,10 @@ #define __DEFAULT_FN_ATTRS128 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(128))) #define __DEFAULT_FN_ATTRS256 __attribute__((__always_inline__, __nodebug__, __target__("avx512vl"), __min_vector_width__(256))) +typedef short __v2hi __attribute__((__vector_size__(4))); +typedef char __v4qi __attribute__((__vector_size__(4))); +typedef char __v2qi __attribute__((__vector_size__(2))); + /* Integer compare */ #define _mm_cmpeq_epi32_mask(A, B) \ @@ -7341,9 +7345,9 @@ _mm256_mask_cvtusepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi32_epi8 (__m128i __A) { - return (__m128i) __builtin_ia32_pmovdb128_mask ((__v4si) __A, - (__v16qi)_mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v4si)__A, __v4qi), (__v4qi){0, 0, 0, 0}, 0, 1, + 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 @@ -7371,9 +7375,10 @@ _mm_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi32_epi8 (__m256i __A) { - return (__m128i) __builtin_ia32_pmovdb256_mask ((__v8si) __A, - (__v16qi)_mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v8si)__A, __v8qi), + (__v8qi){0, 0, 0, 0, 0, 0, 0, 0}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15); } static __inline__ __m128i __DEFAULT_FN_ATTRS256 @@ -7400,9 +7405,9 @@ _mm256_mask_cvtepi32_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi32_epi16 (__m128i __A) { - return (__m128i) __builtin_ia32_pmovdw128_mask ((__v4si) __A, - (__v8hi) _mm_setzero_si128 (), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v4si)__A, __v4hi), (__v4hi){0, 0, 0, 0}, 0, 1, + 2, 3, 4, 5, 6, 7); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 @@ -7456,9 +7461,9 @@ _mm256_mask_cvtepi32_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi8 (__m128i __A) { - return (__m128i) __builtin_ia32_pmovqb128_mask ((__v2di) __A, - (__v16qi) _mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v2di)__A, __v2qi), (__v2qi){0, 0}, 0, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 @@ -7485,9 +7490,9 @@ _mm_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m128i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_epi8 (__m256i __A) { - return (__m128i) __builtin_ia32_pmovqb256_mask ((__v4di) __A, - (__v16qi) _mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v4di)__A, __v4qi), (__v4qi){0, 0, 0, 0}, 0, 1, + 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); } static __inline__ __m128i __DEFAULT_FN_ATTRS256 @@ -7514,9 +7519,8 @@ _mm256_mask_cvtepi64_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi32 (__m128i __A) { - return (__m128i) __builtin_ia32_pmovqd128_mask ((__v2di) __A, - (__v4si)_mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v2di)__A, __v2si), (__v2si){0, 0}, 0, 1, 2, 3); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 @@ -7571,9 +7575,9 @@ _mm256_mask_cvtepi64_storeu_epi32 (void * __P, __mmask8 __M, __m256i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS128 _mm_cvtepi64_epi16 (__m128i __A) { - return (__m128i) __builtin_ia32_pmovqw128_mask ((__v2di) __A, - (__v8hi) _mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v2di)__A, __v2hi), (__v2hi){0, 0}, 0, 1, 2, 3, + 3, 3, 3, 3); } static __inline__ __m128i __DEFAULT_FN_ATTRS128 @@ -7601,9 +7605,9 @@ _mm_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m128i __A) static __inline__ __m128i __DEFAULT_FN_ATTRS256 _mm256_cvtepi64_epi16 (__m256i __A) { - return (__m128i) __builtin_ia32_pmovqw256_mask ((__v4di) __A, - (__v8hi)_mm_undefined_si128(), - (__mmask8) -1); + return (__m128i)__builtin_shufflevector( + __builtin_convertvector((__v4di)__A, __v4hi), (__v4hi){0, 0, 0, 0}, 0, 1, + 2, 3, 4, 5, 6, 7); } static __inline__ __m128i __DEFAULT_FN_ATTRS256 diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c index 540ea223d9..7e4e64381c 100644 --- a/test/CodeGen/avx512vl-builtins.c +++ b/test/CodeGen/avx512vl-builtins.c @@ -8503,7 +8503,8 @@ void test_mm256_mask_cvtusepi64_storeu_epi16(void * __P, __mmask8 __M, __m256i _ __m128i test_mm_cvtepi32_epi8(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi32_epi8 - // CHECK: @llvm.x86.avx512.mask.pmov.db.128 + // CHECK: trunc <4 x i32> %{{.*}} to <4 x i8> + // CHECK: shufflevector <4 x i8> %{{.*}}, <4 x i8> %{{.*}}, <16 x i32> return _mm_cvtepi32_epi8(__A); } @@ -8527,7 +8528,8 @@ void test_mm_mask_cvtepi32_storeu_epi8(void * __P, __mmask8 __M, __m128i __A) { __m128i test_mm256_cvtepi32_epi8(__m256i __A) { // CHECK-LABEL: @test_mm256_cvtepi32_epi8 - // CHECK: @llvm.x86.avx512.mask.pmov.db.256 + // CHECK: trunc <8 x i32> %{{.*}} to <8 x i8> + // CHECK: shufflevector <8 x i8> %{{.*}}, <8 x i8> %{{.*}}, <16 x i32> return _mm256_cvtepi32_epi8(__A); } @@ -8551,7 +8553,8 @@ void test_mm256_mask_cvtepi32_storeu_epi8(void * __P, __mmask8 __M, __m256i __A) __m128i test_mm_cvtepi32_epi16(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi32_epi16 - // CHECK: @llvm.x86.avx512.mask.pmov.dw.128 + // CHECK: trunc <4 x i32> %{{.*}} to <4 x i16> + // CHECK: shufflevector <4 x i16> %{{.*}}, <4 x i16> %{{.*}}, <8 x i32> return _mm_cvtepi32_epi16(__A); } @@ -8599,7 +8602,8 @@ void test_mm256_mask_cvtepi32_storeu_epi16(void * __P, __mmask8 __M, __m256i __ __m128i test_mm_cvtepi64_epi8(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi64_epi8 - // CHECK: @llvm.x86.avx512.mask.pmov.qb.128 + // CHECK: trunc <2 x i64> %{{.*}} to <2 x i8> + // CHECK: shufflevector <2 x i8> %{{.*}}, <2 x i8> %{{.*}}, <16 x i32> return _mm_cvtepi64_epi8(__A); } @@ -8623,7 +8627,8 @@ void test_mm_mask_cvtepi64_storeu_epi8(void * __P, __mmask8 __M, __m128i __A) { __m128i test_mm256_cvtepi64_epi8(__m256i __A) { // CHECK-LABEL: @test_mm256_cvtepi64_epi8 - // CHECK: @llvm.x86.avx512.mask.pmov.qb.256 + // CHECK: trunc <4 x i64> %{{.*}} to <4 x i8> + // CHECK: shufflevector <4 x i8> %{{.*}}, <4 x i8> %{{.*}}, <16 x i32> return _mm256_cvtepi64_epi8(__A); } @@ -8647,7 +8652,8 @@ void test_mm256_mask_cvtepi64_storeu_epi8(void * __P, __mmask8 __M, __m256i __A) __m128i test_mm_cvtepi64_epi32(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi64_epi32 - // CHECK: @llvm.x86.avx512.mask.pmov.qd.128 + // CHECK: trunc <2 x i64> %{{.*}} to <2 x i32> + // CHECK: shufflevector <2 x i32> %{{.*}}, <2 x i32> %{{.*}}, <4 x i32> return _mm_cvtepi64_epi32(__A); } @@ -8697,7 +8703,8 @@ void test_mm256_mask_cvtepi64_storeu_epi32(void * __P, __mmask8 __M, __m256i __A __m128i test_mm_cvtepi64_epi16(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi64_epi16 - // CHECK: @llvm.x86.avx512.mask.pmov.qw.128 + // CHECK: trunc <2 x i64> %{{.*}} to <2 x i16> + // CHECK: shufflevector <2 x i16> %{{.*}}, <2 x i16> %{{.*}}, <8 x i32> return _mm_cvtepi64_epi16(__A); } @@ -8721,7 +8728,8 @@ void test_mm_mask_cvtepi64_storeu_epi16(void * __P, __mmask8 __M, __m128i __A) { __m128i test_mm256_cvtepi64_epi16(__m256i __A) { // CHECK-LABEL: @test_mm256_cvtepi64_epi16 - // CHECK: @llvm.x86.avx512.mask.pmov.qw.256 + // CHECK: trunc <4 x i64> %{{.*}} to <4 x i16> + // CHECK: shufflevector <4 x i16> %{{.*}}, <4 x i16> %{{.*}}, <8 x i32> return _mm256_cvtepi64_epi16(__A); } diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c index 607b011794..c28c3fbd7f 100644 --- a/test/CodeGen/avx512vlbw-builtins.c +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -1792,7 +1792,8 @@ __m128i test_mm256_maskz_cvtusepi16_epi8(__mmask16 __M, __m256i __A) { __m128i test_mm_cvtepi16_epi8(__m128i __A) { // CHECK-LABEL: @test_mm_cvtepi16_epi8 - // CHECK: @llvm.x86.avx512.mask.pmov.wb.128 + // CHECK: trunc <8 x i16> %{{.*}} to <8 x i8> + // CHECK: shufflevector <8 x i8> %{{.*}}, <8 x i8> %{{.*}}, <16 x i32> return _mm_cvtepi16_epi8(__A); } -- GitLab From fca87f4a0ad4852acbe825704d9bf874bfa628ff Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Tue, 10 Jul 2018 10:46:45 +0000 Subject: [PATCH 0474/1023] [MinGW] Treat any -lucrt* as replacing -lmsvcrt Since SVN r314138, we check if the user has specified any particular alternative msvcrt/ucrt version, and skip the default -lmsvcrt in those cases. In addition to the existing names checked, we should also treat a plain -lucrt in the same way, mingw-w64 has now added a separate import library named libucrt.a, in addition to libucrtbase.a. Differential Revision: https://reviews.llvm.org/D49054 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336654 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/MinGW.cpp | 2 +- test/Driver/mingw-msvcrt.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp index 206f52e82d..da71a84b76 100644 --- a/lib/Driver/ToolChains/MinGW.cpp +++ b/lib/Driver/ToolChains/MinGW.cpp @@ -83,7 +83,7 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmingwex"); for (auto Lib : Args.getAllArgValues(options::OPT_l)) - if (StringRef(Lib).startswith("msvcr") || Lib == "ucrtbase") + if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt")) return; CmdArgs.push_back("-lmsvcrt"); } diff --git a/test/Driver/mingw-msvcrt.c b/test/Driver/mingw-msvcrt.c index f83a8c261c..89a8d2a94c 100644 --- a/test/Driver/mingw-msvcrt.c +++ b/test/Driver/mingw-msvcrt.c @@ -1,6 +1,12 @@ // RUN: %clang -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DEFAULT %s // RUN: %clang -v -target i686-pc-windows-gnu -lmsvcr120 -### %s 2>&1 | FileCheck -check-prefix=CHECK_MSVCR120 %s +// RUN: %clang -v -target i686-pc-windows-gnu -lucrtbase -### %s 2>&1 | FileCheck -check-prefix=CHECK_UCRTBASE %s +// RUN: %clang -v -target i686-pc-windows-gnu -lucrt -### %s 2>&1 | FileCheck -check-prefix=CHECK_UCRT %s // CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32" // CHECK_MSVCR120: "-lmsvcr120" // CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRTBASE: "-lucrtbase" +// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRT: "-lucrt" +// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32" -- GitLab From c3b3b46612df8dd7c293a331c804ad58ead65765 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Tue, 10 Jul 2018 10:46:51 +0000 Subject: [PATCH 0475/1023] [MinGW] Skip adding default win32 api libraries if -lwindowsapp is specified In this setup, skip adding all the default windows import libraries, if linking to windowsapp (which replaces them, when targeting the windows store/UWP api subset). With GCC, the same is achieved by using a custom spec file, but since clang doesn't use spec files, we have to allow other means of overriding what default libraries to use (without going all the way to using -nostdlib, which would exclude everything). The same approach, in detecting certain user specified libraries and omitting others from the defaults, was already used in SVN r314138. Differential Revision: https://reviews.llvm.org/D49059 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336655 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/MinGW.cpp | 28 ++++++++++++++++++++-------- test/Driver/mingw-windowsapp.c | 6 ++++++ 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 test/Driver/mingw-windowsapp.c diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp index da71a84b76..a88e00f0c8 100644 --- a/lib/Driver/ToolChains/MinGW.cpp +++ b/lib/Driver/ToolChains/MinGW.cpp @@ -201,6 +201,14 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Bdynamic"); } + bool HasWindowsApp = false; + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { + if (Lib == "windowsapp") { + HasWindowsApp = true; + break; + } + } + if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) @@ -223,15 +231,19 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); - // add system libraries - if (Args.hasArg(options::OPT_mwindows)) { - CmdArgs.push_back("-lgdi32"); - CmdArgs.push_back("-lcomdlg32"); + if (!HasWindowsApp) { + // Add system libraries. If linking to libwindowsapp.a, that import + // library replaces all these and we shouldn't accidentally try to + // link to the normal desktop mode dlls. + if (Args.hasArg(options::OPT_mwindows)) { + CmdArgs.push_back("-lgdi32"); + CmdArgs.push_back("-lcomdlg32"); + } + CmdArgs.push_back("-ladvapi32"); + CmdArgs.push_back("-lshell32"); + CmdArgs.push_back("-luser32"); + CmdArgs.push_back("-lkernel32"); } - CmdArgs.push_back("-ladvapi32"); - CmdArgs.push_back("-lshell32"); - CmdArgs.push_back("-luser32"); - CmdArgs.push_back("-lkernel32"); if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); diff --git a/test/Driver/mingw-windowsapp.c b/test/Driver/mingw-windowsapp.c new file mode 100644 index 0000000000..bf6f2ec3fa --- /dev/null +++ b/test/Driver/mingw-windowsapp.c @@ -0,0 +1,6 @@ +// RUN: %clang -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DEFAULT %s +// RUN: %clang -v -target i686-pc-windows-gnu -### %s -lwindowsapp 2>&1 | FileCheck -check-prefix=CHECK_WINDOWSAPP %s + +// CHECK_DEFAULT: "-lmsvcrt" "-ladvapi32" "-lshell32" "-luser32" "-lkernel32" "-lmingw32" +// CHECK_WINDOWSAPP: "-lwindowsapp" "-lmingw32" +// CHECK_WINDOWSAPP-SAME: "-lmsvcrt" "-lmingw32" -- GitLab From 6d65cdc2f9f94c17c9118e5a77f340323013ffbe Mon Sep 17 00:00:00 2001 From: Omer Paparo Bivas Date: Tue, 10 Jul 2018 12:04:04 +0000 Subject: [PATCH 0476/1023] Fixing builtin __atomic_fetch_min declaration Differential Revision: http://reviews.llvm.org/D49068 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336658 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index e549582cd5..39105a9b37 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -723,7 +723,7 @@ ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t") // GCC does not support these, they are a Clang extension. -ATOMIC_BUILTIN(__atomic_fetch_min, "iiD*i.", "t") +ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t") #undef ATOMIC_BUILTIN -- GitLab From f40124d4f05ecf4f880cf4e8f26922d861f705f3 Mon Sep 17 00:00:00 2001 From: Yuka Takahashi Date: Tue, 10 Jul 2018 12:17:34 +0000 Subject: [PATCH 0477/1023] [modules] Fix 37878; Autoload subdirectory modulemaps with specific LangOpts Summary: Reproducer and errors: https://bugs.llvm.org/show_bug.cgi?id=37878 lookupModule was falling back to loadSubdirectoryModuleMaps when it couldn't find ModuleName in (proper) search paths. This was causing iteration over all files in the search path subdirectories for example "/usr/include/foobar" in bugzilla case. Users don't expect Clang to load modulemaps in subdirectories implicitly, and also the disk access is not cheap. if (AllowExtraModuleMapSearch) true with ObjC with @import ModuleName. Reviewers: rsmith, aprantl, bruno Subscribers: cfe-commits, teemperor, v.g.vassilev Differential Revision: https://reviews.llvm.org/D48367 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336660 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/HeaderSearch.h | 12 ++++++++++-- lib/Frontend/CompilerInstance.cpp | 15 ++++++++++----- lib/Lex/HeaderSearch.cpp | 17 ++++++++++------- lib/Serialization/ASTReader.cpp | 4 +++- test/Modules/Inputs/autoload-subdirectory/a.h | 9 +++++++++ test/Modules/Inputs/autoload-subdirectory/b.h | 1 + test/Modules/Inputs/autoload-subdirectory/c.h | 7 +++++++ .../include/module.modulemap | 3 +++ .../autoload-subdirectory/module.modulemap | 3 +++ test/Modules/autoload-subdirectory.cpp | 10 ++++++++++ 10 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 test/Modules/Inputs/autoload-subdirectory/a.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/b.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/c.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/include/module.modulemap create mode 100644 test/Modules/Inputs/autoload-subdirectory/module.modulemap create mode 100644 test/Modules/autoload-subdirectory.cpp diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index fd52000954..b7147c54fa 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -529,8 +529,12 @@ public: /// search directories to produce a module definition. If not, this lookup /// will only return an already-known module. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module with the given name. - Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true, + bool AllowExtraModuleMapSearch = false); /// Try to find a module map file in the given directory, returning /// \c nullptr if none is found. @@ -595,8 +599,12 @@ private: /// but for compatibility with some buggy frameworks, additional attempts /// may be made to find the module under a related-but-different search-name. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module named ModuleName. - Module *lookupModule(StringRef ModuleName, StringRef SearchName); + Module *lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch = false); /// Retrieve a module with the given name, which may be part of the /// given framework. diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 5727aae5f1..155ead4ac8 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1653,8 +1653,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Retrieve the cached top-level module. Module = Known->second; } else if (ModuleName == getLangOpts().CurrentModule) { - // This is the module we're building. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + // This is the module we're building. + Module = PP->getHeaderSearchInfo().lookupModule( + ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); /// FIXME: perhaps we should (a) look for a module using the module name // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? //if (Module == nullptr) { @@ -1666,7 +1668,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); HeaderSearchOptions &HSOpts = PP->getHeaderSearchInfo().getHeaderSearchOpts(); @@ -1743,7 +1746,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ImportLoc, ARRFlags)) { case ASTReader::Success: { if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { // Error out if Module does not refer to the file in the prebuilt @@ -1874,7 +1878,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); PrivPath.push_back(std::make_pair(&II, Path[0].second)); - if (PP->getHeaderSearchInfo().lookupModule(PrivateModule)) + if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true, + !IsInclusionDirective)) Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); if (Sub) { diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 312bd2d061..b1a2ef1212 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -198,14 +198,15 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, return Result.str().str(); } -Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, + bool AllowExtraModuleMapSearch) { // Look in the module map to determine if there is a module by this name. Module *Module = ModMap.findModule(ModuleName); if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) return Module; StringRef SearchName = ModuleName; - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); // The facility for "private modules" -- adjacent, optional module maps named // module.private.modulemap that are supposed to define private submodules -- @@ -216,13 +217,14 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { // could force building unwanted dependencies into the parent module and cause // dependency cycles. if (!Module && SearchName.consume_back("_Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); if (!Module && SearchName.consume_back("Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); return Module; } -Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch) { Module *Module = nullptr; // Look through the various header search paths to load any available module @@ -281,8 +283,9 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { continue; // Load all module maps in the immediate subdirectories of this search - // directory. - loadSubdirectoryModuleMaps(SearchDirs[Idx]); + // directory if ModuleName was from @import. + if (AllowExtraModuleMapSearch) + loadSubdirectoryModuleMaps(SearchDirs[Idx]); // Look again for the module. Module = ModMap.findModule(ModuleName); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 3277243667..78ca5f7406 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2626,7 +2626,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, "MODULE_DIRECTORY found before MODULE_NAME"); // If we've already loaded a module map file covering this module, we may // have a better path for it (relative to the current build). - Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + Module *M = PP.getHeaderSearchInfo().lookupModule( + F.ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ true); if (M && M->Directory) { // If we're implicitly loading a module, the base directory can't // change between the build and use. diff --git a/test/Modules/Inputs/autoload-subdirectory/a.h b/test/Modules/Inputs/autoload-subdirectory/a.h new file mode 100644 index 0000000000..8be94312e3 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/a.h @@ -0,0 +1,9 @@ +#include "b.h" + +class foo { + int x, y; + +public: + foo(){}; + ~foo(){}; +}; diff --git a/test/Modules/Inputs/autoload-subdirectory/b.h b/test/Modules/Inputs/autoload-subdirectory/b.h new file mode 100644 index 0000000000..bfde5bf79f --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/b.h @@ -0,0 +1 @@ +class bar {}; diff --git a/test/Modules/Inputs/autoload-subdirectory/c.h b/test/Modules/Inputs/autoload-subdirectory/c.h new file mode 100644 index 0000000000..e5a45250f9 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/c.h @@ -0,0 +1,7 @@ +class nyan { + bool x, y; + +public: + nyan(){}; + ~nyan(){}; +}; diff --git a/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap new file mode 100644 index 0000000000..880ae38b97 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" } +module b { header "b.h" } +module c { header "c.h" } diff --git a/test/Modules/Inputs/autoload-subdirectory/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/module.modulemap new file mode 100644 index 0000000000..880ae38b97 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" } +module b { header "b.h" } +module c { header "c.h" } diff --git a/test/Modules/autoload-subdirectory.cpp b/test/Modules/autoload-subdirectory.cpp new file mode 100644 index 0000000000..e76f7056ab --- /dev/null +++ b/test/Modules/autoload-subdirectory.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fmodules -fmodule-name=Foo -I %S/Inputs/autoload-subdirectory/ %s -verify +// expected-no-diagnostics + +#include "a.h" +#import "c.h" + +int main() { + foo neko; + return 0; +} -- GitLab From d94210cb73e785733b9e6e527ad1636c64cd2c92 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Tue, 10 Jul 2018 13:46:05 +0000 Subject: [PATCH 0478/1023] [analyzer] Add option to set maximum symbol complexity threshold Summary: This adds an option, max-symbol-complexity, so an user can set the maximum symbol complexity threshold. Note that the current behaviour is equivalent to max complexity = 0, when taint analysis is not enabled and tests show that in a number of tests, having complexity = 25 yields the same results as complexity = 10000. This patch was extracted and modified from Dominic Chen's patch, D35450. Reviewers: george.karpenkov, NoQ, ddcc Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49093 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336671 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h | 8 ++++++++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 6 ++++++ lib/StaticAnalyzer/Core/SValBuilder.cpp | 6 +++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 367591ae1f..aa59d6ff53 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -294,6 +294,9 @@ private: /// \sa getGraphTrimInterval Optional GraphTrimInterval; + /// \sa getMaxSymbolComplexity + Optional MaxSymbolComplexity; + /// \sa getMaxTimesInlineLarge Optional MaxTimesInlineLarge; @@ -643,6 +646,11 @@ public: /// node reclamation, set the option to "0". unsigned getGraphTrimInterval(); + /// Returns the maximum complexity of symbolic constraint (50 by default). + /// + /// This is controlled by "-analyzer-config max-symbol-complexity" option. + unsigned getMaxSymbolComplexity(); + /// Returns the maximum times a large function could be inlined. /// /// This is controlled by the 'max-times-inline-large' config option. diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 6fa5fec528..75c22a34ea 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -388,6 +388,12 @@ unsigned AnalyzerOptions::getGraphTrimInterval() { return GraphTrimInterval.getValue(); } +unsigned AnalyzerOptions::getMaxSymbolComplexity() { + if (!MaxSymbolComplexity.hasValue()) + MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 10000); + return MaxSymbolComplexity.getValue(); +} + unsigned AnalyzerOptions::getMaxTimesInlineLarge() { if (!MaxTimesInlineLarge.hasValue()) MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32); diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 137e9a7af2..59bf9f8752 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" #include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" @@ -29,6 +30,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" #include "llvm/ADT/APSInt.h" @@ -384,7 +386,9 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State, const SymExpr *symRHS = RHS.getAsSymExpr(); // TODO: When the Max Complexity is reached, we should conjure a symbol // instead of generating an Unknown value and propagate the taint info to it. - const unsigned MaxComp = 10000; // 100000 28X + const unsigned MaxComp = StateMgr.getOwningEngine() + ->getAnalysisManager() + .options.getMaxSymbolComplexity(); if (symLHS && symRHS && (symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp) -- GitLab From 695bff9aae9838e22bfe52909106a76e09782fca Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 10 Jul 2018 14:03:50 +0000 Subject: [PATCH 0479/1023] Update test for backend error message change git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336676 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/backend-unsupported-error.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/backend-unsupported-error.ll b/test/CodeGen/backend-unsupported-error.ll index ade8c052e7..083402ecee 100644 --- a/test/CodeGen/backend-unsupported-error.ll +++ b/test/CodeGen/backend-unsupported-error.ll @@ -3,7 +3,7 @@ ; This is to check that backend errors for unsupported features are formatted correctly -; CHECK: error: test.c:2:20: in function bar i32 (): unsupported call to function foo.2 +; CHECK: error: test.c:2:20: in function bar i32 (): unsupported call to function foo target triple = "r600-unknown-unknown" -- GitLab From eb22ae6c4cd5aff2fdab58df7186bc399853c6fd Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 10 Jul 2018 14:47:31 +0000 Subject: [PATCH 0480/1023] AMDGPU: Try to fix test again git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336681 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/backend-unsupported-error.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/backend-unsupported-error.ll b/test/CodeGen/backend-unsupported-error.ll index 083402ecee..75a5992f23 100644 --- a/test/CodeGen/backend-unsupported-error.ll +++ b/test/CodeGen/backend-unsupported-error.ll @@ -21,7 +21,7 @@ entry: ret i32 %call, !dbg !15 } -attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #0 = { nounwind noinline "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !10} -- GitLab From 7db09e3a6236cc357ce346d72cee4cdaee1b40c9 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Tue, 10 Jul 2018 15:15:24 +0000 Subject: [PATCH 0481/1023] Support -fdebug-prefix-map for assembler source (pass to cc1as). This is useful to omit the debug compilation dir when compiling assembly files with -g. Part of PR38050. Patch by Siddhartha Bagaria! Differential Revision: https://reviews.llvm.org/D48989 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336685 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 3 ++- lib/Driver/ToolChains/Clang.cpp | 23 +++++++++++++++-------- test/Driver/debug-prefix-map.S | 6 ++++++ tools/driver/cc1as_main.cpp | 7 +++++++ 4 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 test/Driver/debug-prefix-map.S diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index f958999f1c..4a5aa904e4 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1741,7 +1741,8 @@ def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group, Flags<[CC1Option]>; def fdebug_prefix_map_EQ - : Joined<["-"], "fdebug-prefix-map=">, Group, Flags<[CC1Option]>, + : Joined<["-"], "fdebug-prefix-map=">, Group, + Flags<[CC1Option,CC1AsOption]>, HelpText<"remap file source paths in debug info">; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source-level debug information">; diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 4129139718..472a4163e5 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -600,6 +600,18 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { } } +/// Add a CC1 and CC1AS option to specify the debug file path prefix map. +static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) { + for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) { + StringRef Map = A->getValue(); + if (Map.find('=') == StringRef::npos) + D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map; + else + CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map)); + A->claim(); + } +} + /// Vectorize at all optimization levels greater than 1 except for -Oz. /// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled. static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) { @@ -3800,14 +3812,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Add in -fdebug-compilation-dir if necessary. addDebugCompDirArg(Args, CmdArgs); - for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) { - StringRef Map = A->getValue(); - if (Map.find('=') == StringRef::npos) - D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map; - else - CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map)); - A->claim(); - } + addDebugPrefixMapArg(D, Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, options::OPT_ftemplate_depth_EQ)) { @@ -5352,6 +5357,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Add the -fdebug-compilation-dir flag if needed. addDebugCompDirArg(Args, CmdArgs); + addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs); + // Set the AT_producer to the clang version when using the integrated // assembler on assembly source files. CmdArgs.push_back("-dwarf-debug-producer"); diff --git a/test/Driver/debug-prefix-map.S b/test/Driver/debug-prefix-map.S new file mode 100644 index 0000000000..2ba66be0ed --- /dev/null +++ b/test/Driver/debug-prefix-map.S @@ -0,0 +1,6 @@ +// RUN: %clang -### -g -fdebug-prefix-map=old=new %s 2>&1 | FileCheck %s + +// CHECK: cc1as +// CHECK-SAME: -fdebug-prefix-map=old=new + +// More tests for this flag in debug-prefix-map.c. diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp index 05edb9f438..09db014019 100644 --- a/tools/driver/cc1as_main.cpp +++ b/tools/driver/cc1as_main.cpp @@ -94,6 +94,7 @@ struct AssemblerInvocation { std::string DwarfDebugFlags; std::string DwarfDebugProducer; std::string DebugCompilationDir; + std::map DebugPrefixMap; llvm::DebugCompressionType CompressDebugSections = llvm::DebugCompressionType::None; std::string MainFileName; @@ -233,6 +234,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); + for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) + Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); + // Frontend Options if (Args.hasArg(OPT_INPUT)) { bool First = true; @@ -377,6 +381,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer)); if (!Opts.DebugCompilationDir.empty()) Ctx.setCompilationDir(Opts.DebugCompilationDir); + if (!Opts.DebugPrefixMap.empty()) + for (const auto &KV : Opts.DebugPrefixMap) + Ctx.addDebugPrefixMapEntry(KV.first, KV.second); if (!Opts.MainFileName.empty()) Ctx.setMainFileName(StringRef(Opts.MainFileName)); Ctx.setDwarfVersion(Opts.DwarfVersion); -- GitLab From 9c99d48420e3e22a640d85bd883e4d63519a27f4 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 10 Jul 2018 17:44:08 +0000 Subject: [PATCH 0482/1023] Fix a typo/regression in r335495. Use getTriple.isMIPS64() to detect 64-bit MIPS ABIs in FreeBSD::getSupportedSanitizers() instead of getTriple.isMIPS32(). Reviewed By: atanasyan Differential Revision: https://reviews.llvm.org/D49143 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336710 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/FreeBSD.cpp | 2 +- test/Driver/fsanitize.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index d3d82e4d3f..c16eabf069 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -408,7 +408,7 @@ bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } SanitizerMask FreeBSD::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; - const bool IsMIPS64 = getTriple().isMIPS32(); + const bool IsMIPS64 = getTriple().isMIPS64(); SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; Res |= SanitizerKind::Vptr; diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 354e7c0296..946f2273cc 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -316,6 +316,12 @@ // RUN: %clang -target mips-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS // CHECK-SANL-MIPS: unsupported option '-fsanitize=leak' for target 'mips-unknown-linux' +// RUN: %clang -target mips-unknown-freebsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS-FREEBSD +// CHECK-SANL-MIPS-FREEBSD: unsupported option '-fsanitize=leak' for target 'mips-unknown-freebsd' + +// RUN: %clang -target mips64-unknown-freebsd -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-MIPS64-FREEBSD +// CHECK-SANL-MIPS64-FREEBSD: "-fsanitize=leak" + // RUN: %clang -target powerpc64-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-PPC64 // RUN: %clang -target powerpc64le-unknown-linux -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-PPC64 // CHECK-SANL-PPC64: "-fsanitize=leak" -- GitLab From d33a97ceed4c92d978cf4a760b79aa9f6745fb94 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 10 Jul 2018 19:48:53 +0000 Subject: [PATCH 0483/1023] Revert r336591 "[libclang] NFC, simplify clang_Cursor_Evaluate" This change is blocking r336590 which is being reverted due to memory leaks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336715 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndex.cpp | 49 ++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index ab606ec92f..a4698830d9 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3889,32 +3889,33 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { return nullptr; } -static const Expr *evaluateDeclExpr(const Decl *D) { - if (!D) - return nullptr; - if (auto *Var = dyn_cast(D)) - return Var->getInit(); - else if (auto *Field = dyn_cast(D)) - return Field->getInClassInitializer(); - return nullptr; -} - -static const Expr *evaluateCompoundStmtExpr(const CompoundStmt *CS) { - assert(CS && "invalid compound statement"); - for (auto *bodyIterator : CS->body()) { - if (const auto *E = dyn_cast(bodyIterator)) - return E; +CXEvalResult clang_Cursor_Evaluate(CXCursor C) { + if (clang_getCursorKind(C) == CXCursor_CompoundStmt) { + const CompoundStmt *compoundStmt = cast(getCursorStmt(C)); + Expr *expr = nullptr; + for (auto *bodyIterator : compoundStmt->body()) { + if ((expr = dyn_cast(bodyIterator))) { + break; + } + } + if (expr) + return const_cast( + reinterpret_cast(evaluateExpr(expr, C))); } - return nullptr; -} -CXEvalResult clang_Cursor_Evaluate(CXCursor C) { - if (const Expr *E = - clang_getCursorKind(C) == CXCursor_CompoundStmt - ? evaluateCompoundStmtExpr(cast(getCursorStmt(C))) - : evaluateDeclExpr(getCursorDecl(C))) - return const_cast( - reinterpret_cast(evaluateExpr(const_cast(E), C))); + const Decl *D = getCursorDecl(C); + if (D) { + const Expr *expr = nullptr; + if (auto *Var = dyn_cast(D)) { + expr = Var->getInit(); + } else if (auto *Field = dyn_cast(D)) { + expr = Field->getInClassInitializer(); + } + if (expr) + return const_cast(reinterpret_cast( + evaluateExpr(const_cast(expr), C))); + return nullptr; + } return nullptr; } -- GitLab From 8430288c2717cbee07d3d5f8398ac127d3227b73 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 10 Jul 2018 19:49:07 +0000 Subject: [PATCH 0484/1023] Revert r336590 "[libclang] evalute compound statement cursors before trying to evaluate" New memory leaks in LibclangParseTest_EvaluateChildExpression_Test::TestBody() git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336716 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndex.cpp | 26 +++++++++--------- unittests/libclang/LibclangTest.cpp | 41 ----------------------------- 2 files changed, 13 insertions(+), 54 deletions(-) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a4698830d9..b61dff3238 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3890,19 +3890,6 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) { } CXEvalResult clang_Cursor_Evaluate(CXCursor C) { - if (clang_getCursorKind(C) == CXCursor_CompoundStmt) { - const CompoundStmt *compoundStmt = cast(getCursorStmt(C)); - Expr *expr = nullptr; - for (auto *bodyIterator : compoundStmt->body()) { - if ((expr = dyn_cast(bodyIterator))) { - break; - } - } - if (expr) - return const_cast( - reinterpret_cast(evaluateExpr(expr, C))); - } - const Decl *D = getCursorDecl(C); if (D) { const Expr *expr = nullptr; @@ -3916,6 +3903,19 @@ CXEvalResult clang_Cursor_Evaluate(CXCursor C) { evaluateExpr(const_cast(expr), C))); return nullptr; } + + const CompoundStmt *compoundStmt = dyn_cast_or_null(getCursorStmt(C)); + if (compoundStmt) { + Expr *expr = nullptr; + for (auto *bodyIterator : compoundStmt->body()) { + if ((expr = dyn_cast(bodyIterator))) { + break; + } + } + if (expr) + return const_cast( + reinterpret_cast(evaluateExpr(expr, C))); + } return nullptr; } diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp index 9629b62475..6fddcb2cbf 100644 --- a/unittests/libclang/LibclangTest.cpp +++ b/unittests/libclang/LibclangTest.cpp @@ -461,47 +461,6 @@ TEST_F(LibclangParseTest, AllSkippedRanges) { clang_disposeSourceRangeList(Ranges); } -TEST_F(LibclangParseTest, EvaluateChildExpression) { - std::string Main = "main.m"; - WriteFile(Main, "#define kFOO @\"foo\"\n" - "void foobar(void) {\n" - " {kFOO;}\n" - "}\n"); - ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, - 0, TUFlags); - - CXCursor C = clang_getTranslationUnitCursor(ClangTU); - clang_visitChildren( - C, - [](CXCursor cursor, CXCursor parent, - CXClientData client_data) -> CXChildVisitResult { - if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) { - int numberedStmt = 0; - clang_visitChildren( - cursor, - [](CXCursor cursor, CXCursor parent, - CXClientData client_data) -> CXChildVisitResult { - int &numberedStmt = *((int *)client_data); - if (clang_getCursorKind(cursor) == CXCursor_CompoundStmt) { - if (numberedStmt) { - CXEvalResult RE = clang_Cursor_Evaluate(cursor); - EXPECT_NE(RE, nullptr); - EXPECT_EQ(clang_EvalResult_getKind(RE), - CXEval_ObjCStrLiteral); - return CXChildVisit_Break; - } - numberedStmt++; - } - return CXChildVisit_Recurse; - }, - &numberedStmt); - EXPECT_EQ(numberedStmt, 1); - } - return CXChildVisit_Continue; - }, - nullptr); -} - class LibclangReparseTest : public LibclangParseTest { public: void DisplayDiagnostics() { -- GitLab From 8275ce24a432238f23f42534d3b2b57741044e43 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 10 Jul 2018 19:55:02 +0000 Subject: [PATCH 0485/1023] Patch to fix pragma metadata for do-while loops Summary: Make sure that loop metadata only is put on the backedge when expanding a do-while loop. Previously we added the loop metadata also on the branch in the pre-header. That could confuse optimization passes and result in the loop metadata being associated with the wrong loop. Fixes https://bugs.llvm.org/show_bug.cgi?id=38011 Committing on behalf of deepak2427 (Deepak Panickal) Reviewers: #clang, ABataev, hfinkel, aaron.ballman, bjope Reviewed By: bjope Subscribers: bjope, rsmith, shenhan, zzheng, xbolva00, lebedev.ri, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D48721 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336717 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGStmt.cpp | 10 ++++----- test/CodeGen/pragma-do-while.cpp | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/pragma-do-while.cpp diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 779bda681e..79662ec009 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -777,11 +777,6 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S, // Emit the body of the loop. llvm::BasicBlock *LoopBody = createBasicBlock("do.body"); - const SourceRange &R = S.getSourceRange(); - LoopStack.push(LoopBody, CGM.getContext(), DoAttrs, - SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd())); - EmitBlockWithFallThrough(LoopBody, &S); { RunCleanupsScope BodyScope(*this); @@ -790,6 +785,11 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S, EmitBlock(LoopCond.getBlock()); + const SourceRange &R = S.getSourceRange(); + LoopStack.push(LoopBody, CGM.getContext(), DoAttrs, + SourceLocToDebugLoc(R.getBegin()), + SourceLocToDebugLoc(R.getEnd())); + // C99 6.8.5.2: "The evaluation of the controlling expression takes place // after each execution of the loop body." diff --git a/test/CodeGen/pragma-do-while.cpp b/test/CodeGen/pragma-do-while.cpp new file mode 100644 index 0000000000..ecab7fc029 --- /dev/null +++ b/test/CodeGen/pragma-do-while.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s + +// We expect to get a loop structure like this: +// do.body: ; preds = %do.cond, ... +// ... +// br label %do.cond +// do.cond: ; preds = %do.body +// ... +// br i1 %cmp, label %do.body, label %do.end +// do.end: ; preds = %do.cond +// ... +// +// Verify that the loop metadata only is put on the backedge. +// +// CHECK-NOT: llvm.loop +// CHECK-LABEL: do.cond: +// CHECK: br {{.*}}, label %do.body, label %do.end, !llvm.loop ![[LMD1:[0-9]+]] +// CHECK-LABEL: do.end: +// CHECK-NOT: llvm.loop +// CHECK: ![[LMD1]] = distinct !{![[LMD1]], ![[LMD2:[0-9]+]]} +// CHECK: ![[LMD2]] = !{!"llvm.loop.unroll.count", i32 4} + +int test(int a[], int n) { + int i = 0; + int sum = 0; + +#pragma unroll 4 + do + { + a[i] = a[i] + 1; + sum = sum + a[i]; + i++; + } while (i < n); + + return sum; +} -- GitLab From 1437ede97caf39872f7378aabe147c80a76a5719 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 10 Jul 2018 20:46:46 +0000 Subject: [PATCH 0486/1023] [NFC] Switch CodeGenFunction to use value init instead of member init lists The member init list for the sole constructor for CodeGenFunction has gotten out of hand, so this patch moves the non-parameter-dependent initializations into the member value inits. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336726 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 6 ++ include/clang/AST/RecursiveASTVisitor.h | 12 +++ include/clang/AST/Type.h | 46 +++++++++ include/clang/AST/TypeLoc.h | 6 ++ include/clang/AST/TypeNodes.def | 1 + include/clang/Sema/Sema.h | 1 + include/clang/Serialization/ASTBitCodes.h | 85 ++++++++-------- lib/AST/ASTContext.cpp | 39 ++++++++ lib/AST/ASTStructuralEquivalence.cpp | 14 +++ lib/AST/ItaniumMangle.cpp | 38 +++++++ lib/AST/MicrosoftMangle.cpp | 10 ++ lib/AST/Type.cpp | 23 +++++ lib/AST/TypePrinter.cpp | 51 +++++++++- lib/CodeGen/CodeGenFunction.cpp | 22 +--- lib/CodeGen/CodeGenFunction.h | 74 +++++++------- lib/Sema/SemaTemplate.cpp | 5 + lib/Sema/SemaTemplateDeduction.cpp | 57 +++++++++++ lib/Sema/SemaType.cpp | 116 ++++++++++++++-------- lib/Sema/TreeTransform.h | 53 ++++++++++ lib/Serialization/ASTReader.cpp | 15 +++ lib/Serialization/ASTWriter.cpp | 12 +++ test/SemaCXX/vector.cpp | 43 ++++++++ tools/libclang/CIndex.cpp | 1 + 23 files changed, 589 insertions(+), 141 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ac317a7769..edb6be0608 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -168,6 +168,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet DependentAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; + mutable llvm::FoldingSet DependentVectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet FunctionProtoTypes; @@ -1321,6 +1322,11 @@ public: /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; + /// Return the unique reference to the type for a dependently sized vector of + /// the specified element type. + QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, + SourceLocation AttrLoc, + VectorType::VectorKind VecKind) const; /// Return the unique reference to an extended vector type /// of the specified element type and size. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 3e6090d312..0d2b670507 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DependentVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) +DEF_TRAVERSE_TYPELOC(DependentVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index dbe96a00f5..551921e663 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1590,6 +1590,7 @@ protected: class VectorTypeBitfields { friend class VectorType; + friend class DependentVectorType; unsigned : NumTypeBits; @@ -3079,6 +3080,51 @@ public: } }; +/// Represents a vector type where either the type or sizeis dependent. +//// +/// For example: +/// \code +/// template +/// class vector { +/// typedef T __attribute__((vector_size(Size))) type; +/// } +/// \endcode +class DependentVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + QualType ElementType; + Expr *SizeExpr; + SourceLocation Loc; + + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, SourceLocation Loc, + VectorType::VectorKind vecKind); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return Loc; } + VectorType::VectorKind getVectorKind() const { + return VectorType::VectorKind(VectorTypeBits.VecKind); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentVector; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, Expr *SizeExpr, + VectorType::VectorKind VecKind); +}; + /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 53d5a1a627..6772a88b6b 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1798,6 +1798,12 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc { }; +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class DependentVectorTypeLoc + : public InheritingConcreteTypeLoc {}; + // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc(T1); + const auto *Vec2 = cast(T2); + if (Vec1->getVectorKind() != Vec2->getVectorKind()) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(), + Vec2->getSizeExpr())) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), + Vec2->getElementType())) + return false; + break; + } + case Type::Vector: case Type::ExtVector: { const auto *Vec1 = cast(T1); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index d8c435991e..341ea5a338 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -539,7 +539,9 @@ private: void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); + void mangleNeonVectorType(const DependentVectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); + void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExprBase(const Expr *base, bool isArrow); @@ -1930,6 +1932,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::VariableArray: case Type::DependentSizedArray: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -3000,6 +3003,11 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { Out << BaseName << EltName; } +void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) { + llvm_unreachable( + "Mangling for Dependent Sized Neon Vector not yet implemented"); +} + static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { switch (EltType->getKind()) { case BuiltinType::SChar: @@ -3067,6 +3075,10 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str(); Out << TypeName.length() << TypeName; } +void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) { + llvm_unreachable( + "Mangling for Dependent Sized AArch64 Neon Vector not yet implemented"); +} // GNU extension: vector types // ::= @@ -3097,6 +3109,32 @@ void CXXNameMangler::mangleType(const VectorType *T) { else mangleType(T->getElementType()); } + +void CXXNameMangler::mangleType(const DependentVectorType *T) { + if ((T->getVectorKind() == VectorType::NeonVector || + T->getVectorKind() == VectorType::NeonPolyVector)) { + llvm::Triple Target = getASTContext().getTargetInfo().getTriple(); + llvm::Triple::ArchType Arch = + getASTContext().getTargetInfo().getTriple().getArch(); + if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) && + !Target.isOSDarwin()) + mangleAArch64NeonVectorType(T); + else + mangleNeonVectorType(T); + return; + } + + Out << "Dv"; + mangleExpression(T->getSizeExpr()); + Out << '_'; + if (T->getVectorKind() == VectorType::AltiVecPixel) + Out << 'p'; + else if (T->getVectorKind() == VectorType::AltiVecBool) + Out << 'b'; + else + mangleType(T->getElementType()); +} + void CXXNameMangler::mangleType(const ExtVectorType *T) { mangleType(static_cast(T)); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 32c26270ec..f9cd24ce9a 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2514,6 +2514,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers Quals, SourceRange Range) { mangleType(static_cast(T), Quals, Range); } + +void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T, + Qualifiers, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent-sized vector type yet"); + Diags.Report(Range.getBegin(), DiagID) << Range; +} + void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ddb45868ec..b25965786d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -177,6 +177,28 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } +DependentVectorType::DependentVectorType(const ASTContext &Context, + QualType ElementType, + QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, + VectorType::VectorKind VecKind) + : Type(DependentVector, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, + ElementType->isVariablyModifiedType(), + ElementType->containsUnexpandedParameterPack() || + (SizeExpr && SizeExpr->containsUnexpandedParameterPack())), + Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { + VectorTypeBits.VecKind = VecKind; +} + +void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType ElementType, Expr *SizeExpr, + VectorType::VectorKind VecKind) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + SizeExpr->Profile(ID, Context, true); +} + DependentSizedExtVectorType::DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, @@ -3783,6 +3805,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index b424b24574..aad52d5e1d 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::RValueReference: case Type::MemberPointer: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -640,7 +641,55 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); -} +} + +void TypePrinter::printDependentVectorBefore(const DependentVectorType *T, + raw_ostream &OS) { + switch (T->getVectorKind()) { + case VectorType::AltiVecPixel: + OS << "__vector __pixel "; + break; + case VectorType::AltiVecBool: + OS << "__vector __bool "; + printBefore(T->getElementType(), OS); + break; + case VectorType::AltiVecVector: + OS << "__vector "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonVector: + OS << "__attribute__((neon_vector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonPolyVector: + OS << "__attribute__((neon_polyvector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::GenericVector: { + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + OS << "__attribute__((__vector_size__("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + OS << ")))) "; + printBefore(T->getElementType(), OS); + break; + } + } +} + +void TypePrinter::printDependentVectorAfter(const DependentVectorType *T, + raw_ostream &OS) { + printAfter(T->getElementType(), OS); +} void TypePrinter::printExtVectorBefore(const ExtVectorType *T, raw_ostream &OS) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 9ccc0910c3..99af1a18e8 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -65,25 +65,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), CGBuilderInserterTy(this)), - CurFn(nullptr), ReturnValue(Address::invalid()), - CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), - IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), - SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr), - BlockPointer(nullptr), LambdaThisCaptureField(nullptr), - NormalCleanupDest(Address::invalid()), NextCleanupDestIndex(1), - FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), - EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()), - DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), - PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), - CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), - NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), - CXXABIThisValue(nullptr), CXXThisValue(nullptr), - CXXStructorImplicitParamDecl(nullptr), - CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), - CurLexicalScope(nullptr), TerminateLandingPad(nullptr), - TerminateHandler(nullptr), TrapBB(nullptr), LargestVectorWidth(0), - ShouldEmitLifetimeMarkers( - shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { + SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()), + PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers( + CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b2bcd1cfbd..d6deb65582 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -214,7 +214,7 @@ public: const Decl *CurCodeDecl; const CGFunctionInfo *CurFnInfo; QualType FnRetTy; - llvm::Function *CurFn; + llvm::Function *CurFn = nullptr; // Holds coroutine data if the current function is a coroutine. We use a // wrapper to manage its lifetime, so that we don't have to define CGCoroData @@ -242,7 +242,7 @@ public: /// ReturnValue - The temporary alloca to hold the return /// value. This is invalid iff the function has no return value. - Address ReturnValue; + Address ReturnValue = Address::invalid(); /// Return true if a label was seen in the current scope. bool hasLabelBeenSeenInCurrentScope() const { @@ -321,7 +321,7 @@ public: /// Captured 'this' type. FieldDecl *CXXThisFieldDecl; }; - CGCapturedStmtInfo *CapturedStmtInfo; + CGCapturedStmtInfo *CapturedStmtInfo = nullptr; /// RAII for correct setting/restoring of CapturedStmtInfo. class CGCapturedStmtRAII { @@ -366,7 +366,7 @@ public: SanitizerSet SanOpts; /// True if CodeGen currently emits code implementing sanitizer checks. - bool IsSanitizerScope; + bool IsSanitizerScope = false; /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. class SanitizerScope { @@ -378,26 +378,26 @@ public: /// In C++, whether we are code generating a thunk. This controls whether we /// should emit cleanups. - bool CurFuncIsThunk; + bool CurFuncIsThunk = false; /// In ARC, whether we should autorelease the return value. - bool AutoreleaseResult; + bool AutoreleaseResult = false; /// Whether we processed a Microsoft-style asm block during CodeGen. These can /// potentially set the return value. - bool SawAsmBlock; + bool SawAsmBlock = false; const FunctionDecl *CurSEHParent = nullptr; /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. - bool IsOutlinedSEHHelper; + bool IsOutlinedSEHHelper = false; - const CodeGen::CGBlockInfo *BlockInfo; - llvm::Value *BlockPointer; + const CodeGen::CGBlockInfo *BlockInfo = nullptr; + llvm::Value *BlockPointer = nullptr; llvm::DenseMap LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField; + FieldDecl *LambdaThisCaptureField = nullptr; /// A mapping from NRVO variables to the flags used to indicate /// when the NRVO has been applied to this variable. @@ -434,23 +434,23 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest; + Address NormalCleanupDest = Address::invalid(); - unsigned NextCleanupDestIndex; + unsigned NextCleanupDestIndex = 1; /// FirstBlockInfo - The head of a singly-linked-list of block layouts. - CGBlockInfo *FirstBlockInfo; + CGBlockInfo *FirstBlockInfo = nullptr; /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. - llvm::BasicBlock *EHResumeBlock; + llvm::BasicBlock *EHResumeBlock = nullptr; /// The exception slot. All landing pads write the current exception pointer /// into this alloca. - llvm::Value *ExceptionSlot; + llvm::Value *ExceptionSlot = nullptr; /// The selector slot. Under the MandatoryCleanup model, all landing pads /// write the current selector value into this alloca. - llvm::AllocaInst *EHSelectorSlot; + llvm::AllocaInst *EHSelectorSlot = nullptr; /// A stack of exception code slots. Entering an __except block pushes a slot /// on the stack and leaving pops one. The __exception_code() intrinsic loads @@ -1087,17 +1087,17 @@ public: private: CGDebugInfo *DebugInfo; - bool DisableDebugInfo; + bool DisableDebugInfo = false; /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. - bool DidCallStackSave; + bool DidCallStackSave = false; /// IndirectBranch - The first time an indirect goto is seen we create a block /// with an indirect branch. Every time we see the address of a label taken, /// we add the label to the indirect goto. Every subsequent indirect goto is /// codegen'd as a jump to the IndirectBranch's basic block. - llvm::IndirectBrInst *IndirectBranch; + llvm::IndirectBrInst *IndirectBranch = nullptr; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -1247,13 +1247,13 @@ private: /// SwitchInsn - This is nearest current switch instruction. It is null if /// current context is not in a switch. - llvm::SwitchInst *SwitchInsn; + llvm::SwitchInst *SwitchInsn = nullptr; /// The branch weights of SwitchInsn when doing instrumentation based PGO. - SmallVector *SwitchWeights; + SmallVector *SwitchWeights = nullptr; /// CaseRangeBlock - This block holds if condition check for last case /// statement range in current switch instruction. - llvm::BasicBlock *CaseRangeBlock; + llvm::BasicBlock *CaseRangeBlock = nullptr; /// OpaqueLValues - Keeps track of the current set of opaque value /// expressions. @@ -1270,13 +1270,13 @@ private: /// A block containing a single 'unreachable' instruction. Created /// lazily by getUnreachableBlock(). - llvm::BasicBlock *UnreachableBlock; + llvm::BasicBlock *UnreachableBlock = nullptr; /// Counts of the number return expressions in the function. - unsigned NumReturnExprs; + unsigned NumReturnExprs = 0; /// Count the number of simple (constant) return expressions in the function. - unsigned NumSimpleReturnExprs; + unsigned NumSimpleReturnExprs = 0; /// The last regular (non-return) debug location (breakpoint) in the function. SourceLocation LastStopPoint; @@ -1396,9 +1396,9 @@ public: private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXABIThisDecl; - llvm::Value *CXXABIThisValue; - llvm::Value *CXXThisValue; + ImplicitParamDecl *CXXABIThisDecl = nullptr; + llvm::Value *CXXABIThisValue = nullptr; + llvm::Value *CXXThisValue = nullptr; CharUnits CXXABIThisAlignment; CharUnits CXXThisAlignment; @@ -1416,16 +1416,16 @@ private: /// CXXStructorImplicitParamDecl - When generating code for a constructor or /// destructor, this will hold the implicit argument (e.g. VTT). - ImplicitParamDecl *CXXStructorImplicitParamDecl; - llvm::Value *CXXStructorImplicitParamValue; + ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr; + llvm::Value *CXXStructorImplicitParamValue = nullptr; /// OutermostConditional - Points to the outermost active /// conditional control. This is used so that we know if a /// temporary should be destroyed conditionally. - ConditionalEvaluation *OutermostConditional; + ConditionalEvaluation *OutermostConditional = nullptr; /// The current lexical scope. - LexicalScope *CurLexicalScope; + LexicalScope *CurLexicalScope = nullptr; /// The current source location that should be used for exception /// handling code. @@ -1456,16 +1456,16 @@ private: CurCodeDecl && CurCodeDecl->getAttr()); } - llvm::BasicBlock *TerminateLandingPad; - llvm::BasicBlock *TerminateHandler; - llvm::BasicBlock *TrapBB; + llvm::BasicBlock *TerminateLandingPad = nullptr; + llvm::BasicBlock *TerminateHandler = nullptr; + llvm::BasicBlock *TrapBB = nullptr; /// Terminate funclets keyed by parent funclet pad. llvm::MapVector TerminateFunclets; /// Largest vector width used in ths function. Will be used to create a /// function attribute. - unsigned LargestVectorWidth; + unsigned LargestVectorWidth = 0; /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 68a5196f6b..72ee8474f5 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5346,6 +5346,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType( + const DependentVectorType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fd4197ce2a..4e2fa31f9d 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1837,6 +1837,55 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; } + case Type::DependentVector: { + const DependentVectorType *VectorParam = cast(Param); + + if (const VectorType *VectorArg = dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); + ArgSize = VectorArg->getNumElements(); + // Note that we use the "array bound" rules here; just like in that + // case, we don't have any particular type for the vector size, but + // we can provide one if necessary. + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize, + S.Context.IntTy, true, Info, + Deduced); + } + + if (const DependentVectorType *VectorArg = + dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced); + } + + return Sema::TDK_NonDeducedMismatch; + } + // (clang extension) // // T __attribute__(((ext_vector_type(N)))) @@ -5227,6 +5276,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentVector: { + const DependentVectorType *VecType = cast(T); + MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced, + Depth, Used); + MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth, + Used); + break; + } case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast(T); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 978c1cc015..90cdf3290a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2294,6 +2294,58 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } +QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, + SourceLocation AttrLoc) { + // The base type must be integer (not Boolean or enumeration) or float, and + // can't already be a vector. + if (!CurType->isDependentType() && + (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; + return QualType(); + } + + if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + llvm::APSInt VecSize(32); + if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_type) + << "vector_size" << AANT_ArgumentIntegerConstant + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (CurType->isDependentType()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + unsigned VectorSize = static_cast(VecSize.getZExtValue() * 8); + unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); + + if (VectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange(); + return QualType(); + } + + // vecSize is specified in bytes - convert to bits. + if (VectorSize % TypeSize) { + Diag(AttrLoc, diag::err_attribute_invalid_size) + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << SizeExpr->getSourceRange(); + return QualType(); + } + + return Context.getVectorType(CurType, VectorSize / TypeSize, + VectorType::GenericVector); +} + /// Build an ext-vector type. /// /// Run the required checks for the extended vector type. @@ -6929,52 +6981,30 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); - llvm::APSInt vecSize(32); - if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || - !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentIntegerConstant - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - // The base type must be integer (not Boolean or enumeration) or float, and - // can't already be a vector. - if (!CurType->isBuiltinType() || CurType->isBooleanType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; - Attr.setInvalid(); - return; - } - unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - // vecSize is specified in bytes - convert to bits. - unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); - // the vector size needs to be an integral multiple of the type size. - if (vectorSize % typeSize) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) { - S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; + Expr *SizeExpr; + // Special case where the argument is a template id. + if (Attr.isArgIdent(0)) { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Id; + Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); + + ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, + Id, false, false); + + if (Size.isInvalid()) + return; + SizeExpr = Size.get(); + } else { + SizeExpr = Attr.getArgAsExpr(0); } - // Success! Instantiate the vector type, the number of elements is > 0, and - // not required to be a power of 2, unlike GCC. - CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, - VectorType::GenericVector); + QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc()); + if (!T.isNull()) + CurType = T; + else + Attr.setInvalid(); } /// Process the OpenCL-like ext_vector_type attribute when it occurs on diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 66c947abb3..a933b6774b 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -818,6 +818,15 @@ public: QualType RebuildVectorType(QualType ElementType, unsigned NumElements, VectorType::VectorKind VecKind); + /// Build a new potentially dependently-sized extended vector type + /// given the element type and number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr, + SourceLocation AttributeLoc, + VectorType::VectorKind); + /// Build a new extended vector type given the element type and /// number of elements. /// @@ -4746,6 +4755,43 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformDependentVectorType( + TypeLocBuilder &TLB, DependentVectorTypeLoc TL) { + const DependentVectorType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + Size = SemaRef.ActOnConstantExpression(Size); + if (Size.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() || + Size.get() != T->getSizeExpr()) { + Result = getDerived().RebuildDependentVectorType( + ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind()); + if (Result.isNull()) + return QualType(); + } + + // Result might be dependent or not. + if (isa(Result)) { + DependentVectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + VectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } + + return Result; +} + template QualType TreeTransform::TransformDependentSizedExtVectorType( TypeLocBuilder &TLB, @@ -12377,6 +12423,13 @@ TreeTransform::RebuildVectorType(QualType ElementType, return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); } +template +QualType TreeTransform::RebuildDependentVectorType( + QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc, + VectorType::VectorKind VecKind) { + return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc); +} + template QualType TreeTransform::RebuildExtVectorType(QualType ElementType, unsigned NumElements, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 78ca5f7406..0f6beddbe5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6371,6 +6371,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPipeType(ElementType, ReadOnly); } + case TYPE_DEPENDENT_SIZED_VECTOR: { + unsigned Idx = 0; + QualType ElementType = readType(*Loc.F, Record, Idx); + Expr *SizeExpr = ReadExpr(*Loc.F); + SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); + unsigned VecKind = Record[Idx]; + + return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, + (VectorType::VectorKind)VecKind); + } + case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { unsigned Idx = 0; @@ -6551,6 +6562,10 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } +void TypeLocReader::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation()); +} + void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index bc569d17f2..02a077fcb7 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -455,6 +455,14 @@ ASTTypeWriter::VisitDependentSizedExtVectorType( Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } +void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { + Record.AddTypeRef(T->getElementType()); + Record.AddStmt(T->getSizeExpr()); + Record.AddSourceLocation(T->getAttributeLoc()); + Record.push_back(T->getVectorKind()); + Code = TYPE_DEPENDENT_SIZED_VECTOR; +} + void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { @@ -676,6 +684,10 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 8fe24a32c8..56a8a6db5b 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x; // PR12649 typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}} + +namespace Templates { +template +struct TemplateVectorType { + typedef Elt __attribute__((__vector_size__(Size))) type; +}; + +template +struct PR15730 { + typedef T __attribute__((vector_size(N * sizeof(T)))) type; + typedef T __attribute__((vector_size(8192))) type2; + typedef T __attribute__((vector_size(3))) type3; +}; + +void Init() { + const TemplateVectorType::type Works = {}; + const TemplateVectorType::type Works2 = {}; + // expected-error@298 {{invalid vector element type 'bool'}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoBool; + // expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoComplex; + // expected-error@298 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type BadSize; + // expected-error@298 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type TooLarge; + // expected-error@298 {{zero vector size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type Zero; + + // expected-error@304 {{vector size too large}} + // expected-error@305 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}} + const PR15730<8, int>::type PR15730_1 = {}; + // expected-error@304 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}} + const PR15730<8, char>::type2 PR15730_2 = {}; +} + +} // namespace Templates diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index b61dff3238..499d9abf9a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1772,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type) +DEFAULT_TYPELOC_IMPL(DependentVector, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) DEFAULT_TYPELOC_IMPL(Vector, Type) DEFAULT_TYPELOC_IMPL(ExtVector, VectorType) -- GitLab From 9c7bda2f19e773d8c7a236f5427d4616262a2e79 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 10 Jul 2018 20:51:41 +0000 Subject: [PATCH 0487/1023] Revert -r336726, which included more files than intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336727 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 6 -- include/clang/AST/RecursiveASTVisitor.h | 12 --- include/clang/AST/Type.h | 46 --------- include/clang/AST/TypeLoc.h | 6 -- include/clang/AST/TypeNodes.def | 1 - include/clang/Sema/Sema.h | 1 - include/clang/Serialization/ASTBitCodes.h | 85 ++++++++-------- lib/AST/ASTContext.cpp | 39 -------- lib/AST/ASTStructuralEquivalence.cpp | 14 --- lib/AST/ItaniumMangle.cpp | 38 ------- lib/AST/MicrosoftMangle.cpp | 10 -- lib/AST/Type.cpp | 23 ----- lib/AST/TypePrinter.cpp | 51 +--------- lib/CodeGen/CodeGenFunction.cpp | 22 +++- lib/CodeGen/CodeGenFunction.h | 74 +++++++------- lib/Sema/SemaTemplate.cpp | 5 - lib/Sema/SemaTemplateDeduction.cpp | 57 ----------- lib/Sema/SemaType.cpp | 116 ++++++++-------------- lib/Sema/TreeTransform.h | 53 ---------- lib/Serialization/ASTReader.cpp | 15 --- lib/Serialization/ASTWriter.cpp | 12 --- test/SemaCXX/vector.cpp | 43 -------- tools/libclang/CIndex.cpp | 1 - 23 files changed, 141 insertions(+), 589 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index edb6be0608..ac317a7769 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -168,7 +168,6 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet DependentAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; - mutable llvm::FoldingSet DependentVectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet FunctionProtoTypes; @@ -1322,11 +1321,6 @@ public: /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; - /// Return the unique reference to the type for a dependently sized vector of - /// the specified element type. - QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, - SourceLocation AttrLoc, - VectorType::VectorKind VecKind) const; /// Return the unique reference to an extended vector type /// of the specified element type and size. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 0d2b670507..3e6090d312 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -993,12 +993,6 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { TRY_TO(TraverseType(T->getPointeeType())); }) -DEF_TRAVERSE_TYPE(DependentVectorType, { - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - TRY_TO(TraverseType(T->getElementType())); -}) - DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1227,12 +1221,6 @@ DEF_TRAVERSE_TYPELOC(VectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) -DEF_TRAVERSE_TYPELOC(DependentVectorType, { - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 551921e663..dbe96a00f5 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1590,7 +1590,6 @@ protected: class VectorTypeBitfields { friend class VectorType; - friend class DependentVectorType; unsigned : NumTypeBits; @@ -3080,51 +3079,6 @@ public: } }; -/// Represents a vector type where either the type or sizeis dependent. -//// -/// For example: -/// \code -/// template -/// class vector { -/// typedef T __attribute__((vector_size(Size))) type; -/// } -/// \endcode -class DependentVectorType : public Type, public llvm::FoldingSetNode { - friend class ASTContext; - - const ASTContext &Context; - QualType ElementType; - Expr *SizeExpr; - SourceLocation Loc; - - DependentVectorType(const ASTContext &Context, QualType ElementType, - QualType CanonType, Expr *SizeExpr, SourceLocation Loc, - VectorType::VectorKind vecKind); - -public: - Expr *getSizeExpr() const { return SizeExpr; } - QualType getElementType() const { return ElementType; } - SourceLocation getAttributeLoc() const { return Loc; } - VectorType::VectorKind getVectorKind() const { - return VectorType::VectorKind(VectorTypeBits.VecKind); - } - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { - return T->getTypeClass() == DependentVector; - } - - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); - } - - static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - QualType ElementType, Expr *SizeExpr, - VectorType::VectorKind VecKind); -}; - /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 6772a88b6b..53d5a1a627 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1798,12 +1798,6 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc { }; -// FIXME: size expression and attribute locations (or keyword if we -// ever fully support altivec syntax). -class DependentVectorTypeLoc - : public InheritingConcreteTypeLoc {}; - // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc(T1); - const auto *Vec2 = cast(T2); - if (Vec1->getVectorKind() != Vec2->getVectorKind()) - return false; - if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(), - Vec2->getSizeExpr())) - return false; - if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), - Vec2->getElementType())) - return false; - break; - } - case Type::Vector: case Type::ExtVector: { const auto *Vec1 = cast(T1); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 341ea5a338..d8c435991e 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -539,9 +539,7 @@ private: void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); - void mangleNeonVectorType(const DependentVectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); - void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExprBase(const Expr *base, bool isArrow); @@ -1932,7 +1930,6 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::VariableArray: case Type::DependentSizedArray: case Type::DependentAddressSpace: - case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -3003,11 +3000,6 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { Out << BaseName << EltName; } -void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) { - llvm_unreachable( - "Mangling for Dependent Sized Neon Vector not yet implemented"); -} - static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { switch (EltType->getKind()) { case BuiltinType::SChar: @@ -3075,10 +3067,6 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str(); Out << TypeName.length() << TypeName; } -void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) { - llvm_unreachable( - "Mangling for Dependent Sized AArch64 Neon Vector not yet implemented"); -} // GNU extension: vector types // ::= @@ -3109,32 +3097,6 @@ void CXXNameMangler::mangleType(const VectorType *T) { else mangleType(T->getElementType()); } - -void CXXNameMangler::mangleType(const DependentVectorType *T) { - if ((T->getVectorKind() == VectorType::NeonVector || - T->getVectorKind() == VectorType::NeonPolyVector)) { - llvm::Triple Target = getASTContext().getTargetInfo().getTriple(); - llvm::Triple::ArchType Arch = - getASTContext().getTargetInfo().getTriple().getArch(); - if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) && - !Target.isOSDarwin()) - mangleAArch64NeonVectorType(T); - else - mangleNeonVectorType(T); - return; - } - - Out << "Dv"; - mangleExpression(T->getSizeExpr()); - Out << '_'; - if (T->getVectorKind() == VectorType::AltiVecPixel) - Out << 'p'; - else if (T->getVectorKind() == VectorType::AltiVecBool) - Out << 'b'; - else - mangleType(T->getElementType()); -} - void CXXNameMangler::mangleType(const ExtVectorType *T) { mangleType(static_cast(T)); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index f9cd24ce9a..32c26270ec 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2514,16 +2514,6 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers Quals, SourceRange Range) { mangleType(static_cast(T), Quals, Range); } - -void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T, - Qualifiers, SourceRange Range) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, - "cannot mangle this dependent-sized vector type yet"); - Diags.Report(Range.getBegin(), DiagID) << Range; -} - void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index b25965786d..ddb45868ec 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -177,28 +177,6 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } -DependentVectorType::DependentVectorType(const ASTContext &Context, - QualType ElementType, - QualType CanonType, Expr *SizeExpr, - SourceLocation Loc, - VectorType::VectorKind VecKind) - : Type(DependentVector, CanonType, /*Dependent=*/true, - /*InstantiationDependent=*/true, - ElementType->isVariablyModifiedType(), - ElementType->containsUnexpandedParameterPack() || - (SizeExpr && SizeExpr->containsUnexpandedParameterPack())), - Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { - VectorTypeBits.VecKind = VecKind; -} - -void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, - const ASTContext &Context, - QualType ElementType, Expr *SizeExpr, - VectorType::VectorKind VecKind) { - ID.AddPointer(ElementType.getAsOpaquePtr()); - SizeExpr->Profile(ID, Context, true); -} - DependentSizedExtVectorType::DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, @@ -3805,7 +3783,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: - case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index aad52d5e1d..b424b24574 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,7 +242,6 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::RValueReference: case Type::MemberPointer: case Type::DependentAddressSpace: - case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -641,55 +640,7 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); -} - -void TypePrinter::printDependentVectorBefore(const DependentVectorType *T, - raw_ostream &OS) { - switch (T->getVectorKind()) { - case VectorType::AltiVecPixel: - OS << "__vector __pixel "; - break; - case VectorType::AltiVecBool: - OS << "__vector __bool "; - printBefore(T->getElementType(), OS); - break; - case VectorType::AltiVecVector: - OS << "__vector "; - printBefore(T->getElementType(), OS); - break; - case VectorType::NeonVector: - OS << "__attribute__((neon_vector_type("; - if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, nullptr, Policy); - OS << "))) "; - printBefore(T->getElementType(), OS); - break; - case VectorType::NeonPolyVector: - OS << "__attribute__((neon_polyvector_type("; - if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, nullptr, Policy); - OS << "))) "; - printBefore(T->getElementType(), OS); - break; - case VectorType::GenericVector: { - // FIXME: We prefer to print the size directly here, but have no way - // to get the size of the type. - OS << "__attribute__((__vector_size__("; - if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, nullptr, Policy); - OS << " * sizeof("; - print(T->getElementType(), OS, StringRef()); - OS << ")))) "; - printBefore(T->getElementType(), OS); - break; - } - } -} - -void TypePrinter::printDependentVectorAfter(const DependentVectorType *T, - raw_ostream &OS) { - printAfter(T->getElementType(), OS); -} +} void TypePrinter::printExtVectorBefore(const ExtVectorType *T, raw_ostream &OS) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 99af1a18e8..9ccc0910c3 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -65,9 +65,25 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), CGBuilderInserterTy(this)), - SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()), - PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers( - CGM.getCodeGenOpts(), CGM.getLangOpts())) { + CurFn(nullptr), ReturnValue(Address::invalid()), + CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), + IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), + SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr), + BlockPointer(nullptr), LambdaThisCaptureField(nullptr), + NormalCleanupDest(Address::invalid()), NextCleanupDestIndex(1), + FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), + EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()), + DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), + PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), + CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), + NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), + CXXABIThisValue(nullptr), CXXThisValue(nullptr), + CXXStructorImplicitParamDecl(nullptr), + CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), + CurLexicalScope(nullptr), TerminateLandingPad(nullptr), + TerminateHandler(nullptr), TrapBB(nullptr), LargestVectorWidth(0), + ShouldEmitLifetimeMarkers( + shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d6deb65582..b2bcd1cfbd 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -214,7 +214,7 @@ public: const Decl *CurCodeDecl; const CGFunctionInfo *CurFnInfo; QualType FnRetTy; - llvm::Function *CurFn = nullptr; + llvm::Function *CurFn; // Holds coroutine data if the current function is a coroutine. We use a // wrapper to manage its lifetime, so that we don't have to define CGCoroData @@ -242,7 +242,7 @@ public: /// ReturnValue - The temporary alloca to hold the return /// value. This is invalid iff the function has no return value. - Address ReturnValue = Address::invalid(); + Address ReturnValue; /// Return true if a label was seen in the current scope. bool hasLabelBeenSeenInCurrentScope() const { @@ -321,7 +321,7 @@ public: /// Captured 'this' type. FieldDecl *CXXThisFieldDecl; }; - CGCapturedStmtInfo *CapturedStmtInfo = nullptr; + CGCapturedStmtInfo *CapturedStmtInfo; /// RAII for correct setting/restoring of CapturedStmtInfo. class CGCapturedStmtRAII { @@ -366,7 +366,7 @@ public: SanitizerSet SanOpts; /// True if CodeGen currently emits code implementing sanitizer checks. - bool IsSanitizerScope = false; + bool IsSanitizerScope; /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. class SanitizerScope { @@ -378,26 +378,26 @@ public: /// In C++, whether we are code generating a thunk. This controls whether we /// should emit cleanups. - bool CurFuncIsThunk = false; + bool CurFuncIsThunk; /// In ARC, whether we should autorelease the return value. - bool AutoreleaseResult = false; + bool AutoreleaseResult; /// Whether we processed a Microsoft-style asm block during CodeGen. These can /// potentially set the return value. - bool SawAsmBlock = false; + bool SawAsmBlock; const FunctionDecl *CurSEHParent = nullptr; /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. - bool IsOutlinedSEHHelper = false; + bool IsOutlinedSEHHelper; - const CodeGen::CGBlockInfo *BlockInfo = nullptr; - llvm::Value *BlockPointer = nullptr; + const CodeGen::CGBlockInfo *BlockInfo; + llvm::Value *BlockPointer; llvm::DenseMap LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField = nullptr; + FieldDecl *LambdaThisCaptureField; /// A mapping from NRVO variables to the flags used to indicate /// when the NRVO has been applied to this variable. @@ -434,23 +434,23 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); + Address NormalCleanupDest; - unsigned NextCleanupDestIndex = 1; + unsigned NextCleanupDestIndex; /// FirstBlockInfo - The head of a singly-linked-list of block layouts. - CGBlockInfo *FirstBlockInfo = nullptr; + CGBlockInfo *FirstBlockInfo; /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. - llvm::BasicBlock *EHResumeBlock = nullptr; + llvm::BasicBlock *EHResumeBlock; /// The exception slot. All landing pads write the current exception pointer /// into this alloca. - llvm::Value *ExceptionSlot = nullptr; + llvm::Value *ExceptionSlot; /// The selector slot. Under the MandatoryCleanup model, all landing pads /// write the current selector value into this alloca. - llvm::AllocaInst *EHSelectorSlot = nullptr; + llvm::AllocaInst *EHSelectorSlot; /// A stack of exception code slots. Entering an __except block pushes a slot /// on the stack and leaving pops one. The __exception_code() intrinsic loads @@ -1087,17 +1087,17 @@ public: private: CGDebugInfo *DebugInfo; - bool DisableDebugInfo = false; + bool DisableDebugInfo; /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. - bool DidCallStackSave = false; + bool DidCallStackSave; /// IndirectBranch - The first time an indirect goto is seen we create a block /// with an indirect branch. Every time we see the address of a label taken, /// we add the label to the indirect goto. Every subsequent indirect goto is /// codegen'd as a jump to the IndirectBranch's basic block. - llvm::IndirectBrInst *IndirectBranch = nullptr; + llvm::IndirectBrInst *IndirectBranch; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -1247,13 +1247,13 @@ private: /// SwitchInsn - This is nearest current switch instruction. It is null if /// current context is not in a switch. - llvm::SwitchInst *SwitchInsn = nullptr; + llvm::SwitchInst *SwitchInsn; /// The branch weights of SwitchInsn when doing instrumentation based PGO. - SmallVector *SwitchWeights = nullptr; + SmallVector *SwitchWeights; /// CaseRangeBlock - This block holds if condition check for last case /// statement range in current switch instruction. - llvm::BasicBlock *CaseRangeBlock = nullptr; + llvm::BasicBlock *CaseRangeBlock; /// OpaqueLValues - Keeps track of the current set of opaque value /// expressions. @@ -1270,13 +1270,13 @@ private: /// A block containing a single 'unreachable' instruction. Created /// lazily by getUnreachableBlock(). - llvm::BasicBlock *UnreachableBlock = nullptr; + llvm::BasicBlock *UnreachableBlock; /// Counts of the number return expressions in the function. - unsigned NumReturnExprs = 0; + unsigned NumReturnExprs; /// Count the number of simple (constant) return expressions in the function. - unsigned NumSimpleReturnExprs = 0; + unsigned NumSimpleReturnExprs; /// The last regular (non-return) debug location (breakpoint) in the function. SourceLocation LastStopPoint; @@ -1396,9 +1396,9 @@ public: private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXABIThisDecl = nullptr; - llvm::Value *CXXABIThisValue = nullptr; - llvm::Value *CXXThisValue = nullptr; + ImplicitParamDecl *CXXABIThisDecl; + llvm::Value *CXXABIThisValue; + llvm::Value *CXXThisValue; CharUnits CXXABIThisAlignment; CharUnits CXXThisAlignment; @@ -1416,16 +1416,16 @@ private: /// CXXStructorImplicitParamDecl - When generating code for a constructor or /// destructor, this will hold the implicit argument (e.g. VTT). - ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr; - llvm::Value *CXXStructorImplicitParamValue = nullptr; + ImplicitParamDecl *CXXStructorImplicitParamDecl; + llvm::Value *CXXStructorImplicitParamValue; /// OutermostConditional - Points to the outermost active /// conditional control. This is used so that we know if a /// temporary should be destroyed conditionally. - ConditionalEvaluation *OutermostConditional = nullptr; + ConditionalEvaluation *OutermostConditional; /// The current lexical scope. - LexicalScope *CurLexicalScope = nullptr; + LexicalScope *CurLexicalScope; /// The current source location that should be used for exception /// handling code. @@ -1456,16 +1456,16 @@ private: CurCodeDecl && CurCodeDecl->getAttr()); } - llvm::BasicBlock *TerminateLandingPad = nullptr; - llvm::BasicBlock *TerminateHandler = nullptr; - llvm::BasicBlock *TrapBB = nullptr; + llvm::BasicBlock *TerminateLandingPad; + llvm::BasicBlock *TerminateHandler; + llvm::BasicBlock *TrapBB; /// Terminate funclets keyed by parent funclet pad. llvm::MapVector TerminateFunclets; /// Largest vector width used in ths function. Will be used to create a /// function attribute. - unsigned LargestVectorWidth = 0; + unsigned LargestVectorWidth; /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 72ee8474f5..68a5196f6b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5346,11 +5346,6 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } -bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType( - const DependentVectorType *T) { - return Visit(T->getElementType()); -} - bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 4e2fa31f9d..fd4197ce2a 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1837,55 +1837,6 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; } - case Type::DependentVector: { - const DependentVectorType *VectorParam = cast(Param); - - if (const VectorType *VectorArg = dyn_cast(Arg)) { - // Perform deduction on the element types. - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, VectorParam->getElementType(), - VectorArg->getElementType(), Info, Deduced, TDF)) - return Result; - - // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP = - getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); - if (!NTTP) - return Sema::TDK_Success; - - llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); - ArgSize = VectorArg->getNumElements(); - // Note that we use the "array bound" rules here; just like in that - // case, we don't have any particular type for the vector size, but - // we can provide one if necessary. - return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize, - S.Context.IntTy, true, Info, - Deduced); - } - - if (const DependentVectorType *VectorArg = - dyn_cast(Arg)) { - // Perform deduction on the element types. - if (Sema::TemplateDeductionResult Result = - DeduceTemplateArgumentsByTypeMatch( - S, TemplateParams, VectorParam->getElementType(), - VectorArg->getElementType(), Info, Deduced, TDF)) - return Result; - - // Perform deduction on the vector size, if we can. - NonTypeTemplateParmDecl *NTTP = - getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); - if (!NTTP) - return Sema::TDK_Success; - - return DeduceNonTypeTemplateArgument( - S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced); - } - - return Sema::TDK_NonDeducedMismatch; - } - // (clang extension) // // T __attribute__(((ext_vector_type(N)))) @@ -5276,14 +5227,6 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, OnlyDeduced, Depth, Used); break; - case Type::DependentVector: { - const DependentVectorType *VecType = cast(T); - MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced, - Depth, Used); - MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth, - Used); - break; - } case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast(T); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 90cdf3290a..978c1cc015 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2294,58 +2294,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } -QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, - SourceLocation AttrLoc) { - // The base type must be integer (not Boolean or enumeration) or float, and - // can't already be a vector. - if (!CurType->isDependentType() && - (!CurType->isBuiltinType() || CurType->isBooleanType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) { - Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; - return QualType(); - } - - if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent()) - return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, - VectorType::GenericVector); - - llvm::APSInt VecSize(32); - if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_type) - << "vector_size" << AANT_ArgumentIntegerConstant - << SizeExpr->getSourceRange(); - return QualType(); - } - - if (CurType->isDependentType()) - return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, - VectorType::GenericVector); - - unsigned VectorSize = static_cast(VecSize.getZExtValue() * 8); - unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); - - if (VectorSize == 0) { - Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange(); - return QualType(); - } - - // vecSize is specified in bytes - convert to bits. - if (VectorSize % TypeSize) { - Diag(AttrLoc, diag::err_attribute_invalid_size) - << SizeExpr->getSourceRange(); - return QualType(); - } - - if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) { - Diag(AttrLoc, diag::err_attribute_size_too_large) - << SizeExpr->getSourceRange(); - return QualType(); - } - - return Context.getVectorType(CurType, VectorSize / TypeSize, - VectorType::GenericVector); -} - /// Build an ext-vector type. /// /// Run the required checks for the extended vector type. @@ -6981,30 +6929,52 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Attr.setInvalid(); return; } - - Expr *SizeExpr; - // Special case where the argument is a template id. - if (Attr.isArgIdent(0)) { - CXXScopeSpec SS; - SourceLocation TemplateKWLoc; - UnqualifiedId Id; - Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, - Id, false, false); - - if (Size.isInvalid()) - return; - SizeExpr = Size.get(); - } else { - SizeExpr = Attr.getArgAsExpr(0); + Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); + llvm::APSInt vecSize(32); + if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || + !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentIntegerConstant + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + // The base type must be integer (not Boolean or enumeration) or float, and + // can't already be a vector. + if (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; + Attr.setInvalid(); + return; } + unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); + // vecSize is specified in bytes - convert to bits. + unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); - QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc()); - if (!T.isNull()) - CurType = T; - else + // the vector size needs to be an integral multiple of the type size. + if (vectorSize % typeSize) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) { + S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + if (vectorSize == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) + << sizeExpr->getSourceRange(); Attr.setInvalid(); + return; + } + + // Success! Instantiate the vector type, the number of elements is > 0, and + // not required to be a power of 2, unlike GCC. + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, + VectorType::GenericVector); } /// Process the OpenCL-like ext_vector_type attribute when it occurs on diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index a933b6774b..66c947abb3 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -818,15 +818,6 @@ public: QualType RebuildVectorType(QualType ElementType, unsigned NumElements, VectorType::VectorKind VecKind); - /// Build a new potentially dependently-sized extended vector type - /// given the element type and number of elements. - /// - /// By default, performs semantic analysis when building the vector type. - /// Subclasses may override this routine to provide different behavior. - QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr, - SourceLocation AttributeLoc, - VectorType::VectorKind); - /// Build a new extended vector type given the element type and /// number of elements. /// @@ -4755,43 +4746,6 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, return Result; } -template -QualType TreeTransform::TransformDependentVectorType( - TypeLocBuilder &TLB, DependentVectorTypeLoc TL) { - const DependentVectorType *T = TL.getTypePtr(); - QualType ElementType = getDerived().TransformType(T->getElementType()); - if (ElementType.isNull()) - return QualType(); - - EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); - Size = SemaRef.ActOnConstantExpression(Size); - if (Size.isInvalid()) - return QualType(); - - QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() || - Size.get() != T->getSizeExpr()) { - Result = getDerived().RebuildDependentVectorType( - ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind()); - if (Result.isNull()) - return QualType(); - } - - // Result might be dependent or not. - if (isa(Result)) { - DependentVectorTypeLoc NewTL = TLB.push(Result); - NewTL.setNameLoc(TL.getNameLoc()); - } else { - VectorTypeLoc NewTL = TLB.push(Result); - NewTL.setNameLoc(TL.getNameLoc()); - } - - return Result; -} - template QualType TreeTransform::TransformDependentSizedExtVectorType( TypeLocBuilder &TLB, @@ -12423,13 +12377,6 @@ TreeTransform::RebuildVectorType(QualType ElementType, return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); } -template -QualType TreeTransform::RebuildDependentVectorType( - QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc, - VectorType::VectorKind VecKind) { - return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc); -} - template QualType TreeTransform::RebuildExtVectorType(QualType ElementType, unsigned NumElements, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 0f6beddbe5..78ca5f7406 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6371,17 +6371,6 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPipeType(ElementType, ReadOnly); } - case TYPE_DEPENDENT_SIZED_VECTOR: { - unsigned Idx = 0; - QualType ElementType = readType(*Loc.F, Record, Idx); - Expr *SizeExpr = ReadExpr(*Loc.F); - SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); - unsigned VecKind = Record[Idx]; - - return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, - (VectorType::VectorKind)VecKind); - } - case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { unsigned Idx = 0; @@ -6562,10 +6551,6 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } -void TypeLocReader::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { - TL.setNameLoc(ReadSourceLocation()); -} - void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 02a077fcb7..bc569d17f2 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -455,14 +455,6 @@ ASTTypeWriter::VisitDependentSizedExtVectorType( Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } -void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { - Record.AddTypeRef(T->getElementType()); - Record.AddStmt(T->getSizeExpr()); - Record.AddSourceLocation(T->getAttributeLoc()); - Record.push_back(T->getVectorKind()); - Code = TYPE_DEPENDENT_SIZED_VECTOR; -} - void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { @@ -684,10 +676,6 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } -void TypeLocWriter::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); -} - void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 56a8a6db5b..8fe24a32c8 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -291,46 +291,3 @@ const int &reference_to_vec_element = vi4(1).x; // PR12649 typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}} - -namespace Templates { -template -struct TemplateVectorType { - typedef Elt __attribute__((__vector_size__(Size))) type; -}; - -template -struct PR15730 { - typedef T __attribute__((vector_size(N * sizeof(T)))) type; - typedef T __attribute__((vector_size(8192))) type2; - typedef T __attribute__((vector_size(3))) type3; -}; - -void Init() { - const TemplateVectorType::type Works = {}; - const TemplateVectorType::type Works2 = {}; - // expected-error@298 {{invalid vector element type 'bool'}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type NoBool; - // expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type NoComplex; - // expected-error@298 {{vector size not an integral multiple of component size}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type BadSize; - // expected-error@298 {{vector size too large}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type TooLarge; - // expected-error@298 {{zero vector size}} - // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} - const TemplateVectorType::type Zero; - - // expected-error@304 {{vector size too large}} - // expected-error@305 {{vector size not an integral multiple of component size}} - // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}} - const PR15730<8, int>::type PR15730_1 = {}; - // expected-error@304 {{vector size too large}} - // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}} - const PR15730<8, char>::type2 PR15730_2 = {}; -} - -} // namespace Templates diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 499d9abf9a..b61dff3238 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1772,7 +1772,6 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type) -DEFAULT_TYPELOC_IMPL(DependentVector, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) DEFAULT_TYPELOC_IMPL(Vector, Type) DEFAULT_TYPELOC_IMPL(ExtVector, VectorType) -- GitLab From 032aa95be6020f58220afb96afceaa25829236c9 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 10 Jul 2018 21:07:50 +0000 Subject: [PATCH 0488/1023] [NFC] Switch CodeGenFunction to use value init instead of member init lists The member init list for the sole constructor for CodeGenFunction has gotten out of hand, so this patch moves the non-parameter-dependent initializations into the member value inits. Note: This is what was intended to be committed in r336726 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336729 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 22 ++-------- lib/CodeGen/CodeGenFunction.h | 74 ++++++++++++++++----------------- 2 files changed, 40 insertions(+), 56 deletions(-) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 9ccc0910c3..99af1a18e8 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -65,25 +65,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), CGBuilderInserterTy(this)), - CurFn(nullptr), ReturnValue(Address::invalid()), - CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), - IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), - SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr), - BlockPointer(nullptr), LambdaThisCaptureField(nullptr), - NormalCleanupDest(Address::invalid()), NextCleanupDestIndex(1), - FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), - EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()), - DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), - PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), - CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), - NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), - CXXABIThisValue(nullptr), CXXThisValue(nullptr), - CXXStructorImplicitParamDecl(nullptr), - CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), - CurLexicalScope(nullptr), TerminateLandingPad(nullptr), - TerminateHandler(nullptr), TrapBB(nullptr), LargestVectorWidth(0), - ShouldEmitLifetimeMarkers( - shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { + SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()), + PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers( + CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b2bcd1cfbd..d6deb65582 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -214,7 +214,7 @@ public: const Decl *CurCodeDecl; const CGFunctionInfo *CurFnInfo; QualType FnRetTy; - llvm::Function *CurFn; + llvm::Function *CurFn = nullptr; // Holds coroutine data if the current function is a coroutine. We use a // wrapper to manage its lifetime, so that we don't have to define CGCoroData @@ -242,7 +242,7 @@ public: /// ReturnValue - The temporary alloca to hold the return /// value. This is invalid iff the function has no return value. - Address ReturnValue; + Address ReturnValue = Address::invalid(); /// Return true if a label was seen in the current scope. bool hasLabelBeenSeenInCurrentScope() const { @@ -321,7 +321,7 @@ public: /// Captured 'this' type. FieldDecl *CXXThisFieldDecl; }; - CGCapturedStmtInfo *CapturedStmtInfo; + CGCapturedStmtInfo *CapturedStmtInfo = nullptr; /// RAII for correct setting/restoring of CapturedStmtInfo. class CGCapturedStmtRAII { @@ -366,7 +366,7 @@ public: SanitizerSet SanOpts; /// True if CodeGen currently emits code implementing sanitizer checks. - bool IsSanitizerScope; + bool IsSanitizerScope = false; /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. class SanitizerScope { @@ -378,26 +378,26 @@ public: /// In C++, whether we are code generating a thunk. This controls whether we /// should emit cleanups. - bool CurFuncIsThunk; + bool CurFuncIsThunk = false; /// In ARC, whether we should autorelease the return value. - bool AutoreleaseResult; + bool AutoreleaseResult = false; /// Whether we processed a Microsoft-style asm block during CodeGen. These can /// potentially set the return value. - bool SawAsmBlock; + bool SawAsmBlock = false; const FunctionDecl *CurSEHParent = nullptr; /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. - bool IsOutlinedSEHHelper; + bool IsOutlinedSEHHelper = false; - const CodeGen::CGBlockInfo *BlockInfo; - llvm::Value *BlockPointer; + const CodeGen::CGBlockInfo *BlockInfo = nullptr; + llvm::Value *BlockPointer = nullptr; llvm::DenseMap LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField; + FieldDecl *LambdaThisCaptureField = nullptr; /// A mapping from NRVO variables to the flags used to indicate /// when the NRVO has been applied to this variable. @@ -434,23 +434,23 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest; + Address NormalCleanupDest = Address::invalid(); - unsigned NextCleanupDestIndex; + unsigned NextCleanupDestIndex = 1; /// FirstBlockInfo - The head of a singly-linked-list of block layouts. - CGBlockInfo *FirstBlockInfo; + CGBlockInfo *FirstBlockInfo = nullptr; /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. - llvm::BasicBlock *EHResumeBlock; + llvm::BasicBlock *EHResumeBlock = nullptr; /// The exception slot. All landing pads write the current exception pointer /// into this alloca. - llvm::Value *ExceptionSlot; + llvm::Value *ExceptionSlot = nullptr; /// The selector slot. Under the MandatoryCleanup model, all landing pads /// write the current selector value into this alloca. - llvm::AllocaInst *EHSelectorSlot; + llvm::AllocaInst *EHSelectorSlot = nullptr; /// A stack of exception code slots. Entering an __except block pushes a slot /// on the stack and leaving pops one. The __exception_code() intrinsic loads @@ -1087,17 +1087,17 @@ public: private: CGDebugInfo *DebugInfo; - bool DisableDebugInfo; + bool DisableDebugInfo = false; /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. - bool DidCallStackSave; + bool DidCallStackSave = false; /// IndirectBranch - The first time an indirect goto is seen we create a block /// with an indirect branch. Every time we see the address of a label taken, /// we add the label to the indirect goto. Every subsequent indirect goto is /// codegen'd as a jump to the IndirectBranch's basic block. - llvm::IndirectBrInst *IndirectBranch; + llvm::IndirectBrInst *IndirectBranch = nullptr; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -1247,13 +1247,13 @@ private: /// SwitchInsn - This is nearest current switch instruction. It is null if /// current context is not in a switch. - llvm::SwitchInst *SwitchInsn; + llvm::SwitchInst *SwitchInsn = nullptr; /// The branch weights of SwitchInsn when doing instrumentation based PGO. - SmallVector *SwitchWeights; + SmallVector *SwitchWeights = nullptr; /// CaseRangeBlock - This block holds if condition check for last case /// statement range in current switch instruction. - llvm::BasicBlock *CaseRangeBlock; + llvm::BasicBlock *CaseRangeBlock = nullptr; /// OpaqueLValues - Keeps track of the current set of opaque value /// expressions. @@ -1270,13 +1270,13 @@ private: /// A block containing a single 'unreachable' instruction. Created /// lazily by getUnreachableBlock(). - llvm::BasicBlock *UnreachableBlock; + llvm::BasicBlock *UnreachableBlock = nullptr; /// Counts of the number return expressions in the function. - unsigned NumReturnExprs; + unsigned NumReturnExprs = 0; /// Count the number of simple (constant) return expressions in the function. - unsigned NumSimpleReturnExprs; + unsigned NumSimpleReturnExprs = 0; /// The last regular (non-return) debug location (breakpoint) in the function. SourceLocation LastStopPoint; @@ -1396,9 +1396,9 @@ public: private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXABIThisDecl; - llvm::Value *CXXABIThisValue; - llvm::Value *CXXThisValue; + ImplicitParamDecl *CXXABIThisDecl = nullptr; + llvm::Value *CXXABIThisValue = nullptr; + llvm::Value *CXXThisValue = nullptr; CharUnits CXXABIThisAlignment; CharUnits CXXThisAlignment; @@ -1416,16 +1416,16 @@ private: /// CXXStructorImplicitParamDecl - When generating code for a constructor or /// destructor, this will hold the implicit argument (e.g. VTT). - ImplicitParamDecl *CXXStructorImplicitParamDecl; - llvm::Value *CXXStructorImplicitParamValue; + ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr; + llvm::Value *CXXStructorImplicitParamValue = nullptr; /// OutermostConditional - Points to the outermost active /// conditional control. This is used so that we know if a /// temporary should be destroyed conditionally. - ConditionalEvaluation *OutermostConditional; + ConditionalEvaluation *OutermostConditional = nullptr; /// The current lexical scope. - LexicalScope *CurLexicalScope; + LexicalScope *CurLexicalScope = nullptr; /// The current source location that should be used for exception /// handling code. @@ -1456,16 +1456,16 @@ private: CurCodeDecl && CurCodeDecl->getAttr()); } - llvm::BasicBlock *TerminateLandingPad; - llvm::BasicBlock *TerminateHandler; - llvm::BasicBlock *TrapBB; + llvm::BasicBlock *TerminateLandingPad = nullptr; + llvm::BasicBlock *TerminateHandler = nullptr; + llvm::BasicBlock *TrapBB = nullptr; /// Terminate funclets keyed by parent funclet pad. llvm::MapVector TerminateFunclets; /// Largest vector width used in ths function. Will be used to create a /// function attribute. - unsigned LargestVectorWidth; + unsigned LargestVectorWidth = 0; /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; -- GitLab From 284abf4f1cb32a5f7a3134209c5d7b83923c720d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 10 Jul 2018 23:04:35 +0000 Subject: [PATCH 0489/1023] Fix determination of whether a reinterpret_cast casts away constness. The "casts away constness" check doesn't care at all how the different layers of the source and destination type were formed: for example, if the source is a pointer and the destination is a pointer-to-member, the types are still decomposed and their pointee qualifications are still checked. This rule is bizarre and somewhat ridiculous, so as an extension we accept code making use of such reinterpret_casts with a warning outside of SFINAE contexts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336738 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 6 + lib/Sema/SemaCast.cpp | 361 +++++++++--------- .../expr.post/expr.reinterpret.cast/p2.cpp | 26 ++ test/Sema/warn-cast-qual.c | 10 +- 4 files changed, 223 insertions(+), 180 deletions(-) create mode 100644 test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0f1ce0e120..e6d2de1791 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6184,6 +6184,12 @@ def err_bad_cxx_cast_bitfield : Error< def err_bad_cxx_cast_qualifiers_away : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 casts away qualifiers">; +def ext_bad_cxx_cast_qualifiers_away_incoherent : ExtWarn< + "ISO C++ does not allow " + "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" + "functional-style cast}0 from %1 to %2 because it casts away qualifiers, " + "even though the source and destination types are unrelated">, + SFINAEFailure, InGroup>; def err_bad_const_cast_dest : Error< "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " "which is not a reference, pointer-to-object, or pointer-to-data-member">; diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 32cb307c86..a2e2950556 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -33,10 +33,16 @@ using namespace clang; enum TryCastResult { TC_NotApplicable, ///< The cast method is not applicable. TC_Success, ///< The cast method is appropriate and successful. + TC_Extension, ///< The cast method is appropriate and accepted as a + ///< language extension. TC_Failed ///< The cast method is appropriate, but failed. A ///< diagnostic has been emitted. }; +static bool isValidCast(TryCastResult TCR) { + return TCR == TC_Success || TCR == TC_Extension; +} + enum CastType { CT_Const, ///< const_cast CT_Static, ///< static_cast @@ -431,95 +437,68 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, } } -/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, -/// this removes one level of indirection from both types, provided that they're -/// the same kind of pointer (plain or to-member). Unlike the Sema function, -/// this one doesn't care if the two pointers-to-member don't point into the -/// same class. This is because CastsAwayConstness doesn't care. -/// And additionally, it handles C++ references. If both the types are -/// references, then their pointee types are returned, -/// else if only one of them is reference, it's pointee type is returned, -/// and the other type is returned as-is. -static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { - const PointerType *T1PtrType = T1->getAs(), - *T2PtrType = T2->getAs(); - if (T1PtrType && T2PtrType) { - T1 = T1PtrType->getPointeeType(); - T2 = T2PtrType->getPointeeType(); - return true; - } - const ObjCObjectPointerType *T1ObjCPtrType = - T1->getAs(), - *T2ObjCPtrType = - T2->getAs(); - if (T1ObjCPtrType) { - if (T2ObjCPtrType) { - T1 = T1ObjCPtrType->getPointeeType(); - T2 = T2ObjCPtrType->getPointeeType(); - return true; - } - else if (T2PtrType) { - T1 = T1ObjCPtrType->getPointeeType(); - T2 = T2PtrType->getPointeeType(); - return true; - } - } - else if (T2ObjCPtrType) { - if (T1PtrType) { - T2 = T2ObjCPtrType->getPointeeType(); - T1 = T1PtrType->getPointeeType(); - return true; - } - } - - const MemberPointerType *T1MPType = T1->getAs(), - *T2MPType = T2->getAs(); - if (T1MPType && T2MPType) { - T1 = T1MPType->getPointeeType(); - T2 = T2MPType->getPointeeType(); - return true; - } - - const BlockPointerType *T1BPType = T1->getAs(), - *T2BPType = T2->getAs(); - if (T1BPType && T2BPType) { - T1 = T1BPType->getPointeeType(); - T2 = T2BPType->getPointeeType(); - return true; - } - - const LValueReferenceType *T1RefType = T1->getAs(), - *T2RefType = T2->getAs(); - if (T1RefType && T2RefType) { - T1 = T1RefType->getPointeeType(); - T2 = T2RefType->getPointeeType(); - return true; - } +namespace { +/// The kind of unwrapping we did when determining whether a conversion casts +/// away constness. +enum CastAwayConstnessKind { + /// The conversion does not cast away constness. + CACK_None = 0, + /// We unwrapped similar types. + CACK_Similar = 1, + /// We unwrapped dissimilar types with similar representations (eg, a pointer + /// versus an Objective-C object pointer). + CACK_SimilarKind = 2, + /// We unwrapped representationally-unrelated types, such as a pointer versus + /// a pointer-to-member. + CACK_Incoherent = 3, +}; +} - if (T1RefType) { - T1 = T1RefType->getPointeeType(); - // T2 = T2; - return true; - } +/// Unwrap one level of types for CastsAwayConstness. +/// +/// Like Sema::UnwrapSimilarPointerTypes, this removes one level of +/// indirection from both types, provided that they're both pointer-like. +/// Unlike the Sema function, doesn't care if the unwrapped pieces are related. +static CastAwayConstnessKind +unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { + if (Context.UnwrapSimilarPointerTypes(T1, T2)) + return CastAwayConstnessKind::CACK_Similar; + + // Special case: if the destination type is a reference type, unwrap it as + // the first level. + if (T2->isReferenceType()) { + T2 = T2->getPointeeType(); + return CastAwayConstnessKind::CACK_Similar; + } + + auto Classify = [](QualType T) { + if (T->isAnyPointerType()) return 1; + if (T->getAs()) return 2; + if (T->getAs()) return 3; + return 0; + }; - if (T2RefType) { - // T1 = T1; - T2 = T2RefType->getPointeeType(); - return true; - } + int T1Class = Classify(T1); + if (!T1Class) + return CastAwayConstnessKind::CACK_None; - return false; + int T2Class = Classify(T2); + if (!T2Class) + return CastAwayConstnessKind::CACK_None; + + T1 = T1->getPointeeType(); + T2 = T2->getPointeeType(); + return T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind + : CastAwayConstnessKind::CACK_Incoherent; } -/// CastsAwayConstness - Check if the pointer conversion from SrcType to -/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by -/// the cast checkers. Both arguments must denote pointer (possibly to member) -/// types. +/// Check if the pointer conversion from SrcType to DestType casts away +/// constness as defined in C++ [expr.const.cast]. This is used by the cast +/// checkers. Both arguments must denote pointer (possibly to member) types. /// /// \param CheckCVR Whether to check for const/volatile/restrict qualifiers. -/// /// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers. -static bool +static CastAwayConstnessKind CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, bool CheckCVR, bool CheckObjCLifetime, QualType *TheOffendingSrcType = nullptr, @@ -527,33 +506,35 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, Qualifiers *CastAwayQualifiers = nullptr) { // If the only checking we care about is for Objective-C lifetime qualifiers, // and we're not in ObjC mode, there's nothing to check. - if (!CheckCVR && CheckObjCLifetime && - !Self.Context.getLangOpts().ObjC1) - return false; - - // Casting away constness is defined in C++ 5.2.11p8 with reference to - // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since - // the rules are non-trivial. So first we construct Tcv *...cv* as described - // in C++ 5.2.11p8. - assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || - SrcType->isBlockPointerType() || - DestType->isLValueReferenceType()) && - "Source type is not pointer or pointer to member."); - assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || - DestType->isBlockPointerType() || - DestType->isLValueReferenceType()) && - "Destination type is not pointer or pointer to member, or reference."); + if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC1) + return CastAwayConstnessKind::CACK_None; + + if (!DestType->isReferenceType()) { + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) && + "Source type is not pointer or pointer to member."); + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || + DestType->isBlockPointerType()) && + "Destination type is not pointer or pointer to member."); + } QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), UnwrappedDestType = Self.Context.getCanonicalType(DestType); - SmallVector cv1, cv2; // Find the qualifiers. We only care about cvr-qualifiers for the // purpose of this check, because other qualifiers (address spaces, // Objective-C GC, etc.) are part of the type's identity. QualType PrevUnwrappedSrcType = UnwrappedSrcType; QualType PrevUnwrappedDestType = UnwrappedDestType; - while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { + auto WorstKind = CastAwayConstnessKind::CACK_Similar; + bool AllConstSoFar = true; + while (auto Kind = unwrapCastAwayConstnessLevel( + Self.Context, UnwrappedSrcType, UnwrappedDestType)) { + // Track the worst kind of unwrap we needed to do before we found a + // problem. + if (Kind > WorstKind) + WorstKind = Kind; + // Determine the relevant qualifiers at this level. Qualifiers SrcQuals, DestQuals; Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); @@ -566,51 +547,71 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, UnwrappedDestType->isObjCObjectType()) SrcQuals.removeConst(); - Qualifiers RetainedSrcQuals, RetainedDestQuals; if (CheckCVR) { - RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers()); - RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers()); + Qualifiers SrcCvrQuals = + Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers()); + Qualifiers DestCvrQuals = + Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers()); + + if (SrcCvrQuals != DestCvrQuals) { + if (CastAwayQualifiers) + *CastAwayQualifiers = SrcCvrQuals - DestCvrQuals; + + // If we removed a cvr-qualifier, this is casting away 'constness'. + if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) { + if (TheOffendingSrcType) + *TheOffendingSrcType = PrevUnwrappedSrcType; + if (TheOffendingDestType) + *TheOffendingDestType = PrevUnwrappedDestType; + return WorstKind; + } - if (RetainedSrcQuals != RetainedDestQuals && TheOffendingSrcType && - TheOffendingDestType && CastAwayQualifiers) { - *TheOffendingSrcType = PrevUnwrappedSrcType; - *TheOffendingDestType = PrevUnwrappedDestType; - *CastAwayQualifiers = RetainedSrcQuals - RetainedDestQuals; + // If any prior level was not 'const', this is also casting away + // 'constness'. We noted the outermost type missing a 'const' already. + if (!AllConstSoFar) + return WorstKind; } } - + if (CheckObjCLifetime && !DestQuals.compatiblyIncludesObjCLifetime(SrcQuals)) - return true; - - cv1.push_back(RetainedSrcQuals); - cv2.push_back(RetainedDestQuals); + return WorstKind; + + // If we found our first non-const-qualified type, this may be the place + // where things start to go wrong. + if (AllConstSoFar && !DestQuals.hasConst()) { + AllConstSoFar = false; + if (TheOffendingSrcType) + *TheOffendingSrcType = PrevUnwrappedSrcType; + if (TheOffendingDestType) + *TheOffendingDestType = PrevUnwrappedDestType; + } PrevUnwrappedSrcType = UnwrappedSrcType; PrevUnwrappedDestType = UnwrappedDestType; } - if (cv1.empty()) - return false; - // Construct void pointers with those qualifiers (in reverse order of - // unwrapping, of course). - QualType SrcConstruct = Self.Context.VoidTy; - QualType DestConstruct = Self.Context.VoidTy; - ASTContext &Context = Self.Context; - for (SmallVectorImpl::reverse_iterator i1 = cv1.rbegin(), - i2 = cv2.rbegin(); - i1 != cv1.rend(); ++i1, ++i2) { - SrcConstruct - = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1)); - DestConstruct - = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2)); - } - - // Test if they're compatible. - bool ObjCLifetimeConversion; - return SrcConstruct != DestConstruct && - !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false, - ObjCLifetimeConversion); + return CastAwayConstnessKind::CACK_None; +} + +static TryCastResult getCastAwayConstnessCastKind(CastAwayConstnessKind CACK, + unsigned &DiagID) { + switch (CACK) { + case CastAwayConstnessKind::CACK_None: + llvm_unreachable("did not cast away constness"); + + case CastAwayConstnessKind::CACK_Similar: + // FIXME: Accept these as an extension too? + case CastAwayConstnessKind::CACK_SimilarKind: + DiagID = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + + case CastAwayConstnessKind::CACK_Incoherent: + DiagID = diag::ext_bad_cxx_cast_qualifiers_away_incoherent; + return TC_Extension; + } + + llvm_unreachable("unexpected cast away constness kind"); } /// CheckDynamicCast - Check that a dynamic_cast\(SrcExpr) is valid. @@ -778,12 +779,13 @@ void CastOperation::CheckConstCast() { return; unsigned msg = diag::err_bad_cxx_cast_generic; - if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success - && msg != 0) { + auto TCR = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg); + if (TCR != TC_Success && msg != 0) { Self.Diag(OpRange.getBegin(), msg) << CT_Const << SrcExpr.get()->getType() << DestType << OpRange; - SrcExpr = ExprError(); } + if (!isValidCast(TCR)) + SrcExpr = ExprError(); } /// Check that a reinterpret_cast\(SrcExpr) is not used as upcast @@ -896,8 +898,7 @@ void CastOperation::CheckReinterpretCast() { TryCastResult tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind); - if (tcr != TC_Success && msg != 0) - { + if (tcr != TC_Success && msg != 0) { if (SrcExpr.isInvalid()) // if conversion failed, don't report another error return; if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { @@ -911,11 +912,14 @@ void CastOperation::CheckReinterpretCast() { diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType, /*listInitialization=*/false); } - SrcExpr = ExprError(); - } else if (tcr == TC_Success) { + } + + if (isValidCast(tcr)) { if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) checkObjCConversion(Sema::CCK_OtherCast); DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); + } else { + SrcExpr = ExprError(); } } @@ -973,14 +977,15 @@ void CastOperation::CheckStaticCast() { diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType, /*listInitialization=*/false); } - SrcExpr = ExprError(); - } else if (tcr == TC_Success) { + } + + if (isValidCast(tcr)) { if (Kind == CK_BitCast) checkCastAlign(); if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) checkObjCConversion(Sema::CCK_OtherCast); - } else if (Kind == CK_BitCast) { - checkCastAlign(); + } else { + SrcExpr = ExprError(); } } @@ -2000,16 +2005,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, SrcMemPtr->isMemberFunctionPointer()) return TC_NotApplicable; - // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away - // constness. - // A reinterpret_cast followed by a const_cast can, though, so in C-style, - // we accept it. - if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, - /*CheckObjCLifetime=*/CStyle)) { - msg = diag::err_bad_cxx_cast_qualifiers_away; - return TC_Failed; - } - if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // We need to determine the inheritance model that the class will use if // haven't yet. @@ -2024,6 +2019,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Failed; } + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away + // constness. + // A reinterpret_cast followed by a const_cast can, though, so in C-style, + // we accept it. + if (auto CACK = + CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, + /*CheckObjCLifetime=*/CStyle)) + return getCastAwayConstnessCastKind(CACK, msg); + // A valid member pointer cast. assert(!IsLValueCast); Kind = CK_ReinterpretMemberPointer; @@ -2140,19 +2144,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_NotApplicable; } - // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. - // The C-style cast operator can. - if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, - /*CheckObjCLifetime=*/CStyle)) { - msg = diag::err_bad_cxx_cast_qualifiers_away; - return TC_Failed; - } - // Cannot convert between block pointers and Objective-C object pointers. if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) return TC_NotApplicable; + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. + // The C-style cast operator can. + TryCastResult SuccessResult = TC_Success; + if (auto CACK = + CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, + /*CheckObjCLifetime=*/CStyle)) + SuccessResult = getCastAwayConstnessCastKind(CACK, msg); + if (IsLValueCast) { Kind = CK_LValueBitCast; } else if (DestType->isObjCObjectPointerType()) { @@ -2170,7 +2174,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // Any pointer can be cast to an Objective-C pointer type with a C-style // cast. if (CStyle && DestType->isObjCObjectPointerType()) { - return TC_Success; + return SuccessResult; } if (CStyle) DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); @@ -2184,7 +2188,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (DestType->isFunctionPointerType()) { // C++ 5.2.10p6: A pointer to a function can be explicitly converted to // a pointer to a function of a different type. - return TC_Success; + return SuccessResult; } // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to @@ -2197,7 +2201,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, Self.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) << OpRange; - return TC_Success; + return SuccessResult; } if (DestType->isFunctionPointerType()) { @@ -2206,7 +2210,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, Self.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) << OpRange; - return TC_Success; + return SuccessResult; } // C++ 5.2.10p7: A pointer to an object can be explicitly converted to @@ -2214,8 +2218,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // Void pointers are not specified, but supported by every compiler out there. // So we finish by allowing everything that remains - it's got to be two // object pointers. - return TC_Success; -} + return SuccessResult; +} void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, bool ListInitialization) { @@ -2295,7 +2299,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, /*CStyle*/true, msg); if (SrcExpr.isInvalid()) return; - if (tcr == TC_Success) + if (isValidCast(tcr)) Kind = CK_NoOp; Sema::CheckedConversionKind CCK @@ -2318,7 +2322,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, } if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - tcr == TC_Success) + isValidCast(tcr)) checkObjCConversion(CCK); if (tcr != TC_Success && msg != 0) { @@ -2342,13 +2346,14 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle), OpRange, SrcExpr.get(), DestType, ListInitialization); } - } else if (Kind == CK_BitCast) { - checkCastAlign(); } - // Clear out SrcExpr if there was a fatal error. - if (tcr != TC_Success) + if (isValidCast(tcr)) { + if (Kind == CK_BitCast) + checkCastAlign(); + } else { SrcExpr = ExprError(); + } } /// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a @@ -2633,11 +2638,13 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr, QualType TheOffendingSrcType, TheOffendingDestType; Qualifiers CastAwayQualifiers; - if (!CastsAwayConstness(Self, SrcType, DestType, true, false, - &TheOffendingSrcType, &TheOffendingDestType, - &CastAwayQualifiers)) + if (CastsAwayConstness(Self, SrcType, DestType, true, false, + &TheOffendingSrcType, &TheOffendingDestType, + &CastAwayQualifiers) != + CastAwayConstnessKind::CACK_Similar) return; + // FIXME: 'restrict' is not properly handled here. int qualifiers = -1; if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) { qualifiers = 0; diff --git a/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp b/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp new file mode 100644 index 0000000000..b03db27ee1 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.reinterpret.cast/p2.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -verify + +// The reinterpret_cast operator shall not cast away constness. +struct X {}; +struct Y {}; +void f(const int * X::* Y::* *p) { + // This applies for similar types... + (void)reinterpret_cast(p); // expected-error {{casts away qualifiers}} + // ... and for cases where the base type is different ... + (void)reinterpret_cast(p); // expected-error {{casts away qualifiers}} + // ... and for cases where pointers to members point to members of different classes ... + (void)reinterpret_cast(p); // expected-error {{casts away qualifiers}} + // ... and even for cases where the path is wholly different! + // (Though we accept such cases as an extension.) + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + + // If qualifiers are added, we need a 'const' at every level above. + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + (void)reinterpret_cast(p); // ok + + (void)reinterpret_cast(p); // expected-warning {{casts away qualifiers}} + (void)reinterpret_cast(p); // ok +} diff --git a/test/Sema/warn-cast-qual.c b/test/Sema/warn-cast-qual.c index a682cad75e..789bde15b1 100644 --- a/test/Sema/warn-cast-qual.c +++ b/test/Sema/warn-cast-qual.c @@ -4,11 +4,15 @@ #include void foo() { - const char * const ptr = 0; - const char * const *ptrptr = 0; + const char *const ptr = 0; + const char *const *ptrptr = 0; + char *const *ptrcptr = 0; + char **ptrptr2 = 0; char *y = (char *)ptr; // expected-warning {{cast from 'const char *' to 'char *' drops const qualifier}} - char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *' drops const qualifier}} + char **y1 = (char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'char **' drops const qualifier}} const char **y2 = (const char **)ptrptr; // expected-warning {{cast from 'const char *const *' to 'const char **' drops const qualifier}} + char *const *y3 = (char *const *)ptrptr; // expected-warning {{cast from 'const char *const' to 'char *const' drops const qualifier}} + const char **y4 = (const char **)ptrcptr; // expected-warning {{cast from 'char *const *' to 'const char **' drops const qualifier}} char *z = (char *)(uintptr_t)(const void *)ptr; // no warning char *z1 = (char *)(const void *)ptr; // expected-warning {{cast from 'const void *' to 'char *' drops const qualifier}} -- GitLab From 176126f8e3acb593bdac18d4ed8ff6b5ff5e0471 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 10 Jul 2018 23:13:01 +0000 Subject: [PATCH 0490/1023] [X86] Fix the test for _mm512_mullox_epi64 to test the intrinsic instead of a copy of the intrinsic implementation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336739 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/avx512f-builtins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index b13e6bbbbf..8162da8b5c 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -3060,7 +3060,7 @@ __m512i test_mm512_mullo_epi32(__m512i __A, __m512i __B) { __m512i test_mm512_mullox_epi64 (__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mullox_epi64 // CHECK: mul <8 x i64> - return (__m512i) ((__v8di) __A * (__v8di) __B); + return (__m512i) _mm512_mullox_epi64(__A, __B); } __m512i test_mm512_mask_mullox_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { -- GitLab From 3c6b78637e54fd4bc2f6413e2f34439b51da65fa Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 10 Jul 2018 23:28:05 +0000 Subject: [PATCH 0491/1023] [X86] Also fix the test for _mm512_mullo_epi64 to test the intrinsic instead of a copy of the intrinsic implementation. This had the same issue I just fixed in r336739. Apparently I copy pasted _mm512_mullo_epi64 when I added _mm512_mullox_epi64. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336740 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/avx512dq-builtins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c index e08501b397..6ac3aff0aa 100644 --- a/test/CodeGen/avx512dq-builtins.c +++ b/test/CodeGen/avx512dq-builtins.c @@ -6,7 +6,7 @@ __m512i test_mm512_mullo_epi64 (__m512i __A, __m512i __B) { // CHECK-LABEL: @test_mm512_mullo_epi64 // CHECK: mul <8 x i64> - return (__m512i) ((__v8di) __A * (__v8di) __B); + return (__m512i) _mm512_mullo_epi64(__A, __B); } __m512i test_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) { -- GitLab From 295c88685f7c285358db0d83f1fc315ac23677e3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Jul 2018 00:19:19 +0000 Subject: [PATCH 0492/1023] DR330: look through array types when forming the cv-decomposition of a type. This allows more qualification conversions, eg. conversion from 'int *(*)[]' -> 'const int *const (*)[]' is now permitted, along with all the consequences of that: more types are similar, more cases are permitted by const_cast, and conversely, fewer "casting away constness" cases are permitted by reinterpret_cast. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336745 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 14 ++++- lib/AST/ASTContext.cpp | 83 ++++++++++++++++++++++--- lib/Sema/SemaCast.cpp | 58 +++++++++-------- lib/Sema/SemaOverload.cpp | 16 +---- lib/StaticAnalyzer/Core/SValBuilder.cpp | 6 +- test/CXX/drs/dr3xx.cpp | 51 +++++++++++++++ test/SemaCXX/const-cast.cpp | 10 ++- www/cxx_dr_status.html | 2 +- 8 files changed, 183 insertions(+), 57 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ac317a7769..ddfbdc2472 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2282,7 +2282,19 @@ public: bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp); - bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); + bool UnwrapSimilarTypes(QualType &T1, QualType &T2); + + /// Determine if two types are similar, according to the C++ rules. That is, + /// determine if they are the same other than qualifiers on the initial + /// sequence of pointer / pointer-to-member / array (and in Clang, object + /// pointer) types and their element types. + /// + /// Clang offers a number of qualifiers in addition to the C++ qualifiers; + /// those qualifiers are also ignored in the 'similarity' check. + bool hasSimilarType(QualType T1, QualType T2); + + /// Determine if two types are similar, ignoring only CVR qualifiers. + bool hasCvrSimilarType(QualType T1, QualType T2); /// Retrieves the "canonical" nested name specifier for a /// given nested name specifier. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index ca54d8f675..832f3a2e7a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4965,15 +4965,49 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, SourceRange()); } -/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that -/// may be similar (C++ 4.4), replaces T1 and T2 with the type that -/// they point to and return true. If T1 and T2 aren't pointer types -/// or pointer-to-member types, or if they are not similar at this -/// level, returns false and leaves T1 and T2 unchanged. Top-level -/// qualifiers on T1 and T2 are ignored. This function will typically -/// be called in a loop that successively "unwraps" pointer and -/// pointer-to-member types to compare them at each level. -bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { +/// Attempt to unwrap two types that may both be array types with the same bound +/// (or both be array types of unknown bound) for the purpose of comparing the +/// cv-decomposition of two types per C++ [conv.qual]. +static void unwrapSimilarArrayTypes(ASTContext &Ctx, QualType &T1, + QualType &T2) { + while (true) { + auto *AT1 = Ctx.getAsArrayType(T1); + if (!AT1) return; + + auto *AT2 = Ctx.getAsArrayType(T2); + if (!AT2) return; + + // If we don't have two array types with the same constant bound nor two + // incomplete array types, we've unwrapped everything we can. + if (auto *CAT1 = dyn_cast(AT1)) { + auto *CAT2 = dyn_cast(AT2); + if (!CAT2 || CAT1->getSize() != CAT2->getSize()) + return; + } else if (!isa(AT1) || + !isa(AT2)) { + return; + } + + T1 = AT1->getElementType(); + T2 = AT2->getElementType(); + } +} + +/// Attempt to unwrap two types that may be similar (C++ [conv.qual]). +/// +/// If T1 and T2 are both pointer types of the same kind, or both array types +/// with the same bound, unwraps layers from T1 and T2 until a pointer type is +/// unwrapped. Top-level qualifiers on T1 and T2 are ignored. +/// +/// This function will typically be called in a loop that successively +/// "unwraps" pointer and pointer-to-member types to compare them at each +/// level. +/// +/// \return \c true if a pointer type was unwrapped, \c false if we reached a +/// pair of types that can't be unwrapped further. +bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) { + unwrapSimilarArrayTypes(*this, T1, T2); + const auto *T1PtrType = T1->getAs(); const auto *T2PtrType = T2->getAs(); if (T1PtrType && T2PtrType) { @@ -5007,6 +5041,37 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { return false; } +bool ASTContext::hasSimilarType(QualType T1, QualType T2) { + while (true) { + Qualifiers Quals; + T1 = getUnqualifiedArrayType(T1, Quals); + T2 = getUnqualifiedArrayType(T2, Quals); + if (hasSameType(T1, T2)) + return true; + if (!UnwrapSimilarTypes(T1, T2)) + return false; + } +} + +bool ASTContext::hasCvrSimilarType(QualType T1, QualType T2) { + while (true) { + Qualifiers Quals1, Quals2; + T1 = getUnqualifiedArrayType(T1, Quals1); + T2 = getUnqualifiedArrayType(T2, Quals2); + + Quals1.removeCVRQualifiers(); + Quals2.removeCVRQualifiers(); + if (Quals1 != Quals2) + return false; + + if (hasSameType(T1, T2)) + return true; + + if (!UnwrapSimilarTypes(T1, T2)) + return false; + } +} + DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const { diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index a2e2950556..ec95032c4e 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -456,12 +456,16 @@ enum CastAwayConstnessKind { /// Unwrap one level of types for CastsAwayConstness. /// -/// Like Sema::UnwrapSimilarPointerTypes, this removes one level of -/// indirection from both types, provided that they're both pointer-like. -/// Unlike the Sema function, doesn't care if the unwrapped pieces are related. +/// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from +/// both types, provided that they're both pointer-like or array-like. Unlike +/// the Sema function, doesn't care if the unwrapped pieces are related. static CastAwayConstnessKind unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { - if (Context.UnwrapSimilarPointerTypes(T1, T2)) + // Note, even if this returns false, it may have unwrapped some number of + // matching "array of" pieces. That's OK, we don't need to check their + // cv-qualifiers (that check is covered by checking the qualifiers on the + // array types themselves). + if (Context.UnwrapSimilarTypes(T1, T2)) return CastAwayConstnessKind::CACK_Similar; // Special case: if the destination type is a reference type, unwrap it as @@ -473,8 +477,11 @@ unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { auto Classify = [](QualType T) { if (T->isAnyPointerType()) return 1; - if (T->getAs()) return 2; - if (T->getAs()) return 3; + if (T->isMemberPointerType()) return 2; + if (T->isBlockPointerType()) return 3; + // We somewhat-arbitrarily don't look through VLA types here. This is at + // least consistent with the behavior of UnwrapSimilarTypes. + if (T->isConstantArrayType() || T->isIncompleteArrayType()) return 4; return 0; }; @@ -486,8 +493,14 @@ unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { if (!T2Class) return CastAwayConstnessKind::CACK_None; - T1 = T1->getPointeeType(); - T2 = T2->getPointeeType(); + auto Unwrap = [&](QualType T) { + if (auto *AT = Context.getAsArrayType(T)) + return AT->getElementType(); + return T->getPointeeType(); + }; + + T1 = Unwrap(T1); + T2 = Unwrap(T2); return T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind : CastAwayConstnessKind::CACK_Incoherent; } @@ -1674,29 +1687,14 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, msg = diag::err_bad_const_cast_dest; return TC_NotApplicable; } - SrcType = Self.Context.getCanonicalType(SrcType); - // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are - // completely equal. - // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers - // in multi-level pointers may change, but the level count must be the same, - // as must be the final pointee type. - while (SrcType != DestType && - Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) { - Qualifiers SrcQuals, DestQuals; - SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals); - DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals); - - // const_cast is permitted to strip cvr-qualifiers, only. Make sure that - // the other qualifiers (e.g., address spaces) are identical. - SrcQuals.removeCVRQualifiers(); - DestQuals.removeCVRQualifiers(); - if (SrcQuals != DestQuals) - return TC_NotApplicable; - } - - // Since we're dealing in canonical types, the remainder must be the same. - if (SrcType != DestType) + // C++ [expr.const.cast]p3: + // "For two similar types T1 and T2, [...]" + // + // We only allow a const_cast to change cvr-qualifiers, not other kinds of + // type qualifiers. (Likewise, we ignore other changes when determining + // whether a cast casts away constness.) + if (!Self.Context.hasCvrSimilarType(SrcType, DestType)) return TC_NotApplicable; if (NeedToMaterializeTemporary) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6f01f19fc5..35c3612c71 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3087,7 +3087,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, // in multi-level pointers, subject to the following rules: [...] bool PreviousToQualsIncludeConst = true; bool UnwrappedAnyPointer = false; - while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) { + while (Context.UnwrapSimilarTypes(FromType, ToType)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -3642,16 +3642,6 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc, return Result; } -static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { - while (Context.UnwrapSimilarPointerTypes(T1, T2)) { - Qualifiers Quals; - T1 = Context.getUnqualifiedArrayType(T1, Quals); - T2 = Context.getUnqualifiedArrayType(T2, Quals); - } - - return Context.hasSameUnqualifiedType(T1, T2); -} - // Per 13.3.3.2p3, compare the given standard conversion sequences to // determine if one is a proper subset of the other. static ImplicitConversionSequence::CompareKind @@ -3675,7 +3665,7 @@ compareStandardConversionSubsets(ASTContext &Context, Result = ImplicitConversionSequence::Worse; else return ImplicitConversionSequence::Indistinguishable; - } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1))) + } else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1))) return ImplicitConversionSequence::Indistinguishable; if (SCS1.Third == SCS2.Third) { @@ -3949,7 +3939,7 @@ CompareQualificationConversions(Sema &S, : ImplicitConversionSequence::Better; } - while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) { + while (S.Context.UnwrapSimilarTypes(T1, T2)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 59bf9f8752..febe7cdb83 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -459,7 +459,7 @@ DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state, /// Assumes the input types are canonical. static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, QualType FromTy) { - while (Context.UnwrapSimilarPointerTypes(ToTy, FromTy)) { + while (Context.UnwrapSimilarTypes(ToTy, FromTy)) { Qualifiers Quals1, Quals2; ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1); FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2); @@ -474,6 +474,10 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy, // If we are casting to void, the 'From' value can be used to represent the // 'To' value. + // + // FIXME: Doing this after unwrapping the types doesn't make any sense. A + // cast from 'int**' to 'void**' is not special in the way that a cast from + // 'int*' to 'void*' is. if (ToTy->isVoidType()) return true; diff --git a/test/CXX/drs/dr3xx.cpp b/test/CXX/drs/dr3xx.cpp index 15261007dd..04fd258a7c 100644 --- a/test/CXX/drs/dr3xx.cpp +++ b/test/CXX/drs/dr3xx.cpp @@ -354,6 +354,57 @@ namespace dr329 { // dr329: 3.5 } } +namespace dr330 { // dr330: 7 + // Conversions between P and Q will be allowed by P0388. + typedef int *(*P)[3]; + typedef const int *const (*Q)[3]; + typedef const int *Qinner[3]; + typedef Qinner const *Q2; // same as Q, but 'const' written outside the array type + typedef const int *const (*R)[4]; + typedef const int *const (*S)[]; + typedef const int *(*T)[]; + void f(P p, Q q, Q2 q2, R r, S s, T t) { + q = p; // ok + q2 = p; // ok + r = p; // expected-error {{incompatible}} + s = p; // expected-error {{incompatible}} (for now) + t = p; // expected-error {{incompatible}} + s = q; // expected-error {{incompatible}} + s = q2; // expected-error {{incompatible}} + s = t; // ok, adding const + t = s; // expected-error {{incompatible}} + (void) const_cast

(q); + (void) const_cast

(q2); + (void) const_cast(p); + (void) const_cast(p); + (void) const_cast(p); // expected-error {{not allowed}} (for now) + (void) const_cast

(s); // expected-error {{not allowed}} (for now) + (void) const_cast(q); // expected-error {{not allowed}} + (void) const_cast(q2); // expected-error {{not allowed}} + (void) const_cast(s); // expected-error {{not allowed}} + (void) const_cast(s); // expected-error {{not allowed}} + (void) const_cast(s); + (void) const_cast(t); + (void) const_cast(q); // expected-error {{not allowed}} + (void) const_cast(t); // expected-error {{not allowed}} + + (void) reinterpret_cast

(q); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast

(q2); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(p); + (void) reinterpret_cast(p); + (void) reinterpret_cast(p); + (void) reinterpret_cast

(s); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(q); + (void) reinterpret_cast(q2); + (void) reinterpret_cast(s); + (void) reinterpret_cast(s); + (void) reinterpret_cast(s); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(t); + (void) reinterpret_cast(q); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(t); + } +} + namespace dr331 { // dr331: yes struct A { A(volatile A&); // expected-note {{candidate}} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp index 87df61cbc7..a9268660f1 100644 --- a/test/SemaCXX/const-cast.cpp +++ b/test/SemaCXX/const-cast.cpp @@ -58,8 +58,14 @@ short *bad_const_cast_test(char const *volatile *const volatile *var) // Non-pointer. char v = const_cast(**var2); // expected-error {{const_cast to 'char', which is not a reference, pointer-to-object, or pointer-to-data-member}} const int *ar[100] = {0}; - // Not even lenient g++ accepts this. - int *(*rar)[100] = const_cast(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[100]' is not allowed}} + extern const int *aub[]; + // const_cast looks through arrays as of DR330. + (void) const_cast(&ar); // ok + (void) const_cast(&aub); // ok + // ... but the array bound must exactly match. + (void) const_cast(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[]' is not allowed}} + (void) const_cast(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[99]' is not allowed}} + (void) const_cast(&aub); // expected-error {{const_cast from 'const int *(*)[]' to 'int *(*)[100]' is not allowed}} f fp1 = 0; // Function pointers. f fp2 = const_cast(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index e47dbd6921..93d4ee93fb 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -2021,7 +2021,7 @@ of class templates 330 CD4 Qualification conversions and pointers to arrays of pointers - Unknown + SVN 331 -- GitLab From e7e3affb96522e46cd36cc0e774c533f3c7c47b8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Jul 2018 00:29:05 +0000 Subject: [PATCH 0493/1023] PR38095: Allow constant-folding of loads through bitcasted pointers if the bitcast only changed cvr-qualifications within the pointer type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336746 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 10 +++++++--- test/Sema/diagnose_if.c | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 828368a3e1..bf21bc65e2 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -5787,8 +5787,8 @@ bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { return evaluateLValue(E->getSubExpr(), Result); } -bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { - const Expr* SubExpr = E->getSubExpr(); +bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { + const Expr *SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: @@ -5805,7 +5805,11 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - Result.Designator.setInvalid(); + // If we changed anything other than cvr-qualifiers, we can't use this + // value for constant folding. FIXME: Qualification conversions should + // always be CK_NoOp, but we get this wrong in C. + if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType())) + Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); diff --git a/test/Sema/diagnose_if.c b/test/Sema/diagnose_if.c index 38a3307d92..00bb4770f0 100644 --- a/test/Sema/diagnose_if.c +++ b/test/Sema/diagnose_if.c @@ -157,3 +157,13 @@ void runAlwaysWarnWithArg(int a) { // Bug: we would complain about `a` being undeclared if this was spelled // __diagnose_if__. void underbarName(int a) __attribute__((__diagnose_if__(a, "", "warning"))); + +// PR38095 +void constCharStar(const char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}} +void charStar(char *str) __attribute__((__diagnose_if__(!str[0], "empty string not allowed", "error"))); // expected-note {{from}} +void runConstCharStar() { + constCharStar("foo"); + charStar("bar"); + constCharStar(""); // expected-error {{empty string not allowed}} + charStar(""); // expected-error {{empty string not allowed}} +} -- GitLab From 7e865695ef6862a9cbe08691c9a4a7dc8a3e6c25 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Jul 2018 00:34:54 +0000 Subject: [PATCH 0494/1023] [docs] List correct default for -ftemplate-depth; also add missing documentation for -fconstexpr-steps. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336747 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/UsersManual.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index b1c286193c..4470dab947 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -2116,10 +2116,15 @@ Controlling implementation limits Sets the limit for recursive constexpr function invocations to N. The default is 512. +.. option:: -fconstexpr-steps=N + + Sets the limit for the number of full-expressions evaluated in a single + constant expression evaluation. The default is 1048576. + .. option:: -ftemplate-depth=N Sets the limit for recursively nested template instantiations to N. The - default is 256. + default is 1024. .. option:: -foperator-arrow-depth=N -- GitLab From f0eae10403f79ea550b2ae052401802b6776dcaa Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Wed, 11 Jul 2018 00:45:48 +0000 Subject: [PATCH 0495/1023] Remove qualtype qualifier in coroutine error to prevent assert in debug Summary: A forward-declared coroutine_traits should trip an error; we need a complete type. Unfortunately, in debug mode only, we trip an assert when attempting to provide the fully qualified type for the error message. If you try to compile a program with a forward-declared coroutine_traits in debug mode, clang will crash. I've included a test for the behavior and removed the q modifier on the error message. This prevents the crash in debug mode and does not change the behavior for the error message on a forward-declaration of a coroutine_traits type. Test Plan: I've included a test for the forward-declaration. Patch by Tanoy Sinha! Reviewers: modocache, GorNishanov Reviewed By: modocache Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49099 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336748 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 +- .../coroutine-traits-undefined-template.cpp | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/SemaCXX/coroutine-traits-undefined-template.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e6d2de1791..a52ac69a33 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -9082,7 +9082,7 @@ def err_coroutine_promise_type_incomplete : Error< "this function cannot be a coroutine: %0 is an incomplete type">; def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " - "specialization %q0">; + "specialization %0">; def err_coroutine_promise_incompatible_return_functions : Error< "the coroutine promise type %0 declares both 'return_value' and 'return_void'">; def err_coroutine_promise_requires_return_function : Error< diff --git a/test/SemaCXX/coroutine-traits-undefined-template.cpp b/test/SemaCXX/coroutine-traits-undefined-template.cpp new file mode 100644 index 0000000000..9016db8dde --- /dev/null +++ b/test/SemaCXX/coroutine-traits-undefined-template.cpp @@ -0,0 +1,21 @@ +// test/SemaCXX/coroutine-traits-undefined-template.cpp + +// This file contains references to sections of the Coroutines TS, which can be +// found at http://wg21.link/coroutines. + +// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result + +namespace std { +namespace experimental { + +template +struct coroutine_traits { + struct promise_type {}; +}; + +template<> struct coroutine_traits; // expected-note {{forward declaration of 'std::experimental::coroutine_traits'}} +}} // namespace std::experimental + +void uses_forward_declaration() { + co_return; // expected-error {{this function cannot be a coroutine: missing definition of specialization 'coroutine_traits'}} +} -- GitLab From 487ab4cfa8b65c414b05c3cd9d29fef1ea185e8a Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Wed, 11 Jul 2018 01:00:53 +0000 Subject: [PATCH 0496/1023] [SemaCXX] Remove comment from coroutines test, NFC Summary: The file name was accidentally included when the test file was added. Test Plan: check-clang git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336750 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/coroutine-traits-undefined-template.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/SemaCXX/coroutine-traits-undefined-template.cpp b/test/SemaCXX/coroutine-traits-undefined-template.cpp index 9016db8dde..4687ed245a 100644 --- a/test/SemaCXX/coroutine-traits-undefined-template.cpp +++ b/test/SemaCXX/coroutine-traits-undefined-template.cpp @@ -1,5 +1,3 @@ -// test/SemaCXX/coroutine-traits-undefined-template.cpp - // This file contains references to sections of the Coroutines TS, which can be // found at http://wg21.link/coroutines. -- GitLab From 545b456622b27879b4bd0ccbea1efc775ce665e0 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 11 Jul 2018 01:23:27 +0000 Subject: [PATCH 0497/1023] [analyzer] Pass through all arguments from the registerChecker() to the checker constructor A lot of checkers could be cleaned up in a similar way Differential Revision: https://reviews.llvm.org/D49050 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336753 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../StaticAnalyzer/Core/CheckerManager.h | 23 ++++--------------- .../Checkers/DynamicTypePropagation.cpp | 15 ++++++------ 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 9d87b440dc..99a8eb01fa 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -144,31 +144,18 @@ public: //===----------------------------------------------------------------------===// /// Used to register checkers. + /// All arguments are automatically passed through to the checker + /// constructor. /// /// \returns a pointer to the checker object. - template - CHECKER *registerChecker() { - CheckerTag tag = getTag(); - CheckerRef &ref = CheckerTags[tag]; - if (ref) - return static_cast(ref); // already registered. - - CHECKER *checker = new CHECKER(); - checker->Name = CurrentCheckName; - CheckerDtors.push_back(CheckerDtor(checker, destruct)); - CHECKER::_register(checker, *this); - ref = checker; - return checker; - } - - template - CHECKER *registerChecker(AnalyzerOptions &AOpts) { + template + CHECKER *registerChecker(AT... Args) { CheckerTag tag = getTag(); CheckerRef &ref = CheckerTags[tag]; if (ref) return static_cast(ref); // already registered. - CHECKER *checker = new CHECKER(AOpts); + CHECKER *checker = new CHECKER(Args...); checker->Name = CurrentCheckName; CheckerDtors.push_back(CheckerDtor(checker, destruct)); CHECKER::_register(checker, *this); diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 126e57645a..914ba86850 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -56,6 +56,12 @@ class DynamicTypePropagation: check::PostStmt, check::PreObjCMessage, check::PostObjCMessage > { +private: + /// This value is set to true, when the Generics checker is turned on. + bool CheckGenerics; +public: + DynamicTypePropagation(bool CheckGenerics) + : CheckGenerics(CheckGenerics) {} const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, CheckerContext &C) const; @@ -107,9 +113,6 @@ public: void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const; void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const; - - /// This value is set to true, when the Generics checker is turned on. - DefaultBool CheckGenerics; }; } // end anonymous namespace @@ -995,11 +998,9 @@ DynamicTypePropagation::GenericsBugVisitor::VisitNode(const ExplodedNode *N, /// Register checkers. void ento::registerObjCGenericsChecker(CheckerManager &mgr) { - DynamicTypePropagation *checker = - mgr.registerChecker(); - checker->CheckGenerics = true; + mgr.registerChecker(/*CheckGenerics=*/true); } void ento::registerDynamicTypePropagation(CheckerManager &mgr) { - mgr.registerChecker(); + mgr.registerChecker(/*CheckGenerics=*/false); } -- GitLab From d431316e00fbb73bb6220ee9c07b8d4051651334 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 11 Jul 2018 01:58:08 +0000 Subject: [PATCH 0498/1023] [analyzer] Partial revert of https://reviews.llvm.org/D49050 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336755 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/DynamicTypePropagation.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 914ba86850..126e57645a 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -56,12 +56,6 @@ class DynamicTypePropagation: check::PostStmt, check::PreObjCMessage, check::PostObjCMessage > { -private: - /// This value is set to true, when the Generics checker is turned on. - bool CheckGenerics; -public: - DynamicTypePropagation(bool CheckGenerics) - : CheckGenerics(CheckGenerics) {} const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, CheckerContext &C) const; @@ -113,6 +107,9 @@ public: void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const; void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const; + + /// This value is set to true, when the Generics checker is turned on. + DefaultBool CheckGenerics; }; } // end anonymous namespace @@ -998,9 +995,11 @@ DynamicTypePropagation::GenericsBugVisitor::VisitNode(const ExplodedNode *N, /// Register checkers. void ento::registerObjCGenericsChecker(CheckerManager &mgr) { - mgr.registerChecker(/*CheckGenerics=*/true); + DynamicTypePropagation *checker = + mgr.registerChecker(); + checker->CheckGenerics = true; } void ento::registerDynamicTypePropagation(CheckerManager &mgr) { - mgr.registerChecker(/*CheckGenerics=*/false); + mgr.registerChecker(); } -- GitLab From bb374a81525139b5ce10f67fb1e8f5eabc4556f0 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 11 Jul 2018 02:01:18 +0000 Subject: [PATCH 0499/1023] [analyzer] Fix bots by changing the analyzer-config tests. To be investigated. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336756 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/analyzer-config.c | 3 +-- test/Analysis/analyzer-config.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c index 2105a4faf4..c09800f44b 100644 --- a/test/Analysis/analyzer-config.c +++ b/test/Analysis/analyzer-config.c @@ -25,7 +25,6 @@ void foo() { // CHECK-NEXT: inline-lambdas = true // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 -// CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 100 // CHECK-NEXT: max-nodes = 225000 // CHECK-NEXT: max-times-inline-large = 32 @@ -36,4 +35,4 @@ void foo() { // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 24 +// CHECK-NEXT: num-entries = 23 diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp index 0eaefe2abf..e87045448d 100644 --- a/test/Analysis/analyzer-config.cpp +++ b/test/Analysis/analyzer-config.cpp @@ -40,7 +40,6 @@ public: // CHECK-NEXT: inline-lambdas = true // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 -// CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 100 // CHECK-NEXT: max-nodes = 225000 // CHECK-NEXT: max-times-inline-large = 32 @@ -51,4 +50,4 @@ public: // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 31 +// CHECK-NEXT: num-entries = 30 -- GitLab From 3ace827b6b1143960561adc4c63e87c67b6ac85b Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Wed, 11 Jul 2018 09:37:24 +0000 Subject: [PATCH 0500/1023] [AST] Structural equivalence of methods Summary: Added structural equivalence check for C++ methods. Improved structural equivalence tests. Added related ASTImporter tests. Reviewers: a.sidorin, szepet, xazax.hun, martong, a_sidorin Reviewed By: martong, a_sidorin Subscribers: a_sidorin, rnkovacs, cfe-commits Differential Revision: https://reviews.llvm.org/D48628 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336776 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 24 +- lib/AST/ASTStructuralEquivalence.cpp | 94 +++- unittests/AST/ASTImporterTest.cpp | 126 ++++++ unittests/AST/StructuralEquivalenceTest.cpp | 448 +++++++++++++++++--- 4 files changed, 619 insertions(+), 73 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 0e3756265e..b9cd608ac1 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -230,6 +230,7 @@ namespace clang { bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); bool IsStructuralMatch(FunctionTemplateDecl *From, FunctionTemplateDecl *To); + bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); @@ -1525,6 +1526,13 @@ bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, return Ctx.IsStructurallyEquivalent(From, To); } +bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + return Ctx.IsStructurallyEquivalent(From, To); +} + bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC) { const llvm::APSInt &FromVal = FromEC->getInitVal(); @@ -2433,13 +2441,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (auto *FoundFunction = dyn_cast(FoundDecl)) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { - if (Importer.IsStructurallyEquivalent(D->getType(), - FoundFunction->getType())) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); - FoundByLookup = FoundFunction; - break; + if (IsStructuralMatch(D, FoundFunction)) { + const FunctionDecl *Definition = nullptr; + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody(Definition)) { + return Importer.Imported( + D, const_cast(Definition)); + } + FoundByLookup = FoundFunction; + break; } // FIXME: Check for overloading more carefully, e.g., by boosting diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index b543991873..367755ffd0 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -250,6 +250,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (T1.isNull() || T2.isNull()) return T1.isNull() && T2.isNull(); + QualType OrigT1 = T1; + QualType OrigT2 = T2; + if (!Context.StrictTypeSpelling) { // We aren't being strict about token-to-token equivalence of types, // so map down to the canonical type. @@ -422,6 +425,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::FunctionProto: { const auto *Proto1 = cast(T1); const auto *Proto2 = cast(T2); + if (Proto1->getNumParams() != Proto2->getNumParams()) return false; for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { @@ -431,23 +435,33 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } if (Proto1->isVariadic() != Proto2->isVariadic()) return false; - if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType()) + + if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) return false; - if (Proto1->getExceptionSpecType() == EST_Dynamic) { - if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) + + // Check exceptions, this information is lost in canonical type. + const auto *OrigProto1 = + cast(OrigT1.getDesugaredType(Context.FromCtx)); + const auto *OrigProto2 = + cast(OrigT2.getDesugaredType(Context.ToCtx)); + auto Spec1 = OrigProto1->getExceptionSpecType(); + auto Spec2 = OrigProto2->getExceptionSpecType(); + + if (Spec1 != Spec2) + return false; + if (Spec1 == EST_Dynamic) { + if (OrigProto1->getNumExceptions() != OrigProto2->getNumExceptions()) return false; - for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, Proto1->getExceptionType(I), - Proto2->getExceptionType(I))) + for (unsigned I = 0, N = OrigProto1->getNumExceptions(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, OrigProto1->getExceptionType(I), + OrigProto2->getExceptionType(I))) return false; } - } else if (isComputedNoexcept(Proto1->getExceptionSpecType())) { - if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(), - Proto2->getNoexceptExpr())) + } else if (isComputedNoexcept(Spec1)) { + if (!IsStructurallyEquivalent(Context, OrigProto1->getNoexceptExpr(), + OrigProto2->getNoexceptExpr())) return false; } - if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) - return false; // Fall through to check the bits common with FunctionNoProtoType. LLVM_FALLTHROUGH; @@ -830,6 +844,56 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence of two methodss. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + CXXMethodDecl *Method1, + CXXMethodDecl *Method2) { + bool PropertiesEqual = + Method1->getDeclKind() == Method2->getDeclKind() && + Method1->getRefQualifier() == Method2->getRefQualifier() && + Method1->getAccess() == Method2->getAccess() && + Method1->getOverloadedOperator() == Method2->getOverloadedOperator() && + Method1->isStatic() == Method2->isStatic() && + Method1->isConst() == Method2->isConst() && + Method1->isVolatile() == Method2->isVolatile() && + Method1->isVirtual() == Method2->isVirtual() && + Method1->isPure() == Method2->isPure() && + Method1->isDefaulted() == Method2->isDefaulted() && + Method1->isDeleted() == Method2->isDeleted(); + if (!PropertiesEqual) + return false; + // FIXME: Check for 'final'. + + if (auto *Constructor1 = dyn_cast(Method1)) { + auto *Constructor2 = cast(Method2); + if (Constructor1->isExplicit() != Constructor2->isExplicit()) + return false; + } + + if (auto *Conversion1 = dyn_cast(Method1)) { + auto *Conversion2 = cast(Method2); + if (Conversion1->isExplicit() != Conversion2->isExplicit()) + return false; + if (!IsStructurallyEquivalent(Context, Conversion1->getConversionType(), + Conversion2->getConversionType())) + return false; + } + + const IdentifierInfo *Name1 = Method1->getIdentifier(); + const IdentifierInfo *Name2 = Method2->getIdentifier(); + if (!::IsStructurallyEquivalent(Name1, Name2)) { + return false; + // TODO: Names do not match, add warning like at check for FieldDecl. + } + + // Check the prototypes. + if (!::IsStructurallyEquivalent(Context, + Method1->getType(), Method2->getType())) + return false; + + return true; +} + /// Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { @@ -1445,6 +1509,14 @@ bool StructuralEquivalenceContext::Finish() { // Kind mismatch. Equivalent = false; } + } else if (auto *MD1 = dyn_cast(D1)) { + if (auto *MD2 = dyn_cast(D2)) { + if (!::IsStructurallyEquivalent(*this, MD1, MD2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } } else if (FunctionDecl *FD1 = dyn_cast(D1)) { if (FunctionDecl *FD2 = dyn_cast(D2)) { if (!::IsStructurallyEquivalent(FD1->getIdentifier(), diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 34ed5b93a8..50f7285a39 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -2243,6 +2243,132 @@ TEST_P(ImportExpr, UnresolvedMemberExpr) { compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))))); } +TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) { + Decl *ToR1; + { + Decl *FromTU = getTuDecl( + "struct A { };", Lang_CXX, "input0.cc"); + auto *FromR = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("A"))); + + ToR1 = Import(FromR, Lang_CXX); + } + + Decl *ToR2; + { + Decl *FromTU = getTuDecl( + "struct A { };", Lang_CXX, "input1.cc"); + auto *FromR = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("A"))); + + ToR2 = Import(FromR, Lang_CXX); + } + + EXPECT_EQ(ToR1, ToR2); +} + +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) { + Decl *ToR1; + { + Decl *FromTU = getTuDecl( + "struct A { int x; };", Lang_CXX, "input0.cc"); + auto *FromR = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("A"))); + ToR1 = Import(FromR, Lang_CXX); + } + Decl *ToR2; + { + Decl *FromTU = getTuDecl( + "struct A { unsigned x; };", Lang_CXX, "input1.cc"); + auto *FromR = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("A"))); + ToR2 = Import(FromR, Lang_CXX); + } + EXPECT_NE(ToR1, ToR2); +} + +TEST_P(ASTImporterTestBase, ImportOfEquivalentField) { + Decl *ToF1; + { + Decl *FromTU = getTuDecl( + "struct A { int x; };", Lang_CXX, "input0.cc"); + auto *FromF = FirstDeclMatcher().match( + FromTU, fieldDecl(hasName("x"))); + ToF1 = Import(FromF, Lang_CXX); + } + Decl *ToF2; + { + Decl *FromTU = getTuDecl( + "struct A { int x; };", Lang_CXX, "input1.cc"); + auto *FromF = FirstDeclMatcher().match( + FromTU, fieldDecl(hasName("x"))); + ToF2 = Import(FromF, Lang_CXX); + } + EXPECT_EQ(ToF1, ToF2); +} + +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) { + Decl *ToF1; + { + Decl *FromTU = getTuDecl( + "struct A { int x; };", Lang_CXX, "input0.cc"); + auto *FromF = FirstDeclMatcher().match( + FromTU, fieldDecl(hasName("x"))); + ToF1 = Import(FromF, Lang_CXX); + } + Decl *ToF2; + { + Decl *FromTU = getTuDecl( + "struct A { unsigned x; };", Lang_CXX, "input1.cc"); + auto *FromF = FirstDeclMatcher().match( + FromTU, fieldDecl(hasName("x"))); + ToF2 = Import(FromF, Lang_CXX); + } + EXPECT_NE(ToF1, ToF2); +} + +TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) { + Decl *ToM1; + { + Decl *FromTU = getTuDecl( + "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc"); + auto *FromM = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("x"), isDefinition())); + ToM1 = Import(FromM, Lang_CXX); + } + Decl *ToM2; + { + Decl *FromTU = getTuDecl( + "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc"); + auto *FromM = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("x"), isDefinition())); + ToM2 = Import(FromM, Lang_CXX); + } + EXPECT_EQ(ToM1, ToM2); +} + +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) { + Decl *ToM1; + { + Decl *FromTU = getTuDecl( + "struct A { void x(); }; void A::x() { }", + Lang_CXX, "input0.cc"); + auto *FromM = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("x"), isDefinition())); + ToM1 = Import(FromM, Lang_CXX); + } + Decl *ToM2; + { + Decl *FromTU = getTuDecl( + "struct A { void x() const; }; void A::x() const { }", + Lang_CXX, "input1.cc"); + auto *FromM = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("x"), isDefinition())); + ToM2 = Import(FromM, Lang_CXX); + } + EXPECT_NE(ToM1, ToM2); +} + struct DeclContextTest : ASTImporterTestBase {}; TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp index a8ac79205d..16998f2420 100644 --- a/unittests/AST/StructuralEquivalenceTest.cpp +++ b/unittests/AST/StructuralEquivalenceTest.cpp @@ -18,13 +18,13 @@ struct StructuralEquivalenceTest : ::testing::Test { std::unique_ptr AST0, AST1; std::string Code0, Code1; // Buffers for SourceManager - // Get a pair of Decl pointers to the synthetised declarations from the given - // code snipets. By default we search for the unique Decl with name 'foo' in - // both snippets. - std::tuple - makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1, - Language Lang, const char *const Identifier = "foo") { - + // Get a pair of node pointers into the synthesized AST from the given code + // snippets. To determine the returned node, a separate matcher is specified + // for both snippets. The first matching node is returned. + template + std::tuple makeDecls( + const std::string &SrcCode0, const std::string &SrcCode1, Language Lang, + const MatcherType &Matcher0, const MatcherType &Matcher1) { this->Code0 = SrcCode0; this->Code1 = SrcCode1; ArgVector Args = getBasicRunOptionsForLanguage(Lang); @@ -34,28 +34,32 @@ struct StructuralEquivalenceTest : ::testing::Test { AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName); AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName); - ASTContext &Ctx0 = AST0->getASTContext(), &Ctx1 = AST1->getASTContext(); - - auto getDecl = [](ASTContext &Ctx, const std::string &Name) -> NamedDecl * { - IdentifierInfo *SearchedII = &Ctx.Idents.get(Name); - assert(SearchedII && "Declaration with the identifier " - "should be specified in test!"); - DeclarationName SearchDeclName(SearchedII); - SmallVector FoundDecls; - Ctx.getTranslationUnitDecl()->localUncachedLookup(SearchDeclName, - FoundDecls); + NodeType *D0 = FirstDeclMatcher().match( + AST0->getASTContext().getTranslationUnitDecl(), Matcher0); + NodeType *D1 = FirstDeclMatcher().match( + AST1->getASTContext().getTranslationUnitDecl(), Matcher1); - // We should find one Decl but one only. - assert(FoundDecls.size() == 1); + return std::make_tuple(D0, D1); + } - return FoundDecls[0]; - }; + // Get a pair of node pointers into the synthesized AST from the given code + // snippets. The same matcher is used for both snippets. + template + std::tuple makeDecls( + const std::string &SrcCode0, const std::string &SrcCode1, Language Lang, + const MatcherType &AMatcher) { + return makeDecls( + SrcCode0, SrcCode1, Lang, AMatcher, AMatcher); + } - NamedDecl *D0 = getDecl(Ctx0, Identifier); - NamedDecl *D1 = getDecl(Ctx1, Identifier); - assert(D0); - assert(D1); - return std::make_tuple(D0, D1); + // Get a pair of Decl pointers to the synthesized declarations from the given + // code snippets. We search for the first NamedDecl with given name in both + // snippets. + std::tuple makeNamedDecls( + const std::string &SrcCode0, const std::string &SrcCode1, + Language Lang, const char *const Identifier = "foo") { + auto Matcher = namedDecl(hasName(Identifier)); + return makeDecls(SrcCode0, SrcCode1, Lang, Matcher); } bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { @@ -110,35 +114,29 @@ TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) { } TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) { - auto Decls = makeNamedDecls( - "template struct foo; template<> struct foo{};", - "template struct foo; template<> struct foo{};", - Lang_CXX); - ClassTemplateSpecializationDecl *Spec0 = - *cast(get<0>(Decls))->spec_begin(); - ClassTemplateSpecializationDecl *Spec1 = - *cast(get<1>(Decls))->spec_begin(); - ASSERT_TRUE(Spec0 != nullptr); - ASSERT_TRUE(Spec1 != nullptr); + auto Decls = makeDecls( + R"(template struct foo; template<> struct foo{};)", + R"(template struct foo; template<> struct foo{};)", + Lang_CXX, + classTemplateSpecializationDecl()); + auto Spec0 = get<0>(Decls); + auto Spec1 = get<1>(Decls); EXPECT_TRUE(testStructuralMatch(Spec0, Spec1)); } TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) { - auto Decls = makeNamedDecls( - "template struct foo; template<> struct foo{};", - "template struct foo; template<> struct foo{};", - Lang_CXX); - ClassTemplateSpecializationDecl *Spec0 = - *cast(get<0>(Decls))->spec_begin(); - ClassTemplateSpecializationDecl *Spec1 = - *cast(get<1>(Decls))->spec_begin(); - ASSERT_TRUE(Spec0 != nullptr); - ASSERT_TRUE(Spec1 != nullptr); + auto Decls = makeDecls( + R"(template struct foo; template<> struct foo{};)", + R"(template struct foo; template<> struct foo{};)", + Lang_CXX, + classTemplateSpecializationDecl()); + auto Spec0 = get<0>(Decls); + auto Spec1 = get<1>(Decls); EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); } TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) { - auto Decls = makeNamedDecls( + auto Decls = makeDecls( R"( struct true_type{}; template struct foo; @@ -149,14 +147,9 @@ TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) { template struct foo; template<> struct foo : true_type {}; )", - Lang_CXX); - ClassTemplateSpecializationDecl *Spec0 = - *cast(get<0>(Decls))->spec_begin(); - ClassTemplateSpecializationDecl *Spec1 = - *cast(get<1>(Decls))->spec_begin(); - ASSERT_TRUE(Spec0 != nullptr); - ASSERT_TRUE(Spec1 != nullptr); - EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); + Lang_CXX, + classTemplateSpecializationDecl()); + EXPECT_FALSE(testStructuralMatch(Decls)); } // This test is disabled for now. @@ -203,5 +196,350 @@ TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) { EXPECT_FALSE(testStructuralMatch(Decls)); } +struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { +}; + +TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { + auto t = makeNamedDecls("void foo(int&);", + "void foo(const int&);", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) { + auto t = makeNamedDecls("void foo(int);", + "void foo(const int);", Lang_CXX); + EXPECT_TRUE(testStructuralMatch(t)); + // consider this OK +} + +TEST_F(StructuralEquivalenceFunctionTest, Throw) { + auto t = makeNamedDecls("void foo();", + "void foo() throw();", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, Noexcept) { + auto t = makeNamedDecls("void foo();", + "void foo() noexcept;", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) { + auto t = makeNamedDecls("void foo() throw();", + "void foo() noexcept;", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) { + auto t = makeNamedDecls("void foo() throw();", + "void foo() noexcept(false);", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) { + auto t = makeNamedDecls("void foo() throw();", + "void foo() noexcept(true);", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) { + // The expression is not checked yet. + auto t = makeNamedDecls("void foo() noexcept(false);", + "void foo() noexcept(true);", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) { + auto t = makeNamedDecls("void foo() noexcept(false);", + "void foo() noexcept(false);", Lang_CXX11); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) { + auto t = makeNamedDecls("void foo() noexcept;", + "void foo() noexcept(false);", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) { + auto t = makeNamedDecls("void foo() noexcept;", + "void foo() noexcept(true);", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ReturnType) { + auto t = makeNamedDecls("char foo();", + "int foo();", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) { + auto t = makeNamedDecls("char foo();", + "const char foo();", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) { + auto t = makeNamedDecls("char &foo();", + "char &&foo();", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ParamCount) { + auto t = makeNamedDecls("void foo(int);", + "void foo(int, int);", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ParamType) { + auto t = makeNamedDecls("void foo(int);", + "void foo(char);", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ParamName) { + auto t = makeNamedDecls("void foo(int a);", + "void foo(int b);", Lang_CXX); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, Variadic) { + auto t = makeNamedDecls("void foo(int x...);", + "void foo(int x);", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) { + auto t = makeNamedDecls("void foo(int *);", + "void foo(int);", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NameInParen) { + auto t = makeNamedDecls( + "void ((foo))();", + "void foo();", + Lang_CXX); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) { + auto t = makeNamedDecls( + "void (foo)() throw(int);", + "void (foo)() noexcept;", + Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) { + auto t = makeNamedDecls( + "struct A { void (foo)() const; };", + "struct A { void (foo)(); };", + Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest { +}; + +TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) { + auto t = makeDecls( + "struct X { void foo(); };", + "struct X { virtual void foo(); };", Lang_CXX, + cxxMethodDecl(hasName("foo"))); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Pure) { + auto t = makeNamedDecls("struct X { virtual void foo(); };", + "struct X { virtual void foo() = 0; };", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) { + // The final-ness is not checked yet. + auto t = makeNamedDecls("struct X { virtual void foo(); };", + "struct X { virtual void foo() final; };", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Const) { + auto t = makeNamedDecls("struct X { void foo(); };", + "struct X { void foo() const; };", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Static) { + auto t = makeNamedDecls("struct X { void foo(); };", + "struct X { static void foo(); };", Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) { + auto t = makeNamedDecls("struct X { void foo(); };", + "struct X { void foo() &&; };", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) { + auto t = makeNamedDecls("struct X { void foo() &; };", + "struct X { void foo() &&; };", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) { + auto t = makeDecls( + "struct X { public: void foo(); };", + "struct X { private: void foo(); };", Lang_CXX, + cxxMethodDecl(hasName("foo"))); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Delete) { + auto t = makeNamedDecls("struct X { void foo(); };", + "struct X { void foo() = delete; };", Lang_CXX11); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { + auto t = makeDecls( + "void foo();", "struct foo { foo(); };", Lang_CXX, + functionDecl(), cxxConstructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { + auto t = makeDecls("struct X { X(); };", + "struct X { X(int); };", Lang_CXX, + cxxConstructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) { + auto t = makeDecls("struct X { X(int); };", + "struct X { explicit X(int); };", + Lang_CXX11, + cxxConstructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { + auto t = makeDecls("struct X { X(); };", + "struct X { X() = default; };", + Lang_CXX11, + cxxConstructorDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) { + auto t = makeDecls("struct X { operator bool(); };", + "struct X { operator char(); };", + Lang_CXX11, + cxxConversionDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, Operator) { + auto t = makeDecls( + "struct X { int operator +(int); };", + "struct X { int operator -(int); };", Lang_CXX, + functionDecl(hasOverloadedOperatorName("+")), + functionDecl(hasOverloadedOperatorName("-"))); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) { + auto t = makeDecls( + "struct X { virtual void f(); }; void X::f() { }", + "struct X { virtual void f() { }; };", + Lang_CXX, + functionDecl(allOf(hasName("f"), isDefinition()))); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) { + auto t = makeDecls( + "struct X { virtual void f(); }; void X::f() { }", + "struct X { void f(); }; void X::f() { }", + Lang_CXX, + functionDecl(allOf(hasName("f"), isDefinition()))); + EXPECT_FALSE(testStructuralMatch(t)); +} + +struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest { +}; + +TEST_F(StructuralEquivalenceRecordTest, Name) { + auto t = makeDecls( + "struct A{ };", + "struct B{ };", + Lang_CXX, + cxxRecordDecl()); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, Fields) { + auto t = makeNamedDecls( + "struct foo{ int x; };", + "struct foo{ char x; };", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) { + // Currently, methods of a class are not checked at class equivalence. + auto t = makeNamedDecls( + "struct foo{ int x(); };", + "struct foo{ char x(); };", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, Bases) { + auto t = makeNamedDecls( + "struct A{ }; struct foo: A { };", + "struct B{ }; struct foo: B { };", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) { + auto t = makeNamedDecls( + "struct A{ }; struct foo: A { };", + "struct A{ }; struct foo: virtual A { };", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) { + // Access specifier in inheritance is not checked yet. + auto t = makeNamedDecls( + "struct A{ }; struct foo: public A { };", + "struct A{ }; struct foo: private A { };", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceRecordTest, Match) { + auto Code = R"( + struct A{ }; + struct B{ }; + struct foo: A, virtual B { + void x(); + int a; + }; + )"; + auto t = makeNamedDecls(Code, Code, Lang_CXX); + EXPECT_TRUE(testStructuralMatch(t)); +} + +TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { + auto t = makeNamedDecls( + "struct A{ }; struct B{ }; void foo(A a, A b);", + "struct A{ }; struct B{ }; void foo(A a, B b);", + Lang_CXX); + EXPECT_FALSE(testStructuralMatch(t)); +} + } // end namespace ast_matchers } // end namespace clang -- GitLab From e26d5569ae33a0c8e10008805b75698653829b3d Mon Sep 17 00:00:00 2001 From: Vladimir Stefanovic Date: Wed, 11 Jul 2018 12:45:25 +0000 Subject: [PATCH 0501/1023] [mips] Add '-mvirt', '-mno-virt', '-mginv', '-mno-ginv' options '-mvirt'/'-mno-virt' enables/disables Virtualization ASE. '-mginv'/'-mno-ginv' enables/disables GINV (Global Invalidate) ASE. Differential revision: https://reviews.llvm.org/D48982 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336798 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 4 ++++ lib/Driver/ToolChains/Arch/Mips.cpp | 4 ++++ test/Driver/mips-features.c | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 4a5aa904e4..5a7e5c9e4e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -2216,6 +2216,10 @@ def mno_abicalls : Flag<["-"], "mno-abicalls">, Group, HelpText<"Disable SVR4-style position-independent code (Mips only)">; def mno_crc : Flag<["-"], "mno-crc">, Group, HelpText<"Disallow use of CRC instructions (Mips only)">; +def mvirt : Flag<["-"], "mvirt">, Group; +def mno_virt : Flag<["-"], "mno-virt">, Group; +def mginv : Flag<["-"], "mginv">, Group; +def mno_ginv : Flag<["-"], "mno-ginv">, Group; def mips1 : Flag<["-"], "mips1">, Alias, AliasArgs<["mips1"]>, Group, HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index 0c0e090719..6d814631d0 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -352,6 +352,10 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, "crc"); + AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt, + "virt"); + AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv, + "ginv"); if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { StringRef Val = StringRef(A->getValue()); diff --git a/test/Driver/mips-features.c b/test/Driver/mips-features.c index e90f3704f2..f63fb8de55 100644 --- a/test/Driver/mips-features.c +++ b/test/Driver/mips-features.c @@ -420,3 +420,27 @@ // RUN: -mcrc -mno-crc 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-CRC %s // CHECK-NO-CRC: "-target-feature" "-crc" +// +// -mvirt +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-virt -mvirt 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-VIRT %s +// CHECK-VIRT: "-target-feature" "+virt" +// +// -mno-virt +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mvirt -mno-virt 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-VIRT %s +// CHECK-NO-VIRT: "-target-feature" "-virt" +// +// -mginv +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-ginv -mginv 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-GINV %s +// CHECK-GINV: "-target-feature" "+ginv" +// +// -mno-ginv +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mginv -mno-ginv 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-GINV %s +// CHECK-NO-GINV: "-target-feature" "-ginv" -- GitLab From d03bdf0a5a75138941271f293147bd9410d31e04 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Wed, 11 Jul 2018 14:08:17 +0000 Subject: [PATCH 0502/1023] [VirtualFileSystem] InMemoryFileSystem::status: Return a Status with the requested name Summary: InMemoryFileSystem::status behaves differently than RealFileSystem::status. The Name contained in the Status returned by RealFileSystem::status will be the path as requested by the caller, whereas InMemoryFileSystem::status returns the normalized path. For example, when requested the status for "../src/first.h", RealFileSystem returns a Status with "../src/first.h" as the Name. InMemoryFileSystem returns "/absolute/path/to/src/first.h". The reason for this change is that I want to make a unit test in the clangd testsuite (where we use an InMemoryFileSystem) to reproduce a bug I get with the clangd program (where a RealFileSystem is used). This difference in behavior "hides" the bug in the unit test version. In general, I guess it's good if InMemoryFileSystem works as much as possible like RealFileSystem. Doing so made the FileEntry::RealPathName value (assigned in FileManager::getFile) wrong when using the InMemoryFileSystem. That's because it assumes that vfs::File::getName will always return the real path. I changed to to use FileSystem::getRealPath instead. Subscribers: ilya-biryukov, ioeric, cfe-commits Differential Revision: https://reviews.llvm.org/D48903 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336807 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/FileManager.cpp | 8 ++- lib/Basic/VirtualFileSystem.cpp | 72 ++++++++++++++++++----- unittests/Basic/VirtualFileSystemTest.cpp | 33 ++++++++++- unittests/Driver/ToolChainTest.cpp | 2 +- 4 files changed, 94 insertions(+), 21 deletions(-) diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 7e2d01c498..0a79800ed7 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -315,9 +315,11 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.InPCH = Data.InPCH; UFE.File = std::move(F); UFE.IsValid = true; - if (UFE.File) - if (auto RealPathName = UFE.File->getName()) - UFE.RealPathName = *RealPathName; + + SmallString<128> RealPathName; + if (!FS->getRealPath(InterndFileName, RealPathName)) + UFE.RealPathName = RealPathName.str(); + return &UFE; } diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index bcfcbdbb90..f8acde94ca 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -471,15 +471,33 @@ enum InMemoryNodeKind { IME_File, IME_Directory }; /// The in memory file system is a tree of Nodes. Every node can either be a /// file or a directory. class InMemoryNode { - Status Stat; InMemoryNodeKind Kind; + Status Stat; + +protected: + /// Return Stat. This should only be used for internal/debugging use. When + /// clients wants the Status of this node, they should use + /// \p getStatus(StringRef). + const Status& getStatus() const { + return Stat; + } public: InMemoryNode(Status Stat, InMemoryNodeKind Kind) - : Stat(std::move(Stat)), Kind(Kind) {} + : Kind(Kind), Stat(std::move(Stat)) {} virtual ~InMemoryNode() = default; - const Status &getStatus() const { return Stat; } + /// Return the \p Status for this node. \p RequestedName should be the name + /// through which the caller referred to this node. It will override + /// \p Status::Name in the return value, to mimic the behavior of \p RealFile. + Status getStatus(StringRef RequestedName) const { + return Status::copyWithNewName(Stat, RequestedName); + } + + /// Get the filename of this node (the name without the directory part). + StringRef getFileName() const { + return llvm::sys::path::filename(Stat.getName()); + } InMemoryNodeKind getKind() const { return Kind; } virtual std::string toString(unsigned Indent) const = 0; }; @@ -504,14 +522,22 @@ public: } }; -/// Adapt a InMemoryFile for VFS' File interface. +/// Adapt a InMemoryFile for VFS' File interface. The goal is to make +/// \p InMemoryFileAdaptor mimic as much as possible the behavior of +/// \p RealFile. class InMemoryFileAdaptor : public File { InMemoryFile &Node; + /// The name to use when returning a Status for this file. + std::string RequestedName; + public: - explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {} + explicit InMemoryFileAdaptor(InMemoryFile &Node, std::string RequestedName) + : Node(Node), RequestedName(std::move(RequestedName)) {} - llvm::ErrorOr status() override { return Node.getStatus(); } + llvm::ErrorOr status() override { + return Node.getStatus(RequestedName); + } llvm::ErrorOr> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -711,7 +737,7 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir, llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path) { auto Node = lookupInMemoryNode(*this, Root.get(), Path); if (Node) - return (*Node)->getStatus(); + return (*Node)->getStatus(Path.str()); return Node.getError(); } @@ -724,7 +750,8 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) { // When we have a file provide a heap-allocated wrapper for the memory buffer // to match the ownership semantics for File. if (auto *F = dyn_cast(*Node)) - return std::unique_ptr(new detail::InMemoryFileAdaptor(*F)); + return std::unique_ptr( + new detail::InMemoryFileAdaptor(*F, Path.str())); // FIXME: errc::not_a_file? return make_error_code(llvm::errc::invalid_argument); @@ -736,21 +763,33 @@ namespace { class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl { detail::InMemoryDirectory::const_iterator I; detail::InMemoryDirectory::const_iterator E; + std::string RequestedDirName; + + void setCurrentEntry() { + if (I != E) { + SmallString<256> Path(RequestedDirName); + llvm::sys::path::append(Path, I->second->getFileName()); + CurrentEntry = I->second->getStatus(Path.str()); + } else { + // When we're at the end, make CurrentEntry invalid and DirIterImpl will + // do the rest. + CurrentEntry = Status(); + } + } public: InMemoryDirIterator() = default; - explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir) - : I(Dir.begin()), E(Dir.end()) { - if (I != E) - CurrentEntry = I->second->getStatus(); + explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir, + std::string RequestedDirName) + : I(Dir.begin()), E(Dir.end()), + RequestedDirName(std::move(RequestedDirName)) { + setCurrentEntry(); } std::error_code increment() override { ++I; - // When we're at the end, make CurrentEntry invalid and DirIterImpl will do - // the rest. - CurrentEntry = I != E ? I->second->getStatus() : Status(); + setCurrentEntry(); return {}; } }; @@ -766,7 +805,8 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir, } if (auto *DirNode = dyn_cast(*Node)) - return directory_iterator(std::make_shared(*DirNode)); + return directory_iterator( + std::make_shared(*DirNode, Dir.str())); EC = make_error_code(llvm::errc::not_a_directory); return directory_iterator(std::make_shared()); diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index c795be07ac..54c355d948 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -794,7 +794,7 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) { auto Stat = FS.status("/b/c"); ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); - ASSERT_EQ("c", Stat->getName()); + ASSERT_EQ("/b/c", Stat->getName()); ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory()); Stat = FS.status("c"); @@ -919,6 +919,37 @@ TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) { ASSERT_TRUE(Stat->isRegularFile()); } +// Test that the name returned by status() is in the same form as the path that +// was requested (to match the behavior of RealFileSystem). +TEST_F(InMemoryFileSystemTest, StatusName) { + NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), + /*User=*/None, + /*Group=*/None, sys::fs::file_type::regular_file); + NormalizedFS.setCurrentWorkingDirectory("/a/b"); + + // Access using InMemoryFileSystem::status. + auto Stat = NormalizedFS.status("../b/c"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" + << NormalizedFS.toString(); + ASSERT_TRUE(Stat->isRegularFile()); + ASSERT_EQ("../b/c", Stat->getName()); + + // Access using InMemoryFileAdaptor::status. + auto File = NormalizedFS.openFileForRead("../b/c"); + ASSERT_FALSE(File.getError()) << File.getError() << "\n" + << NormalizedFS.toString(); + Stat = (*File)->status(); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" + << NormalizedFS.toString(); + ASSERT_TRUE(Stat->isRegularFile()); + ASSERT_EQ("../b/c", Stat->getName()); + + // Access using a directory iterator. + std::error_code EC; + clang::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC); + ASSERT_EQ("../b/c", It->getName()); +} + // NOTE: in the tests below, we use '//root/' as our root directory, since it is // a legal *absolute* path on Windows as well as *nix. class VFSFromYAMLTest : public ::testing::Test { diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp index d4198eaeb1..0d4c545bd7 100644 --- a/unittests/Driver/ToolChainTest.cpp +++ b/unittests/Driver/ToolChainTest.cpp @@ -113,7 +113,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { std::replace(S.begin(), S.end(), '\\', '/'); #endif EXPECT_EQ("Found candidate GCC installation: " - "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n" + "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" "Selected GCC installation: " "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" "Candidate multilib: .;@m32\n" -- GitLab From c53ede86476eae6d4ebe50ceb51800349979db0c Mon Sep 17 00:00:00 2001 From: Kirill Bobyrev Date: Wed, 11 Jul 2018 14:49:49 +0000 Subject: [PATCH 0503/1023] [clangd] Uprank delcarations when "using q::name" is present in the main file Having `using qualified::name;` for some symbol is an important signal for clangd code completion as the user is more likely to use such symbol. This patch helps to uprank the relevant symbols by saving UsingShadowDecl in the new field of CodeCompletionResult and checking whether the corresponding UsingShadowDecl is located in the main file later in ClangD code completion routine. While the relative importance of such signal is a subject to change in the future, this patch simply bumps DeclProximity score to the value of 1.0 which should be enough for now. The patch was tested using `$ ninja check-clang check-clang-tools` No unexpected failures were noticed after running the relevant testsets. Reviewers: sammccall, ioeric Subscribers: MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D49012 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336810 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/CodeCompleteConsumer.h | 11 +++++++-- lib/Sema/SemaCodeComplete.cpp | 29 ++++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 8022fa74c4..606f3b3690 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -45,8 +45,9 @@ class LangOptions; class NamedDecl; class NestedNameSpecifier; class Preprocessor; -class Sema; class RawComment; +class Sema; +class UsingShadowDecl; /// Default priority values for code-completion results based /// on their kind. @@ -836,6 +837,12 @@ public: /// informative rather than required. NestedNameSpecifier *Qualifier = nullptr; + /// If this Decl was unshadowed by using declaration, this can store a + /// pointer to the UsingShadowDecl which was used in the unshadowing process. + /// This information can be used to uprank CodeCompletionResults / which have + /// corresponding `using decl::qualified::name;` nearby. + const UsingShadowDecl *ShadowDecl = nullptr; + /// Build a result that refers to a declaration. CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority, NestedNameSpecifier *Qualifier = nullptr, @@ -847,7 +854,7 @@ public: QualifierIsInformative(QualifierIsInformative), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(Qualifier) { - //FIXME: Add assert to check FixIts range requirements. + // FIXME: Add assert to check FixIts range requirements. computeCursorKindAndAvailability(Accessible); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 9beefc05a2..700f5a2fee 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -859,12 +859,12 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { } // Look through using declarations. - if (const UsingShadowDecl *Using = - dyn_cast(R.Declaration)) { - MaybeAddResult(Result(Using->getTargetDecl(), - getBasePriority(Using->getTargetDecl()), - R.Qualifier), - CurContext); + if (const UsingShadowDecl *Using = dyn_cast(R.Declaration)) { + CodeCompletionResult Result(Using->getTargetDecl(), + getBasePriority(Using->getTargetDecl()), + R.Qualifier); + Result.ShadowDecl = Using; + MaybeAddResult(Result, CurContext); return; } @@ -977,10 +977,11 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, // Look through using declarations. if (const UsingShadowDecl *Using = dyn_cast(R.Declaration)) { - AddResult(Result(Using->getTargetDecl(), - getBasePriority(Using->getTargetDecl()), - R.Qualifier), - CurContext, Hiding); + CodeCompletionResult Result(Using->getTargetDecl(), + getBasePriority(Using->getTargetDecl()), + R.Qualifier); + Result.ShadowDecl = Using; + AddResult(Result, CurContext, Hiding); return; } @@ -1004,10 +1005,10 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (AsNestedNameSpecifier) { R.StartsNestedNameSpecifier = true; R.Priority = CCP_NestedNameSpecifier; - } - else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass && - isa(R.Declaration->getDeclContext() - ->getRedeclContext())) + } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && + InBaseClass && + isa( + R.Declaration->getDeclContext()->getRedeclContext())) R.QualifierIsInformative = true; // If this result is supposed to have an informative qualifier, add one. -- GitLab From 1d90e7314049f86752943b0568a805a7f11b7b89 Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Wed, 11 Jul 2018 15:26:26 +0000 Subject: [PATCH 0504/1023] [AST] Fix for structural equivalence tests in rL336776. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336817 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/StructuralEquivalenceTest.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp index 16998f2420..df37b72263 100644 --- a/unittests/AST/StructuralEquivalenceTest.cpp +++ b/unittests/AST/StructuralEquivalenceTest.cpp @@ -404,14 +404,14 @@ TEST_F(StructuralEquivalenceCXXMethodTest, Delete) { TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { auto t = makeDecls( "void foo();", "struct foo { foo(); };", Lang_CXX, - functionDecl(), cxxConstructorDecl()); + functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo"))); EXPECT_FALSE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { auto t = makeDecls("struct X { X(); };", "struct X { X(int); };", Lang_CXX, - cxxConstructorDecl()); + cxxConstructorDecl(hasName("X"))); EXPECT_FALSE(testStructuralMatch(t)); } @@ -419,7 +419,7 @@ TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) { auto t = makeDecls("struct X { X(int); };", "struct X { explicit X(int); };", Lang_CXX11, - cxxConstructorDecl()); + cxxConstructorDecl(hasName("X"))); EXPECT_FALSE(testStructuralMatch(t)); } @@ -427,7 +427,7 @@ TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { auto t = makeDecls("struct X { X(); };", "struct X { X() = default; };", Lang_CXX11, - cxxConstructorDecl()); + cxxConstructorDecl(hasName("X"))); EXPECT_FALSE(testStructuralMatch(t)); } @@ -474,7 +474,8 @@ TEST_F(StructuralEquivalenceRecordTest, Name) { "struct A{ };", "struct B{ };", Lang_CXX, - cxxRecordDecl()); + cxxRecordDecl(hasName("A")), + cxxRecordDecl(hasName("B"))); EXPECT_FALSE(testStructuralMatch(t)); } -- GitLab From 27d314134831ebd9f50c94189c021169e973ca3d Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Wed, 11 Jul 2018 18:43:07 +0000 Subject: [PATCH 0505/1023] Revert "[VirtualFileSystem] InMemoryFileSystem::status: Return a Status with the requested name" This reverts commit r336807. This breaks users of ClangTool::mapVirtualFile. Will try to investigate a fix. See also the discussion on https://reviews.llvm.org/D48903 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336831 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/FileManager.cpp | 8 +-- lib/Basic/VirtualFileSystem.cpp | 72 +++++------------------ unittests/Basic/VirtualFileSystemTest.cpp | 33 +---------- unittests/Driver/ToolChainTest.cpp | 2 +- 4 files changed, 21 insertions(+), 94 deletions(-) diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 0a79800ed7..7e2d01c498 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -315,11 +315,9 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.InPCH = Data.InPCH; UFE.File = std::move(F); UFE.IsValid = true; - - SmallString<128> RealPathName; - if (!FS->getRealPath(InterndFileName, RealPathName)) - UFE.RealPathName = RealPathName.str(); - + if (UFE.File) + if (auto RealPathName = UFE.File->getName()) + UFE.RealPathName = *RealPathName; return &UFE; } diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index f8acde94ca..bcfcbdbb90 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -471,33 +471,15 @@ enum InMemoryNodeKind { IME_File, IME_Directory }; /// The in memory file system is a tree of Nodes. Every node can either be a /// file or a directory. class InMemoryNode { - InMemoryNodeKind Kind; Status Stat; - -protected: - /// Return Stat. This should only be used for internal/debugging use. When - /// clients wants the Status of this node, they should use - /// \p getStatus(StringRef). - const Status& getStatus() const { - return Stat; - } + InMemoryNodeKind Kind; public: InMemoryNode(Status Stat, InMemoryNodeKind Kind) - : Kind(Kind), Stat(std::move(Stat)) {} + : Stat(std::move(Stat)), Kind(Kind) {} virtual ~InMemoryNode() = default; - /// Return the \p Status for this node. \p RequestedName should be the name - /// through which the caller referred to this node. It will override - /// \p Status::Name in the return value, to mimic the behavior of \p RealFile. - Status getStatus(StringRef RequestedName) const { - return Status::copyWithNewName(Stat, RequestedName); - } - - /// Get the filename of this node (the name without the directory part). - StringRef getFileName() const { - return llvm::sys::path::filename(Stat.getName()); - } + const Status &getStatus() const { return Stat; } InMemoryNodeKind getKind() const { return Kind; } virtual std::string toString(unsigned Indent) const = 0; }; @@ -522,22 +504,14 @@ public: } }; -/// Adapt a InMemoryFile for VFS' File interface. The goal is to make -/// \p InMemoryFileAdaptor mimic as much as possible the behavior of -/// \p RealFile. +/// Adapt a InMemoryFile for VFS' File interface. class InMemoryFileAdaptor : public File { InMemoryFile &Node; - /// The name to use when returning a Status for this file. - std::string RequestedName; - public: - explicit InMemoryFileAdaptor(InMemoryFile &Node, std::string RequestedName) - : Node(Node), RequestedName(std::move(RequestedName)) {} + explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {} - llvm::ErrorOr status() override { - return Node.getStatus(RequestedName); - } + llvm::ErrorOr status() override { return Node.getStatus(); } llvm::ErrorOr> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -737,7 +711,7 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir, llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path) { auto Node = lookupInMemoryNode(*this, Root.get(), Path); if (Node) - return (*Node)->getStatus(Path.str()); + return (*Node)->getStatus(); return Node.getError(); } @@ -750,8 +724,7 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) { // When we have a file provide a heap-allocated wrapper for the memory buffer // to match the ownership semantics for File. if (auto *F = dyn_cast(*Node)) - return std::unique_ptr( - new detail::InMemoryFileAdaptor(*F, Path.str())); + return std::unique_ptr(new detail::InMemoryFileAdaptor(*F)); // FIXME: errc::not_a_file? return make_error_code(llvm::errc::invalid_argument); @@ -763,33 +736,21 @@ namespace { class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl { detail::InMemoryDirectory::const_iterator I; detail::InMemoryDirectory::const_iterator E; - std::string RequestedDirName; - - void setCurrentEntry() { - if (I != E) { - SmallString<256> Path(RequestedDirName); - llvm::sys::path::append(Path, I->second->getFileName()); - CurrentEntry = I->second->getStatus(Path.str()); - } else { - // When we're at the end, make CurrentEntry invalid and DirIterImpl will - // do the rest. - CurrentEntry = Status(); - } - } public: InMemoryDirIterator() = default; - explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir, - std::string RequestedDirName) - : I(Dir.begin()), E(Dir.end()), - RequestedDirName(std::move(RequestedDirName)) { - setCurrentEntry(); + explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir) + : I(Dir.begin()), E(Dir.end()) { + if (I != E) + CurrentEntry = I->second->getStatus(); } std::error_code increment() override { ++I; - setCurrentEntry(); + // When we're at the end, make CurrentEntry invalid and DirIterImpl will do + // the rest. + CurrentEntry = I != E ? I->second->getStatus() : Status(); return {}; } }; @@ -805,8 +766,7 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir, } if (auto *DirNode = dyn_cast(*Node)) - return directory_iterator( - std::make_shared(*DirNode, Dir.str())); + return directory_iterator(std::make_shared(*DirNode)); EC = make_error_code(llvm::errc::not_a_directory); return directory_iterator(std::make_shared()); diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index 54c355d948..c795be07ac 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -794,7 +794,7 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) { auto Stat = FS.status("/b/c"); ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); - ASSERT_EQ("/b/c", Stat->getName()); + ASSERT_EQ("c", Stat->getName()); ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory()); Stat = FS.status("c"); @@ -919,37 +919,6 @@ TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) { ASSERT_TRUE(Stat->isRegularFile()); } -// Test that the name returned by status() is in the same form as the path that -// was requested (to match the behavior of RealFileSystem). -TEST_F(InMemoryFileSystemTest, StatusName) { - NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), - /*User=*/None, - /*Group=*/None, sys::fs::file_type::regular_file); - NormalizedFS.setCurrentWorkingDirectory("/a/b"); - - // Access using InMemoryFileSystem::status. - auto Stat = NormalizedFS.status("../b/c"); - ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" - << NormalizedFS.toString(); - ASSERT_TRUE(Stat->isRegularFile()); - ASSERT_EQ("../b/c", Stat->getName()); - - // Access using InMemoryFileAdaptor::status. - auto File = NormalizedFS.openFileForRead("../b/c"); - ASSERT_FALSE(File.getError()) << File.getError() << "\n" - << NormalizedFS.toString(); - Stat = (*File)->status(); - ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" - << NormalizedFS.toString(); - ASSERT_TRUE(Stat->isRegularFile()); - ASSERT_EQ("../b/c", Stat->getName()); - - // Access using a directory iterator. - std::error_code EC; - clang::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC); - ASSERT_EQ("../b/c", It->getName()); -} - // NOTE: in the tests below, we use '//root/' as our root directory, since it is // a legal *absolute* path on Windows as well as *nix. class VFSFromYAMLTest : public ::testing::Test { diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp index 0d4c545bd7..d4198eaeb1 100644 --- a/unittests/Driver/ToolChainTest.cpp +++ b/unittests/Driver/ToolChainTest.cpp @@ -113,7 +113,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { std::replace(S.begin(), S.end(), '\\', '/'); #endif EXPECT_EQ("Found candidate GCC installation: " - "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" + "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n" "Selected GCC installation: " "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" "Candidate multilib: .;@m32\n" -- GitLab From 9b025e6998efc88ca433ab192015fe143efecb56 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Wed, 11 Jul 2018 19:08:02 +0000 Subject: [PATCH 0506/1023] [analyzer] Track multiple raw pointer symbols in DanglingInternalBufferChecker. Previously, the checker only tracked one raw pointer symbol for each container object. But member functions returning a pointer to the object's inner buffer may be called on the object several times. These pointer symbols are now collected in a set inside the program state map and thus all of them is checked for use-after-free problems. Differential Revision: https://reviews.llvm.org/D49057 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336835 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../DanglingInternalBufferChecker.cpp | 68 ++++++++++++++----- test/Analysis/dangling-internal-buffer.cpp | 24 +++++++ 2 files changed, 74 insertions(+), 18 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp index fe575cc5fc..2df86fdd3a 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -24,10 +24,23 @@ using namespace clang; using namespace ento; -// FIXME: member functions that return a pointer to the container's internal -// buffer may be called on the object many times, so the object's memory -// region should have a list of pointer symbols associated with it. -REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef) +using PtrSet = llvm::ImmutableSet; + +// Associate container objects with a set of raw pointer symbols. +REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet) + +// This is a trick to gain access to PtrSet's Factory. +namespace clang { +namespace ento { +template<> struct ProgramStateTrait + : public ProgramStatePartialTrait { + static void *GDMIndex() { + static int Index = 0; + return &Index; + } +}; +} // end namespace ento +} // end namespace clang namespace { @@ -61,7 +74,7 @@ public: bool isSymbolTracked(ProgramStateRef State, SymbolRef Sym) { RawPtrMapTy Map = State->get(); for (const auto Entry : Map) { - if (Entry.second == Sym) + if (Entry.second.contains(Sym)) return true; } return false; @@ -88,11 +101,11 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, return; SVal Obj = ICall->getCXXThisVal(); - const auto *TypedR = dyn_cast_or_null(Obj.getAsRegion()); - if (!TypedR) + const auto *ObjRegion = dyn_cast_or_null(Obj.getAsRegion()); + if (!ObjRegion) return; - auto *TypeDecl = TypedR->getValueType()->getAsCXXRecordDecl(); + auto *TypeDecl = ObjRegion->getValueType()->getAsCXXRecordDecl(); if (TypeDecl->getName() != "basic_string") return; @@ -100,20 +113,30 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) { SVal RawPtr = Call.getReturnValue(); - if (!RawPtr.isUnknown()) { - State = State->set(TypedR, RawPtr.getAsSymbol()); + if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) { + // Start tracking this raw pointer by adding it to the set of symbols + // associated with this container object in the program state map. + PtrSet::Factory &F = State->getStateManager().get_context(); + const PtrSet *SetPtr = State->get(ObjRegion); + PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet(); + assert(C.wasInlined || !Set.contains(Sym)); + Set = F.add(Set, Sym); + State = State->set(ObjRegion, Set); C.addTransition(State); } return; } if (isa(ICall)) { - if (State->contains(TypedR)) { - const SymbolRef *StrBufferPtr = State->get(TypedR); - // FIXME: What if Origin is null? + if (const PtrSet *PS = State->get(ObjRegion)) { + // Mark all pointer symbols associated with the deleted object released. const Expr *Origin = Call.getOriginExpr(); - State = allocation_state::markReleased(State, *StrBufferPtr, Origin); - State = State->remove(TypedR); + for (const auto Symbol : *PS) { + // NOTE: `Origin` may be null, and will be stored so in the symbol's + // `RefState` in MallocChecker's `RegionState` program state map. + State = allocation_state::markReleased(State, Symbol, Origin); + } + State = State->remove(ObjRegion); C.addTransition(State); return; } @@ -123,15 +146,24 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const { ProgramStateRef State = C.getState(); + PtrSet::Factory &F = State->getStateManager().get_context(); RawPtrMapTy RPM = State->get(); for (const auto Entry : RPM) { - if (!SymReaper.isLive(Entry.second)) - State = State->remove(Entry.first); if (!SymReaper.isLiveRegion(Entry.first)) { - // Due to incomplete destructor support, some dead regions might still + // Due to incomplete destructor support, some dead regions might // remain in the program state map. Clean them up. State = State->remove(Entry.first); } + if (const PtrSet *OldSet = State->get(Entry.first)) { + PtrSet CleanedUpSet = *OldSet; + for (const auto Symbol : Entry.second) { + if (!SymReaper.isLive(Symbol)) + CleanedUpSet = F.remove(CleanedUpSet, Symbol); + } + State = CleanedUpSet.isEmpty() + ? State->remove(Entry.first) + : State->set(Entry.first, CleanedUpSet); + } } C.addTransition(State); } diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp index d5a8940bae..f77229c630 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -108,6 +108,30 @@ void deref_after_scope_char32_t_data() { // expected-note@-1 {{Use of memory after it is freed}} } +void multiple_symbols(bool cond) { + const char *c1, *d1; + { + std::string s1; + c1 = s1.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} + d1 = s1.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + const char *local = s1.c_str(); + consume(local); // no-warning + } // expected-note {{Internal buffer is released because the object was destroyed}} + // expected-note@-1 {{Internal buffer is released because the object was destroyed}} + std::string s2; + const char *c2 = s2.c_str(); + if (cond) { + // expected-note@-1 {{Assuming 'cond' is not equal to 0}} + // expected-note@-2 {{Taking true branch}} + // expected-note@-3 {{Assuming 'cond' is 0}} + // expected-note@-4 {{Taking false branch}} + consume(c1); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} + } else { + consume(d1); // expected-warning {{Use of memory after it is freed}} + } // expected-note@-1 {{Use of memory after it is freed}} +} + void deref_after_scope_cstr_ok() { const char *c; std::string s; -- GitLab From e14ae935c97fa188520267f118eafa6d022a0a46 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 11 Jul 2018 19:09:21 +0000 Subject: [PATCH 0507/1023] [NFC] Replace usage of QualType.getTypePtr()-> with operator-> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336836 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f6faf38c95..13ef46b541 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8253,7 +8253,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool &AddToScope) { QualType R = TInfo->getType(); - assert(R.getTypePtr()->isFunctionType()); + assert(R->isFunctionType()); // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); -- GitLab From 28a5dcbf3d1c0284839e156b2c0729439ffd7851 Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Wed, 11 Jul 2018 19:51:40 +0000 Subject: [PATCH 0508/1023] [NFC] typo git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336840 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ConstantEmitter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/ConstantEmitter.h b/lib/CodeGen/ConstantEmitter.h index 90c9fcd8cf..b4d1b65743 100644 --- a/lib/CodeGen/ConstantEmitter.h +++ b/lib/CodeGen/ConstantEmitter.h @@ -50,7 +50,7 @@ public: : CGM(CGM), CGF(CGF) {} /// Initialize this emission in the context of the given function. - /// Use this if the expression might contain contextaul references like + /// Use this if the expression might contain contextual references like /// block addresses or PredefinedExprs. ConstantEmitter(CodeGenFunction &CGF) : CGM(CGF.CGM), CGF(&CGF) {} -- GitLab From 924068e9a76bf2160d68f4fe65c6f2262afaa46b Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Wed, 11 Jul 2018 20:17:54 +0000 Subject: [PATCH 0509/1023] Fix setting of empty implicit-section-name attribute Code in `CodeGenModule::SetFunctionAttributes()` could set an empty attribute `implicit-section-name` on a function that is affected by `#pragma clang text="section"`. This is incorrect because the attribute should contain a valid section name. If the function additionally also used `__attribute__((section("section")))` then this could result in emitting the function in a section with an empty name. The patch fixes the issue by removing the problematic code that sets empty `implicit-section-name` from `CodeGenModule::SetFunctionAttributes()` because it is sufficient to set this attribute only from a similar code in `setNonAliasAttributes()` when the function is emitted. Differential Revision: https://reviews.llvm.org/D48916 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336842 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 4 -- test/CodeGen/clang-sections-attribute.c | 76 +++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/clang-sections-attribute.c diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 13afd4bdb8..b412d3083f 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1485,10 +1485,6 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, setLinkageForGV(F, FD); setGVProperties(F, FD); - if (FD->getAttr()) { - F->addFnAttr("implicit-section-name"); - } - if (const SectionAttr *SA = FD->getAttr()) F->setSection(SA->getName()); diff --git a/test/CodeGen/clang-sections-attribute.c b/test/CodeGen/clang-sections-attribute.c new file mode 100644 index 0000000000..7223d7d97a --- /dev/null +++ b/test/CodeGen/clang-sections-attribute.c @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s + +// Test interaction between __attribute__((section())) and '#pragma clang +// section' directives. The attribute should always have higher priority than +// the pragma. + +// Text tests. +#pragma clang section text=".ext_fun_pragma" +void ext_fun(void) __attribute__((section(".ext_fun_attr"))); +void ext_fun(void) {} +#pragma clang section text="" + +void ext_fun2(void) __attribute__((section(".ext_fun2_attr"))); +#pragma clang section text=".ext_fun2_pragma" +void ext_fun2(void) {} +#pragma clang section text="" + +#pragma clang section text=".int_fun_pragma" +static void int_fun(void) __attribute__((section(".int_fun_attr"), used)); +static void int_fun(void) {} +#pragma clang section text="" + +static void int_fun2(void) __attribute__((section(".int_fun2_attr"), used)); +#pragma clang section text=".int_fun2_pragma" +static void int_fun2(void) {} +#pragma clang section text="" + +// Rodata tests. +#pragma clang section rodata=".ext_const_pragma" +__attribute__((section(".ext_const_attr"))) +const int ext_const = 1; +#pragma clang section rodata="" + +#pragma clang section rodata=".int_const_pragma" +__attribute__((section(".int_const_attr"), used)) +static const int int_const = 1; +#pragma clang section rodata="" + +// Data tests. +#pragma clang section data=".ext_var_pragma" +__attribute__((section(".ext_var_attr"))) +int ext_var = 1; +#pragma clang section data="" + +#pragma clang section data=".int_var_pragma" +__attribute__((section(".int_var_attr"), used)) +static int int_var = 1; +#pragma clang section data="" + +// Bss tests. +#pragma clang section bss=".ext_zvar_pragma" +__attribute__((section(".ext_zvar_attr"))) +int ext_zvar; +#pragma clang section bss="" + +#pragma clang section bss=".int_zvar_pragma" +__attribute__((section(".int_zvar_attr"), used)) +static int int_zvar; +#pragma clang section bss="" + +// CHECK: @ext_const = constant i32 1, section ".ext_const_attr", align 4{{$}} +// CHECK: @int_const = internal constant i32 1, section ".int_const_attr", align 4{{$}} +// CHECK: @ext_var = global i32 1, section ".ext_var_attr", align 4{{$}} +// CHECK: @int_var = internal global i32 1, section ".int_var_attr", align 4{{$}} +// CHECK: @ext_zvar = global i32 0, section ".ext_zvar_attr", align 4{{$}} +// CHECK: @int_zvar = internal global i32 0, section ".int_zvar_attr", align 4{{$}} +// CHECK: define void @ext_fun() #0 section ".ext_fun_attr" +// CHECK: define void @ext_fun2() #0 section ".ext_fun2_attr" +// CHECK: define internal void @int_fun() #0 section ".int_fun_attr" +// CHECK: define internal void @int_fun2() #0 section ".int_fun2_attr" +// +// Function attributes should not include implicit-section-name. +// CHECK-NOT: attributes #0 = {{.*}}implicit-section-name +// +// No other attribute group should be present in the file. +// CHECK-NOT: attributes #1 -- GitLab From 9c70ef5a9d450bd54d0b60c76d8b4efbba8a0eac Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Wed, 11 Jul 2018 20:26:20 +0000 Subject: [PATCH 0510/1023] [FileCheck] Add -allow-deprecated-dag-overlap to failing clang tests See https://reviews.llvm.org/D47106 for details. Reviewed By: probinson Differential Revision: https://reviews.llvm.org/D47172 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336844 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/dso-local-executable.c | 18 +- test/CodeGen/may-alias.c | 6 +- test/CodeGenCUDA/convergent.cu | 4 +- test/CodeGenCUDA/device-stub.cu | 16 +- test/CodeGenCXX/debug-info-line-if.cpp | 2 +- test/CodeGenCXX/dllexport.cpp | 12 +- test/CodeGenCXX/inline-hint.cpp | 6 +- test/CodeGenCXX/linetable-eh.cpp | 2 +- test/CodeGenCXX/mangle-ms-cxx14.cpp | 4 +- .../microsoft-abi-member-pointers.cpp | 2 +- test/CodeGenCXX/regcall.cpp | 8 +- test/CodeGenCXX/runtime-dllstorage.cpp | 30 +- .../vtable-available-externally.cpp | 28 +- test/CodeGenObjC/dllstorage.m | 6 +- test/Driver/cuda-no-pgo-or-coverage.cu | 8 +- test/OpenMP/for_codegen.cpp | 16 +- test/OpenMP/for_reduction_codegen.cpp | 16 +- test/OpenMP/for_reduction_codegen_UDR.cpp | 8 +- test/OpenMP/sections_reduction_codegen.cpp | 16 +- test/OpenMP/target_map_codegen.cpp | 464 +++++++++--------- test/OpenMP/target_parallel_codegen.cpp | 32 +- test/OpenMP/target_parallel_for_codegen.cpp | 32 +- .../target_parallel_for_simd_codegen.cpp | 32 +- test/OpenMP/target_simd_codegen.cpp | 32 +- test/OpenMP/target_teams_codegen.cpp | 32 +- .../target_teams_distribute_codegen.cpp | 32 +- ..._teams_distribute_firstprivate_codegen.cpp | 24 +- ...istribute_parallel_for_private_codegen.cpp | 44 +- ...bute_parallel_for_simd_private_codegen.cpp | 44 +- ...arget_teams_distribute_private_codegen.cpp | 24 +- .../target_teams_distribute_simd_codegen.cpp | 32 +- ...s_distribute_simd_firstprivate_codegen.cpp | 24 +- ..._teams_distribute_simd_private_codegen.cpp | 24 +- .../teams_distribute_firstprivate_codegen.cpp | 24 +- ...istribute_parallel_for_private_codegen.cpp | 24 +- ...bute_parallel_for_simd_private_codegen.cpp | 24 +- .../teams_distribute_private_codegen.cpp | 24 +- ...s_distribute_simd_firstprivate_codegen.cpp | 24 +- .../teams_distribute_simd_private_codegen.cpp | 24 +- test/Profile/c-captured.c | 4 +- test/Profile/c-general.c | 8 +- test/Profile/cxx-lambda.cpp | 8 +- test/SemaCXX/pragma-optimize.cpp | 6 +- 43 files changed, 625 insertions(+), 625 deletions(-) diff --git a/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c index 44d5ecf754..6e434a67ef 100644 --- a/test/CodeGen/dso-local-executable.c +++ b/test/CodeGen/dso-local-executable.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm %s -o - | FileCheck --check-prefix=COFF %s +// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=COFF %s // COFF-DAG: @bar = external dso_local global i32 // COFF-DAG: @weak_bar = extern_weak dso_local global i32 // COFF-DAG: declare dso_local void @foo() @@ -9,7 +9,7 @@ // COFF-DAG: @import_var = external dllimport global i32 // COFF-DAG: declare dllimport void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck --check-prefix=STATIC %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=STATIC %s // STATIC-DAG: @bar = external dso_local global i32 // STATIC-DAG: @weak_bar = extern_weak dso_local global i32 // STATIC-DAG: declare dso_local void @foo() @@ -20,7 +20,7 @@ // STATIC-DAG: @import_var = external dso_local global i32 // STATIC-DAG: declare dso_local void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=PIE-COPY %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-COPY %s // PIE-COPY-DAG: @bar = external dso_local global i32 // PIE-COPY-DAG: @weak_bar = extern_weak global i32 // PIE-COPY-DAG: declare void @foo() @@ -31,7 +31,7 @@ // PIE-COPY-DAG: @import_var = external dso_local global i32 // PIE-COPY-DAG: declare void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie %s -o - | FileCheck --check-prefix=PIE %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE %s // PIE-DAG: @bar = external global i32 // PIE-DAG: @weak_bar = extern_weak global i32 // PIE-DAG: declare void @foo() @@ -42,7 +42,7 @@ // PIE-DAG: @import_var = external global i32 // PIE-DAG: declare void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static -fno-plt %s -o - | FileCheck --check-prefix=NOPLT %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static -fno-plt %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=NOPLT %s // NOPLT-DAG: @bar = external dso_local global i32 // NOPLT-DAG: @weak_bar = extern_weak dso_local global i32 // NOPLT-DAG: declare void @foo() @@ -53,7 +53,7 @@ // NOPLT-DAG: @import_var = external dso_local global i32 // NOPLT-DAG: declare void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -fno-plt -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=PIE-COPY-NOPLT %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -fno-plt -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-COPY-NOPLT %s // PIE-COPY-NOPLT-DAG: @bar = external dso_local global i32 // PIE-COPY-NOPLT-DAG: @weak_bar = extern_weak global i32 // PIE-COPY-NOPLT-DAG: declare void @foo() @@ -64,8 +64,8 @@ // PIE-COPY-NOPLT-DAG: @import_var = external dso_local global i32 // PIE-COPY-NOPLT-DAG: declare void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -fno-plt %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s -// RUN: %clang_cc1 -triple powerpc64le-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -fno-plt %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-NO-PLT %s +// RUN: %clang_cc1 -triple powerpc64le-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=PIE-NO-PLT %s // PIE-NO-PLT-DAG: @bar = external global i32 // PIE-NO-PLT-DAG: @weak_bar = extern_weak global i32 // PIE-NO-PLT-DAG: declare void @foo() @@ -76,7 +76,7 @@ // PIE-NO-PLT-DAG: @import_var = external global i32 // PIE-NO-PLT-DAG: declare void @import_func() -// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck --check-prefix=SHARED %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix=SHARED %s // SHARED-DAG: @bar = external global i32 // SHARED-DAG: @weak_bar = extern_weak global i32 // SHARED-DAG: declare void @foo() diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c index 5f72d058f8..cba62af4bb 100644 --- a/test/CodeGen/may-alias.c +++ b/test/CodeGen/may-alias.c @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \ // RUN: -no-struct-path-tbaa -disable-llvm-passes -o - %s | \ -// RUN: FileCheck %s -check-prefixes=CHECK,SCALAR +// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,SCALAR // RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \ // RUN: -disable-llvm-passes -o - %s | \ -// RUN: FileCheck %s -check-prefixes=CHECK,OLD-PATH +// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,OLD-PATH // RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 \ // RUN: -new-struct-path-tbaa -disable-llvm-passes -o - %s | \ -// RUN: FileCheck %s -check-prefixes=CHECK,NEW-PATH +// RUN: FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=CHECK,NEW-PATH // Types with the may_alias attribute should be considered equivalent // to char for aliasing. diff --git a/test/CodeGenCUDA/convergent.cu b/test/CodeGenCUDA/convergent.cu index 62818f9e5a..dd410cc644 100644 --- a/test/CodeGenCUDA/convergent.cu +++ b/test/CodeGenCUDA/convergent.cu @@ -2,11 +2,11 @@ // REQUIRES: nvptx-registered-target // RUN: %clang_cc1 -fcuda-is-device -triple nvptx-nvidia-cuda -emit-llvm \ -// RUN: -disable-llvm-passes -o - %s | FileCheck -check-prefix DEVICE %s +// RUN: -disable-llvm-passes -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix DEVICE %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm \ // RUN: -disable-llvm-passes -o - %s | \ -// RUN: FileCheck -check-prefix HOST %s +// RUN: FileCheck -allow-deprecated-dag-overlap -check-prefix HOST %s #include "Inputs/cuda.h" diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu index 7aae4fb3ec..85f53c3b4f 100644 --- a/test/CodeGenCUDA/device-stub.cu +++ b/test/CodeGenCUDA/device-stub.cu @@ -1,27 +1,27 @@ // RUN: echo "GPU binary would be here" > %t // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-include-gpubinary %t -o - \ -// RUN: | FileCheck %s --check-prefixes=ALL,NORDC,CUDA,CUDANORDC +// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,CUDA,CUDANORDC // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS \ -// RUN: | FileCheck %s -check-prefixes=NOGLOBALS,CUDANOGLOBALS +// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,CUDANOGLOBALS // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - \ -// RUN: | FileCheck %s --check-prefixes=ALL,RDC,CUDA,CUDARDC +// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,RDC,CUDA,CUDARDC // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - \ -// RUN: | FileCheck %s -check-prefix=NOGPUBIN +// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-include-gpubinary %t -o - -x hip\ -// RUN: | FileCheck %s --check-prefixes=ALL,NORDC,HIP +// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-include-gpubinary %t -o - -DNOGLOBALS -x hip \ -// RUN: | FileCheck %s -check-prefixes=NOGLOBALS,HIPNOGLOBALS +// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,HIPNOGLOBALS // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - -x hip \ -// RUN: | FileCheck %s --check-prefixes=ALL,RDC,HIP,HIPRDC +// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,RDC,HIP,HIPRDC // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - -x hip\ -// RUN: | FileCheck %s -check-prefix=NOGPUBIN +// RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN #include "Inputs/cuda.h" diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index 41770b1356..7e6cdb2eb9 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s // PR19864 extern int v[2]; int a = 0, b = 0; diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 3921144e86..a7b6aad357 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-passes -o - %s -w -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s -// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s -// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck -allow-deprecated-dag-overlap --check-prefix=GNU --check-prefix=G32 %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck -allow-deprecated-dag-overlap --check-prefix=GNU --check-prefix=G64 %s // Helper structs to make templates more expressive. struct ImplicitInst_Exported {}; diff --git a/test/CodeGenCXX/inline-hint.cpp b/test/CodeGenCXX/inline-hint.cpp index c4de751ba7..e8c067dec1 100644 --- a/test/CodeGenCXX/inline-hint.cpp +++ b/test/CodeGenCXX/inline-hint.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=SUITABLE +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=HINTED +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=NOINLINE // Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A struct A { diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp index 8c0a3971c5..b31df54f7c 100644 --- a/test/CodeGenCXX/linetable-eh.cpp +++ b/test/CodeGenCXX/linetable-eh.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck -allow-deprecated-dag-overlap %s // Test that emitting a landing pad does not affect the line table // entries for the code that triggered it. diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp index db282d2f14..c58d055880 100644 --- a/test/CodeGenCXX/mangle-ms-cxx14.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2015 -// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck %s --check-prefix=CHECK --check-prefix=MSVC2013 +// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=19.00 | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=MSVC2015 +// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 -fms-compatibility-version=18.00 | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=MSVC2013 template int x = 0; diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 471524ef72..cb3b41bbb4 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck -allow-deprecated-dag-overlap %s // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64 // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp index a9af4a4b30..fbc1dbf7d7 100644 --- a/test/CodeGenCXX/regcall.cpp +++ b/test/CodeGenCXX/regcall.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN64 %s -// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN32 %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN64 %s -// RUN: %clang_cc1 -triple i386-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -check-prefix=CHECK-WIN32 %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN64 %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -std=c++11 %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-LIN -check-prefix=CHECK-LIN32 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-WIN64 %s +// RUN: %clang_cc1 -triple i386-windows-msvc -emit-llvm -std=c++11 %s -o - -DWIN_TEST | FileCheck -allow-deprecated-dag-overlap -check-prefix=CHECK-WIN32 %s int __regcall foo(int i); diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp index 74ba66ff62..7220fa50b0 100644 --- a/test/CodeGenCXX/runtime-dllstorage.cpp +++ b/test/CodeGenCXX/runtime-dllstorage.cpp @@ -1,21 +1,21 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC -// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC - -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-MS -check-prefix CHECK-MS-DYNAMIC +// RUN: %clang_cc1 -triple i686-windows-msvc -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-MS -check-prefix CHECK-MS-STATIC + +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-NODECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-NODECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IMPORT-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DIMPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IMPORT-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DEXPORT_DECLARATIONS -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -DDECL -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-DECL-IA -check-prefix CHECK-DYANMIC-IA-CXA-ATEXIT +// RUN: %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -DDECL -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-DECL-IA -check-prefix CHECK-IA-STATIC-CXA-ATEXIT // %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -check-prefix CHECK-DYNAMIC-IA-ATEXIT // %clang_cc1 -triple i686-windows-itanium -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -fno-use-cxa-atexit -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -check-prefix CHECK-STATIC-IA-ATEXIT -// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA -// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA -// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA +// RUN: %clang_cc1 -triple i686-windows-gnu -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-DYNAMIC-IA +// RUN: %clang_cc1 -triple i686-windows-cygnus -std=c++11 -fdeclspec -fms-compatibility -fexceptions -fcxx-exceptions -flto-visibility-public-std -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap %s -check-prefix CHECK-IA -check-prefix CHECK-STATIC-IA #if defined(IMPORT_DECLARATIONS) namespace __cxxabiv1 { diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index b52527d36c..24c2eac23b 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,20 +1,20 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases -// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t -// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t -// RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t -// RUN: FileCheck --check-prefix=CHECK-TEST8 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST9 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST10 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST11 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST12 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST13 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt -// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST1 %s < %t +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST2 %s < %t +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST5 %s < %t +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST8 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST9 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST10 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST11 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST12 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST13 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST14 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST15 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST16 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable #include diff --git a/test/CodeGenObjC/dllstorage.m b/test/CodeGenObjC/dllstorage.m index 32aceb6f45..2cc4dc72a0 100644 --- a/test/CodeGenObjC/dllstorage.m +++ b/test/CodeGenObjC/dllstorage.m @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s -// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s -// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-FW %s +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s +// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s +// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-FW %s // CHECK-IR-DAG: @_objc_empty_cache = external dllimport global %struct._objc_cache diff --git a/test/Driver/cuda-no-pgo-or-coverage.cu b/test/Driver/cuda-no-pgo-or-coverage.cu index a2cb610f75..1bfd8f4325 100644 --- a/test/Driver/cuda-no-pgo-or-coverage.cu +++ b/test/Driver/cuda-no-pgo-or-coverage.cu @@ -9,19 +9,19 @@ // // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \ // RUN: -fprofile-instr-generate %s 2>&1 | \ -// RUN: FileCheck --check-prefixes=CHECK,PROF %s +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,PROF %s // // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \ // RUN: -coverage %s 2>&1 | \ -// RUN: FileCheck --check-prefixes=CHECK,GCOV %s +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,GCOV %s // // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \ // RUN: -ftest-coverage %s 2>&1 | \ -// RUN: FileCheck --check-prefixes=CHECK,GCOV %s +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,GCOV %s // // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 \ // RUN: -fprofile-instr-generate -fcoverage-mapping %s 2>&1 | \ -// RUN: FileCheck --check-prefixes=CHECK,PROF,GCOV %s +// RUN: FileCheck -allow-deprecated-dag-overlap --check-prefixes=CHECK,PROF,GCOV %s // // // CHECK-NOT: error: unsupported option '-fprofile diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp index 002ce16c53..ad8674fdde 100644 --- a/test/OpenMP/for_codegen.cpp +++ b/test/OpenMP/for_codegen.cpp @@ -1,14 +1,14 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck %s --check-prefix=CHECK --check-prefix=LIFETIME +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=CHECK --check-prefix=LIFETIME // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG -// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck %s --check-prefix=PROF-INSTR-PATH +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=TERM_DEBUG +// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=PROF-INSTR-PATH -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -main-file-name for_codegen.cpp %s -o - -emit-llvm -fprofile-instrument=clang -fprofile-instrument-path=for_codegen-test.profraw | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // // expected-no-diagnostics diff --git a/test/OpenMP/for_reduction_codegen.cpp b/test/OpenMP/for_reduction_codegen.cpp index 323692af28..55323122f3 100644 --- a/test/OpenMP/for_reduction_codegen.cpp +++ b/test/OpenMP/for_reduction_codegen.cpp @@ -1,14 +1,14 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s -// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=LAMBDA %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=BLOCKS %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics #ifndef HEADER diff --git a/test/OpenMP/for_reduction_codegen_UDR.cpp b/test/OpenMP/for_reduction_codegen_UDR.cpp index 94fcfa9253..0a6ba1d610 100644 --- a/test/OpenMP/for_reduction_codegen_UDR.cpp +++ b/test/OpenMP/for_reduction_codegen_UDR.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics #ifndef HEADER diff --git a/test/OpenMP/sections_reduction_codegen.cpp b/test/OpenMP/sections_reduction_codegen.cpp index c76e3e1b71..43b08b1160 100644 --- a/test/OpenMP/sections_reduction_codegen.cpp +++ b/test/OpenMP/sections_reduction_codegen.cpp @@ -1,14 +1,14 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s -// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=LAMBDA %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap -check-prefix=BLOCKS %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics #ifndef HEADER diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp index 5b54af6a6c..95ba61785c 100644 --- a/test/OpenMP/target_map_codegen.cpp +++ b/test/OpenMP/target_map_codegen.cpp @@ -7,19 +7,19 @@ /// ///==========================================================================/// -// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 +// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-64 // RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-64 -// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-64 +// RUN: %clang_cc1 -DCK1 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-32 // RUN: %clang_cc1 -DCK1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK1 --check-prefix CK1-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK1 --check-prefix CK1-32 -// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCK1 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCK1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} #ifdef CK1 @@ -80,19 +80,19 @@ void implicit_maps_integer (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 +// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-64 // RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-64 -// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-64 +// RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-32 // RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK2 --check-prefix CK2-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-32 -// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s -// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DCK2 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DCK2 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} #ifdef CK2 @@ -172,19 +172,19 @@ void implicit_maps_reference (int a, int *b){ // CK2: getelementptr inbounds i32, i32* [[TT]], i32 1 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 +// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-64 // RUN: %clang_cc1 -DCK3 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-64 -// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-64 +// RUN: %clang_cc1 -DCK3 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-32 // RUN: %clang_cc1 -DCK3 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK3 --check-prefix CK3-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK3 --check-prefix CK3-32 -// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s +// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s // RUN: %clang_cc1 -DCK3 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s -// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY2 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s +// RUN: %clang_cc1 -DCK3 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s // RUN: %clang_cc1 -DCK3 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY2 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY2 %s // SIMD-ONLY2-NOT: {{__kmpc|__tgt}} #ifdef CK3 @@ -226,19 +226,19 @@ void implicit_maps_parameter (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 +// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-64 // RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-64 -// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-64 +// RUN: %clang_cc1 -DCK4 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-32 // RUN: %clang_cc1 -DCK4 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK4 --check-prefix CK4-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK4 --check-prefix CK4-32 -// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s +// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s // RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s -// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY3 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s +// RUN: %clang_cc1 -DCK4 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s // RUN: %clang_cc1 -DCK4 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY3 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY3 %s // SIMD-ONLY3-NOT: {{__kmpc|__tgt}} #ifdef CK4 @@ -292,19 +292,19 @@ void implicit_maps_nested_integer (int a){ // CK4: define internal void [[KERNELP2]](i32* {{[^,]+}}, i32* {{[^,]+}}, i32* {{[^,]+}}) #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 +// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-64 // RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-64 -// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-64 +// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-32 // RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK5 --check-prefix CK5-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK5 --check-prefix CK5-32 -// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY4 %s +// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s // RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s -// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY4 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s +// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s // RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY4 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY4 %s // SIMD-ONLY4-NOT: {{__kmpc|__tgt}} #ifdef CK5 @@ -353,19 +353,19 @@ void implicit_maps_nested_integer_and_enum (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 +// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-64 // RUN: %clang_cc1 -DCK6 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-64 -// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-64 +// RUN: %clang_cc1 -DCK6 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-32 // RUN: %clang_cc1 -DCK6 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK6 --check-prefix CK6-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK6 --check-prefix CK6-32 -// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY5 %s +// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s // RUN: %clang_cc1 -DCK6 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY5 %s -// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY5 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s +// RUN: %clang_cc1 -DCK6 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s // RUN: %clang_cc1 -DCK6 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY5 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY5 %s // SIMD-ONLY5-NOT: {{__kmpc|__tgt}} #ifdef CK6 // CK6-LABEL: @.__omp_offloading_{{.*}}implicit_maps_host_global{{.*}}_l397.region_id = weak constant i8 0 @@ -409,19 +409,19 @@ void implicit_maps_host_global (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 +// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-64 // RUN: %clang_cc1 -DCK7 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64 -// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-64 +// RUN: %clang_cc1 -DCK7 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-32 // RUN: %clang_cc1 -DCK7 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK7 --check-prefix CK7-32 -// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY6 %s +// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s // RUN: %clang_cc1 -DCK7 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY6 %s -// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY6 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s +// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s // RUN: %clang_cc1 -DCK7 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY6 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY6 %s // SIMD-ONLY6-NOT: {{__kmpc|__tgt}} #ifdef CK7 @@ -481,19 +481,19 @@ void implicit_maps_double (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8 // RUN: %clang_cc1 -DCK8 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 -// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8 +// RUN: %clang_cc1 -DCK8 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8 // RUN: %clang_cc1 -DCK8 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK8 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK8 -// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY7 %s +// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s // RUN: %clang_cc1 -DCK8 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY7 %s -// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY7 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s +// RUN: %clang_cc1 -DCK8 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s // RUN: %clang_cc1 -DCK8 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY7 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY7 %s // SIMD-ONLY7-NOT: {{__kmpc|__tgt}} #ifdef CK8 @@ -535,19 +535,19 @@ void implicit_maps_float (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9 // RUN: %clang_cc1 -DCK9 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 -// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9 +// RUN: %clang_cc1 -DCK9 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9 // RUN: %clang_cc1 -DCK9 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK9 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK9 -// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY8 %s +// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s // RUN: %clang_cc1 -DCK9 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY8 %s -// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY8 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s +// RUN: %clang_cc1 -DCK9 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s // RUN: %clang_cc1 -DCK9 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY8 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY8 %s // SIMD-ONLY8-NOT: {{__kmpc|__tgt}} #ifdef CK9 @@ -586,19 +586,19 @@ void implicit_maps_array (int a){ // CK9: {{.+}} = getelementptr inbounds [2 x double], [2 x double]* [[REF]], i[[sz]] 0, i[[sz]] 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10 // RUN: %clang_cc1 -DCK10 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 -// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10 +// RUN: %clang_cc1 -DCK10 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10 // RUN: %clang_cc1 -DCK10 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK10 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK10 -// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY9 %s +// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s // RUN: %clang_cc1 -DCK10 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY9 %s -// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY9 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s +// RUN: %clang_cc1 -DCK10 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s // RUN: %clang_cc1 -DCK10 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY9 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY9 %s // SIMD-ONLY9-NOT: {{__kmpc|__tgt}} #ifdef CK10 @@ -638,19 +638,19 @@ void implicit_maps_pointer (){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11 // RUN: %clang_cc1 -DCK11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 -// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11 +// RUN: %clang_cc1 -DCK11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11 // RUN: %clang_cc1 -DCK11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK11 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK11 -// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY10 %s +// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s // RUN: %clang_cc1 -DCK11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY10 %s -// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY10 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s +// RUN: %clang_cc1 -DCK11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s // RUN: %clang_cc1 -DCK11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY10 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY10 %s // SIMD-ONLY10-NOT: {{__kmpc|__tgt}} #ifdef CK11 @@ -688,19 +688,19 @@ void implicit_maps_double_complex (int a){ // CK11: {{.+}} = getelementptr inbounds { double, double }, { double, double }* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 +// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-64 // RUN: %clang_cc1 -DCK12 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-64 -// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-64 +// RUN: %clang_cc1 -DCK12 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-32 // RUN: %clang_cc1 -DCK12 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK12 --check-prefix CK12-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK12 --check-prefix CK12-32 -// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY11 %s +// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s // RUN: %clang_cc1 -DCK12 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY11 %s -// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY11 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s +// RUN: %clang_cc1 -DCK12 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s // RUN: %clang_cc1 -DCK12 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY11 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY11 %s // SIMD-ONLY11-NOT: {{__kmpc|__tgt}} #ifdef CK12 @@ -759,19 +759,19 @@ void implicit_maps_float_complex (int a){ // CK12-32: {{.+}} = getelementptr inbounds { float, float }, { float, float }* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13 // RUN: %clang_cc1 -DCK13 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 -// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13 +// RUN: %clang_cc1 -DCK13 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13 // RUN: %clang_cc1 -DCK13 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK13 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK13 -// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY12 %s +// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s // RUN: %clang_cc1 -DCK13 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY12 %s -// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY12 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s +// RUN: %clang_cc1 -DCK13 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s // RUN: %clang_cc1 -DCK13 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY12 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY12 %s // SIMD-ONLY12-NOT: {{__kmpc|__tgt}} #ifdef CK13 @@ -841,19 +841,19 @@ void implicit_maps_variable_length_array (int a){ // CK13: {{.+}} = getelementptr inbounds double, double* [[REF]], i[[sz]] %{{.+}} #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 +// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-64 // RUN: %clang_cc1 -DCK14 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-64 -// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-64 +// RUN: %clang_cc1 -DCK14 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-32 // RUN: %clang_cc1 -DCK14 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK14 --check-prefix CK14-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK14 --check-prefix CK14-32 -// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY13 %s +// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s // RUN: %clang_cc1 -DCK14 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY13 %s -// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY13 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s +// RUN: %clang_cc1 -DCK14 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s // RUN: %clang_cc1 -DCK14 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY13 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY13 %s // SIMD-ONLY13-NOT: {{__kmpc|__tgt}} #ifdef CK14 @@ -934,19 +934,19 @@ void implicit_maps_class (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 +// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-64 // RUN: %clang_cc1 -DCK15 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-64 -// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-64 +// RUN: %clang_cc1 -DCK15 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-32 // RUN: %clang_cc1 -DCK15 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK15 --check-prefix CK15-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK15 --check-prefix CK15-32 -// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY14 %s +// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s // RUN: %clang_cc1 -DCK15 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY14 %s -// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY14 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s +// RUN: %clang_cc1 -DCK15 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s // RUN: %clang_cc1 -DCK15 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY14 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY14 %s // SIMD-ONLY14-NOT: {{__kmpc|__tgt}} #ifdef CK15 @@ -1112,19 +1112,19 @@ void implicit_maps_templated_class (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 +// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-64 // RUN: %clang_cc1 -DCK16 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-64 -// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-64 +// RUN: %clang_cc1 -DCK16 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-32 // RUN: %clang_cc1 -DCK16 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK16 --check-prefix CK16-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK16 --check-prefix CK16-32 -// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY15 %s +// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s // RUN: %clang_cc1 -DCK16 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY15 %s -// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY15 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s +// RUN: %clang_cc1 -DCK16 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s // RUN: %clang_cc1 -DCK16 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY15 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY15 %s // SIMD-ONLY15-NOT: {{__kmpc|__tgt}} #ifdef CK16 @@ -1173,19 +1173,19 @@ void implicit_maps_templated_function (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17 // RUN: %clang_cc1 -DCK17 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 -// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17 +// RUN: %clang_cc1 -DCK17 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17 // RUN: %clang_cc1 -DCK17 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK17 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK17 -// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY16 %s +// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s // RUN: %clang_cc1 -DCK17 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY16 %s -// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY16 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s +// RUN: %clang_cc1 -DCK17 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s // RUN: %clang_cc1 -DCK17 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY16 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY16 %s // SIMD-ONLY16-NOT: {{__kmpc|__tgt}} #ifdef CK17 @@ -1230,19 +1230,19 @@ void implicit_maps_struct (int a){ // CK17: {{.+}} = getelementptr inbounds [[ST]], [[ST]]* [[REF]], i32 0, i32 0 #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 +// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-64 // RUN: %clang_cc1 -DCK18 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-64 -// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-64 +// RUN: %clang_cc1 -DCK18 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-32 // RUN: %clang_cc1 -DCK18 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK18 --check-prefix CK18-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK18 --check-prefix CK18-32 -// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY17 %s +// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s // RUN: %clang_cc1 -DCK18 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY17 %s -// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY17 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s +// RUN: %clang_cc1 -DCK18 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s // RUN: %clang_cc1 -DCK18 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY17 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY17 %s // SIMD-ONLY17-NOT: {{__kmpc|__tgt}} #ifdef CK18 @@ -1290,19 +1290,19 @@ void implicit_maps_template_type_capture (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64 +// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64 // RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64 -// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64 +// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32 // RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32 -// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s // RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY18 %s -// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s // RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s // SIMD-ONLY18-NOT: {{__kmpc|__tgt}} #ifdef CK19 @@ -2758,19 +2758,19 @@ void explicit_maps_single (int ii){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64 +// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-64 // RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64 -// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-64 +// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-32 // RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK20 --check-prefix CK20-32 -// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s +// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s // RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s -// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s +// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s // RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY19 %s // SIMD-ONLY19-NOT: {{__kmpc|__tgt}} #ifdef CK20 @@ -2886,19 +2886,19 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-64 +// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64 // RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-64 -// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64 +// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32 // RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK21 --check-prefix CK21-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32 -// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s // RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY20 %s -// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s // RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s // SIMD-ONLY20-NOT: {{__kmpc|__tgt}} #ifdef CK21 // CK21: [[ST:%.+]] = type { i32, i32, float* } @@ -3089,19 +3089,19 @@ int explicit_maps_template_args_and_members(int a){ // CK21: define {{.+}}[[CALL05]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-64 +// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-64 // RUN: %clang_cc1 -DCK22 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-64 -// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-64 +// RUN: %clang_cc1 -DCK22 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-32 // RUN: %clang_cc1 -DCK22 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK22 --check-prefix CK22-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK22 --check-prefix CK22-32 -// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY21 %s +// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s // RUN: %clang_cc1 -DCK22 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY21 %s -// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY21 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s +// RUN: %clang_cc1 -DCK22 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s // RUN: %clang_cc1 -DCK22 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY21 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY21 %s // SIMD-ONLY21-NOT: {{__kmpc|__tgt}} #ifdef CK22 @@ -3459,19 +3459,19 @@ int explicit_maps_globals(void){ // CK22: define {{.+}}[[CALL14]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-64 +// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-64 // RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-64 -// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-32 +// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-64 +// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-32 // RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK23 --check-prefix CK23-32 +// RUN: %clang_cc1 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK23 --check-prefix CK23-32 -// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY22 %s +// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s // RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY22 %s -// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY22 %s +// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s +// RUN: %clang_cc1 -std=c++11 -DCK23 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s // RUN: %clang_cc1 -std=c++11 -DCK23 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY22 %s +// RUN: %clang_cc1 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY22 %s // SIMD-ONLY22-NOT: {{__kmpc|__tgt}} #ifdef CK23 @@ -3640,19 +3640,19 @@ int explicit_maps_inside_captured(int a){ // CK23: define {{.+}}[[CALL05]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-64 +// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-64 // RUN: %clang_cc1 -DCK24 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-64 -// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-64 +// RUN: %clang_cc1 -DCK24 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-32 // RUN: %clang_cc1 -DCK24 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK24 --check-prefix CK24-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK24 --check-prefix CK24-32 -// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY23 %s +// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s // RUN: %clang_cc1 -DCK24 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY23 %s -// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY23 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s +// RUN: %clang_cc1 -DCK24 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s // RUN: %clang_cc1 -DCK24 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY23 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY23 %s // SIMD-ONLY23-NOT: {{__kmpc|__tgt}} #ifdef CK24 @@ -4127,19 +4127,19 @@ int explicit_maps_struct_fields(int a){ // CK24: define {{.+}}[[CALL24]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-64 +// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-64 // RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-64 -// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-32 +// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-64 +// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-32 // RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK25 --check-prefix CK25-32 +// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK25 --check-prefix CK25-32 -// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY24 %s +// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s // RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY24 %s -// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY24 %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s +// RUN: %clang_cc1 -DCK25 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s // RUN: %clang_cc1 -DCK25 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY24 %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY24 %s // SIMD-ONLY24-NOT: {{__kmpc|__tgt}} #ifdef CK25 // CK25: [[ST:%.+]] = type { i32, float } @@ -4231,19 +4231,19 @@ int explicit_maps_with_inner_lambda(int a){ // CK25: define {{.+}}[[LAMBDA2]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-64 +// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-64 // RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-64 -// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-32 +// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-64 +// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-32 // RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK26 --check-prefix CK26-32 +// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK26 --check-prefix CK26-32 -// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY25 %s +// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s // RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY25 %s -// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY25 %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s +// RUN: %clang_cc1 -DCK26 -std=c++11 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s // RUN: %clang_cc1 -DCK26 -std=c++11 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY25 %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY25 %s // SIMD-ONLY25-NOT: {{__kmpc|__tgt}} #ifdef CK26 // CK26: [[ST:%.+]] = type { i32, float*, i32, float* } @@ -4427,19 +4427,19 @@ int explicit_maps_with_private_class_members(){ } #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-64 +// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-64 // RUN: %clang_cc1 -DCK27 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-64 -// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-64 +// RUN: %clang_cc1 -DCK27 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-32 // RUN: %clang_cc1 -DCK27 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK27 --check-prefix CK27-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK27 --check-prefix CK27-32 -// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY26 %s +// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s // RUN: %clang_cc1 -DCK27 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY26 %s -// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY26 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s +// RUN: %clang_cc1 -DCK27 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s // RUN: %clang_cc1 -DCK27 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY26 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY26 %s // SIMD-ONLY26-NOT: {{__kmpc|__tgt}} #ifdef CK27 @@ -4656,19 +4656,19 @@ void zero_size_section_and_private_maps (int ii){ // CK27: define {{.+}}[[CALL07]] #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-64 +// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-64 // RUN: %clang_cc1 -DCK28 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-64 -// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-64 +// RUN: %clang_cc1 -DCK28 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-32 // RUN: %clang_cc1 -DCK28 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK28 --check-prefix CK28-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK28 --check-prefix CK28-32 -// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY27 %s +// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s // RUN: %clang_cc1 -DCK28 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY27 %s -// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY27 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s +// RUN: %clang_cc1 -DCK28 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s // RUN: %clang_cc1 -DCK28 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY27 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY27 %s // SIMD-ONLY27-NOT: {{__kmpc|__tgt}} #ifdef CK28 @@ -4729,19 +4729,19 @@ void explicit_maps_pointer_references (int *p){ } #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-64 +// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-64 // RUN: %clang_cc1 -DCK29 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-64 -// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-64 +// RUN: %clang_cc1 -DCK29 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-32 // RUN: %clang_cc1 -DCK29 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK29 --check-prefix CK29-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK29 --check-prefix CK29-32 -// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY28 %s +// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s // RUN: %clang_cc1 -DCK29 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY28 %s -// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY28 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s +// RUN: %clang_cc1 -DCK29 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s // RUN: %clang_cc1 -DCK29 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY28 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY28 %s // SIMD-ONLY28-NOT: {{__kmpc|__tgt}} #ifdef CK29 diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp index 02f60adb48..d1920ecf25 100644 --- a/test/OpenMP/target_parallel_codegen.cpp +++ b/test/OpenMP/target_parallel_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp index c56b35e6e3..7b022edbf7 100644 --- a/test/OpenMP/target_parallel_for_codegen.cpp +++ b/test/OpenMP/target_parallel_for_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp index e325799dcf..a49ce0d564 100644 --- a/test/OpenMP/target_parallel_for_simd_codegen.cpp +++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp index 9a5fb57696..3d3fa795e3 100644 --- a/test/OpenMP/target_simd_codegen.cpp +++ b/test/OpenMP/target_simd_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp index 24f30e072c..0850389c0e 100644 --- a/test/OpenMP/target_teams_codegen.cpp +++ b/test/OpenMP/target_teams_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp index 89053b09e0..b659c121fc 100644 --- a/test/OpenMP/target_teams_distribute_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp index 04aa0e6582..5487fa86e8 100644 --- a/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp index dc2183d49a..87a1499689 100644 --- a/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp @@ -1,49 +1,49 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // Test target codegen - host bc file has to be created first. (no significant differences with host version of target region) // RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64 // RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // // RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp index 46c76a06c3..88169197d1 100644 --- a/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp @@ -1,49 +1,49 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix HHECK --check-prefix HCHECK-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix HLAMBDA --check-prefix HLAMBDA-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // Test target codegen - host bc file has to be created first. (no significant differences with host version of target region) // RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 --check-prefix TLAMBDA --check-prefix TLAMBDA-64 // RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // // RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix SIMD-ONLY0 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix SIMD-ONLY0 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_private_codegen.cpp b/test/OpenMP/target_teams_distribute_private_codegen.cpp index 457156e3e9..f52d3b040f 100644 --- a/test/OpenMP/target_teams_distribute_private_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp index 21ba88f8ad..7646f4ab3a 100644 --- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp @@ -1,37 +1,37 @@ // Test host codegen. -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // Test target codegen - host bc file has to be created first. // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-64 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-64 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix TCHECK --check-prefix TCHECK-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix TCHECK --check-prefix TCHECK-32 // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm-bc %s -o %t-x86-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=45 -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -fopenmp-is-device -fopenmp-host-ir-file-path %t-x86-host.bc -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp index 2964bfb2d2..b2b911e888 100644 --- a/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp index f17550f9f5..4fa4d04c70 100644 --- a/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_firstprivate_codegen.cpp index d68fcdd032..562e986df0 100644 --- a/test/OpenMP/teams_distribute_firstprivate_codegen.cpp +++ b/test/OpenMP/teams_distribute_firstprivate_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp index 1c55a14814..5fc7ee12eb 100644 --- a/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp +++ b/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp index 4fb506e56f..b2c8c22b84 100644 --- a/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_private_codegen.cpp b/test/OpenMP/teams_distribute_private_codegen.cpp index 111c00975c..8880e2f517 100644 --- a/test/OpenMP/teams_distribute_private_codegen.cpp +++ b/test/OpenMP/teams_distribute_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp b/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp index 6b248cfd37..27320191fa 100644 --- a/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp +++ b/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -Wno-openmp-target -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -Wno-openmp-target | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/OpenMP/teams_distribute_simd_private_codegen.cpp b/test/OpenMP/teams_distribute_simd_private_codegen.cpp index 6ed092c76b..fc7000a699 100644 --- a/test/OpenMP/teams_distribute_simd_private_codegen.cpp +++ b/test/OpenMP/teams_distribute_simd_private_codegen.cpp @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-64 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-64 +// RUN: %clang_cc1 -DCHECK -verify -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 // RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CHECK --check-prefix CHECK-32 +// RUN: %clang_cc1 -DCHECK -fopenmp -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CHECK --check-prefix CHECK-32 -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -verify -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -std=c++11 -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -DCHECK -fopenmp-simd -x c++ -triple i386-unknown-unknown -fopenmp-targets=i386-pc-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 // RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix LAMBDA --check-prefix LAMBDA-64 +// RUN: %clang_cc1 -DLAMBDA -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix LAMBDA --check-prefix LAMBDA-64 -// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -verify -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s -// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY1 %s +// RUN: %clang_cc1 -DLAMBDA -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics diff --git a/test/Profile/c-captured.c b/test/Profile/c-captured.c index bae2dcb6ef..0e265a7229 100644 --- a/test/Profile/c-captured.c +++ b/test/Profile/c-captured.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -check-prefix=PGOGEN -check-prefix=PGOALL %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOGEN -check-prefix=PGOALL %s // RUN: llvm-profdata merge %S/Inputs/c-captured.proftext -o %t.profdata -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -check-prefix=PGOUSE -check-prefix=PGOALL %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE -check-prefix=PGOALL %s // PGOGEN: @[[DCC:__profc_debug_captured]] = private global [3 x i64] zeroinitializer // PGOGEN: @[[CSC:__profc_c_captured.c___captured_stmt]] = private global [2 x i64] zeroinitializer diff --git a/test/Profile/c-general.c b/test/Profile/c-general.c index da3b7f2552..22b4288a5f 100644 --- a/test/Profile/c-general.c +++ b/test/Profile/c-general.c @@ -1,12 +1,12 @@ // Test instrumentation of general constructs in C. -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -check-prefix=PGOGEN %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOGEN %s // RUN: llvm-profdata merge %S/Inputs/c-general.proftext -o %t.profdata -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -check-prefix=PGOUSE %s -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v3 | FileCheck -check-prefix=PGOUSE %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v3 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s // Also check compatibility with older profiles. -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -check-prefix=PGOUSE %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v1 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s // PGOGEN: @[[SLC:__profc_simple_loops]] = private global [4 x i64] zeroinitializer // PGOGEN: @[[IFC:__profc_conditionals]] = private global [11 x i64] zeroinitializer diff --git a/test/Profile/cxx-lambda.cpp b/test/Profile/cxx-lambda.cpp index 2b422912f4..645f1603e0 100644 --- a/test/Profile/cxx-lambda.cpp +++ b/test/Profile/cxx-lambda.cpp @@ -1,13 +1,13 @@ // Tests for instrumentation of C++11 lambdas // RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-lambda.cpp -std=c++11 -o - -emit-llvm -fprofile-instrument=clang > %tgen -// RUN: FileCheck --input-file=%tgen -check-prefix=PGOGEN %s -// RUN: FileCheck --input-file=%tgen -check-prefix=LMBGEN %s +// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tgen -check-prefix=PGOGEN %s +// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tgen -check-prefix=LMBGEN %s // RUN: llvm-profdata merge %S/Inputs/cxx-lambda.proftext -o %t.profdata // RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-lambda.cpp -std=c++11 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata > %tuse -// RUN: FileCheck --input-file=%tuse -check-prefix=PGOUSE %s -// RUN: FileCheck --input-file=%tuse -check-prefix=LMBUSE %s +// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tuse -check-prefix=PGOUSE %s +// RUN: FileCheck -allow-deprecated-dag-overlap --input-file=%tuse -check-prefix=LMBUSE %s // PGOGEN: @[[LWC:__profc__Z7lambdasv]] = private global [4 x i64] zeroinitializer // PGOGEN: @[[MAC:__profc_main]] = private global [1 x i64] zeroinitializer diff --git a/test/SemaCXX/pragma-optimize.cpp b/test/SemaCXX/pragma-optimize.cpp index cda46c552a..132a59985f 100644 --- a/test/SemaCXX/pragma-optimize.cpp +++ b/test/SemaCXX/pragma-optimize.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s -// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck %s -// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck %s +// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck -allow-deprecated-dag-overlap %s +// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck -allow-deprecated-dag-overlap %s +// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck -allow-deprecated-dag-overlap %s #pragma clang optimize off -- GitLab From 0c4483d9394896cd5d7057144a4cff2a4a03dd40 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Jul 2018 21:07:04 +0000 Subject: [PATCH 0511/1023] Fix determination of whether one set of cvr-qualifiers is compatible with another in template argument deduction. We happened to typically get away with getting this wrong, because the cases where we'd produce a bogus deduction were caught by the final "deduced A is compatible with A" check. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336852 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 12 ++++++------ .../temp.deduct/temp.deduct.type/p1.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fd4197ce2a..760207fece 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1019,8 +1019,10 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } -/// Determine whether the parameter has qualifiers that are either -/// inconsistent with or a superset of the argument's qualifiers. +/// Determine whether the parameter has qualifiers that the argument +/// lacks. Put another way, determine whether there is no way to add +/// a deduced set of qualifiers to the ParamType that would result in +/// its qualifiers matching those of the ArgType. static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, QualType ArgType) { Qualifiers ParamQs = ParamType.getQualifiers(); @@ -1044,10 +1046,8 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, ParamQs.hasObjCLifetime()) return true; - // CVR qualifier superset. - return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) && - ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers()) - == ParamQs.getCVRQualifiers()); + // CVR qualifiers inconsistent or a superset. + return (ParamQs.getCVRQualifiers() & ~ArgQs.getCVRQualifiers()) != 0; } /// Compare types for equality with respect to possibly compatible diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp new file mode 100644 index 0000000000..33d8182ab1 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p1.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify %s + +// an attempt is made to find template argument values that will make P, after +// substitution of the deduced values, compatible with A + +namespace cv_mismatch { + template struct X {}; + template void f(X); // expected-note {{cannot deduce a type for 'T' that would make 'const T' equal 'volatile int'}} + void g() { f(X()); } // expected-error {{no matching}} +} -- GitLab From e45150d3b17ee2298a07e344c8b20595f239cd45 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 11 Jul 2018 22:19:14 +0000 Subject: [PATCH 0512/1023] os_log: When there are multiple privacy annotations in the format string, choose the strictest one instead of the last. Also fix an undefined behavior. Move the pointer update to a later point to avoid adding StringRef::npos to the pointer. rdar://problem/40706280 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336863 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/PrintfFormatString.cpp | 11 ++++++----- test/CodeGen/builtins.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 2e5841ecae..00591ab2b0 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -135,17 +135,16 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, MatchedStr = Matches[1]; I += Matches[0].size(); - // Set the privacy flag if there is a privacy annotation in the - // comma-delimited segment. This overrides any privacy annotations that - // appeared in previous comma-delimited segments. + // Set the privacy flag if the privacy annotation in the + // comma-delimited segment is at least as strict as the privacy + // annotations in previous comma-delimited segments. if (MatchedStr.equals("private")) PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; - else if (MatchedStr.equals("public")) + else if (PrivacyFlags == 0 && MatchedStr.equals("public")) PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; } else { size_t CommaOrBracePos = Str.find_if([](char c) { return c == ',' || c == '}'; }); - I += CommaOrBracePos + 1; if (CommaOrBracePos == StringRef::npos) { // Neither a comma nor the closing brace was found. @@ -153,6 +152,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, H.HandleIncompleteSpecifier(Start, E - Start); return true; } + + I += CommaOrBracePos + 1; } // Continue until the closing brace is found. } while (*(I - 1) == ','); diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 4059f16fbf..77b479e4c1 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -421,7 +421,7 @@ void test_builtin_os_log(void *buf, int i, const char *data) { // CHECK: %[[V5:.*]] = load i8*, i8** %[[DATA_ADDR]] // CHECK: %[[V6:.*]] = ptrtoint i8* %[[V5]] to i64 // CHECK: call void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49(i8* %[[V1]], i32 %[[V2]], i64 %[[V4]], i32 16, i64 %[[V6]]) - __builtin_os_log_format(buf, "%d %{private,public}s %{public,private}.16P", i, data, data); + __builtin_os_log_format(buf, "%d %{public}s %{private}.16P", i, data, data); // privacy annotations aren't recognized when they are preceded or followed // by non-whitespace characters. @@ -443,7 +443,7 @@ void test_builtin_os_log(void *buf, int i, const char *data) { // The last privacy annotation in the string wins. // CHECK: call void @__os_log_helper_1_3_1_8_33( - __builtin_os_log_format(buf, "%{ public, private, public, private}s", "abc"); + __builtin_os_log_format(buf, "%{ private, public, private, public}s", "abc"); } // CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_3_4_4_0_8_34_4_17_8_49 -- GitLab From ce51829da05caa49bfbaaef28694bc770f0eb233 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 Jul 2018 23:19:41 +0000 Subject: [PATCH 0513/1023] Fix deduction for conversion function templates converting to reference types. We previously tried to use the "parameter is a reference" logic here, but that doesn't work because it gets P and A backwards. Instead, add a separate implementation of the "deduced A can be less qualified than A" rule. This also exposes that we incorrectly stripped cv-qualifiers from the referent of A if it was a reference. However, if we don't do that, we get the wrong results when P is a reference. In an attempt to match what sanity dictates and what other implementations are doing, we now remove cv-qualifiers from A and P unless both are reference types. I've brought this up on the core reflector too, to try to get the standard fixed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336867 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 33 +++++++-- .../temp.deduct/temp.deduct.conv/p4.cpp | 68 +++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 760207fece..5c3f2ca32c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -99,6 +99,11 @@ namespace clang { /// deduction where the parameter is a function type that can be converted /// to the argument type. TDF_AllowCompatibleFunctionType = 0x20, + + /// Within template argument deduction for a conversion function, we are + /// matching with an argument type for which the original argument was + /// a reference. + TDF_ArgWithReferenceType = 0x40, }; } @@ -1354,6 +1359,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (TDF & TDF_ParamWithReferenceType) { if (hasInconsistentOrSupersetQualifiersOf(Param, Arg)) return Sema::TDK_NonDeducedMismatch; + } else if (TDF & TDF_ArgWithReferenceType) { + // C++ [temp.deduct.conv]p4: + // If the original A is a reference type, A can be more cv-qualified + // than the deduced A + if (!Arg.getQualifiers().compatiblyIncludes(Param.getQualifiers())) + return Sema::TDK_NonDeducedMismatch; + + // Strip out all extra qualifiers from the argument to figure out the + // type we're converting to, prior to the qualification conversion. + Qualifiers Quals; + Arg = S.Context.getUnqualifiedArrayType(Arg, Quals); + Arg = S.Context.getQualifiedType(Arg, Param.getQualifiers()); } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) return Sema::TDK_NonDeducedMismatch; @@ -4025,12 +4042,20 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, // C++0x [temp.deduct.conv]p4: // [...] If A is a reference type, the type referred to by A is used // for type deduction. - if (const ReferenceType *ARef = A->getAs()) - A = ARef->getPointeeType().getUnqualifiedType(); + if (const ReferenceType *ARef = A->getAs()) { + A = ARef->getPointeeType(); + // We work around a defect in the standard here: cv-qualifiers are also + // removed from P and A in this case, unless P was a reference type. This + // seems to mostly match what other compilers are doing. + if (!FromType->getAs()) { + A = A.getUnqualifiedType(); + P = P.getUnqualifiedType(); + } + // C++ [temp.deduct.conv]p3: // // If A is not a reference type: - else { + } else { assert(!A->isReferenceType() && "Reference types were handled above"); // - If P is an array type, the pointer type produced by the @@ -4079,7 +4104,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, // cv-qualified than the deduced A (i.e., the type referred to // by the reference) if (ToType->isReferenceType()) - TDF |= TDF_ParamWithReferenceType; + TDF |= TDF_ArgWithReferenceType; // - The deduced A can be another pointer or pointer to member // type that can be converted to A via a qualification // conversion. diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp index b45ed96d14..89478ed39f 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify struct AnyT { template @@ -62,3 +64,69 @@ void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) { // deduce T = 'const double' const double X::* X::* pm1 = apm; // expected-note {{instantiation of}} } + +namespace non_ptr_ref_cv_qual { + template + struct ConvToT { + template operator T() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_t_1 = ConvToT(); + // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove + // the top-level cv-quaifiers from A *after* removing the reference type, if + // P is not also a reference type. This matches what other compilers are + // doing, and is necessary to support real-world code. + const int &test_conv_to_t_2 = ConvToT(); + + // Example code that would be broken by the standard's rule. + struct Dest {}; + Dest d1a((ConvToT())); + Dest d1b = ConvToT(); + Dest &d2 = (d1a = ConvToT()); + + template + struct ConvToTRef { + template operator T&() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_t_ref_1 = ConvToTRef(); + const int &test_conv_to_t_ref_2 = ConvToTRef(); + + Dest d3a((ConvToTRef())); // initialize the copy ctor parameter with 'const Dest&' + Dest d3b = ConvToTRef(); // convert to non-const T via [over.match.copy]/1.2 + Dest &d4 = (d3a = ConvToTRef()); + + template + struct ConvToConstT { + template operator const T() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_const_t_1 = ConvToConstT(); + const int &test_conv_to_const_t_2 = ConvToConstT(); + + template + struct ConvToConstTRef { + template operator const T&() { + using Check = T; + using Check = Expected; + } + }; + const int test_conv_to_const_t_ref_1 = ConvToConstTRef(); + const int &test_conv_to_const_t_ref_2 = ConvToConstTRef(); + + template using Arr = T[N]; + struct ConvToArr { + template + operator Arr &() { + static_assert(N == 3, ""); + } + }; + int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok + const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion +} -- GitLab From 2cd0afaeb39b51af80e3101638d01d047a1311b8 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Thu, 12 Jul 2018 09:42:05 +0000 Subject: [PATCH 0514/1023] [ASTImporter] Refactor Decl creation Summary: Generalize the creation of Decl nodes during Import. With this patch we do the same things after and before a new AST node is created (::Create) The import logic should be really simple, we create the node, then we mark that as imported, then we recursively import the parts for that node and then set them on that node. However, the AST is actually a graph, so we have to handle circles. If we mark something as imported (`MapImported()`) then we return with the corresponding `To` decl whenever we want to import that node again, this way circles are handled. In order to make this algorithm work we must ensure things, which are handled in the generic CreateDecl<> template: * There are no `Import()` calls in between any node creation (::Create) and the `MapImported()` call. * Before actually creating an AST node (::Create), we must check if the Node had been imported already, if yes then return with that one. One very important case for this is connected to templates: we may start an import both from the templated decl of a template and from the template itself. Now, the virtual `Imported` function is called in `ASTImporter::Impor(Decl *)`, but only once, when the `Decl` is imported. One point of this refactor is to separate responsibilities. The original `Imported()` had 3 responsibilities: - notify subclasses when an import happened - register the decl into `ImportedDecls` - initialise the Decl (set attributes, etc) Now all of these are in separate functions: - `Imported` - `MapImported` - `InitializeImportedDecl` I tried to check all the clients, I executed tests for `ExternalASTMerger.cpp` and some unittests for lldb. Reviewers: a.sidorin, balazske, xazax.hun, r.stahl Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47632 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336896 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTImporter.h | 10 +- include/clang/AST/ASTStructuralEquivalence.h | 13 +- include/clang/AST/DeclBase.h | 2 +- lib/AST/ASTImporter.cpp | 904 ++++++++++--------- lib/AST/ASTStructuralEquivalence.cpp | 9 + lib/AST/ExternalASTMerger.cpp | 8 +- lib/Sema/SemaType.cpp | 1 + unittests/AST/ASTImporterTest.cpp | 102 ++- unittests/AST/StructuralEquivalenceTest.cpp | 5 +- 9 files changed, 594 insertions(+), 460 deletions(-) diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index de3bfbdf04..6e6a192625 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -314,13 +314,13 @@ class Attr; /// \param D A declaration in the "to" context. virtual void CompleteDecl(Decl* D); - /// Note that we have imported the "from" declaration by mapping it - /// to the (potentially-newly-created) "to" declaration. - /// /// Subclasses can override this function to observe all of the \c From -> /// \c To declaration mappings as they are imported. - virtual Decl *Imported(Decl *From, Decl *To); - + virtual Decl *Imported(Decl *From, Decl *To) { return To; } + + /// Store and assign the imported declaration to its counterpart. + Decl *MapImported(Decl *From, Decl *To); + /// Called by StructuralEquivalenceContext. If a RecordDecl is /// being compared to another RecordDecl as part of import, completing the /// other RecordDecl may trigger importation of the first RecordDecl. This diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index d21be992c4..c39d9d9dc1 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -30,6 +30,14 @@ class QualType; class RecordDecl; class SourceLocation; +/// \brief Whether to perform a normal or minimal equivalence check. +/// In case of `Minimal`, we do not perform a recursive check of decls with +/// external storage. +enum class StructuralEquivalenceKind { + Default, + Minimal, +}; + struct StructuralEquivalenceContext { /// AST contexts for which we are checking structural equivalence. ASTContext &FromCtx, &ToCtx; @@ -47,6 +55,8 @@ struct StructuralEquivalenceContext { /// (which we have already complained about). llvm::DenseSet> &NonEquivalentDecls; + StructuralEquivalenceKind EqKind; + /// Whether we're being strict about the spelling of types when /// unifying two types. bool StrictTypeSpelling; @@ -63,10 +73,11 @@ struct StructuralEquivalenceContext { StructuralEquivalenceContext( ASTContext &FromCtx, ASTContext &ToCtx, llvm::DenseSet> &NonEquivalentDecls, + StructuralEquivalenceKind EqKind, bool StrictTypeSpelling = false, bool Complain = true, bool ErrorOnTagTypeMismatch = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), + EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling), ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {} DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 8307be90e8..5ca5907832 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -309,7 +309,7 @@ private: protected: friend class ASTDeclReader; friend class ASTDeclWriter; - friend class ASTImporter; + friend class ASTNodeImporter; friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index b9cd608ac1..07b6723300 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -90,11 +90,83 @@ namespace clang { return getCanonicalForwardRedeclChain(FD); } + void updateFlags(const Decl *From, Decl *To) { + // Check if some flags or attrs are new in 'From' and copy into 'To'. + // FIXME: Other flags or attrs? + if (From->isUsed(false) && !To->isUsed(false)) + To->setIsUsed(); + } + class ASTNodeImporter : public TypeVisitor, public DeclVisitor, public StmtVisitor { ASTImporter &Importer; + // Wrapper for an overload set. + template struct CallOverloadedCreateFun { + template + auto operator()(Args &&... args) + -> decltype(ToDeclT::Create(std::forward(args)...)) { + return ToDeclT::Create(std::forward(args)...); + } + }; + + // Always use these functions to create a Decl during import. There are + // certain tasks which must be done after the Decl was created, e.g. we + // must immediately register that as an imported Decl. The parameter `ToD` + // will be set to the newly created Decl or if had been imported before + // then to the already imported Decl. Returns a bool value set to true if + // the `FromD` had been imported before. + template + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&... args) { + // There may be several overloads of ToDeclT::Create. We must make sure + // to call the one which would be chosen by the arguments, thus we use a + // wrapper for the overload set. + CallOverloadedCreateFun OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward(args)...); + } + // Use this overload if a special Type is needed to be created. E.g if we + // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl` + // then: + // TypedefNameDecl *ToTypedef; + // GetImportedOrCreateDecl(ToTypedef, FromD, ...); + template + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&... args) { + CallOverloadedCreateFun OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward(args)...); + } + // Use this version if a special create function must be + // used, e.g. CXXRecordDecl::CreateLambda . + template + LLVM_NODISCARD bool + GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, + FromDeclT *FromD, Args &&... args) { + ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(FromD)); + if (ToD) + return true; // Already imported. + ToD = CreateFun(std::forward(args)...); + InitializeImportedDecl(FromD, ToD); + return false; // A new Decl is created. + } + + void InitializeImportedDecl(Decl *FromD, Decl *ToD) { + Importer.MapImported(FromD, ToD); + ToD->IdentifierNamespace = FromD->IdentifierNamespace; + if (FromD->hasAttrs()) + for (const Attr *FromAttr : FromD->getAttrs()) + ToD->addAttr(Importer.Import(FromAttr)); + if (FromD->isUsed()) + ToD->setIsUsed(); + if (FromD->isImplicit()) + ToD->setImplicit(); + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} @@ -1485,6 +1557,12 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo( return false; } +static StructuralEquivalenceKind +getStructuralEquivalenceKind(const ASTImporter &Importer) { + return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal + : StructuralEquivalenceKind::Default; +} + bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain) { // Eliminate a potential failure point where we attempt to re-import @@ -1499,6 +1577,7 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, StructuralEquivalenceContext Ctx(Importer.getFromContext(), ToRecord->getASTContext(), Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer), false, Complain); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } @@ -1507,14 +1586,15 @@ bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, bool Complain) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, Complain); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, Complain); return Ctx.IsStructurallyEquivalent(FromVar, ToVar); } bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), - Importer.getNonEquivalentDecls()); + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } @@ -1522,14 +1602,16 @@ bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, FunctionTemplateDecl *To) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); return Ctx.IsStructurallyEquivalent(From, To); } bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1547,7 +1629,8 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1555,7 +1638,8 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1581,9 +1665,11 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + EmptyDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc)) + return ToD; + ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; } @@ -1592,7 +1678,7 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); - Importer.Imported(D, ToD); + Importer.MapImported(D, ToD); return ToD; } @@ -1606,19 +1692,17 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { if (!DC) return nullptr; - AccessSpecDecl *accessSpecDecl - = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(), - DC, Loc, ColonLoc); - - if (!accessSpecDecl) - return nullptr; + AccessSpecDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), + DC, Loc, ColonLoc)) + return ToD; // Lexical DeclContext and Semantic DeclContext // is always the same for the accessSpec. - accessSpecDecl->setLexicalDeclContext(DC); - DC->addDeclInternal(accessSpecDecl); + ToD->setLexicalDeclContext(DC); + DC->addDeclInternal(ToD); - return accessSpecDecl; + return ToD; } Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -1640,13 +1724,14 @@ Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { if (!ToMsg && FromMsg) return nullptr; - StaticAssertDecl *ToD = StaticAssertDecl::Create( - Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, - Importer.Import(D->getRParenLoc()), D->isFailed()); + StaticAssertDecl *ToD; + if (GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed())) + return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); - Importer.Imported(D, ToD); return ToD; } @@ -1697,11 +1782,11 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { - ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, - D->isInline(), - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl( + ToNamespace, D, Importer.getToContext(), DC, D->isInline(), + Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/nullptr)) + return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -1714,7 +1799,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { cast(DC)->setAnonymousNamespace(ToNamespace); } } - Importer.Imported(D, ToNamespace); + Importer.MapImported(D, ToNamespace); ImportDeclContext(D); @@ -1747,13 +1832,15 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { if (D->getQualifierLoc() && !ToQLoc) return nullptr; - NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), - Importer.Import(D->getAliasLoc()), ToII, ToQLoc, - Importer.Import(D->getTargetNameLoc()), TargetDecl); + NamespaceAliasDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, + Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), + TargetDecl)) + return ToD; ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; @@ -1784,7 +1871,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (auto *FoundTypedef = dyn_cast(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) - return Importer.Imported(D, FoundTypedef); + return Importer.MapImported(D, FoundTypedef); } ConflictingDecls.push_back(FoundDecl); @@ -1804,27 +1891,23 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (T.isNull()) return nullptr; - // Some nodes (like anonymous tags referred by typedefs) are allowed to - // import their enclosing typedef directly. Check if this is the case. - if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) - return AlreadyImported; - // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); + TypedefNameDecl *ToTypedef; - if (IsAlias) - ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, StartL, Loc, - Name.getAsIdentifierInfo(), TInfo); - else - ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + if (IsAlias) { + if (GetImportedOrCreateDecl( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; + } else if (GetImportedOrCreateDecl( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToTypedef); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast(D) : nullptr; @@ -1865,7 +1948,7 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundAlias = dyn_cast(FoundDecl)) - return Importer.Imported(D, FoundAlias); + return Importer.MapImported(D, FoundAlias); ConflictingDecls.push_back(FoundDecl); } @@ -1888,14 +1971,15 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { if (!TemplDecl) return nullptr; - TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + TypeAliasTemplateDecl *ToAlias; + if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc, + Name, Params, TemplDecl)) + return ToAlias; TemplDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToAlias); LexicalDC->addDeclInternal(ToAlias); return ToAlias; } @@ -1913,15 +1997,16 @@ Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { assert(LexicalDC->isFunctionOrMethod()); - LabelDecl *ToLabel = D->isGnuLocal() - ? LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getLocStart())) - : LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo()); - Importer.Imported(D, ToLabel); + LabelDecl *ToLabel; + if (D->isGnuLocal() + ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo())) + return ToLabel; auto *Label = cast_or_null(Importer.Import(D->getStmt())); if (!Label) @@ -1970,7 +2055,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (auto *FoundEnum = dyn_cast(Found)) { if (IsStructuralMatch(D, FoundEnum)) - return Importer.Imported(D, FoundEnum); + return Importer.MapImported(D, FoundEnum); } ConflictingDecls.push_back(FoundDecl); @@ -1982,18 +2067,19 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { ConflictingDecls.size()); } } - + // Create the enum declaration. - EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), nullptr, - D->isScoped(), D->isScopedUsingClassTag(), - D->isFixed()); + EnumDecl *D2; + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed())) + return D2; + // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, D2); LexicalDC->addDeclInternal(D2); // Import the integer type. @@ -2025,7 +2111,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this record. @@ -2096,7 +2182,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // unit only had a forward declaration anyway; call it the same // function. // FIXME: For C++, we should also merge methods here. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward @@ -2141,11 +2227,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (auto *DCXX = dyn_cast(D)) { if (DCXX->isLambda()) { TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); - D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(), - DC, TInfo, Loc, - DCXX->isDependentLambda(), - DCXX->isGenericLambda(), - DCXX->getLambdaCaptureDefault()); + if (GetImportedOrCreateSpecialDecl( + D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), + DC, TInfo, Loc, DCXX->isDependentLambda(), + DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + return D2CXX; Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); if (DCXX->getLambdaContextDecl() && !CDecl) return nullptr; @@ -2155,25 +2241,27 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // Sema::ActOnStartCXXMemberDeclarations CXXRecordDecl *const PrevDecl = nullptr; const bool DelayTypeCreation = true; - D2CXX = CXXRecordDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl, + DelayTypeCreation)) + return D2CXX; Importer.getToContext().getTypeDeclType( D2CXX, dyn_cast(DC)); } else { - D2CXX = CXXRecordDecl::Create(Importer.getToContext(), - D->getTagKind(), - DC, StartLoc, Loc, - Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), + cast_or_null(PrevDecl))) + return D2CXX; } + D2 = D2CXX; D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) LexicalDC->addDeclInternal(D2); - Importer.Imported(D, D2); - if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { auto *ToDescribed = cast_or_null( @@ -2218,22 +2306,20 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Import(MemberInfo->getPointOfInstantiation())); } } else { - D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, StartLoc, Loc, Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl)) + return D2; D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); } - + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); - if (PrevDecl) { - // FIXME: do this for all Redeclarables, not just RecordDecls. - D2->setPreviousDecl(PrevDecl); - } } - - Importer.Imported(D, D2); + + Importer.MapImported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) return nullptr; @@ -2269,7 +2355,7 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (auto *FoundEnumConstant = dyn_cast(FoundDecl)) { if (IsStructuralMatch(D, FoundEnumConstant)) - return Importer.Imported(D, FoundEnumConstant); + return Importer.MapImported(D, FoundEnumConstant); } ConflictingDecls.push_back(FoundDecl); @@ -2288,13 +2374,14 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (D->getInitExpr() && !Init) return nullptr; - EnumConstantDecl *ToEnumerator - = EnumConstantDecl::Create(Importer.getToContext(), cast(DC), Loc, - Name.getAsIdentifierInfo(), T, - Init, D->getInitVal()); + EnumConstantDecl *ToEnumerator; + if (GetImportedOrCreateDecl( + ToEnumerator, D, Importer.getToContext(), cast(DC), Loc, + Name.getAsIdentifierInfo(), T, Init, D->getInitVal())) + return ToEnumerator; + ToEnumerator->setAccess(D->getAccess()); ToEnumerator->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToEnumerator); LexicalDC->addDeclInternal(ToEnumerator); return ToEnumerator; } @@ -2445,7 +2532,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { const FunctionDecl *Definition = nullptr; if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody(Definition)) { - return Importer.Imported( + return Importer.MapImported( D, const_cast(Definition)); } FoundByLookup = FoundFunction; @@ -2526,14 +2613,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FunctionDecl *ToFunction = nullptr; SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (auto *FromConstructor = dyn_cast(D)) { - ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - FromConstructor->isExplicit(), - D->isInlineSpecified(), - D->isImplicit(), - D->isConstexpr()); + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), cast(DC), + InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + return ToFunction; if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { SmallVector CtorInitializers; for (auto *I : FromConstructor->inits()) { @@ -2550,37 +2634,30 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToCtor->setNumCtorInitializers(NumInitializers); } } else if (isa(D)) { - ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - D->isImplicit()); - } else if (auto *FromConversion = dyn_cast(D)) { - ToFunction = CXXConversionDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - FromConversion->isExplicit(), - D->isConstexpr(), - SourceLocation()); + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), cast(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + D->isImplicit())) + return ToFunction; + } else if (CXXConversionDecl *FromConversion = + dyn_cast(D)) { + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), cast(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + FromConversion->isExplicit(), D->isConstexpr(), SourceLocation())) + return ToFunction; } else if (auto *Method = dyn_cast(D)) { - ToFunction = CXXMethodDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - Method->getStorageClass(), - Method->isInlineSpecified(), - D->isConstexpr(), - SourceLocation()); + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), cast(DC), + InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), + Method->isInlineSpecified(), D->isConstexpr(), SourceLocation())) + return ToFunction; } else { - ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, - InnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), - D->isInlineSpecified(), - D->hasWrittenPrototype(), - D->isConstexpr()); + if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC, + InnerLocStart, NameInfo, T, TInfo, + D->getStorageClass(), D->isInlineSpecified(), + D->hasWrittenPrototype(), D->isConstexpr())) + return ToFunction; } // Import the qualifier, if any. @@ -2591,7 +2668,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); ToFunction->setRangeEnd(Importer.Import(D->getLocEnd())); - Importer.Imported(D, ToFunction); // Set the parameters. for (auto *Param : Parameters) { @@ -2722,7 +2798,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2744,11 +2820,13 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (!BitWidth && D->getBitWidth()) return nullptr; - FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, BitWidth, D->isMutable(), - D->getInClassInitStyle()); + FieldDecl *ToField; + if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, BitWidth, + D->isMutable(), D->getInClassInitStyle())) + return ToField; + ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (Expr *FromInitializer = D->getInClassInitializer()) { @@ -2759,7 +2837,6 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return nullptr; } ToField->setImplicit(D->isImplicit()); - Importer.Imported(D, ToField); LexicalDC->addDeclInternal(ToField); return ToField; } @@ -2787,7 +2864,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2819,16 +2896,18 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { NamedChain[i++] = cast(D); } - IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( - Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, - {NamedChain, D->getChainingSize()}); + llvm::MutableArrayRef CH = {NamedChain, D->getChainingSize()}; + IndirectFieldDecl *ToIndirectField; + if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC, + Loc, Name.getAsIdentifierInfo(), T, CH)) + // FIXME here we leak `NamedChain` which is allocated before + return ToIndirectField; for (const auto *A : D->attrs()) ToIndirectField->addAttr(Importer.Import(A)); ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIndirectField); LexicalDC->addDeclInternal(ToIndirectField); return ToIndirectField; } @@ -2847,19 +2926,20 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { FriendDecl *ImportedFriend = RD->getFirstFriend(); StructuralEquivalenceContext Context( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); while (ImportedFriend) { if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { if (Context.IsStructurallyEquivalent(D->getFriendDecl(), ImportedFriend->getFriendDecl())) - return Importer.Imported(D, ImportedFriend); + return Importer.MapImported(D, ImportedFriend); } else if (D->getFriendType() && ImportedFriend->getFriendType()) { if (Importer.IsStructurallyEquivalent( D->getFriendType()->getType(), ImportedFriend->getFriendType()->getType(), true)) - return Importer.Imported(D, ImportedFriend); + return Importer.MapImported(D, ImportedFriend); } ImportedFriend = ImportedFriend->getNextFriend(); } @@ -2887,12 +2967,11 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { ToTPLists[I] = List; } - FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - ToFU, Importer.Import(D->getFriendLoc()), - ToTPLists); - - Importer.Imported(D, FrD); + FriendDecl *FrD; + if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), ToFU, + Importer.Import(D->getFriendLoc()), ToTPLists)) + return FrD; FrD->setAccess(D->getAccess()); FrD->setLexicalDeclContext(LexicalDC); @@ -2918,7 +2997,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (auto *FoundIvar = dyn_cast(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { - Importer.Imported(D, FoundIvar); + Importer.MapImported(D, FoundIvar); return FoundIvar; } @@ -2940,14 +3019,15 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (!BitWidth && D->getBitWidth()) return nullptr; - ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), - cast(DC), - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize()); + ObjCIvarDecl *ToIvar; + if (GetImportedOrCreateDecl( + ToIvar, D, Importer.getToContext(), cast(DC), + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth, + D->getSynthesize())) + return ToIvar; + ToIvar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); return ToIvar; } @@ -3018,10 +3098,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { } if (MergeWithVar) { - // An equivalent variable with external linkage has been found. Link + // An equivalent variable with external linkage has been found. Link // the two declarations, then merge them. - Importer.Imported(D, MergeWithVar); - + Importer.MapImported(D, MergeWithVar); + updateFlags(D, MergeWithVar); + if (VarDecl *DDef = D->getDefinition()) { if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) { Importer.ToDiag(ExistingDef->getLocation(), @@ -3058,24 +3139,21 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, - D->getStorageClass()); + VarDecl *ToVar; + if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass())) + return ToVar; + ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToVar); // Templated declarations should never appear in the enclosing DeclContext. if (!D->getDescribedVarTemplate()) LexicalDC->addDeclInternal(ToVar); - if (!D->isFileVarDecl() && - D->isUsed()) - ToVar->setIsUsed(); - // Merge the initializer. if (ImportDefinition(D, ToVar)) return nullptr; @@ -3105,10 +3183,12 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { return nullptr; // Create the imported parameter. - auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, - D->getParameterKind()); - return Importer.Imported(D, ToParm); + ImplicitParamDecl *ToParm = nullptr; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), T, + D->getParameterKind())) + return ToParm; + return ToParm; } Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { @@ -3131,11 +3211,13 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getStorageClass(), - /*DefaultArg*/ nullptr); + ParmVarDecl *ToParm; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass(), + /*DefaultArg*/ nullptr)) + return ToParm; // Set the default argument. ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); @@ -3165,10 +3247,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { D->getFunctionScopeIndex()); } - if (D->isUsed()) - ToParm->setIsUsed(); - - return Importer.Imported(D, ToParm); + return ToParm; } Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { @@ -3240,7 +3319,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // FIXME: Any other bits we need to merge? - return Importer.Imported(D, FoundMethod); + return Importer.MapImported(D, FoundMethod); } } @@ -3251,11 +3330,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( - Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), - Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(), - D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), - D->getImplementationControl(), D->hasRelatedResultType()); + ObjCMethodDecl *ToMethod; + if (GetImportedOrCreateDecl( + ToMethod, D, Importer.getToContext(), Loc, + Importer.Import(D->getLocEnd()), Name.getObjCSelector(), ResultTy, + ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(), + D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), + D->getImplementationControl(), D->hasRelatedResultType())) + return ToMethod; // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. @@ -3284,7 +3366,6 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); ToMethod->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToMethod); LexicalDC->addDeclInternal(ToMethod); return ToMethod; } @@ -3304,16 +3385,14 @@ Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { if (!BoundInfo) return nullptr; - ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create( - Importer.getToContext(), DC, - D->getVariance(), - Importer.Import(D->getVarianceLoc()), - D->getIndex(), - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getColonLoc()), - BoundInfo); - Importer.Imported(D, Result); + ObjCTypeParamDecl *Result; + if (GetImportedOrCreateDecl( + Result, D, Importer.getToContext(), DC, D->getVariance(), + Importer.Import(D->getVarianceLoc()), D->getIndex(), + Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(), + Importer.Import(D->getColonLoc()), BoundInfo)) + return Result; + Result->setLexicalDeclContext(LexicalDC); return Result; } @@ -3339,18 +3418,18 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { - ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Loc, - Importer.Import(D->getCategoryNameLoc()), - Name.getAsIdentifierInfo(), - ToInterface, - /*TypeParamList=*/nullptr, - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); + + if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), Loc, + Importer.Import(D->getCategoryNameLoc()), + Name.getAsIdentifierInfo(), ToInterface, + /*TypeParamList=*/nullptr, + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc()))) + return ToCategory; + ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); - Importer.Imported(D, ToCategory); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToCategory->setTypeParamList(ImportObjCTypeParamList( @@ -3377,7 +3456,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { ToCategory->setProtocolList(Protocols.data(), Protocols.size(), ProtocolLocs.data(), Importer.getToContext()); } else { - Importer.Imported(D, ToCategory); + Importer.MapImported(D, ToCategory); } // Import all of the members of this category. @@ -3446,7 +3525,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of a protocol. @@ -3472,15 +3551,16 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, - Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC, + Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc()), + /*PrevDecl=*/nullptr)) + return ToProto; ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } - - Importer.Imported(D, ToProto); + + Importer.MapImported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) return nullptr; @@ -3496,14 +3576,11 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { SourceLocation LangLoc = Importer.Import(D->getLocation()); bool HasBraces = D->hasBraces(); - - LinkageSpecDecl *ToLinkageSpec = - LinkageSpecDecl::Create(Importer.getToContext(), - DC, - ExternLoc, - LangLoc, - D->getLanguage(), - HasBraces); + + LinkageSpecDecl *ToLinkageSpec; + if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC, + ExternLoc, LangLoc, D->getLanguage(), HasBraces)) + return ToLinkageSpec; if (HasBraces) { SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); @@ -3513,8 +3590,6 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { ToLinkageSpec->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLinkageSpec); - Importer.Imported(D, ToLinkageSpec); - return ToLinkageSpec; } @@ -3532,13 +3607,15 @@ Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), - NameInfo, D->hasTypename()); + UsingDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + D->hasTypename())) + return ToUsing; + ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); - Importer.Imported(D, ToUsing); if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { @@ -3581,12 +3658,13 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { if (!ToTarget) return nullptr; - UsingShadowDecl *ToShadow = UsingShadowDecl::Create( - Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + UsingShadowDecl *ToShadow; + if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, + ToUsing, ToTarget)) + return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); - Importer.Imported(D, ToShadow); if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { @@ -3624,14 +3702,17 @@ Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { if (!ToNominated) return nullptr; - UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getNamespaceKeyLocation()), - Importer.Import(D->getQualifierLoc()), - Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + UsingDirectiveDecl *ToUsingDir; + if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), + ToNominated, ToComAncestor)) + return ToUsingDir; + ToUsingDir->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingDir); - Importer.Imported(D, ToUsingDir); return ToUsingDir; } @@ -3650,12 +3731,13 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), NameInfo, - Importer.Import(D->getEllipsisLoc())); + UnresolvedUsingValueDecl *ToUsingValue; + if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc()))) + return ToUsingValue; - Importer.Imported(D, ToUsingValue); ToUsingValue->setAccess(D->getAccess()); ToUsingValue->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingValue); @@ -3674,13 +3756,14 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( if (ToD) return ToD; - UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getTypenameLoc()), - Importer.Import(D->getQualifierLoc()), Loc, Name, - Importer.Import(D->getEllipsisLoc())); + UnresolvedUsingTypenameDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc()))) + return ToUsing; - Importer.Imported(D, ToUsing); ToUsing->setAccess(D->getAccess()); ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); @@ -3812,7 +3895,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of an @interface. @@ -3840,16 +3923,16 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Create an interface declaration, if one does not already exist. ObjCInterfaceDecl *ToIface = MergeWithIface; if (!ToIface) { - ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Name.getAsIdentifierInfo(), - /*TypeParamList=*/nullptr, - /*PrevDecl=*/nullptr, Loc, - D->isImplicitInterfaceDecl()); + if (GetImportedOrCreateDecl( + ToIface, D, Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), + /*TypeParamList=*/nullptr, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl())) + return ToIface; ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); } - Importer.Imported(D, ToIface); + Importer.MapImported(D, ToIface); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToIface->setTypeParamList(ImportObjCTypeParamList( @@ -3874,13 +3957,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { return nullptr; SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); - ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getIdentifier()), - Category->getClassInterface(), - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - CategoryNameLoc); - + if (GetImportedOrCreateDecl( + ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getIdentifier()), Category->getClassInterface(), + Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), CategoryNameLoc)) + return ToImpl; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3894,7 +3977,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { Category->setImplementation(ToImpl); } - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); ImportDeclContext(D); return ToImpl; } @@ -3919,15 +4002,15 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { if (!Impl) { // We haven't imported an implementation yet. Create a new @implementation // now. - Impl = ObjCImplementationDecl::Create(Importer.getToContext(), - Importer.ImportContext(D->getDeclContext()), - Iface, Super, - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - Importer.Import(D->getSuperClassLoc()), - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); - + if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(), + Importer.ImportContext(D->getDeclContext()), + Iface, Super, Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), + Importer.Import(D->getSuperClassLoc()), + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc()))) + return Impl; + if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3935,12 +4018,12 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { return nullptr; Impl->setLexicalDeclContext(LexicalDC); } - + // Associate the implementation with the class it implements. Iface->setImplementation(Impl); - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); } else { - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || @@ -4006,7 +4089,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // FIXME: Check property attributes, getters, setters, etc.? // Consider these properties to be equivalent. - Importer.Imported(D, FoundProp); + Importer.MapImported(D, FoundProp); return FoundProp; } } @@ -4017,15 +4100,14 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return nullptr; // Create the new property. - ObjCPropertyDecl *ToProperty - = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getAtLoc()), - Importer.Import(D->getLParenLoc()), - Importer.Import(D->getType()), - TSI, - D->getPropertyImplementation()); - Importer.Imported(D, ToProperty); + ObjCPropertyDecl *ToProperty; + if (GetImportedOrCreateDecl( + ToProperty, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()), + Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()), + TSI, D->getPropertyImplementation())) + return ToProperty; + ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); @@ -4079,16 +4161,15 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { ObjCPropertyImplDecl *ToImpl = InImpl->FindPropertyImplDecl(Property->getIdentifier(), Property->getQueryKind()); - if (!ToImpl) { - ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - Property, - D->getPropertyImplementation(), - Ivar, - Importer.Import(D->getPropertyIvarDeclLoc())); + if (!ToImpl) { + if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Importer.Import(D->getLocation()), Property, + D->getPropertyImplementation(), Ivar, + Importer.Import(D->getPropertyIvarDeclLoc()))) + return ToImpl; + ToImpl->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToImpl); LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize @@ -4121,7 +4202,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } // Merge the existing implementation with the new implementation. - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); } return ToImpl; @@ -4133,15 +4214,14 @@ Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // is created. // FIXME: Import default argument. - return TemplateTypeParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - D->getDepth(), - D->getIndex(), - Importer.Import(D->getIdentifier()), - D->wasDeclaredWithTypename(), - D->isParameterPack()); + TemplateTypeParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()), + D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), + D->wasDeclaredWithTypename(), D->isParameterPack()); + return ToD; } Decl * @@ -4165,13 +4245,15 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return nullptr; // FIXME: Import default argument. - - return NonTypeTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getInnerLocStart()), - Loc, D->getDepth(), D->getPosition(), - Name.getAsIdentifierInfo(), - T, D->isParameterPack(), TInfo); + + NonTypeTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), + D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), + TInfo); + return ToD; } Decl * @@ -4183,7 +4265,7 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - + // Import template parameters. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -4191,13 +4273,14 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { return nullptr; // FIXME: Import default argument. - - return TemplateTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Loc, D->getDepth(), D->getPosition(), - D->isParameterPack(), - Name.getAsIdentifierInfo(), - TemplateParams); + + TemplateTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(), + D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(), + TemplateParams); + return ToD; } // Returns the definition for a (forward) declaration of a ClassTemplateDecl, if @@ -4223,7 +4306,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this class template. @@ -4262,9 +4345,9 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (IsStructuralMatch(D, FoundTemplate)) { // The class templates structurally match; call it the same template. - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); } } @@ -4289,29 +4372,23 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!ToTemplated) return nullptr; - // Resolve possible cyclic import. - if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) - return AlreadyImported; - // Create the class template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) return nullptr; - ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, - Loc, Name, TemplateParams, - ToTemplated); + ClassTemplateDecl *D2; + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, + TemplateParams, ToTemplated)) + return D2; + ToTemplated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); - // Note the relationship between the class templates. - Importer.Imported(D, D2); - Importer.Imported(FromTemplated, ToTemplated); - if (FromTemplated->isCompleteDefinition() && !ToTemplated->isCompleteDefinition()) { // FIXME: Import definition! @@ -4331,7 +4408,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *ClassTemplate = @@ -4378,7 +4455,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { @@ -4402,19 +4479,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!ToTPList && PartialSpec->getTemplateParameters()) return nullptr; - D2 = ClassTemplatePartialSpecializationDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, - ToTPList, ClassTemplate, - llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), - ToTAInfo, CanonInjType, nullptr); + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ToTPList, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, nullptr)) + return D2; } else { - D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), - D->getTagKind(), DC, - StartLoc, IdLoc, - ClassTemplate, - TemplateArgs, - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr)) + return D2; } D2->setSpecializationKind(D->getSpecializationKind()); @@ -4425,8 +4501,6 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - Importer.Imported(D, D2); - if (auto *TSI = D->getTypeAsWritten()) { TypeSourceInfo *TInfo = Importer.Import(TSI); if (!TInfo) @@ -4452,7 +4526,6 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( LexicalDC->addDeclInternal(D2); } } - Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return nullptr; @@ -4471,7 +4544,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this variable template. @@ -4498,9 +4571,9 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (auto *FoundTemplate = dyn_cast(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { // The variable templates structurally match; call it the same template. - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); } } @@ -4534,18 +4607,17 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (!TemplateParams) return nullptr; - VarTemplateDecl *ToVarTD = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated); + VarTemplateDecl *ToVarTD; + if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc, + Name, TemplateParams, ToTemplated)) + return ToVarTD; + ToTemplated->setDescribedVarTemplate(ToVarTD); ToVarTD->setAccess(D->getAccess()); ToVarTD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToVarTD); - // Note the relationship between the variable templates. - Importer.Imported(D, ToVarTD); - Importer.Imported(DTemplated, ToTemplated); - if (DTemplated->isThisDeclarationADefinition() && !ToTemplated->isThisDeclarationADefinition()) { // FIXME: Import definition! @@ -4565,7 +4637,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *VarTemplate = cast_or_null( @@ -4611,7 +4683,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // variable. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { @@ -4643,9 +4715,12 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (!ToTPList) return nullptr; - auto *ToPartial = PartVarSpecDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, VarTemplate, - T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos); + PartVarSpecDecl *ToPartial; + if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, + StartLoc, IdLoc, ToTPList, VarTemplate, T, + TInfo, D->getStorageClass(), TemplateArgs, + ArgInfos)) + return ToPartial; auto *FromInst = FromPartial->getInstantiatedFromMember(); auto *ToInst = cast_or_null(Importer.Import(FromInst)); @@ -4658,9 +4733,10 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( D2 = ToPartial; } else { // Full specialization - D2 = VarTemplateSpecializationDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, - D->getStorageClass(), TemplateArgs); + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc, + IdLoc, VarTemplate, T, TInfo, + D->getStorageClass(), TemplateArgs)) + return D2; } SourceLocation POI = D->getPointOfInstantiation(); @@ -4686,8 +4762,6 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( D2->setAccess(D->getAccess()); } - Importer.Imported(D, D2); - // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if // declaration has initializer. Should this be fixed in the AST?.. Anyway, // we have to check the declaration for initializer - otherwise, it won't be @@ -4725,7 +4799,7 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { if (IsStructuralMatch(D, FoundFunction)) { - Importer.Imported(D, FoundFunction); + Importer.MapImported(D, FoundFunction); // FIXME: Actually try to merge the body and other attributes. return FoundFunction; } @@ -4744,13 +4818,14 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (!TemplatedFD) return nullptr; - FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + FunctionTemplateDecl *ToFunc; + if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, + Params, TemplatedFD)) + return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToFunc); LexicalDC->addDeclInternal(ToFunc); return ToFunc; @@ -6835,6 +6910,7 @@ Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) { llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD); if (Pos != ImportedDecls.end()) { Decl *ToD = Pos->second; + // FIXME: move this call to ImportDeclParts(). ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD); return ToD; } else { @@ -6848,22 +6924,22 @@ Decl *ASTImporter::Import(Decl *FromD) { ASTNodeImporter Importer(*this); - // Check whether we've already imported this declaration. - llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) { - Decl *ToD = Pos->second; - Importer.ImportDefinitionIfNeeded(FromD, ToD); + // Check whether we've already imported this declaration. + Decl *ToD = GetAlreadyImportedOrNull(FromD); + if (ToD) { + // If FromD has some updated flags after last import, apply it + updateFlags(FromD, ToD); return ToD; } - - // Import the type - Decl *ToD = Importer.Visit(FromD); + + // Import the type. + ToD = Importer.Visit(FromD); if (!ToD) return nullptr; - // Record the imported declaration. - ImportedDecls[FromD] = ToD; - ToD->IdentifierNamespace = FromD->IdentifierNamespace; + // Notify subclasses. + Imported(FromD, ToD); + return ToD; } @@ -7471,17 +7547,12 @@ void ASTImporter::CompleteDecl (Decl *D) { } } -Decl *ASTImporter::Imported(Decl *From, Decl *To) { - if (From->hasAttrs()) { - for (const auto *FromAttr : From->getAttrs()) - To->addAttr(Import(FromAttr)); - } - if (From->isUsed()) { - To->setIsUsed(); - } - if (From->isImplicit()) { - To->setImplicit(); - } +Decl *ASTImporter::MapImported(Decl *From, Decl *To) { + llvm::DenseMap::iterator Pos = ImportedDecls.find(From); + assert((Pos == ImportedDecls.end() || Pos->second == To) && + "Try to import an already imported Decl"); + if (Pos != ImportedDecls.end()) + return Pos->second; ImportedDecls[From] = To; return To; } @@ -7494,6 +7565,7 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, return true; StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, - false, Complain); + getStructuralEquivalenceKind(*this), false, + Complain); return Ctx.IsStructurallyEquivalent(From, To); } diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index 367755ffd0..d158680a69 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -955,6 +955,15 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!D1 || !D2) return true; + // If any of the records has external storage and we do a minimal check (or + // AST import) we assmue they are equivalent. (If we didn't have this + // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger + // another AST import which in turn would call the structural equivalency + // check again and finally we'd have an improper result.) + if (Context.EqKind == StructuralEquivalenceKind::Minimal) + if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage()) + return true; + if (auto *D1CXX = dyn_cast(D1)) { if (auto *D2CXX = dyn_cast(D2)) { if (D1CXX->hasExternalLexicalStorage() && diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index edf1310d17..ae28c588ca 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -154,7 +154,7 @@ public: ToContainer->setMustBuildLookupTable(); assert(Parent.CanComplete(ToContainer)); } - return ASTImporter::Imported(From, To); + return To; } ASTImporter &GetReverse() { return Reverse; } }; @@ -229,7 +229,7 @@ void ExternalASTMerger::CompleteType(TagDecl *Tag) { SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag); if (!SourceTag->getDefinition()) return false; - Forward.Imported(SourceTag, Tag); + Forward.MapImported(SourceTag, Tag); Forward.ImportDefinition(SourceTag); Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); return true; @@ -248,7 +248,7 @@ void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) { SourceInterface); if (!SourceInterface->getDefinition()) return false; - Forward.Imported(SourceInterface, Interface); + Forward.MapImported(SourceInterface, Interface); Forward.ImportDefinition(SourceInterface); return true; }); @@ -304,7 +304,7 @@ void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC, void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, ASTImporter &Importer) { Origins[ToDC] = Origin; - Importer.ASTImporter::Imported(cast(Origin.DC), const_cast(cast(ToDC))); + Importer.ASTImporter::MapImported(cast(Origin.DC), const_cast(cast(ToDC))); } ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 978c1cc015..c7e251d35b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -7537,6 +7537,7 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) { // and isolate from other C++ specific checks. StructuralEquivalenceContext Ctx( D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls, + StructuralEquivalenceKind::Default, false /*StrictTypeSpelling*/, true /*Complain*/, true /*ErrorOnTagTypeMismatch*/); return Ctx.IsStructurallyEquivalent(D, Suggested); diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 50f7285a39..1b3678c123 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -284,12 +284,15 @@ class ASTImporterTestBase : public ParameterizedTestsFixture { // Buffer for the To context, must live in the test scope. std::string ToCode; + // Represents a "From" translation unit and holds an importer object which we + // use to import from this translation unit. struct TU { // Buffer for the context, must live in the test scope. std::string Code; std::string FileName; std::unique_ptr Unit; TranslationUnitDecl *TUDecl = nullptr; + std::unique_ptr Importer; TU(StringRef Code, StringRef FileName, ArgVector Args) : Code(Code), FileName(FileName), Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args, @@ -297,6 +300,16 @@ class ASTImporterTestBase : public ParameterizedTestsFixture { TUDecl(Unit->getASTContext().getTranslationUnitDecl()) { Unit->enableSourceFileDiagnostics(); } + + Decl *import(ASTUnit *ToAST, Decl *FromDecl) { + assert(ToAST); + if (!Importer) { + Importer.reset(new ASTImporter( + ToAST->getASTContext(), ToAST->getFileManager(), + Unit->getASTContext(), Unit->getFileManager(), false)); + } + return Importer->Import(FromDecl); + } }; // We may have several From contexts and related translation units. In each @@ -329,14 +342,10 @@ public: ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); ToAST->enableSourceFileDiagnostics(); - ASTContext &FromCtx = FromTU.Unit->getASTContext(), - &ToCtx = ToAST->getASTContext(); + ASTContext &FromCtx = FromTU.Unit->getASTContext(); createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code); - ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, - FromTU.Unit->getFileManager(), false); - IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier); assert(ImportedII && "Declaration with the given identifier " "should be specified in test!"); @@ -347,7 +356,8 @@ public: assert(FoundDecls.size() == 1); - Decl *Imported = Importer.Import(FoundDecls.front()); + Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front()); + assert(Imported); return std::make_tuple(*FoundDecls.begin(), Imported); } @@ -401,11 +411,7 @@ public: assert(It != FromTUs.end()); createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code); - ASTContext &FromCtx = From->getASTContext(), - &ToCtx = ToAST->getASTContext(); - ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, - FromCtx.getSourceManager().getFileManager(), false); - return Importer.Import(From); + return It->import(ToAST.get(), From); } ~ASTImporterTestBase() { @@ -1089,8 +1095,7 @@ TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { EXPECT_EQ(ToTemplated1, ToTemplated); } -TEST_P(ASTImporterTestBase, - DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) { +TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) { Decl *FromTU = getTuDecl("template void f(){}", Lang_CXX); auto From = FirstDeclMatcher().match( FromTU, functionTemplateDecl()); @@ -1166,7 +1171,7 @@ TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) { ASSERT_EQ(ToTemplated1, ToTemplated); } -TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) { +TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) { Decl *From, *To; std::tie(From, To) = getImportedDecl( R"( @@ -1711,6 +1716,49 @@ TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) { EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl()); } +TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) { + auto Pattern = varDecl(hasName("x")); + VarDecl *Imported1; + { + Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Imported1 = cast(Import(FromD, Lang_CXX)); + } + VarDecl *Imported2; + { + Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + Imported2 = cast(Import(FromD, Lang_CXX)); + } + EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl()); + EXPECT_FALSE(Imported2->isUsed(false)); + { + Decl *FromTU = + getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc"); + auto *FromD = + FirstDeclMatcher().match(FromTU, functionDecl()); + Import(FromD, Lang_CXX); + } + EXPECT_TRUE(Imported2->isUsed(false)); +} + +TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) { + auto Pattern = varDecl(hasName("x")); + + Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(FromTU, Pattern); + + auto *Imported1 = cast(Import(FromD, Lang_CXX)); + + ASSERT_FALSE(Imported1->isUsed(false)); + + FromD->setIsUsed(); + auto *Imported2 = cast(Import(FromD, Lang_CXX)); + + EXPECT_EQ(Imported1, Imported2); + EXPECT_TRUE(Imported2->isUsed(false)); +} + struct ImportFunctions : ASTImporterTestBase {}; TEST_P(ImportFunctions, @@ -2043,14 +2091,10 @@ TEST_P(ImportFriendFunctions, EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); } -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. +// Disabled temporarily, because the new structural equivalence check +// (https://reviews.llvm.org/D48628) breaks it. +// PreviousDecl is not set because there is no structural match. +// FIXME Enable! TEST_P(ImportFriendFunctions, DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { auto Pattern = functionDecl(hasName("f")); @@ -2080,16 +2124,12 @@ TEST_P(ImportFriendFunctions, (*ImportedD->param_begin())->getOriginalType()); } -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. +// Disabled temporarily, because the new structural equivalence check +// (https://reviews.llvm.org/D48628) breaks it. +// PreviousDecl is not set because there is no structural match. +// FIXME Enable! TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { + DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { auto Pattern = functionDecl(hasName("f")); Decl *FromTU = getTuDecl( diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp index df37b72263..551986fc1c 100644 --- a/unittests/AST/StructuralEquivalenceTest.cpp +++ b/unittests/AST/StructuralEquivalenceTest.cpp @@ -64,8 +64,9 @@ struct StructuralEquivalenceTest : ::testing::Test { bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { llvm::DenseSet> NonEquivalentDecls; - StructuralEquivalenceContext Ctx(D0->getASTContext(), D1->getASTContext(), - NonEquivalentDecls, false, false); + StructuralEquivalenceContext Ctx( + D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls, + StructuralEquivalenceKind::Default, false, false); return Ctx.IsStructurallyEquivalent(D0, D1); } -- GitLab From 9432413567afd0c6f83144b33860e1f43b4a2d22 Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Thu, 12 Jul 2018 11:50:21 +0000 Subject: [PATCH 0515/1023] [ASTImporter] Fix infinite recursion on function import with struct definition in parameters Summary: Importing a function having a struct definition in the parameter list causes a crash in the importer via infinite recursion. This patch avoids the crash and reports such functions as not supported. Unit tests make sure that normal struct definitions inside function bodies work normally on the other hand and LLDB-like type imports also do. Reviewers: a.sidorin, martong Differential Revision: https://reviews.llvm.org/D47946 Patch by Zoltan Gera! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336898 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 20 ++++++- unittests/AST/ASTImporterTest.cpp | 98 +++++++++++++++++++++++++------ 2 files changed, 98 insertions(+), 20 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 07b6723300..56ca9bbae4 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1138,8 +1138,26 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { + // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. + // example: int struct_in_proto(struct data_t{int a;int b;} *d); + DeclContext *OrigDC = D->getDeclContext(); + FunctionDecl *FunDecl; + if (isa(D) && (FunDecl = dyn_cast(OrigDC)) && + FunDecl->hasBody()) { + SourceRange RecR = D->getSourceRange(); + SourceRange BodyR = FunDecl->getBody()->getSourceRange(); + // If RecordDecl is not in Body (it is a param), we bail out. + if (RecR.isValid() && BodyR.isValid() && + (RecR.getBegin() < BodyR.getBegin() || + BodyR.getEnd() < RecR.getEnd())) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + return true; + } + } + // Import the context of this declaration. - DC = Importer.ImportContext(D->getDeclContext()); + DC = Importer.ImportContext(OrigDC); if (!DC) return true; diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 1b3678c123..cd8254c0a0 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -301,14 +301,25 @@ class ASTImporterTestBase : public ParameterizedTestsFixture { Unit->enableSourceFileDiagnostics(); } - Decl *import(ASTUnit *ToAST, Decl *FromDecl) { + void lazyInitImporter(ASTUnit *ToAST) { assert(ToAST); if (!Importer) { Importer.reset(new ASTImporter( ToAST->getASTContext(), ToAST->getFileManager(), Unit->getASTContext(), Unit->getFileManager(), false)); } + assert(&ToAST->getASTContext() == &Importer->getToContext()); + createVirtualFileIfNeeded(ToAST, FileName, Code); + } + + Decl *import(ASTUnit *ToAST, Decl *FromDecl) { + lazyInitImporter(ToAST); return Importer->Import(FromDecl); + } + + QualType import(ASTUnit *ToAST, QualType FromType) { + lazyInitImporter(ToAST); + return Importer->Import(FromType); } }; @@ -321,6 +332,26 @@ class ASTImporterTestBase : public ParameterizedTestsFixture { // vector is expanding, with the list we won't have these issues. std::list FromTUs; + void lazyInitToAST(Language ToLang) { + if (ToAST) + return; + ArgVector ToArgs = getArgVectorForLanguage(ToLang); + // Build the AST from an empty file. + ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc"); + ToAST->enableSourceFileDiagnostics(); + } + + TU *findFromTU(Decl *From) { + // Create a virtual file in the To Ctx which corresponds to the file from + // which we want to import the `From` Decl. Without this source locations + // will be invalid in the ToCtx. + auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) { + return E.TUDecl == From->getTranslationUnitDecl(); + }); + assert(It != FromTUs.end()); + return &*It; + } + public: // We may have several From context but only one To context. std::unique_ptr ToAST; @@ -394,26 +425,17 @@ public: // May be called several times in a given test. // The different instances of the param From may have different ASTContext. Decl *Import(Decl *From, Language ToLang) { - if (!ToAST) { - ArgVector ToArgs = getArgVectorForLanguage(ToLang); - // Build the AST from an empty file. - ToAST = - tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc"); - ToAST->enableSourceFileDiagnostics(); - } - - // Create a virtual file in the To Ctx which corresponds to the file from - // which we want to import the `From` Decl. Without this source locations - // will be invalid in the ToCtx. - auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) { - return E.TUDecl == From->getTranslationUnitDecl(); - }); - assert(It != FromTUs.end()); - createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code); - - return It->import(ToAST.get(), From); + lazyInitToAST(ToLang); + TU *FromTU = findFromTU(From); + return FromTU->import(ToAST.get(), From); } + QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) { + lazyInitToAST(ToLang); + TU *FromTU = findFromTU(TUDecl); + return FromTU->import(ToAST.get(), FromType); + } + ~ASTImporterTestBase() { if (!::testing::Test::HasFailure()) return; @@ -943,6 +965,44 @@ TEST_P(ImportExpr, ImportTypeTraitExprValDep) { typeTraitExpr(hasType(booleanType()))))))))); } +TEST_P(ImportDecl, ImportRecordDeclInFunc) { + MatchVerifier Verifier; + testImport("int declToImport() { " + " struct data_t {int a;int b;};" + " struct data_t d;" + " return 0;" + "}", + Lang_C, "", Lang_C, Verifier, + functionDecl(hasBody(compoundStmt( + has(declStmt(hasSingleDecl(varDecl(hasName("d"))))))))); +} + +TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) { + Decl *FromTU = getTuDecl("int declToImport() { " + " struct data_t {int a;int b;};" + " struct data_t d;" + " return 0;" + "}", + Lang_C, "input.c"); + auto FromVar = + FirstDeclMatcher().match(FromTU, varDecl(hasName("d"))); + ASSERT_TRUE(FromVar); + auto ToType = + ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C); + EXPECT_FALSE(ToType.isNull()); +} + +TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) { + // This construct is not supported by ASTImporter. + Decl *FromTU = + getTuDecl("int declToImport(struct data_t{int a;int b;} *d){ return 0; }", + Lang_C, "input.c"); + auto From = FirstDeclMatcher().match(FromTU, functionDecl()); + ASSERT_TRUE(From); + auto To = Import(From, Lang_C); + EXPECT_EQ(To, nullptr); +} + const internal::VariadicDynCastAllOfMatcher cxxPseudoDestructorExpr; -- GitLab From baad1141d2dd8105aaebd8c7bf79ee832b0e34a2 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 12 Jul 2018 13:13:46 +0000 Subject: [PATCH 0516/1023] [analyzer][UninitializedObjectChecker] Moved non-member functions out of the anonymous namespace As the code for the checker grew, it became increasinly difficult to see whether a function was global or statically defined. In this patch, anything that isn't a type declaration or definition was moved out of the anonymous namespace and is marked as static. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336901 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index 773fcb2269..016be6fed8 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -50,8 +50,6 @@ public: void checkEndFunction(CheckerContext &C) const; }; -llvm::ImmutableListFactory Factory; - /// Represents a field chain. A field chain is a vector of fields where the /// first element of the chain is the object under checking (not stored), and /// every other element is a field, and the element that precedes it is the @@ -205,32 +203,37 @@ private: // TODO: Add a support for nonloc::LocAsInteger. }; +} // end of anonymous namespace + +// Static variable instantionations. + +static llvm::ImmutableListFactory Factory; + // Utility function declarations. /// Returns the object that was constructed by CtorDecl, or None if that isn't /// possible. -Optional +static Optional getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context); /// Checks whether the constructor under checking is called by another /// constructor. -bool isCalledByConstructor(const CheckerContext &Context); +static bool isCalledByConstructor(const CheckerContext &Context); /// Returns whether FD can be (transitively) dereferenced to a void pointer type /// (void*, void**, ...). The type of the region behind a void pointer isn't /// known, and thus FD can not be analyzed. -bool isVoidPointer(const FieldDecl *FD); +static bool isVoidPointer(const FieldDecl *FD); /// Returns true if T is a primitive type. We'll call a type primitive if it's /// either a BuiltinType or an EnumeralType. -bool isPrimitiveType(const QualType &T) { +static bool isPrimitiveType(const QualType &T) { return T->isBuiltinType() || T->isEnumeralType(); } /// Constructs a note message for a given FieldChainInfo object. -void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain); - -} // end of anonymous namespace +static void printNoteMessage(llvm::raw_ostream &Out, + const FieldChainInfo &Chain); //===----------------------------------------------------------------------===// // Methods for UninitializedObjectChecker. @@ -638,9 +641,7 @@ void FieldChainInfo::printTail( // Utility functions. //===----------------------------------------------------------------------===// -namespace { - -bool isVoidPointer(const FieldDecl *FD) { +static bool isVoidPointer(const FieldDecl *FD) { QualType T = FD->getType(); while (!T.isNull()) { @@ -651,7 +652,7 @@ bool isVoidPointer(const FieldDecl *FD) { return false; } -Optional +static Optional getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) { Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(), @@ -668,7 +669,7 @@ getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) { // TODO: We should also check that if the constructor was called by another // constructor, whether those two are in any relation to one another. In it's // current state, this introduces some false negatives. -bool isCalledByConstructor(const CheckerContext &Context) { +static bool isCalledByConstructor(const CheckerContext &Context) { const LocationContext *LC = Context.getLocationContext()->getParent(); while (LC) { @@ -680,7 +681,8 @@ bool isCalledByConstructor(const CheckerContext &Context) { return false; } -void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain) { +static void printNoteMessage(llvm::raw_ostream &Out, + const FieldChainInfo &Chain) { if (Chain.isPointer()) { if (Chain.isDereferenced()) Out << "uninitialized pointee 'this->"; @@ -692,8 +694,6 @@ void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain) { Out << "'"; } -} // end of anonymous namespace - void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { auto Chk = Mgr.registerChecker(); Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption( -- GitLab From 1d0cf8aa79a6542390f7e2ecc74dff3f10970c2a Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 12 Jul 2018 14:54:25 +0000 Subject: [PATCH 0517/1023] [Tooling] Get working directory properly without assuming real file system. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336910 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Tooling/Tooling.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp index c22ad93c76..a106154f4b 100644 --- a/lib/Tooling/Tooling.cpp +++ b/lib/Tooling/Tooling.cpp @@ -411,10 +411,14 @@ int ClangTool::run(ToolAction *Action) { // This just needs to be some symbol in the binary. static int StaticSymbol; - llvm::SmallString<128> InitialDirectory; - if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory)) + std::string InitialDirectory; + if (llvm::ErrorOr CWD = + OverlayFileSystem->getCurrentWorkingDirectory()) { + InitialDirectory = std::move(*CWD); + } else { llvm::report_fatal_error("Cannot detect current path: " + - Twine(EC.message())); + Twine(CWD.getError().message())); + } // First insert all absolute paths into the in-memory VFS. These are global // for all compile commands. -- GitLab From 76bc0933505a0195df31966fc4634ca96fe005a7 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 12 Jul 2018 17:38:48 +0000 Subject: [PATCH 0518/1023] Revert "[modules] Fix 37878; Autoload subdirectory modulemaps with specific LangOpts" This reverts commit f40124d4f05ecf4f880cf4e8f26922d861f705f3 / r336660. This change shouldn't be affecting `@import` behavior, but turns out it is: https://ci.swift.org/view/swift-master-next/job/oss-swift-incremental-RA-osx-master-next/2800/consoleFull#-12570166563122a513-f36a-4c87-8ed7-cbc36a1ec144 Working on a reduced testcase for this, reverting in the meantime. rdar://problem/42102222 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336920 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/HeaderSearch.h | 12 ++---------- lib/Frontend/CompilerInstance.cpp | 15 +++++---------- lib/Lex/HeaderSearch.cpp | 17 +++++++---------- lib/Serialization/ASTReader.cpp | 4 +--- test/Modules/Inputs/autoload-subdirectory/a.h | 9 --------- test/Modules/Inputs/autoload-subdirectory/b.h | 1 - test/Modules/Inputs/autoload-subdirectory/c.h | 7 ------- .../include/module.modulemap | 3 --- .../autoload-subdirectory/module.modulemap | 3 --- test/Modules/autoload-subdirectory.cpp | 10 ---------- 10 files changed, 15 insertions(+), 66 deletions(-) delete mode 100644 test/Modules/Inputs/autoload-subdirectory/a.h delete mode 100644 test/Modules/Inputs/autoload-subdirectory/b.h delete mode 100644 test/Modules/Inputs/autoload-subdirectory/c.h delete mode 100644 test/Modules/Inputs/autoload-subdirectory/include/module.modulemap delete mode 100644 test/Modules/Inputs/autoload-subdirectory/module.modulemap delete mode 100644 test/Modules/autoload-subdirectory.cpp diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index b7147c54fa..fd52000954 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -529,12 +529,8 @@ public: /// search directories to produce a module definition. If not, this lookup /// will only return an already-known module. /// - /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps - /// in subdirectories. - /// /// \returns The module with the given name. - Module *lookupModule(StringRef ModuleName, bool AllowSearch = true, - bool AllowExtraModuleMapSearch = false); + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); /// Try to find a module map file in the given directory, returning /// \c nullptr if none is found. @@ -599,12 +595,8 @@ private: /// but for compatibility with some buggy frameworks, additional attempts /// may be made to find the module under a related-but-different search-name. /// - /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps - /// in subdirectories. - /// /// \returns The module named ModuleName. - Module *lookupModule(StringRef ModuleName, StringRef SearchName, - bool AllowExtraModuleMapSearch = false); + Module *lookupModule(StringRef ModuleName, StringRef SearchName); /// Retrieve a module with the given name, which may be part of the /// given framework. diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 155ead4ac8..5727aae5f1 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1653,10 +1653,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Retrieve the cached top-level module. Module = Known->second; } else if (ModuleName == getLangOpts().CurrentModule) { - // This is the module we're building. - Module = PP->getHeaderSearchInfo().lookupModule( - ModuleName, /*AllowSearch*/ true, - /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); + // This is the module we're building. + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); /// FIXME: perhaps we should (a) look for a module using the module name // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? //if (Module == nullptr) { @@ -1668,8 +1666,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, - !IsInclusionDirective); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); HeaderSearchOptions &HSOpts = PP->getHeaderSearchInfo().getHeaderSearchOpts(); @@ -1746,8 +1743,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ImportLoc, ARRFlags)) { case ASTReader::Success: { if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, - !IsInclusionDirective); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { // Error out if Module does not refer to the file in the prebuilt @@ -1878,8 +1874,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); PrivPath.push_back(std::make_pair(&II, Path[0].second)); - if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true, - !IsInclusionDirective)) + if (PP->getHeaderSearchInfo().lookupModule(PrivateModule)) Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); if (Sub) { diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index b1a2ef1212..312bd2d061 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -198,15 +198,14 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, return Result.str().str(); } -Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, - bool AllowExtraModuleMapSearch) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { // Look in the module map to determine if there is a module by this name. Module *Module = ModMap.findModule(ModuleName); if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) return Module; StringRef SearchName = ModuleName; - Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); + Module = lookupModule(ModuleName, SearchName); // The facility for "private modules" -- adjacent, optional module maps named // module.private.modulemap that are supposed to define private submodules -- @@ -217,14 +216,13 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, // could force building unwanted dependencies into the parent module and cause // dependency cycles. if (!Module && SearchName.consume_back("_Private")) - Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); + Module = lookupModule(ModuleName, SearchName); if (!Module && SearchName.consume_back("Private")) - Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); + Module = lookupModule(ModuleName, SearchName); return Module; } -Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, - bool AllowExtraModuleMapSearch) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { Module *Module = nullptr; // Look through the various header search paths to load any available module @@ -283,9 +281,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, continue; // Load all module maps in the immediate subdirectories of this search - // directory if ModuleName was from @import. - if (AllowExtraModuleMapSearch) - loadSubdirectoryModuleMaps(SearchDirs[Idx]); + // directory. + loadSubdirectoryModuleMaps(SearchDirs[Idx]); // Look again for the module. Module = ModMap.findModule(ModuleName); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 78ca5f7406..3277243667 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2626,9 +2626,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, "MODULE_DIRECTORY found before MODULE_NAME"); // If we've already loaded a module map file covering this module, we may // have a better path for it (relative to the current build). - Module *M = PP.getHeaderSearchInfo().lookupModule( - F.ModuleName, /*AllowSearch*/ true, - /*AllowExtraModuleMapSearch*/ true); + Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); if (M && M->Directory) { // If we're implicitly loading a module, the base directory can't // change between the build and use. diff --git a/test/Modules/Inputs/autoload-subdirectory/a.h b/test/Modules/Inputs/autoload-subdirectory/a.h deleted file mode 100644 index 8be94312e3..0000000000 --- a/test/Modules/Inputs/autoload-subdirectory/a.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "b.h" - -class foo { - int x, y; - -public: - foo(){}; - ~foo(){}; -}; diff --git a/test/Modules/Inputs/autoload-subdirectory/b.h b/test/Modules/Inputs/autoload-subdirectory/b.h deleted file mode 100644 index bfde5bf79f..0000000000 --- a/test/Modules/Inputs/autoload-subdirectory/b.h +++ /dev/null @@ -1 +0,0 @@ -class bar {}; diff --git a/test/Modules/Inputs/autoload-subdirectory/c.h b/test/Modules/Inputs/autoload-subdirectory/c.h deleted file mode 100644 index e5a45250f9..0000000000 --- a/test/Modules/Inputs/autoload-subdirectory/c.h +++ /dev/null @@ -1,7 +0,0 @@ -class nyan { - bool x, y; - -public: - nyan(){}; - ~nyan(){}; -}; diff --git a/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap deleted file mode 100644 index 880ae38b97..0000000000 --- a/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap +++ /dev/null @@ -1,3 +0,0 @@ -module a { header "a.h" } -module b { header "b.h" } -module c { header "c.h" } diff --git a/test/Modules/Inputs/autoload-subdirectory/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/module.modulemap deleted file mode 100644 index 880ae38b97..0000000000 --- a/test/Modules/Inputs/autoload-subdirectory/module.modulemap +++ /dev/null @@ -1,3 +0,0 @@ -module a { header "a.h" } -module b { header "b.h" } -module c { header "c.h" } diff --git a/test/Modules/autoload-subdirectory.cpp b/test/Modules/autoload-subdirectory.cpp deleted file mode 100644 index e76f7056ab..0000000000 --- a/test/Modules/autoload-subdirectory.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -fmodules -fmodule-name=Foo -I %S/Inputs/autoload-subdirectory/ %s -verify -// expected-no-diagnostics - -#include "a.h" -#import "c.h" - -int main() { - foo neko; - return 0; -} -- GitLab From 9aa189d2b986701dc78873d828feed1f47a4e28b Mon Sep 17 00:00:00 2001 From: Nicolas Lesser Date: Thu, 12 Jul 2018 17:43:49 +0000 Subject: [PATCH 0519/1023] [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336922 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 45 ++++++++++++++++++++++++------------- test/SemaCXX/references.cpp | 19 ++++++++++++++++ 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6e695ff6ee..320d93a99a 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -7567,6 +7567,19 @@ bool InitializationSequence::Diagnose(Sema &S, if (!Failed()) return false; + // When we want to diagnose only one element of a braced-init-list, + // we need to factor it out. + Expr *OnlyArg; + if (Args.size() == 1) { + auto *List = dyn_cast(Args[0]); + if (List && List->getNumInits() == 1) + OnlyArg = List->getInit(0); + else + OnlyArg = Args[0]; + } + else + OnlyArg = nullptr; + QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: @@ -7627,7 +7640,7 @@ bool InitializationSequence::Diagnose(Sema &S, ? diag::err_array_init_different_type : diag::err_array_init_non_constant_array)) << DestType.getNonReferenceType() - << Args[0]->getType() + << OnlyArg->getType() << Args[0]->getSourceRange(); break; @@ -7638,7 +7651,7 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_AddressOfOverloadFailed: { DeclAccessPair Found; - S.ResolveAddressOfOverloadedFunction(Args[0], + S.ResolveAddressOfOverloadedFunction(OnlyArg, DestType.getNonReferenceType(), true, Found); @@ -7646,9 +7659,9 @@ bool InitializationSequence::Diagnose(Sema &S, } case FK_AddressOfUnaddressableFunction: { - auto *FD = cast(cast(Args[0])->getDecl()); + auto *FD = cast(cast(OnlyArg)->getDecl()); S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, - Args[0]->getLocStart()); + OnlyArg->getLocStart()); break; } @@ -7658,11 +7671,11 @@ bool InitializationSequence::Diagnose(Sema &S, case OR_Ambiguous: if (Failure == FK_UserConversionOverloadFailed) S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) - << Args[0]->getType() << DestType + << OnlyArg->getType() << DestType << Args[0]->getSourceRange(); else S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) - << DestType << Args[0]->getType() + << DestType << OnlyArg->getType() << Args[0]->getSourceRange(); FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); @@ -7672,10 +7685,10 @@ bool InitializationSequence::Diagnose(Sema &S, if (!S.RequireCompleteType(Kind.getLocation(), DestType.getNonReferenceType(), diag::err_typecheck_nonviable_condition_incomplete, - Args[0]->getType(), Args[0]->getSourceRange())) + OnlyArg->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << (Entity.getKind() == InitializedEntity::EK_Result) - << Args[0]->getType() << Args[0]->getSourceRange() + << OnlyArg->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); @@ -7683,7 +7696,7 @@ bool InitializationSequence::Diagnose(Sema &S, case OR_Deleted: { S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) - << Args[0]->getType() << DestType.getNonReferenceType() + << OnlyArg->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl @@ -7719,7 +7732,7 @@ bool InitializationSequence::Diagnose(Sema &S, : diag::err_lvalue_reference_bind_to_unrelated) << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() - << Args[0]->getType() + << OnlyArg->getType() << Args[0]->getSourceRange(); break; @@ -7744,12 +7757,12 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_RValueReferenceBindingToLValue: S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) - << DestType.getNonReferenceType() << Args[0]->getType() + << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_ReferenceInitDropsQualifiers: { - QualType SourceType = Args[0]->getType(); + QualType SourceType = OnlyArg->getType(); QualType NonRefType = DestType.getNonReferenceType(); Qualifiers DroppedQualifiers = SourceType.getQualifiers() - NonRefType.getQualifiers(); @@ -7765,18 +7778,18 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ReferenceInitFailed: S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) << DestType.getNonReferenceType() - << Args[0]->isLValue() - << Args[0]->getType() + << OnlyArg->isLValue() + << OnlyArg->getType() << Args[0]->getSourceRange(); emitBadConversionNotes(S, Entity, Args[0]); break; case FK_ConversionFailed: { - QualType FromType = Args[0]->getType(); + QualType FromType = OnlyArg->getType(); PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType - << Args[0]->isLValue() + << OnlyArg->isLValue() << FromType << Args[0]->getSourceRange(); S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index b34b740bd4..e32f4a8b0b 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s int g(int); void f() { @@ -55,6 +56,24 @@ void test5() { // const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 const volatile int cvi = 1; const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} + +#if __cplusplus >= 201103L + const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}} + + const int a = 2; + int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}} + + const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}} + + void func(); + void func(int); + int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}} + int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}} + // expected-note@-4{{candidate function}} + // expected-note@-4{{candidate function}} + // expected-note@-6{{candidate function}} + // expected-note@-6{{candidate function}} +#endif } // C++ [dcl.init.ref]p3 -- GitLab From bbe94cb02c6302a2638402f01d264d46e25757ce Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 12 Jul 2018 18:32:11 +0000 Subject: [PATCH 0520/1023] [Tooling] Make standalone executor support user-provided vfs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336928 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Tooling/StandaloneExecution.h | 1 + lib/Tooling/StandaloneExecution.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h index 7d1d0d68a4..572330e4cc 100644 --- a/include/clang/Tooling/StandaloneExecution.h +++ b/include/clang/Tooling/StandaloneExecution.h @@ -37,6 +37,7 @@ public: StandaloneToolExecutor( const CompilationDatabase &Compilations, llvm::ArrayRef SourcePaths, + IntrusiveRefCntPtr BaseFS = vfs::getRealFileSystem(), std::shared_ptr PCHContainerOps = std::make_shared()); diff --git a/lib/Tooling/StandaloneExecution.cpp b/lib/Tooling/StandaloneExecution.cpp index eea8e39d13..7312baf9dc 100644 --- a/lib/Tooling/StandaloneExecution.cpp +++ b/lib/Tooling/StandaloneExecution.cpp @@ -30,9 +30,11 @@ static ArgumentsAdjuster getDefaultArgumentsAdjusters() { StandaloneToolExecutor::StandaloneToolExecutor( const CompilationDatabase &Compilations, llvm::ArrayRef SourcePaths, + IntrusiveRefCntPtr BaseFS, std::shared_ptr PCHContainerOps) - : Tool(Compilations, SourcePaths), Context(&Results), - ArgsAdjuster(getDefaultArgumentsAdjusters()) { + : Tool(Compilations, SourcePaths, std::move(PCHContainerOps), + std::move(BaseFS)), + Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) { // Use self-defined default argument adjusters instead of the default // adjusters that come with the old `ClangTool`. Tool.clearArgumentsAdjusters(); @@ -43,7 +45,7 @@ StandaloneToolExecutor::StandaloneToolExecutor( std::shared_ptr PCHContainerOps) : OptionsParser(std::move(Options)), Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(), - PCHContainerOps), + std::move(PCHContainerOps)), Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) { Tool.clearArgumentsAdjusters(); } -- GitLab From 6be26adfb3d9c7630c5cea4c7e7e5b963a01bfbc Mon Sep 17 00:00:00 2001 From: Nicolas Lesser Date: Thu, 12 Jul 2018 18:45:41 +0000 Subject: [PATCH 0521/1023] [C++17] Disallow lambdas in template parameters (PR33696). Summary: This revision disallows lambdas in template parameters, as reported in PR33696. Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D37442 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336930 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + include/clang/Sema/Sema.h | 62 +++++++++++-------- lib/Parse/ParseDecl.cpp | 4 +- lib/Parse/ParseDeclCXX.cpp | 2 +- lib/Parse/ParseStmt.cpp | 4 +- lib/Parse/ParseTemplate.cpp | 4 +- lib/Sema/Sema.cpp | 2 +- lib/Sema/SemaExpr.cpp | 43 ++++++------- lib/Sema/SemaExprCXX.cpp | 10 ++- lib/Sema/TreeTransform.h | 6 +- .../p2-template-parameter.cpp | 7 +++ 11 files changed, 86 insertions(+), 60 deletions(-) create mode 100644 test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a52ac69a33..51690b644a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6493,6 +6493,8 @@ let CategoryName = "Lambda Issue" in { "lambda expression in an unevaluated operand">; def err_lambda_in_constant_expression : Error< "a lambda expression may not appear inside of a constant expression">; + def err_lambda_in_invalid_context : Error< + "a lambda expression cannot appear in this context">; def err_lambda_return_init_list : Error< "cannot deduce lambda return type from initializer list">; def err_lambda_capture_default_arg : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 527c376bd2..56fb874818 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -979,15 +979,21 @@ public: /// expressions for which we have deferred checking the destructor. SmallVector DelayedDecltypeBinds; + /// \brief Describes whether we are in an expression constext which we have + /// to handle differently. + enum ExpressionKind { + EK_Decltype, EK_TemplateArgument, EK_Other + } ExprContext; + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, CleanupInfo ParentCleanup, Decl *ManglingContextDecl, - bool IsDecltype) - : Context(Context), ParentCleanup(ParentCleanup), - IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), - NumTypos(0), - ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } + ExpressionKind ExprContext) + : Context(Context), ParentCleanup(ParentCleanup), + NumCleanupObjects(NumCleanupObjects), NumTypos(0), + ManglingContextDecl(ManglingContextDecl), MangleNumbering(), + ExprContext(ExprContext) {} /// Retrieve the mangling numbering context, used to consistently /// number constructs like lambdas for mangling. @@ -3989,13 +3995,15 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, ArrayRef Args); - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false); + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - ReuseLambdaContextDecl_t, - bool IsDecltype = false); + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); void PopExpressionEvaluationContext(); void DiscardCleanupsInEvaluationContext(); @@ -10748,25 +10756,25 @@ class EnterExpressionEvaluationContext { bool Entered = true; public: - - EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false, - bool ShouldEnter = true) + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = nullptr, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other, + bool ShouldEnter = true) : Actions(Actions), Entered(ShouldEnter) { if (Entered) Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - IsDecltype); + ExprContext); } - EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext, - Sema::ReuseLambdaContextDecl_t, - bool IsDecltype = false) - : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext, - Sema::ReuseLambdaContextDecl, - IsDecltype); + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Sema::ReuseLambdaContextDecl_t, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext( + NewContext, Sema::ReuseLambdaContextDecl, ExprContext); } enum InitListTag { InitList }; @@ -10780,7 +10788,7 @@ public: if (ShouldEnter && Actions.isUnevaluatedContext() && Actions.getLangOpts().CPlusPlus11) { Actions.PushExpressionEvaluationContext( - Sema::ExpressionEvaluationContext::UnevaluatedList, nullptr, false); + Sema::ExpressionEvaluationContext::UnevaluatedList); Entered = true; } } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d1f87c9df0..c580d1777d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -309,9 +309,7 @@ unsigned Parser::ParseAttributeArgsCommon( EnterExpressionEvaluationContext Unevaluated( Actions, Uneval ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, - /*IsDecltype=*/false); + : Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult ArgExpr( Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index de759c8c94..a969a0f849 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -942,7 +942,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, - /*IsDecltype=*/true); + Sema::ExpressionEvaluationContextRecord::EK_Decltype); Result = Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 107fa55637..8dba6386d0 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1196,7 +1196,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { { EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, - false, + Sema::ExpressionEvaluationContextRecord::EK_Other, /*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition); ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); } @@ -1230,7 +1230,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, - false, + Sema::ExpressionEvaluationContextRecord::EK_Other, /*ShouldEnter=*/ConstexprCondition && *ConstexprCondition); ElseStmt = ParseStatement(); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 5d47161ff5..f701f4639c 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1235,7 +1235,9 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // argument before trying to disambiguate. EnterExpressionEvaluationContext EnterConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, + /*LambdaContextDecl=*/nullptr, + /*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); if (isCXXTypeId(TypeIdAsTemplateArgument)) { TypeResult TypeArg = ParseTypeName( /*Range=*/nullptr, DeclaratorContext::TemplateArgContext); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index d6d105c3b0..b26cf3c043 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -163,7 +163,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ExprEvalContexts.emplace_back( ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{}, - nullptr, false); + nullptr, ExpressionEvaluationContextRecord::EK_Other); PreallocatedFunctionScope.reset(new FunctionScopeInfo(Diags)); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 820e5a9553..51c1c84c27 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14132,22 +14132,22 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) { } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl, - bool IsDecltype) { +Sema::PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, + ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, - LambdaContextDecl, IsDecltype); + LambdaContextDecl, ExprContext); Cleanup.reset(); if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - ReuseLambdaContextDecl_t, - bool IsDecltype) { +Sema::PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, + ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl; - PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype); + PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext); } void Sema::PopExpressionEvaluationContext() { @@ -14155,30 +14155,30 @@ void Sema::PopExpressionEvaluationContext() { unsigned NumTypos = Rec.NumTypos; if (!Rec.Lambdas.empty()) { - if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) { + using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind; + if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() || + (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) { unsigned D; if (Rec.isUnevaluated()) { // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). D = diag::err_lambda_unevaluated_operand; - } else { + } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) { // C++1y [expr.const]p2: // A conditional-expression e is a core constant expression unless the // evaluation of e, following the rules of the abstract machine, would // evaluate [...] a lambda-expression. D = diag::err_lambda_in_constant_expression; - } + } else if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument) { + // C++17 [expr.prim.lamda]p2: + // A lambda-expression shall not appear [...] in a template-argument. + D = diag::err_lambda_in_invalid_context; + } else + llvm_unreachable("Couldn't infer lambda error message."); - // C++1z allows lambda expressions as core constant expressions. - // FIXME: In C++1z, reinstate the restrictions on lambda expressions (CWG - // 1607) from appearing within template-arguments and array-bounds that - // are part of function-signatures. Be mindful that P0315 (Lambdas in - // unevaluated contexts) might lift some of these restrictions in a - // future version. - if (!Rec.isConstantEvaluated() || !getLangOpts().CPlusPlus17) - for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); + for (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. @@ -15637,7 +15637,8 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, // If we're inside a decltype's expression, don't check for a valid return // type or construct temporaries until we know whether this is the last call. - if (ExprEvalContexts.back().IsDecltype) { + if (ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype) { ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE); return false; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8dd9c19bd3..8ed795abbb 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -6434,7 +6434,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (RD->isInvalidDecl() || RD->isDependentContext()) return E; - bool IsDecltype = ExprEvalContexts.back().IsDecltype; + bool IsDecltype = ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype; CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD); if (Destructor) { @@ -6516,7 +6517,9 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { /// are omitted for the 'topmost' call in the decltype expression. If the /// topmost call bound a temporary, strip that temporary off the expression. ExprResult Sema::ActOnDecltypeExpression(Expr *E) { - assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression"); + assert(ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype && + "not in a decltype expression"); // C++11 [expr.call]p11: // If a function call is a prvalue of object type, @@ -6558,7 +6561,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { TopBind = nullptr; // Disable the special decltype handling now. - ExprEvalContexts.back().IsDecltype = false; + ExprEvalContexts.back().ExprContext = + ExpressionEvaluationContextRecord::EK_Other; // In MS mode, don't perform any extra checking of call return types within a // decltype expression. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 66c947abb3..6ee5eca75c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -3859,6 +3859,10 @@ template bool TreeTransform::TransformTemplateArgument( const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output, bool Uneval) { + EnterExpressionEvaluationContext EEEC( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated, + /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ + Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); const TemplateArgument &Arg = Input.getArgument(); switch (Arg.getKind()) { case TemplateArgument::Null: @@ -5494,7 +5498,7 @@ QualType TreeTransform::TransformDecltypeType(TypeLocBuilder &TLB, // decltype expressions are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, - /*IsDecltype=*/true); + Sema::ExpressionEvaluationContextRecord::EK_Decltype); ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); if (E.isInvalid()) diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp new file mode 100644 index 0000000000..f120a63bad --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++17 %s -verify + +template struct Nothing {}; + +void pr33696() { + Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}} +} -- GitLab From 894b021e2f4b9a7a2d0c97249fdd5db61cb33174 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Jul 2018 18:49:13 +0000 Subject: [PATCH 0522/1023] Add tests for function conversions in conversion function template deduction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336931 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 3 +++ .../temp.deduct/temp.deduct.conv/p4.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 5c3f2ca32c..8ae22136e1 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1645,6 +1645,9 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, } } // FIXME: Detect non-deduced exception specification mismatches? + // + // Careful about [temp.deduct.call] and [temp.deduct.conv], which allow + // top-level differences in noexcept-specifications. return Sema::TDK_Success; } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp index 89478ed39f..085976b081 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -129,4 +129,21 @@ namespace non_ptr_ref_cv_qual { }; int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion + +#if __cplusplus >= 201702L + template using Function = T(U...) noexcept(Noexcept); + template struct ConvToFunction { + template operator Function&(); // expected-note {{candidate}} + }; + void (&fn1)(int) noexcept(false) = ConvToFunction(); + void (&fn2)(int) noexcept(true) = ConvToFunction(); // expected-error {{no viable}} + void (&fn3)(int) noexcept(false) = ConvToFunction(); + void (&fn4)(int) noexcept(true) = ConvToFunction(); + + struct ConvToFunctionDeducingNoexcept { + template operator Function&(); + }; + void (&fn5)(int) noexcept(false) = ConvToFunctionDeducingNoexcept(); + void (&fn6)(int) noexcept(true) = ConvToFunctionDeducingNoexcept(); +#endif } -- GitLab From a58a89b042da31b4201e61ad7ec0e1b1822177ed Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 12 Jul 2018 18:54:04 +0000 Subject: [PATCH 0523/1023] [Hexagon] Diagnose intrinsics not supported by selected CPU/HVX git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336933 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 8 +- include/clang/Sema/Sema.h | 2 + lib/Basic/Targets/Hexagon.cpp | 4 + lib/Sema/SemaChecking.cpp | 794 ++++++++++++++++++++- test/Sema/builtins-hexagon-v55.c | 17 + test/Sema/builtins-hexagon-v60.c | 16 + test/Sema/builtins-hexagon-v62.c | 15 + test/Sema/builtins-hexagon-v65.c | 15 + test/Sema/builtins-hvx-none.c | 26 + test/Sema/builtins-hvx-v60.c | 25 + test/Sema/builtins-hvx-v62.c | 24 + test/Sema/builtins-hvx-v65.c | 23 + 12 files changed, 966 insertions(+), 3 deletions(-) create mode 100644 test/Sema/builtins-hexagon-v55.c create mode 100644 test/Sema/builtins-hexagon-v60.c create mode 100644 test/Sema/builtins-hexagon-v62.c create mode 100644 test/Sema/builtins-hexagon-v65.c create mode 100644 test/Sema/builtins-hvx-none.c create mode 100644 test/Sema/builtins-hvx-v60.c create mode 100644 test/Sema/builtins-hvx-v62.c create mode 100644 test/Sema/builtins-hvx-v65.c diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 51690b644a..1915f7e3be 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8181,9 +8181,15 @@ def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; def err_x86_builtin_invalid_scale : Error< "scale argument must be 1, 2, 4, or 8">; +def err_hexagon_builtin_unsupported_cpu : Error< + "builtin is not supported on this CPU">; +def err_hexagon_builtin_requires_hvx : Error< + "builtin requires HVX">; +def err_hexagon_builtin_unsupported_hvx : Error< + "builtin is not supported on this version of HVX">; + def err_builtin_target_unsupported : Error< "builtin is not supported on this target">; - def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; def err_builtin_setjmp_unsupported : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 56fb874818..c5f62bd400 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -10418,6 +10418,8 @@ private: bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); diff --git a/lib/Basic/Targets/Hexagon.cpp b/lib/Basic/Targets/Hexagon.cpp index f122200801..0ef1f6db28 100644 --- a/lib/Basic/Targets/Hexagon.cpp +++ b/lib/Basic/Targets/Hexagon.cpp @@ -131,6 +131,10 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = { }; bool HexagonTargetInfo::hasFeature(StringRef Feature) const { + std::string VS = "hvxv" + HVXVersion; + if (Feature == VS) + return true; + return llvm::StringSwitch(Feature) .Case("hexagon", true) .Case("hvx", HasHVX) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index cd2aabb894..5b800ec5ae 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1731,8 +1731,791 @@ bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); } -bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, - CallExpr *TheCall) { +bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) { + static const std::map> ValidCPU = { + { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, {"v62", "v65"} }, + }; + + static const std::map> ValidHVX = { + { Hexagon::BI__builtin_HEXAGON_V6_extractw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_hi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lo, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_not, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_valignb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vand, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vassign, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vassignp, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgb, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguw, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcombine, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vd0, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdd0, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdelta, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlut4, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewuh_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyih_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyihb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiowh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwh_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyiwub_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_64_acc_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyowh_sacc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyub_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyubv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuh_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhe_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmpyuhv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmux, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vmux_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgb, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgb_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnavgw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamth, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamth_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnormamtw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnot, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vnot_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackeh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhb_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackhub_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackob, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackob_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackoh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackoh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwh_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpackwuh_sat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vpopcounth_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqb_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqh_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vprefixqw_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrdelta, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrdelta_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpybv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B, {"v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubv_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vror, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vror_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundhub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduhub_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrounduwuh_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vroundwuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsathub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsathub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatuwuh_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatwh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsatwh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufeh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufeh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffeb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffob, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffob_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshuffvdd_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoeh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vshufoh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubb_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubbsat_dv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubh_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubhw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsububsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubububb_sat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuhw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubuwsat_dv_128B, {"v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubw_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vsubwsat_dv_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vswap, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vswap_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpybus_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vtmpyhb_acc_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackob, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackob_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackoh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackub, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackub_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vunpackuh_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vxor, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vxor_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vzb, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vzb_128B, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vzh, {"v60", "v62", "v65"} }, + { Hexagon::BI__builtin_HEXAGON_V6_vzh_128B, {"v60", "v62", "v65"} }, + }; + + const TargetInfo &TI = Context.getTargetInfo(); + + auto FC = ValidCPU.find(BuiltinID); + if (FC != ValidCPU.end()) { + const TargetOptions &Opts = TI.getTargetOpts(); + StringRef CPU = Opts.CPU; + if (!CPU.empty()) { + assert(CPU.startswith("hexagon") && "Unexpected CPU name"); + CPU.consume_front("hexagon"); + if (llvm::none_of(FC->second, [CPU](StringRef S) { return S == CPU; })) + return Diag(TheCall->getLocStart(), + diag::err_hexagon_builtin_unsupported_cpu); + } + } + + auto FH = ValidHVX.find(BuiltinID); + if (FH != ValidHVX.end()) { + if (!TI.hasFeature("hvx")) + return Diag(TheCall->getLocStart(), + diag::err_hexagon_builtin_requires_hvx); + + bool IsValid = llvm::any_of(FH->second, + [&TI] (StringRef V) { + std::string F = "hvx" + V.str(); + return TI.hasFeature(F); + }); + if (!IsValid) + return Diag(TheCall->getLocStart(), + diag::err_hexagon_builtin_unsupported_hvx); + } + + return false; +} + +bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) { struct ArgInfo { ArgInfo(unsigned O, bool S, unsigned W, unsigned A) : OpNum(O), IsSigned(S), BitWidth(W), Align(A) {} @@ -1950,6 +2733,13 @@ bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, return Error; } +bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + return CheckHexagonBuiltinCpu(BuiltinID, TheCall) || + CheckHexagonBuiltinArgument(BuiltinID, TheCall); +} + + // CheckMipsBuiltinFunctionCall - Checks the constant value passed to the // intrinsic is correct. The switch statement is ordered by DSP, MSA. The // ordering for DSP is unspecified. MSA is ordered by the data format used diff --git a/test/Sema/builtins-hexagon-v55.c b/test/Sema/builtins-hexagon-v55.c new file mode 100644 index 0000000000..e5e233d1f1 --- /dev/null +++ b/test/Sema/builtins-hexagon-v55.c @@ -0,0 +1,17 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv55 + +unsigned builtin_needs_v60(unsigned Rs) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_S6_rol_i_r(Rs, 3); +} + +unsigned long long builtin_needs_v62(unsigned Rs) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_S6_vsplatrbp(Rs); +} + +unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt); +} diff --git a/test/Sema/builtins-hexagon-v60.c b/test/Sema/builtins-hexagon-v60.c new file mode 100644 index 0000000000..d4f081bf66 --- /dev/null +++ b/test/Sema/builtins-hexagon-v60.c @@ -0,0 +1,16 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv60 + +unsigned builtin_needs_v60(unsigned Rs) { + return __builtin_HEXAGON_S6_rol_i_r(Rs, 3); +} + +unsigned long long builtin_needs_v62(unsigned Rs) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_S6_vsplatrbp(Rs); +} + +unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt); +} diff --git a/test/Sema/builtins-hexagon-v62.c b/test/Sema/builtins-hexagon-v62.c new file mode 100644 index 0000000000..ed3907bc82 --- /dev/null +++ b/test/Sema/builtins-hexagon-v62.c @@ -0,0 +1,15 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv62 + +unsigned builtin_needs_v60(unsigned Rs) { + return __builtin_HEXAGON_S6_rol_i_r(Rs, 3); +} + +unsigned long long builtin_needs_v62(unsigned Rs) { + return __builtin_HEXAGON_S6_vsplatrbp(Rs); +} + +unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) { + // expected-error@+1 {{builtin is not supported on this CPU}} + return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt); +} diff --git a/test/Sema/builtins-hexagon-v65.c b/test/Sema/builtins-hexagon-v65.c new file mode 100644 index 0000000000..bb8a1ce5e1 --- /dev/null +++ b/test/Sema/builtins-hexagon-v65.c @@ -0,0 +1,15 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 %s -triple hexagon -fsyntax-only -verify -target-cpu hexagonv65 + +// expected-no-diagnostics +unsigned builtin_needs_v60(unsigned Rs) { + return __builtin_HEXAGON_S6_rol_i_r(Rs, 3); +} + +unsigned long long builtin_needs_v62(unsigned Rs) { + return __builtin_HEXAGON_S6_vsplatrbp(Rs); +} + +unsigned builtin_needs_v65(unsigned long long Rss, unsigned long long Rtt) { + return __builtin_HEXAGON_A6_vcmpbeq_notany(Rss, Rtt); +} diff --git a/test/Sema/builtins-hvx-none.c b/test/Sema/builtins-hvx-none.c new file mode 100644 index 0000000000..c43b34f1c5 --- /dev/null +++ b/test/Sema/builtins-hvx-none.c @@ -0,0 +1,26 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon %s -fsyntax-only -verify + +typedef long Vect1024 __attribute__((__vector_size__(128))) + __attribute__((aligned(128))); +typedef long Vect2048 __attribute__((__vector_size__(256))) + __attribute__((aligned(128))); + +typedef Vect1024 HVX_Vector; +typedef Vect2048 HVX_VectorPair; + + +HVX_Vector builtin_needs_v60(HVX_VectorPair a) { + // expected-error@+1 {{builtin requires HVX}} + return __builtin_HEXAGON_V6_hi_128B(a); +} + +HVX_Vector builtin_needs_v62(char a) { + // expected-error@+1 {{builtin requires HVX}} + return __builtin_HEXAGON_V6_lvsplatb_128B(a); +} + +HVX_VectorPair builtin_needs_v65() { + // expected-error@+1 {{builtin requires HVX}} + return __builtin_HEXAGON_V6_vdd0_128B(); +} diff --git a/test/Sema/builtins-hvx-v60.c b/test/Sema/builtins-hvx-v60.c new file mode 100644 index 0000000000..7d298e989e --- /dev/null +++ b/test/Sema/builtins-hvx-v60.c @@ -0,0 +1,25 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv60 -target-cpu hexagonv60 -fsyntax-only -verify + +typedef long Vect1024 __attribute__((__vector_size__(128))) + __attribute__((aligned(128))); +typedef long Vect2048 __attribute__((__vector_size__(256))) + __attribute__((aligned(128))); + +typedef Vect1024 HVX_Vector; +typedef Vect2048 HVX_VectorPair; + + +HVX_Vector builtin_needs_v60(HVX_VectorPair a) { + return __builtin_HEXAGON_V6_hi_128B(a); +} + +HVX_Vector builtin_needs_v62(char a) { + // expected-error@+1 {{builtin is not supported on this version of HVX}} + return __builtin_HEXAGON_V6_lvsplatb_128B(a); +} + +HVX_VectorPair builtin_needs_v65() { + // expected-error@+1 {{builtin is not supported on this version of HVX}} + return __builtin_HEXAGON_V6_vdd0_128B(); +} diff --git a/test/Sema/builtins-hvx-v62.c b/test/Sema/builtins-hvx-v62.c new file mode 100644 index 0000000000..b73af96376 --- /dev/null +++ b/test/Sema/builtins-hvx-v62.c @@ -0,0 +1,24 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv62 -target-cpu hexagonv62 -fsyntax-only -verify + +typedef long Vect1024 __attribute__((__vector_size__(128))) + __attribute__((aligned(128))); +typedef long Vect2048 __attribute__((__vector_size__(256))) + __attribute__((aligned(128))); + +typedef Vect1024 HVX_Vector; +typedef Vect2048 HVX_VectorPair; + + +HVX_Vector builtin_needs_v60(HVX_VectorPair a) { + return __builtin_HEXAGON_V6_hi_128B(a); +} + +HVX_Vector builtin_needs_v62(char a) { + return __builtin_HEXAGON_V6_lvsplatb_128B(a); +} + +HVX_VectorPair builtin_needs_v65() { + // expected-error@+1 {{builtin is not supported on this version of HVX}} + return __builtin_HEXAGON_V6_vdd0_128B(); +} diff --git a/test/Sema/builtins-hvx-v65.c b/test/Sema/builtins-hvx-v65.c new file mode 100644 index 0000000000..be6b7b0955 --- /dev/null +++ b/test/Sema/builtins-hvx-v65.c @@ -0,0 +1,23 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon %s -target-feature +hvx-length128b -target-feature +hvxv65 -target-cpu hexagonv65 -fsyntax-only -verify + +typedef long Vect1024 __attribute__((__vector_size__(128))) + __attribute__((aligned(128))); +typedef long Vect2048 __attribute__((__vector_size__(256))) + __attribute__((aligned(128))); + +typedef Vect1024 HVX_Vector; +typedef Vect2048 HVX_VectorPair; + +// expected-no-diagnostics +HVX_Vector builtin_needs_v60(HVX_VectorPair a) { + return __builtin_HEXAGON_V6_hi_128B(a); +} + +HVX_Vector builtin_needs_v62(char a) { + return __builtin_HEXAGON_V6_lvsplatb_128B(a); +} + +HVX_VectorPair builtin_needs_v65() { + return __builtin_HEXAGON_V6_vdd0_128B(); +} -- GitLab From 1a48fc4684eba5a26f1bd0b4c7077bbd3253e1df Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 12 Jul 2018 19:44:39 +0000 Subject: [PATCH 0524/1023] [Hexagon] Fix testcases failing after r336933 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336936 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/builtins-hexagon.c | 1590 +------------------------------ test/CodeGen/builtins-hvx128.c | 802 ++++++++++++++++ test/CodeGen/builtins-hvx64.c | 802 ++++++++++++++++ 3 files changed, 1605 insertions(+), 1589 deletions(-) create mode 100644 test/CodeGen/builtins-hvx128.c create mode 100644 test/CodeGen/builtins-hvx64.c diff --git a/test/CodeGen/builtins-hexagon.c b/test/CodeGen/builtins-hexagon.c index 3b4d8d057a..b4c0642ef3 100644 --- a/test/CodeGen/builtins-hexagon.c +++ b/test/CodeGen/builtins-hexagon.c @@ -1,5 +1,5 @@ // REQUIRES: hexagon-registered-target -// RUN: %clang_cc1 -triple hexagon-unknown-elf -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -emit-llvm %s -o - | FileCheck %s void test() { int v64 __attribute__((__vector_size__(64))); @@ -1722,1594 +1722,6 @@ void test() { __builtin_HEXAGON_S6_vtrunehb_ppp(0, 0); // CHECK: @llvm.hexagon.S6.vtrunohb.ppp __builtin_HEXAGON_S6_vtrunohb_ppp(0, 0); - // CHECK: @llvm.hexagon.V6.extractw - __builtin_HEXAGON_V6_extractw(v64, 0); - // CHECK: @llvm.hexagon.V6.extractw.128B - __builtin_HEXAGON_V6_extractw_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.hi - __builtin_HEXAGON_V6_hi(v128); - // CHECK: @llvm.hexagon.V6.hi.128B - __builtin_HEXAGON_V6_hi_128B(v256); - // CHECK: @llvm.hexagon.V6.lo - __builtin_HEXAGON_V6_lo(v128); - // CHECK: @llvm.hexagon.V6.lo.128B - __builtin_HEXAGON_V6_lo_128B(v256); - // CHECK: @llvm.hexagon.V6.lvsplatb - __builtin_HEXAGON_V6_lvsplatb(0); - // CHECK: @llvm.hexagon.V6.lvsplatb.128B - __builtin_HEXAGON_V6_lvsplatb_128B(0); - // CHECK: @llvm.hexagon.V6.lvsplath - __builtin_HEXAGON_V6_lvsplath(0); - // CHECK: @llvm.hexagon.V6.lvsplath.128B - __builtin_HEXAGON_V6_lvsplath_128B(0); - // CHECK: @llvm.hexagon.V6.lvsplatw - __builtin_HEXAGON_V6_lvsplatw(0); - // CHECK: @llvm.hexagon.V6.lvsplatw.128B - __builtin_HEXAGON_V6_lvsplatw_128B(0); - // CHECK: @llvm.hexagon.V6.pred.and - __builtin_HEXAGON_V6_pred_and(v64, v64); - // CHECK: @llvm.hexagon.V6.pred.and.128B - __builtin_HEXAGON_V6_pred_and_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.pred.and.n - __builtin_HEXAGON_V6_pred_and_n(v64, v64); - // CHECK: @llvm.hexagon.V6.pred.and.n.128B - __builtin_HEXAGON_V6_pred_and_n_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.pred.not - __builtin_HEXAGON_V6_pred_not(v64); - // CHECK: @llvm.hexagon.V6.pred.not.128B - __builtin_HEXAGON_V6_pred_not_128B(v128); - // CHECK: @llvm.hexagon.V6.pred.or - __builtin_HEXAGON_V6_pred_or(v64, v64); - // CHECK: @llvm.hexagon.V6.pred.or.128B - __builtin_HEXAGON_V6_pred_or_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.pred.or.n - __builtin_HEXAGON_V6_pred_or_n(v64, v64); - // CHECK: @llvm.hexagon.V6.pred.or.n.128B - __builtin_HEXAGON_V6_pred_or_n_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.pred.scalar2 - __builtin_HEXAGON_V6_pred_scalar2(0); - // CHECK: @llvm.hexagon.V6.pred.scalar2.128B - __builtin_HEXAGON_V6_pred_scalar2_128B(0); - // CHECK: @llvm.hexagon.V6.pred.scalar2v2 - __builtin_HEXAGON_V6_pred_scalar2v2(0); - // CHECK: @llvm.hexagon.V6.pred.scalar2v2.128B - __builtin_HEXAGON_V6_pred_scalar2v2_128B(0); - // CHECK: @llvm.hexagon.V6.pred.xor - __builtin_HEXAGON_V6_pred_xor(v64, v64); - // CHECK: @llvm.hexagon.V6.pred.xor.128B - __builtin_HEXAGON_V6_pred_xor_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.shuffeqh - __builtin_HEXAGON_V6_shuffeqh(v64, v64); - // CHECK: @llvm.hexagon.V6.shuffeqh.128B - __builtin_HEXAGON_V6_shuffeqh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.shuffeqw - __builtin_HEXAGON_V6_shuffeqw(v64, v64); - // CHECK: @llvm.hexagon.V6.shuffeqw.128B - __builtin_HEXAGON_V6_shuffeqw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai - __builtin_HEXAGON_V6_vS32b_nqpred_ai(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai - __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai - __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai.128B - __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai - __builtin_HEXAGON_V6_vS32b_qpred_ai(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai.128B - __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vabsb - __builtin_HEXAGON_V6_vabsb(v64); - // CHECK: @llvm.hexagon.V6.vabsb.128B - __builtin_HEXAGON_V6_vabsb_128B(v128); - // CHECK: @llvm.hexagon.V6.vabsb.sat - __builtin_HEXAGON_V6_vabsb_sat(v64); - // CHECK: @llvm.hexagon.V6.vabsb.sat.128B - __builtin_HEXAGON_V6_vabsb_sat_128B(v128); - // CHECK: @llvm.hexagon.V6.vabsdiffh - __builtin_HEXAGON_V6_vabsdiffh(v64, v64); - // CHECK: @llvm.hexagon.V6.vabsdiffh.128B - __builtin_HEXAGON_V6_vabsdiffh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vabsdiffub - __builtin_HEXAGON_V6_vabsdiffub(v64, v64); - // CHECK: @llvm.hexagon.V6.vabsdiffub.128B - __builtin_HEXAGON_V6_vabsdiffub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vabsdiffuh - __builtin_HEXAGON_V6_vabsdiffuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vabsdiffuh.128B - __builtin_HEXAGON_V6_vabsdiffuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vabsdiffw - __builtin_HEXAGON_V6_vabsdiffw(v64, v64); - // CHECK: @llvm.hexagon.V6.vabsdiffw.128B - __builtin_HEXAGON_V6_vabsdiffw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vabsh - __builtin_HEXAGON_V6_vabsh(v64); - // CHECK: @llvm.hexagon.V6.vabsh.128B - __builtin_HEXAGON_V6_vabsh_128B(v128); - // CHECK: @llvm.hexagon.V6.vabsh.sat - __builtin_HEXAGON_V6_vabsh_sat(v64); - // CHECK: @llvm.hexagon.V6.vabsh.sat.128B - __builtin_HEXAGON_V6_vabsh_sat_128B(v128); - // CHECK: @llvm.hexagon.V6.vabsw - __builtin_HEXAGON_V6_vabsw(v64); - // CHECK: @llvm.hexagon.V6.vabsw.128B - __builtin_HEXAGON_V6_vabsw_128B(v128); - // CHECK: @llvm.hexagon.V6.vabsw.sat - __builtin_HEXAGON_V6_vabsw_sat(v64); - // CHECK: @llvm.hexagon.V6.vabsw.sat.128B - __builtin_HEXAGON_V6_vabsw_sat_128B(v128); - // CHECK: @llvm.hexagon.V6.vaddb - __builtin_HEXAGON_V6_vaddb(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddb.128B - __builtin_HEXAGON_V6_vaddb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddb.dv - __builtin_HEXAGON_V6_vaddb_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddb.dv.128B - __builtin_HEXAGON_V6_vaddb_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddbnq - __builtin_HEXAGON_V6_vaddbnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddbnq.128B - __builtin_HEXAGON_V6_vaddbnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddbq - __builtin_HEXAGON_V6_vaddbq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddbq.128B - __builtin_HEXAGON_V6_vaddbq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddbsat - __builtin_HEXAGON_V6_vaddbsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddbsat.128B - __builtin_HEXAGON_V6_vaddbsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddbsat.dv - __builtin_HEXAGON_V6_vaddbsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddbsat.dv.128B - __builtin_HEXAGON_V6_vaddbsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddcarry - __builtin_HEXAGON_V6_vaddcarry(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vaddcarry.128B - __builtin_HEXAGON_V6_vaddcarry_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vaddclbh - __builtin_HEXAGON_V6_vaddclbh(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddclbh.128B - __builtin_HEXAGON_V6_vaddclbh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddclbw - __builtin_HEXAGON_V6_vaddclbw(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddclbw.128B - __builtin_HEXAGON_V6_vaddclbw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddh - __builtin_HEXAGON_V6_vaddh(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddh.128B - __builtin_HEXAGON_V6_vaddh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddh.dv - __builtin_HEXAGON_V6_vaddh_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddh.dv.128B - __builtin_HEXAGON_V6_vaddh_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddhnq - __builtin_HEXAGON_V6_vaddhnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddhnq.128B - __builtin_HEXAGON_V6_vaddhnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddhq - __builtin_HEXAGON_V6_vaddhq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddhq.128B - __builtin_HEXAGON_V6_vaddhq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddhsat - __builtin_HEXAGON_V6_vaddhsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddhsat.128B - __builtin_HEXAGON_V6_vaddhsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddhsat.dv - __builtin_HEXAGON_V6_vaddhsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddhsat.dv.128B - __builtin_HEXAGON_V6_vaddhsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddhw - __builtin_HEXAGON_V6_vaddhw(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddhw.128B - __builtin_HEXAGON_V6_vaddhw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddhw.acc - __builtin_HEXAGON_V6_vaddhw_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddhw.acc.128B - __builtin_HEXAGON_V6_vaddhw_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddubh - __builtin_HEXAGON_V6_vaddubh(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddubh.128B - __builtin_HEXAGON_V6_vaddubh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddubh.acc - __builtin_HEXAGON_V6_vaddubh_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddubh.acc.128B - __builtin_HEXAGON_V6_vaddubh_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddubsat - __builtin_HEXAGON_V6_vaddubsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddubsat.128B - __builtin_HEXAGON_V6_vaddubsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddubsat.dv - __builtin_HEXAGON_V6_vaddubsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddubsat.dv.128B - __builtin_HEXAGON_V6_vaddubsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddububb.sat - __builtin_HEXAGON_V6_vaddububb_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddububb.sat.128B - __builtin_HEXAGON_V6_vaddububb_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduhsat - __builtin_HEXAGON_V6_vadduhsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vadduhsat.128B - __builtin_HEXAGON_V6_vadduhsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduhsat.dv - __builtin_HEXAGON_V6_vadduhsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduhsat.dv.128B - __builtin_HEXAGON_V6_vadduhsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vadduhw - __builtin_HEXAGON_V6_vadduhw(v64, v64); - // CHECK: @llvm.hexagon.V6.vadduhw.128B - __builtin_HEXAGON_V6_vadduhw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduhw.acc - __builtin_HEXAGON_V6_vadduhw_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vadduhw.acc.128B - __builtin_HEXAGON_V6_vadduhw_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vadduwsat - __builtin_HEXAGON_V6_vadduwsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vadduwsat.128B - __builtin_HEXAGON_V6_vadduwsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduwsat.dv - __builtin_HEXAGON_V6_vadduwsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vadduwsat.dv.128B - __builtin_HEXAGON_V6_vadduwsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddw - __builtin_HEXAGON_V6_vaddw(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddw.128B - __builtin_HEXAGON_V6_vaddw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddw.dv - __builtin_HEXAGON_V6_vaddw_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddw.dv.128B - __builtin_HEXAGON_V6_vaddw_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vaddwnq - __builtin_HEXAGON_V6_vaddwnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddwnq.128B - __builtin_HEXAGON_V6_vaddwnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddwq - __builtin_HEXAGON_V6_vaddwq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vaddwq.128B - __builtin_HEXAGON_V6_vaddwq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vaddwsat - __builtin_HEXAGON_V6_vaddwsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vaddwsat.128B - __builtin_HEXAGON_V6_vaddwsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddwsat.dv - __builtin_HEXAGON_V6_vaddwsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vaddwsat.dv.128B - __builtin_HEXAGON_V6_vaddwsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.valignb - __builtin_HEXAGON_V6_valignb(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.valignb.128B - __builtin_HEXAGON_V6_valignb_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.valignbi - __builtin_HEXAGON_V6_valignbi(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.valignbi.128B - __builtin_HEXAGON_V6_valignbi_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vand - __builtin_HEXAGON_V6_vand(v64, v64); - // CHECK: @llvm.hexagon.V6.vand.128B - __builtin_HEXAGON_V6_vand_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vandnqrt - __builtin_HEXAGON_V6_vandnqrt(v64, 0); - // CHECK: @llvm.hexagon.V6.vandnqrt.128B - __builtin_HEXAGON_V6_vandnqrt_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vandnqrt.acc - __builtin_HEXAGON_V6_vandnqrt_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vandnqrt.acc.128B - __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vandqrt - __builtin_HEXAGON_V6_vandqrt(v64, 0); - // CHECK: @llvm.hexagon.V6.vandqrt.128B - __builtin_HEXAGON_V6_vandqrt_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vandqrt.acc - __builtin_HEXAGON_V6_vandqrt_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vandqrt.acc.128B - __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vandvnqv - __builtin_HEXAGON_V6_vandvnqv(v64, v64); - // CHECK: @llvm.hexagon.V6.vandvnqv.128B - __builtin_HEXAGON_V6_vandvnqv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vandvqv - __builtin_HEXAGON_V6_vandvqv(v64, v64); - // CHECK: @llvm.hexagon.V6.vandvqv.128B - __builtin_HEXAGON_V6_vandvqv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vandvrt - __builtin_HEXAGON_V6_vandvrt(v64, 0); - // CHECK: @llvm.hexagon.V6.vandvrt.128B - __builtin_HEXAGON_V6_vandvrt_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vandvrt.acc - __builtin_HEXAGON_V6_vandvrt_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vandvrt.acc.128B - __builtin_HEXAGON_V6_vandvrt_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vaslh - __builtin_HEXAGON_V6_vaslh(v64, 0); - // CHECK: @llvm.hexagon.V6.vaslh.128B - __builtin_HEXAGON_V6_vaslh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vaslh.acc - __builtin_HEXAGON_V6_vaslh_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vaslh.acc.128B - __builtin_HEXAGON_V6_vaslh_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vaslhv - __builtin_HEXAGON_V6_vaslhv(v64, v64); - // CHECK: @llvm.hexagon.V6.vaslhv.128B - __builtin_HEXAGON_V6_vaslhv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vaslw - __builtin_HEXAGON_V6_vaslw(v64, 0); - // CHECK: @llvm.hexagon.V6.vaslw.128B - __builtin_HEXAGON_V6_vaslw_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vaslw.acc - __builtin_HEXAGON_V6_vaslw_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vaslw.acc.128B - __builtin_HEXAGON_V6_vaslw_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vaslwv - __builtin_HEXAGON_V6_vaslwv(v64, v64); - // CHECK: @llvm.hexagon.V6.vaslwv.128B - __builtin_HEXAGON_V6_vaslwv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vasrh - __builtin_HEXAGON_V6_vasrh(v64, 0); - // CHECK: @llvm.hexagon.V6.vasrh.128B - __builtin_HEXAGON_V6_vasrh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vasrh.acc - __builtin_HEXAGON_V6_vasrh_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrh.acc.128B - __builtin_HEXAGON_V6_vasrh_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrhbrndsat - __builtin_HEXAGON_V6_vasrhbrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrhbrndsat.128B - __builtin_HEXAGON_V6_vasrhbrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrhbsat - __builtin_HEXAGON_V6_vasrhbsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrhbsat.128B - __builtin_HEXAGON_V6_vasrhbsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrhubrndsat - __builtin_HEXAGON_V6_vasrhubrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrhubrndsat.128B - __builtin_HEXAGON_V6_vasrhubrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrhubsat - __builtin_HEXAGON_V6_vasrhubsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrhubsat.128B - __builtin_HEXAGON_V6_vasrhubsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrhv - __builtin_HEXAGON_V6_vasrhv(v64, v64); - // CHECK: @llvm.hexagon.V6.vasrhv.128B - __builtin_HEXAGON_V6_vasrhv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vasruhubrndsat - __builtin_HEXAGON_V6_vasruhubrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasruhubrndsat.128B - __builtin_HEXAGON_V6_vasruhubrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasruhubsat - __builtin_HEXAGON_V6_vasruhubsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasruhubsat.128B - __builtin_HEXAGON_V6_vasruhubsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasruwuhrndsat - __builtin_HEXAGON_V6_vasruwuhrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasruwuhrndsat.128B - __builtin_HEXAGON_V6_vasruwuhrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasruwuhsat - __builtin_HEXAGON_V6_vasruwuhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasruwuhsat.128B - __builtin_HEXAGON_V6_vasruwuhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrw - __builtin_HEXAGON_V6_vasrw(v64, 0); - // CHECK: @llvm.hexagon.V6.vasrw.128B - __builtin_HEXAGON_V6_vasrw_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vasrw.acc - __builtin_HEXAGON_V6_vasrw_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrw.acc.128B - __builtin_HEXAGON_V6_vasrw_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwh - __builtin_HEXAGON_V6_vasrwh(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrwh.128B - __builtin_HEXAGON_V6_vasrwh_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwhrndsat - __builtin_HEXAGON_V6_vasrwhrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrwhrndsat.128B - __builtin_HEXAGON_V6_vasrwhrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwhsat - __builtin_HEXAGON_V6_vasrwhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrwhsat.128B - __builtin_HEXAGON_V6_vasrwhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwuhrndsat - __builtin_HEXAGON_V6_vasrwuhrndsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrwuhrndsat.128B - __builtin_HEXAGON_V6_vasrwuhrndsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwuhsat - __builtin_HEXAGON_V6_vasrwuhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vasrwuhsat.128B - __builtin_HEXAGON_V6_vasrwuhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vasrwv - __builtin_HEXAGON_V6_vasrwv(v64, v64); - // CHECK: @llvm.hexagon.V6.vasrwv.128B - __builtin_HEXAGON_V6_vasrwv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vassign - __builtin_HEXAGON_V6_vassign(v64); - // CHECK: @llvm.hexagon.V6.vassign.128B - __builtin_HEXAGON_V6_vassign_128B(v128); - // CHECK: @llvm.hexagon.V6.vassignp - __builtin_HEXAGON_V6_vassignp(v128); - // CHECK: @llvm.hexagon.V6.vassignp.128B - __builtin_HEXAGON_V6_vassignp_128B(v256); - // CHECK: @llvm.hexagon.V6.vavgb - __builtin_HEXAGON_V6_vavgb(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgb.128B - __builtin_HEXAGON_V6_vavgb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgbrnd - __builtin_HEXAGON_V6_vavgbrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgbrnd.128B - __builtin_HEXAGON_V6_vavgbrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgh - __builtin_HEXAGON_V6_vavgh(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgh.128B - __builtin_HEXAGON_V6_vavgh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavghrnd - __builtin_HEXAGON_V6_vavghrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavghrnd.128B - __builtin_HEXAGON_V6_vavghrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgub - __builtin_HEXAGON_V6_vavgub(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgub.128B - __builtin_HEXAGON_V6_vavgub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgubrnd - __builtin_HEXAGON_V6_vavgubrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgubrnd.128B - __builtin_HEXAGON_V6_vavgubrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavguh - __builtin_HEXAGON_V6_vavguh(v64, v64); - // CHECK: @llvm.hexagon.V6.vavguh.128B - __builtin_HEXAGON_V6_vavguh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavguhrnd - __builtin_HEXAGON_V6_vavguhrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavguhrnd.128B - __builtin_HEXAGON_V6_vavguhrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavguw - __builtin_HEXAGON_V6_vavguw(v64, v64); - // CHECK: @llvm.hexagon.V6.vavguw.128B - __builtin_HEXAGON_V6_vavguw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavguwrnd - __builtin_HEXAGON_V6_vavguwrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavguwrnd.128B - __builtin_HEXAGON_V6_vavguwrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgw - __builtin_HEXAGON_V6_vavgw(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgw.128B - __builtin_HEXAGON_V6_vavgw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vavgwrnd - __builtin_HEXAGON_V6_vavgwrnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vavgwrnd.128B - __builtin_HEXAGON_V6_vavgwrnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vcl0h - __builtin_HEXAGON_V6_vcl0h(v64); - // CHECK: @llvm.hexagon.V6.vcl0h.128B - __builtin_HEXAGON_V6_vcl0h_128B(v128); - // CHECK: @llvm.hexagon.V6.vcl0w - __builtin_HEXAGON_V6_vcl0w(v64); - // CHECK: @llvm.hexagon.V6.vcl0w.128B - __builtin_HEXAGON_V6_vcl0w_128B(v128); - // CHECK: @llvm.hexagon.V6.vcombine - __builtin_HEXAGON_V6_vcombine(v64, v64); - // CHECK: @llvm.hexagon.V6.vcombine.128B - __builtin_HEXAGON_V6_vcombine_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vd0 - __builtin_HEXAGON_V6_vd0(); - // CHECK: @llvm.hexagon.V6.vd0.128B - __builtin_HEXAGON_V6_vd0_128B(); - // CHECK: @llvm.hexagon.V6.vdd0 - __builtin_HEXAGON_V6_vdd0(); - // CHECK: @llvm.hexagon.V6.vdd0.128B - __builtin_HEXAGON_V6_vdd0_128B(); - // CHECK: @llvm.hexagon.V6.vdealb - __builtin_HEXAGON_V6_vdealb(v64); - // CHECK: @llvm.hexagon.V6.vdealb.128B - __builtin_HEXAGON_V6_vdealb_128B(v128); - // CHECK: @llvm.hexagon.V6.vdealb4w - __builtin_HEXAGON_V6_vdealb4w(v64, v64); - // CHECK: @llvm.hexagon.V6.vdealb4w.128B - __builtin_HEXAGON_V6_vdealb4w_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vdealh - __builtin_HEXAGON_V6_vdealh(v64); - // CHECK: @llvm.hexagon.V6.vdealh.128B - __builtin_HEXAGON_V6_vdealh_128B(v128); - // CHECK: @llvm.hexagon.V6.vdealvdd - __builtin_HEXAGON_V6_vdealvdd(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vdealvdd.128B - __builtin_HEXAGON_V6_vdealvdd_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdelta - __builtin_HEXAGON_V6_vdelta(v64, v64); - // CHECK: @llvm.hexagon.V6.vdelta.128B - __builtin_HEXAGON_V6_vdelta_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vdmpybus - __builtin_HEXAGON_V6_vdmpybus(v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.128B - __builtin_HEXAGON_V6_vdmpybus_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.acc - __builtin_HEXAGON_V6_vdmpybus_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.acc.128B - __builtin_HEXAGON_V6_vdmpybus_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.dv - __builtin_HEXAGON_V6_vdmpybus_dv(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.dv.128B - __builtin_HEXAGON_V6_vdmpybus_dv_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc - __builtin_HEXAGON_V6_vdmpybus_dv_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc.128B - __builtin_HEXAGON_V6_vdmpybus_dv_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb - __builtin_HEXAGON_V6_vdmpyhb(v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.128B - __builtin_HEXAGON_V6_vdmpyhb_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.acc - __builtin_HEXAGON_V6_vdmpyhb_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.acc.128B - __builtin_HEXAGON_V6_vdmpyhb_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.dv - __builtin_HEXAGON_V6_vdmpyhb_dv(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.128B - __builtin_HEXAGON_V6_vdmpyhb_dv_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc - __builtin_HEXAGON_V6_vdmpyhb_dv_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc.128B - __builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhisat - __builtin_HEXAGON_V6_vdmpyhisat(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhisat.128B - __builtin_HEXAGON_V6_vdmpyhisat_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc - __builtin_HEXAGON_V6_vdmpyhisat_acc(v64, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc.128B - __builtin_HEXAGON_V6_vdmpyhisat_acc_128B(v128, v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsat - __builtin_HEXAGON_V6_vdmpyhsat(v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsat.128B - __builtin_HEXAGON_V6_vdmpyhsat_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc - __builtin_HEXAGON_V6_vdmpyhsat_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc.128B - __builtin_HEXAGON_V6_vdmpyhsat_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsuisat - __builtin_HEXAGON_V6_vdmpyhsuisat(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.128B - __builtin_HEXAGON_V6_vdmpyhsuisat_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc - __builtin_HEXAGON_V6_vdmpyhsuisat_acc(v64, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc.128B - __builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B(v128, v256, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsusat - __builtin_HEXAGON_V6_vdmpyhsusat(v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsusat.128B - __builtin_HEXAGON_V6_vdmpyhsusat_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc - __builtin_HEXAGON_V6_vdmpyhsusat_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc.128B - __builtin_HEXAGON_V6_vdmpyhsusat_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdmpyhvsat - __builtin_HEXAGON_V6_vdmpyhvsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vdmpyhvsat.128B - __builtin_HEXAGON_V6_vdmpyhvsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc - __builtin_HEXAGON_V6_vdmpyhvsat_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc.128B - __builtin_HEXAGON_V6_vdmpyhvsat_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vdsaduh - __builtin_HEXAGON_V6_vdsaduh(v128, 0); - // CHECK: @llvm.hexagon.V6.vdsaduh.128B - __builtin_HEXAGON_V6_vdsaduh_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vdsaduh.acc - __builtin_HEXAGON_V6_vdsaduh_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vdsaduh.acc.128B - __builtin_HEXAGON_V6_vdsaduh_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.veqb - __builtin_HEXAGON_V6_veqb(v64, v64); - // CHECK: @llvm.hexagon.V6.veqb.128B - __builtin_HEXAGON_V6_veqb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.veqb.and - __builtin_HEXAGON_V6_veqb_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqb.and.128B - __builtin_HEXAGON_V6_veqb_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqb.or - __builtin_HEXAGON_V6_veqb_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqb.or.128B - __builtin_HEXAGON_V6_veqb_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqb.xor - __builtin_HEXAGON_V6_veqb_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqb.xor.128B - __builtin_HEXAGON_V6_veqb_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqh - __builtin_HEXAGON_V6_veqh(v64, v64); - // CHECK: @llvm.hexagon.V6.veqh.128B - __builtin_HEXAGON_V6_veqh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.veqh.and - __builtin_HEXAGON_V6_veqh_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqh.and.128B - __builtin_HEXAGON_V6_veqh_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqh.or - __builtin_HEXAGON_V6_veqh_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqh.or.128B - __builtin_HEXAGON_V6_veqh_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqh.xor - __builtin_HEXAGON_V6_veqh_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqh.xor.128B - __builtin_HEXAGON_V6_veqh_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqw - __builtin_HEXAGON_V6_veqw(v64, v64); - // CHECK: @llvm.hexagon.V6.veqw.128B - __builtin_HEXAGON_V6_veqw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.veqw.and - __builtin_HEXAGON_V6_veqw_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqw.and.128B - __builtin_HEXAGON_V6_veqw_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqw.or - __builtin_HEXAGON_V6_veqw_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqw.or.128B - __builtin_HEXAGON_V6_veqw_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.veqw.xor - __builtin_HEXAGON_V6_veqw_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.veqw.xor.128B - __builtin_HEXAGON_V6_veqw_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgathermh - __builtin_HEXAGON_V6_vgathermh(0, 0, 0, v64); - // CHECK: @llvm.hexagon.V6.vgathermh.128B - __builtin_HEXAGON_V6_vgathermh_128B(0, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgathermhq - __builtin_HEXAGON_V6_vgathermhq(0, v64, 0, 0, v64); - // CHECK: @llvm.hexagon.V6.vgathermhq.128B - __builtin_HEXAGON_V6_vgathermhq_128B(0, v128, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgathermhw - __builtin_HEXAGON_V6_vgathermhw(0, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgathermhw.128B - __builtin_HEXAGON_V6_vgathermhw_128B(0, 0, 0, v256); - // CHECK: @llvm.hexagon.V6.vgathermhwq - __builtin_HEXAGON_V6_vgathermhwq(0, v64, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgathermhwq.128B - __builtin_HEXAGON_V6_vgathermhwq_128B(0, v128, 0, 0, v256); - // CHECK: @llvm.hexagon.V6.vgathermw - __builtin_HEXAGON_V6_vgathermw(0, 0, 0, v64); - // CHECK: @llvm.hexagon.V6.vgathermw.128B - __builtin_HEXAGON_V6_vgathermw_128B(0, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgathermwq - __builtin_HEXAGON_V6_vgathermwq(0, v64, 0, 0, v64); - // CHECK: @llvm.hexagon.V6.vgathermwq.128B - __builtin_HEXAGON_V6_vgathermwq_128B(0, v128, 0, 0, v128); - // CHECK: @llvm.hexagon.V6.vgtb - __builtin_HEXAGON_V6_vgtb(v64, v64); - // CHECK: @llvm.hexagon.V6.vgtb.128B - __builtin_HEXAGON_V6_vgtb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgtb.and - __builtin_HEXAGON_V6_vgtb_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtb.and.128B - __builtin_HEXAGON_V6_vgtb_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtb.or - __builtin_HEXAGON_V6_vgtb_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtb.or.128B - __builtin_HEXAGON_V6_vgtb_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtb.xor - __builtin_HEXAGON_V6_vgtb_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtb.xor.128B - __builtin_HEXAGON_V6_vgtb_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgth - __builtin_HEXAGON_V6_vgth(v64, v64); - // CHECK: @llvm.hexagon.V6.vgth.128B - __builtin_HEXAGON_V6_vgth_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgth.and - __builtin_HEXAGON_V6_vgth_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgth.and.128B - __builtin_HEXAGON_V6_vgth_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgth.or - __builtin_HEXAGON_V6_vgth_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgth.or.128B - __builtin_HEXAGON_V6_vgth_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgth.xor - __builtin_HEXAGON_V6_vgth_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgth.xor.128B - __builtin_HEXAGON_V6_vgth_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtub - __builtin_HEXAGON_V6_vgtub(v64, v64); - // CHECK: @llvm.hexagon.V6.vgtub.128B - __builtin_HEXAGON_V6_vgtub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgtub.and - __builtin_HEXAGON_V6_vgtub_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtub.and.128B - __builtin_HEXAGON_V6_vgtub_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtub.or - __builtin_HEXAGON_V6_vgtub_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtub.or.128B - __builtin_HEXAGON_V6_vgtub_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtub.xor - __builtin_HEXAGON_V6_vgtub_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtub.xor.128B - __builtin_HEXAGON_V6_vgtub_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuh - __builtin_HEXAGON_V6_vgtuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuh.128B - __builtin_HEXAGON_V6_vgtuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuh.and - __builtin_HEXAGON_V6_vgtuh_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuh.and.128B - __builtin_HEXAGON_V6_vgtuh_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuh.or - __builtin_HEXAGON_V6_vgtuh_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuh.or.128B - __builtin_HEXAGON_V6_vgtuh_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuh.xor - __builtin_HEXAGON_V6_vgtuh_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuh.xor.128B - __builtin_HEXAGON_V6_vgtuh_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuw - __builtin_HEXAGON_V6_vgtuw(v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuw.128B - __builtin_HEXAGON_V6_vgtuw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuw.and - __builtin_HEXAGON_V6_vgtuw_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuw.and.128B - __builtin_HEXAGON_V6_vgtuw_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuw.or - __builtin_HEXAGON_V6_vgtuw_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuw.or.128B - __builtin_HEXAGON_V6_vgtuw_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtuw.xor - __builtin_HEXAGON_V6_vgtuw_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtuw.xor.128B - __builtin_HEXAGON_V6_vgtuw_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtw - __builtin_HEXAGON_V6_vgtw(v64, v64); - // CHECK: @llvm.hexagon.V6.vgtw.128B - __builtin_HEXAGON_V6_vgtw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vgtw.and - __builtin_HEXAGON_V6_vgtw_and(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtw.and.128B - __builtin_HEXAGON_V6_vgtw_and_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtw.or - __builtin_HEXAGON_V6_vgtw_or(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtw.or.128B - __builtin_HEXAGON_V6_vgtw_or_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vgtw.xor - __builtin_HEXAGON_V6_vgtw_xor(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vgtw.xor.128B - __builtin_HEXAGON_V6_vgtw_xor_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vinsertwr - __builtin_HEXAGON_V6_vinsertwr(v64, 0); - // CHECK: @llvm.hexagon.V6.vinsertwr.128B - __builtin_HEXAGON_V6_vinsertwr_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vlalignb - __builtin_HEXAGON_V6_vlalignb(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlalignb.128B - __builtin_HEXAGON_V6_vlalignb_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlalignbi - __builtin_HEXAGON_V6_vlalignbi(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlalignbi.128B - __builtin_HEXAGON_V6_vlalignbi_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlsrb - __builtin_HEXAGON_V6_vlsrb(v64, 0); - // CHECK: @llvm.hexagon.V6.vlsrb.128B - __builtin_HEXAGON_V6_vlsrb_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vlsrh - __builtin_HEXAGON_V6_vlsrh(v64, 0); - // CHECK: @llvm.hexagon.V6.vlsrh.128B - __builtin_HEXAGON_V6_vlsrh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vlsrhv - __builtin_HEXAGON_V6_vlsrhv(v64, v64); - // CHECK: @llvm.hexagon.V6.vlsrhv.128B - __builtin_HEXAGON_V6_vlsrhv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vlsrw - __builtin_HEXAGON_V6_vlsrw(v64, 0); - // CHECK: @llvm.hexagon.V6.vlsrw.128B - __builtin_HEXAGON_V6_vlsrw_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vlsrwv - __builtin_HEXAGON_V6_vlsrwv(v64, v64); - // CHECK: @llvm.hexagon.V6.vlsrwv.128B - __builtin_HEXAGON_V6_vlsrwv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vlut4 - __builtin_HEXAGON_V6_vlut4(v64, 0); - // CHECK: @llvm.hexagon.V6.vlut4.128B - __builtin_HEXAGON_V6_vlut4_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb - __builtin_HEXAGON_V6_vlutvvb(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.128B - __builtin_HEXAGON_V6_vlutvvb_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.nm - __builtin_HEXAGON_V6_vlutvvb_nm(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.nm.128B - __builtin_HEXAGON_V6_vlutvvb_nm_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.oracc - __builtin_HEXAGON_V6_vlutvvb_oracc(v64, v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.oracc.128B - __builtin_HEXAGON_V6_vlutvvb_oracc_128B(v128, v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.oracci - __builtin_HEXAGON_V6_vlutvvb_oracci(v64, v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvvb.oracci.128B - __builtin_HEXAGON_V6_vlutvvb_oracci_128B(v128, v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvvbi - __builtin_HEXAGON_V6_vlutvvbi(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvvbi.128B - __builtin_HEXAGON_V6_vlutvvbi_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh - __builtin_HEXAGON_V6_vlutvwh(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.128B - __builtin_HEXAGON_V6_vlutvwh_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.nm - __builtin_HEXAGON_V6_vlutvwh_nm(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.nm.128B - __builtin_HEXAGON_V6_vlutvwh_nm_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.oracc - __builtin_HEXAGON_V6_vlutvwh_oracc(v128, v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.oracc.128B - __builtin_HEXAGON_V6_vlutvwh_oracc_128B(v256, v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.oracci - __builtin_HEXAGON_V6_vlutvwh_oracci(v128, v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvwh.oracci.128B - __builtin_HEXAGON_V6_vlutvwh_oracci_128B(v256, v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vlutvwhi - __builtin_HEXAGON_V6_vlutvwhi(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vlutvwhi.128B - __builtin_HEXAGON_V6_vlutvwhi_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmaskedstorenq - __builtin_HEXAGON_V6_vmaskedstorenq(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vmaskedstorenq.128B - __builtin_HEXAGON_V6_vmaskedstorenq_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vmaskedstorentnq - __builtin_HEXAGON_V6_vmaskedstorentnq(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vmaskedstorentnq.128B - __builtin_HEXAGON_V6_vmaskedstorentnq_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vmaskedstorentq - __builtin_HEXAGON_V6_vmaskedstorentq(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vmaskedstorentq.128B - __builtin_HEXAGON_V6_vmaskedstorentq_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vmaskedstoreq - __builtin_HEXAGON_V6_vmaskedstoreq(v64, 0, v64); - // CHECK: @llvm.hexagon.V6.vmaskedstoreq.128B - __builtin_HEXAGON_V6_vmaskedstoreq_128B(v128, 0, v128); - // CHECK: @llvm.hexagon.V6.vmaxb - __builtin_HEXAGON_V6_vmaxb(v64, v64); - // CHECK: @llvm.hexagon.V6.vmaxb.128B - __builtin_HEXAGON_V6_vmaxb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmaxh - __builtin_HEXAGON_V6_vmaxh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmaxh.128B - __builtin_HEXAGON_V6_vmaxh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmaxub - __builtin_HEXAGON_V6_vmaxub(v64, v64); - // CHECK: @llvm.hexagon.V6.vmaxub.128B - __builtin_HEXAGON_V6_vmaxub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmaxuh - __builtin_HEXAGON_V6_vmaxuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmaxuh.128B - __builtin_HEXAGON_V6_vmaxuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmaxw - __builtin_HEXAGON_V6_vmaxw(v64, v64); - // CHECK: @llvm.hexagon.V6.vmaxw.128B - __builtin_HEXAGON_V6_vmaxw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vminb - __builtin_HEXAGON_V6_vminb(v64, v64); - // CHECK: @llvm.hexagon.V6.vminb.128B - __builtin_HEXAGON_V6_vminb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vminh - __builtin_HEXAGON_V6_vminh(v64, v64); - // CHECK: @llvm.hexagon.V6.vminh.128B - __builtin_HEXAGON_V6_vminh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vminub - __builtin_HEXAGON_V6_vminub(v64, v64); - // CHECK: @llvm.hexagon.V6.vminub.128B - __builtin_HEXAGON_V6_vminub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vminuh - __builtin_HEXAGON_V6_vminuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vminuh.128B - __builtin_HEXAGON_V6_vminuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vminw - __builtin_HEXAGON_V6_vminw(v64, v64); - // CHECK: @llvm.hexagon.V6.vminw.128B - __builtin_HEXAGON_V6_vminw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpabus - __builtin_HEXAGON_V6_vmpabus(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpabus.128B - __builtin_HEXAGON_V6_vmpabus_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vmpabus.acc - __builtin_HEXAGON_V6_vmpabus_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpabus.acc.128B - __builtin_HEXAGON_V6_vmpabus_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vmpabusv - __builtin_HEXAGON_V6_vmpabusv(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpabusv.128B - __builtin_HEXAGON_V6_vmpabusv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vmpabuu - __builtin_HEXAGON_V6_vmpabuu(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpabuu.128B - __builtin_HEXAGON_V6_vmpabuu_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vmpabuu.acc - __builtin_HEXAGON_V6_vmpabuu_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpabuu.acc.128B - __builtin_HEXAGON_V6_vmpabuu_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vmpabuuv - __builtin_HEXAGON_V6_vmpabuuv(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpabuuv.128B - __builtin_HEXAGON_V6_vmpabuuv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vmpahb - __builtin_HEXAGON_V6_vmpahb(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpahb.128B - __builtin_HEXAGON_V6_vmpahb_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vmpahb.acc - __builtin_HEXAGON_V6_vmpahb_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpahb.acc.128B - __builtin_HEXAGON_V6_vmpahb_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vmpahhsat - __builtin_HEXAGON_V6_vmpahhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpahhsat.128B - __builtin_HEXAGON_V6_vmpahhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpauhb - __builtin_HEXAGON_V6_vmpauhb(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpauhb.128B - __builtin_HEXAGON_V6_vmpauhb_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vmpauhb.acc - __builtin_HEXAGON_V6_vmpauhb_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpauhb.acc.128B - __builtin_HEXAGON_V6_vmpauhb_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vmpauhuhsat - __builtin_HEXAGON_V6_vmpauhuhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpauhuhsat.128B - __builtin_HEXAGON_V6_vmpauhuhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpsuhuhsat - __builtin_HEXAGON_V6_vmpsuhuhsat(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpsuhuhsat.128B - __builtin_HEXAGON_V6_vmpsuhuhsat_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpybus - __builtin_HEXAGON_V6_vmpybus(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpybus.128B - __builtin_HEXAGON_V6_vmpybus_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpybus.acc - __builtin_HEXAGON_V6_vmpybus_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpybus.acc.128B - __builtin_HEXAGON_V6_vmpybus_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpybusv - __builtin_HEXAGON_V6_vmpybusv(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpybusv.128B - __builtin_HEXAGON_V6_vmpybusv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpybusv.acc - __builtin_HEXAGON_V6_vmpybusv_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpybusv.acc.128B - __builtin_HEXAGON_V6_vmpybusv_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpybv - __builtin_HEXAGON_V6_vmpybv(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpybv.128B - __builtin_HEXAGON_V6_vmpybv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpybv.acc - __builtin_HEXAGON_V6_vmpybv_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpybv.acc.128B - __builtin_HEXAGON_V6_vmpybv_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyewuh - __builtin_HEXAGON_V6_vmpyewuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyewuh.128B - __builtin_HEXAGON_V6_vmpyewuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyewuh.64 - __builtin_HEXAGON_V6_vmpyewuh_64(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyewuh.64.128B - __builtin_HEXAGON_V6_vmpyewuh_64_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyh - __builtin_HEXAGON_V6_vmpyh(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyh.128B - __builtin_HEXAGON_V6_vmpyh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyh.acc - __builtin_HEXAGON_V6_vmpyh_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyh.acc.128B - __builtin_HEXAGON_V6_vmpyh_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyhsat.acc - __builtin_HEXAGON_V6_vmpyhsat_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyhsat.acc.128B - __builtin_HEXAGON_V6_vmpyhsat_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyhsrs - __builtin_HEXAGON_V6_vmpyhsrs(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyhsrs.128B - __builtin_HEXAGON_V6_vmpyhsrs_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyhss - __builtin_HEXAGON_V6_vmpyhss(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyhss.128B - __builtin_HEXAGON_V6_vmpyhss_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyhus - __builtin_HEXAGON_V6_vmpyhus(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyhus.128B - __builtin_HEXAGON_V6_vmpyhus_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyhus.acc - __builtin_HEXAGON_V6_vmpyhus_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyhus.acc.128B - __builtin_HEXAGON_V6_vmpyhus_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyhv - __builtin_HEXAGON_V6_vmpyhv(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyhv.128B - __builtin_HEXAGON_V6_vmpyhv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyhv.acc - __builtin_HEXAGON_V6_vmpyhv_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyhv.acc.128B - __builtin_HEXAGON_V6_vmpyhv_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyhvsrs - __builtin_HEXAGON_V6_vmpyhvsrs(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyhvsrs.128B - __builtin_HEXAGON_V6_vmpyhvsrs_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyieoh - __builtin_HEXAGON_V6_vmpyieoh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyieoh.128B - __builtin_HEXAGON_V6_vmpyieoh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyiewh.acc - __builtin_HEXAGON_V6_vmpyiewh_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyiewh.acc.128B - __builtin_HEXAGON_V6_vmpyiewh_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyiewuh - __builtin_HEXAGON_V6_vmpyiewuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyiewuh.128B - __builtin_HEXAGON_V6_vmpyiewuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc - __builtin_HEXAGON_V6_vmpyiewuh_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc.128B - __builtin_HEXAGON_V6_vmpyiewuh_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyih - __builtin_HEXAGON_V6_vmpyih(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyih.128B - __builtin_HEXAGON_V6_vmpyih_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyih.acc - __builtin_HEXAGON_V6_vmpyih_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyih.acc.128B - __builtin_HEXAGON_V6_vmpyih_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyihb - __builtin_HEXAGON_V6_vmpyihb(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyihb.128B - __builtin_HEXAGON_V6_vmpyihb_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyihb.acc - __builtin_HEXAGON_V6_vmpyihb_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyihb.acc.128B - __builtin_HEXAGON_V6_vmpyihb_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiowh - __builtin_HEXAGON_V6_vmpyiowh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyiowh.128B - __builtin_HEXAGON_V6_vmpyiowh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyiwb - __builtin_HEXAGON_V6_vmpyiwb(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwb.128B - __builtin_HEXAGON_V6_vmpyiwb_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwb.acc - __builtin_HEXAGON_V6_vmpyiwb_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwb.acc.128B - __builtin_HEXAGON_V6_vmpyiwb_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwh - __builtin_HEXAGON_V6_vmpyiwh(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwh.128B - __builtin_HEXAGON_V6_vmpyiwh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwh.acc - __builtin_HEXAGON_V6_vmpyiwh_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwh.acc.128B - __builtin_HEXAGON_V6_vmpyiwh_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwub - __builtin_HEXAGON_V6_vmpyiwub(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwub.128B - __builtin_HEXAGON_V6_vmpyiwub_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwub.acc - __builtin_HEXAGON_V6_vmpyiwub_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyiwub.acc.128B - __builtin_HEXAGON_V6_vmpyiwub_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyowh - __builtin_HEXAGON_V6_vmpyowh(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyowh.128B - __builtin_HEXAGON_V6_vmpyowh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc - __builtin_HEXAGON_V6_vmpyowh_64_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc.128B - __builtin_HEXAGON_V6_vmpyowh_64_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyowh.rnd - __builtin_HEXAGON_V6_vmpyowh_rnd(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.128B - __builtin_HEXAGON_V6_vmpyowh_rnd_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc - __builtin_HEXAGON_V6_vmpyowh_rnd_sacc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc.128B - __builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyowh.sacc - __builtin_HEXAGON_V6_vmpyowh_sacc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyowh.sacc.128B - __builtin_HEXAGON_V6_vmpyowh_sacc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyub - __builtin_HEXAGON_V6_vmpyub(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyub.128B - __builtin_HEXAGON_V6_vmpyub_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyub.acc - __builtin_HEXAGON_V6_vmpyub_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyub.acc.128B - __builtin_HEXAGON_V6_vmpyub_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyubv - __builtin_HEXAGON_V6_vmpyubv(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyubv.128B - __builtin_HEXAGON_V6_vmpyubv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyubv.acc - __builtin_HEXAGON_V6_vmpyubv_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyubv.acc.128B - __builtin_HEXAGON_V6_vmpyubv_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyuh - __builtin_HEXAGON_V6_vmpyuh(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyuh.128B - __builtin_HEXAGON_V6_vmpyuh_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyuh.acc - __builtin_HEXAGON_V6_vmpyuh_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyuh.acc.128B - __builtin_HEXAGON_V6_vmpyuh_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyuhe - __builtin_HEXAGON_V6_vmpyuhe(v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyuhe.128B - __builtin_HEXAGON_V6_vmpyuhe_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyuhe.acc - __builtin_HEXAGON_V6_vmpyuhe_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vmpyuhe.acc.128B - __builtin_HEXAGON_V6_vmpyuhe_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vmpyuhv - __builtin_HEXAGON_V6_vmpyuhv(v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyuhv.128B - __builtin_HEXAGON_V6_vmpyuhv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vmpyuhv.acc - __builtin_HEXAGON_V6_vmpyuhv_acc(v128, v64, v64); - // CHECK: @llvm.hexagon.V6.vmpyuhv.acc.128B - __builtin_HEXAGON_V6_vmpyuhv_acc_128B(v256, v128, v128); - // CHECK: @llvm.hexagon.V6.vmux - __builtin_HEXAGON_V6_vmux(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vmux.128B - __builtin_HEXAGON_V6_vmux_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vnavgb - __builtin_HEXAGON_V6_vnavgb(v64, v64); - // CHECK: @llvm.hexagon.V6.vnavgb.128B - __builtin_HEXAGON_V6_vnavgb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vnavgh - __builtin_HEXAGON_V6_vnavgh(v64, v64); - // CHECK: @llvm.hexagon.V6.vnavgh.128B - __builtin_HEXAGON_V6_vnavgh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vnavgub - __builtin_HEXAGON_V6_vnavgub(v64, v64); - // CHECK: @llvm.hexagon.V6.vnavgub.128B - __builtin_HEXAGON_V6_vnavgub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vnavgw - __builtin_HEXAGON_V6_vnavgw(v64, v64); - // CHECK: @llvm.hexagon.V6.vnavgw.128B - __builtin_HEXAGON_V6_vnavgw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vnormamth - __builtin_HEXAGON_V6_vnormamth(v64); - // CHECK: @llvm.hexagon.V6.vnormamth.128B - __builtin_HEXAGON_V6_vnormamth_128B(v128); - // CHECK: @llvm.hexagon.V6.vnormamtw - __builtin_HEXAGON_V6_vnormamtw(v64); - // CHECK: @llvm.hexagon.V6.vnormamtw.128B - __builtin_HEXAGON_V6_vnormamtw_128B(v128); - // CHECK: @llvm.hexagon.V6.vnot - __builtin_HEXAGON_V6_vnot(v64); - // CHECK: @llvm.hexagon.V6.vnot.128B - __builtin_HEXAGON_V6_vnot_128B(v128); - // CHECK: @llvm.hexagon.V6.vor - __builtin_HEXAGON_V6_vor(v64, v64); - // CHECK: @llvm.hexagon.V6.vor.128B - __builtin_HEXAGON_V6_vor_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackeb - __builtin_HEXAGON_V6_vpackeb(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackeb.128B - __builtin_HEXAGON_V6_vpackeb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackeh - __builtin_HEXAGON_V6_vpackeh(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackeh.128B - __builtin_HEXAGON_V6_vpackeh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackhb.sat - __builtin_HEXAGON_V6_vpackhb_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackhb.sat.128B - __builtin_HEXAGON_V6_vpackhb_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackhub.sat - __builtin_HEXAGON_V6_vpackhub_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackhub.sat.128B - __builtin_HEXAGON_V6_vpackhub_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackob - __builtin_HEXAGON_V6_vpackob(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackob.128B - __builtin_HEXAGON_V6_vpackob_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackoh - __builtin_HEXAGON_V6_vpackoh(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackoh.128B - __builtin_HEXAGON_V6_vpackoh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackwh.sat - __builtin_HEXAGON_V6_vpackwh_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackwh.sat.128B - __builtin_HEXAGON_V6_vpackwh_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpackwuh.sat - __builtin_HEXAGON_V6_vpackwuh_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vpackwuh.sat.128B - __builtin_HEXAGON_V6_vpackwuh_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vpopcounth - __builtin_HEXAGON_V6_vpopcounth(v64); - // CHECK: @llvm.hexagon.V6.vpopcounth.128B - __builtin_HEXAGON_V6_vpopcounth_128B(v128); - // CHECK: @llvm.hexagon.V6.vprefixqb - __builtin_HEXAGON_V6_vprefixqb(v64); - // CHECK: @llvm.hexagon.V6.vprefixqb.128B - __builtin_HEXAGON_V6_vprefixqb_128B(v128); - // CHECK: @llvm.hexagon.V6.vprefixqh - __builtin_HEXAGON_V6_vprefixqh(v64); - // CHECK: @llvm.hexagon.V6.vprefixqh.128B - __builtin_HEXAGON_V6_vprefixqh_128B(v128); - // CHECK: @llvm.hexagon.V6.vprefixqw - __builtin_HEXAGON_V6_vprefixqw(v64); - // CHECK: @llvm.hexagon.V6.vprefixqw.128B - __builtin_HEXAGON_V6_vprefixqw_128B(v128); - // CHECK: @llvm.hexagon.V6.vrdelta - __builtin_HEXAGON_V6_vrdelta(v64, v64); - // CHECK: @llvm.hexagon.V6.vrdelta.128B - __builtin_HEXAGON_V6_vrdelta_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpybub.rtt - __builtin_HEXAGON_V6_vrmpybub_rtt(v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.128B - __builtin_HEXAGON_V6_vrmpybub_rtt_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc - __builtin_HEXAGON_V6_vrmpybub_rtt_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc.128B - __builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpybus - __builtin_HEXAGON_V6_vrmpybus(v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpybus.128B - __builtin_HEXAGON_V6_vrmpybus_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpybus.acc - __builtin_HEXAGON_V6_vrmpybus_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpybus.acc.128B - __builtin_HEXAGON_V6_vrmpybus_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpybusi - __builtin_HEXAGON_V6_vrmpybusi(v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpybusi.128B - __builtin_HEXAGON_V6_vrmpybusi_128B(v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpybusi.acc - __builtin_HEXAGON_V6_vrmpybusi_acc(v128, v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpybusi.acc.128B - __builtin_HEXAGON_V6_vrmpybusi_acc_128B(v256, v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpybusv - __builtin_HEXAGON_V6_vrmpybusv(v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpybusv.128B - __builtin_HEXAGON_V6_vrmpybusv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpybusv.acc - __builtin_HEXAGON_V6_vrmpybusv_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpybusv.acc.128B - __builtin_HEXAGON_V6_vrmpybusv_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpybv - __builtin_HEXAGON_V6_vrmpybv(v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpybv.128B - __builtin_HEXAGON_V6_vrmpybv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpybv.acc - __builtin_HEXAGON_V6_vrmpybv_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpybv.acc.128B - __builtin_HEXAGON_V6_vrmpybv_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpyub - __builtin_HEXAGON_V6_vrmpyub(v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.128B - __builtin_HEXAGON_V6_vrmpyub_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.acc - __builtin_HEXAGON_V6_vrmpyub_acc(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.acc.128B - __builtin_HEXAGON_V6_vrmpyub_acc_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.rtt - __builtin_HEXAGON_V6_vrmpyub_rtt(v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.128B - __builtin_HEXAGON_V6_vrmpyub_rtt_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc - __builtin_HEXAGON_V6_vrmpyub_rtt_acc(v128, v64, 0); - // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc.128B - __builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B(v256, v128, 0); - // CHECK: @llvm.hexagon.V6.vrmpyubi - __builtin_HEXAGON_V6_vrmpyubi(v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpyubi.128B - __builtin_HEXAGON_V6_vrmpyubi_128B(v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpyubi.acc - __builtin_HEXAGON_V6_vrmpyubi_acc(v128, v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpyubi.acc.128B - __builtin_HEXAGON_V6_vrmpyubi_acc_128B(v256, v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vrmpyubv - __builtin_HEXAGON_V6_vrmpyubv(v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpyubv.128B - __builtin_HEXAGON_V6_vrmpyubv_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrmpyubv.acc - __builtin_HEXAGON_V6_vrmpyubv_acc(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vrmpyubv.acc.128B - __builtin_HEXAGON_V6_vrmpyubv_acc_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vror - __builtin_HEXAGON_V6_vror(v64, 0); - // CHECK: @llvm.hexagon.V6.vror.128B - __builtin_HEXAGON_V6_vror_128B(v128, 0); - // CHECK: @llvm.hexagon.V6.vroundhb - __builtin_HEXAGON_V6_vroundhb(v64, v64); - // CHECK: @llvm.hexagon.V6.vroundhb.128B - __builtin_HEXAGON_V6_vroundhb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vroundhub - __builtin_HEXAGON_V6_vroundhub(v64, v64); - // CHECK: @llvm.hexagon.V6.vroundhub.128B - __builtin_HEXAGON_V6_vroundhub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrounduhub - __builtin_HEXAGON_V6_vrounduhub(v64, v64); - // CHECK: @llvm.hexagon.V6.vrounduhub.128B - __builtin_HEXAGON_V6_vrounduhub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrounduwuh - __builtin_HEXAGON_V6_vrounduwuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vrounduwuh.128B - __builtin_HEXAGON_V6_vrounduwuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vroundwh - __builtin_HEXAGON_V6_vroundwh(v64, v64); - // CHECK: @llvm.hexagon.V6.vroundwh.128B - __builtin_HEXAGON_V6_vroundwh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vroundwuh - __builtin_HEXAGON_V6_vroundwuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vroundwuh.128B - __builtin_HEXAGON_V6_vroundwuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vrsadubi - __builtin_HEXAGON_V6_vrsadubi(v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrsadubi.128B - __builtin_HEXAGON_V6_vrsadubi_128B(v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vrsadubi.acc - __builtin_HEXAGON_V6_vrsadubi_acc(v128, v128, 0, 0); - // CHECK: @llvm.hexagon.V6.vrsadubi.acc.128B - __builtin_HEXAGON_V6_vrsadubi_acc_128B(v256, v256, 0, 0); - // CHECK: @llvm.hexagon.V6.vsathub - __builtin_HEXAGON_V6_vsathub(v64, v64); - // CHECK: @llvm.hexagon.V6.vsathub.128B - __builtin_HEXAGON_V6_vsathub_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsatuwuh - __builtin_HEXAGON_V6_vsatuwuh(v64, v64); - // CHECK: @llvm.hexagon.V6.vsatuwuh.128B - __builtin_HEXAGON_V6_vsatuwuh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsatwh - __builtin_HEXAGON_V6_vsatwh(v64, v64); - // CHECK: @llvm.hexagon.V6.vsatwh.128B - __builtin_HEXAGON_V6_vsatwh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsb - __builtin_HEXAGON_V6_vsb(v64); - // CHECK: @llvm.hexagon.V6.vsb.128B - __builtin_HEXAGON_V6_vsb_128B(v128); - // CHECK: @llvm.hexagon.V6.vscattermh - __builtin_HEXAGON_V6_vscattermh(0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermh.128B - __builtin_HEXAGON_V6_vscattermh_128B(0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vscattermh.add - __builtin_HEXAGON_V6_vscattermh_add(0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermh.add.128B - __builtin_HEXAGON_V6_vscattermh_add_128B(0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vscattermhq - __builtin_HEXAGON_V6_vscattermhq(v64, 0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermhq.128B - __builtin_HEXAGON_V6_vscattermhq_128B(v128, 0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vscattermhw - __builtin_HEXAGON_V6_vscattermhw(0, 0, v128, v64); - // CHECK: @llvm.hexagon.V6.vscattermhw.128B - __builtin_HEXAGON_V6_vscattermhw_128B(0, 0, v256, v128); - // CHECK: @llvm.hexagon.V6.vscattermhw.add - __builtin_HEXAGON_V6_vscattermhw_add(0, 0, v128, v64); - // CHECK: @llvm.hexagon.V6.vscattermhw.add.128B - __builtin_HEXAGON_V6_vscattermhw_add_128B(0, 0, v256, v128); - // CHECK: @llvm.hexagon.V6.vscattermhwq - __builtin_HEXAGON_V6_vscattermhwq(v64, 0, 0, v128, v64); - // CHECK: @llvm.hexagon.V6.vscattermhwq.128B - __builtin_HEXAGON_V6_vscattermhwq_128B(v128, 0, 0, v256, v128); - // CHECK: @llvm.hexagon.V6.vscattermw - __builtin_HEXAGON_V6_vscattermw(0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermw.128B - __builtin_HEXAGON_V6_vscattermw_128B(0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vscattermw.add - __builtin_HEXAGON_V6_vscattermw_add(0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermw.add.128B - __builtin_HEXAGON_V6_vscattermw_add_128B(0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vscattermwq - __builtin_HEXAGON_V6_vscattermwq(v64, 0, 0, v64, v64); - // CHECK: @llvm.hexagon.V6.vscattermwq.128B - __builtin_HEXAGON_V6_vscattermwq_128B(v128, 0, 0, v128, v128); - // CHECK: @llvm.hexagon.V6.vsh - __builtin_HEXAGON_V6_vsh(v64); - // CHECK: @llvm.hexagon.V6.vsh.128B - __builtin_HEXAGON_V6_vsh_128B(v128); - // CHECK: @llvm.hexagon.V6.vshufeh - __builtin_HEXAGON_V6_vshufeh(v64, v64); - // CHECK: @llvm.hexagon.V6.vshufeh.128B - __builtin_HEXAGON_V6_vshufeh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vshuffb - __builtin_HEXAGON_V6_vshuffb(v64); - // CHECK: @llvm.hexagon.V6.vshuffb.128B - __builtin_HEXAGON_V6_vshuffb_128B(v128); - // CHECK: @llvm.hexagon.V6.vshuffeb - __builtin_HEXAGON_V6_vshuffeb(v64, v64); - // CHECK: @llvm.hexagon.V6.vshuffeb.128B - __builtin_HEXAGON_V6_vshuffeb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vshuffh - __builtin_HEXAGON_V6_vshuffh(v64); - // CHECK: @llvm.hexagon.V6.vshuffh.128B - __builtin_HEXAGON_V6_vshuffh_128B(v128); - // CHECK: @llvm.hexagon.V6.vshuffob - __builtin_HEXAGON_V6_vshuffob(v64, v64); - // CHECK: @llvm.hexagon.V6.vshuffob.128B - __builtin_HEXAGON_V6_vshuffob_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vshuffvdd - __builtin_HEXAGON_V6_vshuffvdd(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vshuffvdd.128B - __builtin_HEXAGON_V6_vshuffvdd_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vshufoeb - __builtin_HEXAGON_V6_vshufoeb(v64, v64); - // CHECK: @llvm.hexagon.V6.vshufoeb.128B - __builtin_HEXAGON_V6_vshufoeb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vshufoeh - __builtin_HEXAGON_V6_vshufoeh(v64, v64); - // CHECK: @llvm.hexagon.V6.vshufoeh.128B - __builtin_HEXAGON_V6_vshufoeh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vshufoh - __builtin_HEXAGON_V6_vshufoh(v64, v64); - // CHECK: @llvm.hexagon.V6.vshufoh.128B - __builtin_HEXAGON_V6_vshufoh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubb - __builtin_HEXAGON_V6_vsubb(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubb.128B - __builtin_HEXAGON_V6_vsubb_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubb.dv - __builtin_HEXAGON_V6_vsubb_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubb.dv.128B - __builtin_HEXAGON_V6_vsubb_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubbnq - __builtin_HEXAGON_V6_vsubbnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubbnq.128B - __builtin_HEXAGON_V6_vsubbnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubbq - __builtin_HEXAGON_V6_vsubbq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubbq.128B - __builtin_HEXAGON_V6_vsubbq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubbsat - __builtin_HEXAGON_V6_vsubbsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubbsat.128B - __builtin_HEXAGON_V6_vsubbsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubbsat.dv - __builtin_HEXAGON_V6_vsubbsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubbsat.dv.128B - __builtin_HEXAGON_V6_vsubbsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubcarry - __builtin_HEXAGON_V6_vsubcarry(v64, v64, 0); - // CHECK: @llvm.hexagon.V6.vsubcarry.128B - __builtin_HEXAGON_V6_vsubcarry_128B(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vsubh - __builtin_HEXAGON_V6_vsubh(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubh.128B - __builtin_HEXAGON_V6_vsubh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubh.dv - __builtin_HEXAGON_V6_vsubh_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubh.dv.128B - __builtin_HEXAGON_V6_vsubh_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubhnq - __builtin_HEXAGON_V6_vsubhnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubhnq.128B - __builtin_HEXAGON_V6_vsubhnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubhq - __builtin_HEXAGON_V6_vsubhq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubhq.128B - __builtin_HEXAGON_V6_vsubhq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubhsat - __builtin_HEXAGON_V6_vsubhsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubhsat.128B - __builtin_HEXAGON_V6_vsubhsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubhsat.dv - __builtin_HEXAGON_V6_vsubhsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubhsat.dv.128B - __builtin_HEXAGON_V6_vsubhsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubhw - __builtin_HEXAGON_V6_vsubhw(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubhw.128B - __builtin_HEXAGON_V6_vsubhw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsububh - __builtin_HEXAGON_V6_vsububh(v64, v64); - // CHECK: @llvm.hexagon.V6.vsububh.128B - __builtin_HEXAGON_V6_vsububh_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsububsat - __builtin_HEXAGON_V6_vsububsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsububsat.128B - __builtin_HEXAGON_V6_vsububsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsububsat.dv - __builtin_HEXAGON_V6_vsububsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsububsat.dv.128B - __builtin_HEXAGON_V6_vsububsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubububb.sat - __builtin_HEXAGON_V6_vsubububb_sat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubububb.sat.128B - __builtin_HEXAGON_V6_vsubububb_sat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuhsat - __builtin_HEXAGON_V6_vsubuhsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubuhsat.128B - __builtin_HEXAGON_V6_vsubuhsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuhsat.dv - __builtin_HEXAGON_V6_vsubuhsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuhsat.dv.128B - __builtin_HEXAGON_V6_vsubuhsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubuhw - __builtin_HEXAGON_V6_vsubuhw(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubuhw.128B - __builtin_HEXAGON_V6_vsubuhw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuwsat - __builtin_HEXAGON_V6_vsubuwsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubuwsat.128B - __builtin_HEXAGON_V6_vsubuwsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuwsat.dv - __builtin_HEXAGON_V6_vsubuwsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubuwsat.dv.128B - __builtin_HEXAGON_V6_vsubuwsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubw - __builtin_HEXAGON_V6_vsubw(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubw.128B - __builtin_HEXAGON_V6_vsubw_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubw.dv - __builtin_HEXAGON_V6_vsubw_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubw.dv.128B - __builtin_HEXAGON_V6_vsubw_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vsubwnq - __builtin_HEXAGON_V6_vsubwnq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubwnq.128B - __builtin_HEXAGON_V6_vsubwnq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubwq - __builtin_HEXAGON_V6_vsubwq(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vsubwq.128B - __builtin_HEXAGON_V6_vsubwq_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vsubwsat - __builtin_HEXAGON_V6_vsubwsat(v64, v64); - // CHECK: @llvm.hexagon.V6.vsubwsat.128B - __builtin_HEXAGON_V6_vsubwsat_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubwsat.dv - __builtin_HEXAGON_V6_vsubwsat_dv(v128, v128); - // CHECK: @llvm.hexagon.V6.vsubwsat.dv.128B - __builtin_HEXAGON_V6_vsubwsat_dv_128B(v256, v256); - // CHECK: @llvm.hexagon.V6.vswap - __builtin_HEXAGON_V6_vswap(v64, v64, v64); - // CHECK: @llvm.hexagon.V6.vswap.128B - __builtin_HEXAGON_V6_vswap_128B(v128, v128, v128); - // CHECK: @llvm.hexagon.V6.vtmpyb - __builtin_HEXAGON_V6_vtmpyb(v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpyb.128B - __builtin_HEXAGON_V6_vtmpyb_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vtmpyb.acc - __builtin_HEXAGON_V6_vtmpyb_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpyb.acc.128B - __builtin_HEXAGON_V6_vtmpyb_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vtmpybus - __builtin_HEXAGON_V6_vtmpybus(v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpybus.128B - __builtin_HEXAGON_V6_vtmpybus_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vtmpybus.acc - __builtin_HEXAGON_V6_vtmpybus_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpybus.acc.128B - __builtin_HEXAGON_V6_vtmpybus_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vtmpyhb - __builtin_HEXAGON_V6_vtmpyhb(v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpyhb.128B - __builtin_HEXAGON_V6_vtmpyhb_128B(v256, 0); - // CHECK: @llvm.hexagon.V6.vtmpyhb.acc - __builtin_HEXAGON_V6_vtmpyhb_acc(v128, v128, 0); - // CHECK: @llvm.hexagon.V6.vtmpyhb.acc.128B - __builtin_HEXAGON_V6_vtmpyhb_acc_128B(v256, v256, 0); - // CHECK: @llvm.hexagon.V6.vunpackb - __builtin_HEXAGON_V6_vunpackb(v64); - // CHECK: @llvm.hexagon.V6.vunpackb.128B - __builtin_HEXAGON_V6_vunpackb_128B(v128); - // CHECK: @llvm.hexagon.V6.vunpackh - __builtin_HEXAGON_V6_vunpackh(v64); - // CHECK: @llvm.hexagon.V6.vunpackh.128B - __builtin_HEXAGON_V6_vunpackh_128B(v128); - // CHECK: @llvm.hexagon.V6.vunpackob - __builtin_HEXAGON_V6_vunpackob(v128, v64); - // CHECK: @llvm.hexagon.V6.vunpackob.128B - __builtin_HEXAGON_V6_vunpackob_128B(v256, v128); - // CHECK: @llvm.hexagon.V6.vunpackoh - __builtin_HEXAGON_V6_vunpackoh(v128, v64); - // CHECK: @llvm.hexagon.V6.vunpackoh.128B - __builtin_HEXAGON_V6_vunpackoh_128B(v256, v128); - // CHECK: @llvm.hexagon.V6.vunpackub - __builtin_HEXAGON_V6_vunpackub(v64); - // CHECK: @llvm.hexagon.V6.vunpackub.128B - __builtin_HEXAGON_V6_vunpackub_128B(v128); - // CHECK: @llvm.hexagon.V6.vunpackuh - __builtin_HEXAGON_V6_vunpackuh(v64); - // CHECK: @llvm.hexagon.V6.vunpackuh.128B - __builtin_HEXAGON_V6_vunpackuh_128B(v128); - // CHECK: @llvm.hexagon.V6.vxor - __builtin_HEXAGON_V6_vxor(v64, v64); - // CHECK: @llvm.hexagon.V6.vxor.128B - __builtin_HEXAGON_V6_vxor_128B(v128, v128); - // CHECK: @llvm.hexagon.V6.vzb - __builtin_HEXAGON_V6_vzb(v64); - // CHECK: @llvm.hexagon.V6.vzb.128B - __builtin_HEXAGON_V6_vzb_128B(v128); - // CHECK: @llvm.hexagon.V6.vzh - __builtin_HEXAGON_V6_vzh(v64); - // CHECK: @llvm.hexagon.V6.vzh.128B - __builtin_HEXAGON_V6_vzh_128B(v128); // CHECK: @llvm.hexagon.Y2.dccleana __builtin_HEXAGON_Y2_dccleana(0); // CHECK: @llvm.hexagon.Y2.dccleaninva diff --git a/test/CodeGen/builtins-hvx128.c b/test/CodeGen/builtins-hvx128.c new file mode 100644 index 0000000000..c482d7bd35 --- /dev/null +++ b/test/CodeGen/builtins-hvx128.c @@ -0,0 +1,802 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128 -emit-llvm %s -o - | FileCheck %s + +void test() { + int v128 __attribute__((__vector_size__(128))); + int v256 __attribute__((__vector_size__(256))); + + // CHECK: @llvm.hexagon.V6.extractw.128B + __builtin_HEXAGON_V6_extractw_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.hi.128B + __builtin_HEXAGON_V6_hi_128B(v256); + // CHECK: @llvm.hexagon.V6.lo.128B + __builtin_HEXAGON_V6_lo_128B(v256); + // CHECK: @llvm.hexagon.V6.lvsplatb.128B + __builtin_HEXAGON_V6_lvsplatb_128B(0); + // CHECK: @llvm.hexagon.V6.lvsplath.128B + __builtin_HEXAGON_V6_lvsplath_128B(0); + // CHECK: @llvm.hexagon.V6.lvsplatw.128B + __builtin_HEXAGON_V6_lvsplatw_128B(0); + // CHECK: @llvm.hexagon.V6.pred.and.128B + __builtin_HEXAGON_V6_pred_and_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.pred.and.n.128B + __builtin_HEXAGON_V6_pred_and_n_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.pred.not.128B + __builtin_HEXAGON_V6_pred_not_128B(v128); + // CHECK: @llvm.hexagon.V6.pred.or.128B + __builtin_HEXAGON_V6_pred_or_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.pred.or.n.128B + __builtin_HEXAGON_V6_pred_or_n_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.pred.scalar2.128B + __builtin_HEXAGON_V6_pred_scalar2_128B(0); + // CHECK: @llvm.hexagon.V6.pred.scalar2v2.128B + __builtin_HEXAGON_V6_pred_scalar2v2_128B(0); + // CHECK: @llvm.hexagon.V6.pred.xor.128B + __builtin_HEXAGON_V6_pred_xor_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.shuffeqh.128B + __builtin_HEXAGON_V6_shuffeqh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.shuffeqw.128B + __builtin_HEXAGON_V6_shuffeqw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai.128B + __builtin_HEXAGON_V6_vS32b_nqpred_ai_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai.128B + __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai.128B + __builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai.128B + __builtin_HEXAGON_V6_vS32b_qpred_ai_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vabsb.128B + __builtin_HEXAGON_V6_vabsb_128B(v128); + // CHECK: @llvm.hexagon.V6.vabsb.sat.128B + __builtin_HEXAGON_V6_vabsb_sat_128B(v128); + // CHECK: @llvm.hexagon.V6.vabsdiffh.128B + __builtin_HEXAGON_V6_vabsdiffh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vabsdiffub.128B + __builtin_HEXAGON_V6_vabsdiffub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vabsdiffuh.128B + __builtin_HEXAGON_V6_vabsdiffuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vabsdiffw.128B + __builtin_HEXAGON_V6_vabsdiffw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vabsh.128B + __builtin_HEXAGON_V6_vabsh_128B(v128); + // CHECK: @llvm.hexagon.V6.vabsh.sat.128B + __builtin_HEXAGON_V6_vabsh_sat_128B(v128); + // CHECK: @llvm.hexagon.V6.vabsw.128B + __builtin_HEXAGON_V6_vabsw_128B(v128); + // CHECK: @llvm.hexagon.V6.vabsw.sat.128B + __builtin_HEXAGON_V6_vabsw_sat_128B(v128); + // CHECK: @llvm.hexagon.V6.vaddb.128B + __builtin_HEXAGON_V6_vaddb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddb.dv.128B + __builtin_HEXAGON_V6_vaddb_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddbnq.128B + __builtin_HEXAGON_V6_vaddbnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddbq.128B + __builtin_HEXAGON_V6_vaddbq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddbsat.128B + __builtin_HEXAGON_V6_vaddbsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddbsat.dv.128B + __builtin_HEXAGON_V6_vaddbsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddcarry.128B + __builtin_HEXAGON_V6_vaddcarry_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vaddclbh.128B + __builtin_HEXAGON_V6_vaddclbh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddclbw.128B + __builtin_HEXAGON_V6_vaddclbw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddh.128B + __builtin_HEXAGON_V6_vaddh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddh.dv.128B + __builtin_HEXAGON_V6_vaddh_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddhnq.128B + __builtin_HEXAGON_V6_vaddhnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhq.128B + __builtin_HEXAGON_V6_vaddhq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhsat.128B + __builtin_HEXAGON_V6_vaddhsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhsat.dv.128B + __builtin_HEXAGON_V6_vaddhsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddhw.128B + __builtin_HEXAGON_V6_vaddhw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhw.acc.128B + __builtin_HEXAGON_V6_vaddhw_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddubh.128B + __builtin_HEXAGON_V6_vaddubh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddubh.acc.128B + __builtin_HEXAGON_V6_vaddubh_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddubsat.128B + __builtin_HEXAGON_V6_vaddubsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddubsat.dv.128B + __builtin_HEXAGON_V6_vaddubsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddububb.sat.128B + __builtin_HEXAGON_V6_vaddububb_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vadduhsat.128B + __builtin_HEXAGON_V6_vadduhsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vadduhsat.dv.128B + __builtin_HEXAGON_V6_vadduhsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vadduhw.128B + __builtin_HEXAGON_V6_vadduhw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vadduhw.acc.128B + __builtin_HEXAGON_V6_vadduhw_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vadduwsat.128B + __builtin_HEXAGON_V6_vadduwsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vadduwsat.dv.128B + __builtin_HEXAGON_V6_vadduwsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddw.128B + __builtin_HEXAGON_V6_vaddw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddw.dv.128B + __builtin_HEXAGON_V6_vaddw_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vaddwnq.128B + __builtin_HEXAGON_V6_vaddwnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddwq.128B + __builtin_HEXAGON_V6_vaddwq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vaddwsat.128B + __builtin_HEXAGON_V6_vaddwsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddwsat.dv.128B + __builtin_HEXAGON_V6_vaddwsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.valignb.128B + __builtin_HEXAGON_V6_valignb_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.valignbi.128B + __builtin_HEXAGON_V6_valignbi_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vand.128B + __builtin_HEXAGON_V6_vand_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vandnqrt.128B + __builtin_HEXAGON_V6_vandnqrt_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vandnqrt.acc.128B + __builtin_HEXAGON_V6_vandnqrt_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vandqrt.128B + __builtin_HEXAGON_V6_vandqrt_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vandqrt.acc.128B + __builtin_HEXAGON_V6_vandqrt_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vandvnqv.128B + __builtin_HEXAGON_V6_vandvnqv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vandvqv.128B + __builtin_HEXAGON_V6_vandvqv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vandvrt.128B + __builtin_HEXAGON_V6_vandvrt_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vandvrt.acc.128B + __builtin_HEXAGON_V6_vandvrt_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vaslh.128B + __builtin_HEXAGON_V6_vaslh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vaslh.acc.128B + __builtin_HEXAGON_V6_vaslh_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vaslhv.128B + __builtin_HEXAGON_V6_vaslhv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vaslw.128B + __builtin_HEXAGON_V6_vaslw_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vaslw.acc.128B + __builtin_HEXAGON_V6_vaslw_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vaslwv.128B + __builtin_HEXAGON_V6_vaslwv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vasrh.128B + __builtin_HEXAGON_V6_vasrh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vasrh.acc.128B + __builtin_HEXAGON_V6_vasrh_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrhbrndsat.128B + __builtin_HEXAGON_V6_vasrhbrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrhbsat.128B + __builtin_HEXAGON_V6_vasrhbsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrhubrndsat.128B + __builtin_HEXAGON_V6_vasrhubrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrhubsat.128B + __builtin_HEXAGON_V6_vasrhubsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrhv.128B + __builtin_HEXAGON_V6_vasrhv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vasruhubrndsat.128B + __builtin_HEXAGON_V6_vasruhubrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasruhubsat.128B + __builtin_HEXAGON_V6_vasruhubsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasruwuhrndsat.128B + __builtin_HEXAGON_V6_vasruwuhrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasruwuhsat.128B + __builtin_HEXAGON_V6_vasruwuhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrw.128B + __builtin_HEXAGON_V6_vasrw_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vasrw.acc.128B + __builtin_HEXAGON_V6_vasrw_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwh.128B + __builtin_HEXAGON_V6_vasrwh_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwhrndsat.128B + __builtin_HEXAGON_V6_vasrwhrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwhsat.128B + __builtin_HEXAGON_V6_vasrwhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwuhrndsat.128B + __builtin_HEXAGON_V6_vasrwuhrndsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwuhsat.128B + __builtin_HEXAGON_V6_vasrwuhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vasrwv.128B + __builtin_HEXAGON_V6_vasrwv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vassign.128B + __builtin_HEXAGON_V6_vassign_128B(v128); + // CHECK: @llvm.hexagon.V6.vassignp.128B + __builtin_HEXAGON_V6_vassignp_128B(v256); + // CHECK: @llvm.hexagon.V6.vavgb.128B + __builtin_HEXAGON_V6_vavgb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgbrnd.128B + __builtin_HEXAGON_V6_vavgbrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgh.128B + __builtin_HEXAGON_V6_vavgh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavghrnd.128B + __builtin_HEXAGON_V6_vavghrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgub.128B + __builtin_HEXAGON_V6_vavgub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgubrnd.128B + __builtin_HEXAGON_V6_vavgubrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavguh.128B + __builtin_HEXAGON_V6_vavguh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavguhrnd.128B + __builtin_HEXAGON_V6_vavguhrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavguw.128B + __builtin_HEXAGON_V6_vavguw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavguwrnd.128B + __builtin_HEXAGON_V6_vavguwrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgw.128B + __builtin_HEXAGON_V6_vavgw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vavgwrnd.128B + __builtin_HEXAGON_V6_vavgwrnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vcl0h.128B + __builtin_HEXAGON_V6_vcl0h_128B(v128); + // CHECK: @llvm.hexagon.V6.vcl0w.128B + __builtin_HEXAGON_V6_vcl0w_128B(v128); + // CHECK: @llvm.hexagon.V6.vcombine.128B + __builtin_HEXAGON_V6_vcombine_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vd0.128B + __builtin_HEXAGON_V6_vd0_128B(); + // CHECK: @llvm.hexagon.V6.vdd0.128B + __builtin_HEXAGON_V6_vdd0_128B(); + // CHECK: @llvm.hexagon.V6.vdealb.128B + __builtin_HEXAGON_V6_vdealb_128B(v128); + // CHECK: @llvm.hexagon.V6.vdealb4w.128B + __builtin_HEXAGON_V6_vdealb4w_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vdealh.128B + __builtin_HEXAGON_V6_vdealh_128B(v128); + // CHECK: @llvm.hexagon.V6.vdealvdd.128B + __builtin_HEXAGON_V6_vdealvdd_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdelta.128B + __builtin_HEXAGON_V6_vdelta_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vdmpybus.128B + __builtin_HEXAGON_V6_vdmpybus_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.acc.128B + __builtin_HEXAGON_V6_vdmpybus_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.dv.128B + __builtin_HEXAGON_V6_vdmpybus_dv_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc.128B + __builtin_HEXAGON_V6_vdmpybus_dv_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.128B + __builtin_HEXAGON_V6_vdmpyhb_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.acc.128B + __builtin_HEXAGON_V6_vdmpyhb_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.128B + __builtin_HEXAGON_V6_vdmpyhb_dv_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc.128B + __builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhisat.128B + __builtin_HEXAGON_V6_vdmpyhisat_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc.128B + __builtin_HEXAGON_V6_vdmpyhisat_acc_128B(v128, v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsat.128B + __builtin_HEXAGON_V6_vdmpyhsat_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc.128B + __builtin_HEXAGON_V6_vdmpyhsat_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.128B + __builtin_HEXAGON_V6_vdmpyhsuisat_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc.128B + __builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B(v128, v256, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsusat.128B + __builtin_HEXAGON_V6_vdmpyhsusat_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc.128B + __builtin_HEXAGON_V6_vdmpyhsusat_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhvsat.128B + __builtin_HEXAGON_V6_vdmpyhvsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc.128B + __builtin_HEXAGON_V6_vdmpyhvsat_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vdsaduh.128B + __builtin_HEXAGON_V6_vdsaduh_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vdsaduh.acc.128B + __builtin_HEXAGON_V6_vdsaduh_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.veqb.128B + __builtin_HEXAGON_V6_veqb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.veqb.and.128B + __builtin_HEXAGON_V6_veqb_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqb.or.128B + __builtin_HEXAGON_V6_veqb_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqb.xor.128B + __builtin_HEXAGON_V6_veqb_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqh.128B + __builtin_HEXAGON_V6_veqh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.veqh.and.128B + __builtin_HEXAGON_V6_veqh_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqh.or.128B + __builtin_HEXAGON_V6_veqh_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqh.xor.128B + __builtin_HEXAGON_V6_veqh_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqw.128B + __builtin_HEXAGON_V6_veqw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.veqw.and.128B + __builtin_HEXAGON_V6_veqw_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqw.or.128B + __builtin_HEXAGON_V6_veqw_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.veqw.xor.128B + __builtin_HEXAGON_V6_veqw_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgathermh.128B + __builtin_HEXAGON_V6_vgathermh_128B(0, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgathermhq.128B + __builtin_HEXAGON_V6_vgathermhq_128B(0, v128, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgathermhw.128B + __builtin_HEXAGON_V6_vgathermhw_128B(0, 0, 0, v256); + // CHECK: @llvm.hexagon.V6.vgathermhwq.128B + __builtin_HEXAGON_V6_vgathermhwq_128B(0, v128, 0, 0, v256); + // CHECK: @llvm.hexagon.V6.vgathermw.128B + __builtin_HEXAGON_V6_vgathermw_128B(0, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgathermwq.128B + __builtin_HEXAGON_V6_vgathermwq_128B(0, v128, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgtb.128B + __builtin_HEXAGON_V6_vgtb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgtb.and.128B + __builtin_HEXAGON_V6_vgtb_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtb.or.128B + __builtin_HEXAGON_V6_vgtb_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtb.xor.128B + __builtin_HEXAGON_V6_vgtb_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgth.128B + __builtin_HEXAGON_V6_vgth_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgth.and.128B + __builtin_HEXAGON_V6_vgth_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgth.or.128B + __builtin_HEXAGON_V6_vgth_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgth.xor.128B + __builtin_HEXAGON_V6_vgth_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtub.128B + __builtin_HEXAGON_V6_vgtub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgtub.and.128B + __builtin_HEXAGON_V6_vgtub_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtub.or.128B + __builtin_HEXAGON_V6_vgtub_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtub.xor.128B + __builtin_HEXAGON_V6_vgtub_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuh.128B + __builtin_HEXAGON_V6_vgtuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuh.and.128B + __builtin_HEXAGON_V6_vgtuh_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuh.or.128B + __builtin_HEXAGON_V6_vgtuh_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuh.xor.128B + __builtin_HEXAGON_V6_vgtuh_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuw.128B + __builtin_HEXAGON_V6_vgtuw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuw.and.128B + __builtin_HEXAGON_V6_vgtuw_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuw.or.128B + __builtin_HEXAGON_V6_vgtuw_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtuw.xor.128B + __builtin_HEXAGON_V6_vgtuw_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtw.128B + __builtin_HEXAGON_V6_vgtw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vgtw.and.128B + __builtin_HEXAGON_V6_vgtw_and_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtw.or.128B + __builtin_HEXAGON_V6_vgtw_or_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vgtw.xor.128B + __builtin_HEXAGON_V6_vgtw_xor_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vinsertwr.128B + __builtin_HEXAGON_V6_vinsertwr_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vlalignb.128B + __builtin_HEXAGON_V6_vlalignb_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlalignbi.128B + __builtin_HEXAGON_V6_vlalignbi_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlsrb.128B + __builtin_HEXAGON_V6_vlsrb_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vlsrh.128B + __builtin_HEXAGON_V6_vlsrh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vlsrhv.128B + __builtin_HEXAGON_V6_vlsrhv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vlsrw.128B + __builtin_HEXAGON_V6_vlsrw_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vlsrwv.128B + __builtin_HEXAGON_V6_vlsrwv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vlut4.128B + __builtin_HEXAGON_V6_vlut4_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.128B + __builtin_HEXAGON_V6_vlutvvb_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.nm.128B + __builtin_HEXAGON_V6_vlutvvb_nm_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.oracc.128B + __builtin_HEXAGON_V6_vlutvvb_oracc_128B(v128, v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.oracci.128B + __builtin_HEXAGON_V6_vlutvvb_oracci_128B(v128, v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvvbi.128B + __builtin_HEXAGON_V6_vlutvvbi_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.128B + __builtin_HEXAGON_V6_vlutvwh_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.nm.128B + __builtin_HEXAGON_V6_vlutvwh_nm_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.oracc.128B + __builtin_HEXAGON_V6_vlutvwh_oracc_128B(v256, v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.oracci.128B + __builtin_HEXAGON_V6_vlutvwh_oracci_128B(v256, v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vlutvwhi.128B + __builtin_HEXAGON_V6_vlutvwhi_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmaskedstorenq.128B + __builtin_HEXAGON_V6_vmaskedstorenq_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vmaskedstorentnq.128B + __builtin_HEXAGON_V6_vmaskedstorentnq_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vmaskedstorentq.128B + __builtin_HEXAGON_V6_vmaskedstorentq_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vmaskedstoreq.128B + __builtin_HEXAGON_V6_vmaskedstoreq_128B(v128, 0, v128); + // CHECK: @llvm.hexagon.V6.vmaxb.128B + __builtin_HEXAGON_V6_vmaxb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmaxh.128B + __builtin_HEXAGON_V6_vmaxh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmaxub.128B + __builtin_HEXAGON_V6_vmaxub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmaxuh.128B + __builtin_HEXAGON_V6_vmaxuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmaxw.128B + __builtin_HEXAGON_V6_vmaxw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vminb.128B + __builtin_HEXAGON_V6_vminb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vminh.128B + __builtin_HEXAGON_V6_vminh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vminub.128B + __builtin_HEXAGON_V6_vminub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vminuh.128B + __builtin_HEXAGON_V6_vminuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vminw.128B + __builtin_HEXAGON_V6_vminw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpabus.128B + __builtin_HEXAGON_V6_vmpabus_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vmpabus.acc.128B + __builtin_HEXAGON_V6_vmpabus_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vmpabusv.128B + __builtin_HEXAGON_V6_vmpabusv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vmpabuu.128B + __builtin_HEXAGON_V6_vmpabuu_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vmpabuu.acc.128B + __builtin_HEXAGON_V6_vmpabuu_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vmpabuuv.128B + __builtin_HEXAGON_V6_vmpabuuv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vmpahb.128B + __builtin_HEXAGON_V6_vmpahb_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vmpahb.acc.128B + __builtin_HEXAGON_V6_vmpahb_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vmpahhsat.128B + __builtin_HEXAGON_V6_vmpahhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpauhb.128B + __builtin_HEXAGON_V6_vmpauhb_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vmpauhb.acc.128B + __builtin_HEXAGON_V6_vmpauhb_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vmpauhuhsat.128B + __builtin_HEXAGON_V6_vmpauhuhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpsuhuhsat.128B + __builtin_HEXAGON_V6_vmpsuhuhsat_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpybus.128B + __builtin_HEXAGON_V6_vmpybus_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpybus.acc.128B + __builtin_HEXAGON_V6_vmpybus_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpybusv.128B + __builtin_HEXAGON_V6_vmpybusv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpybusv.acc.128B + __builtin_HEXAGON_V6_vmpybusv_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpybv.128B + __builtin_HEXAGON_V6_vmpybv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpybv.acc.128B + __builtin_HEXAGON_V6_vmpybv_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyewuh.128B + __builtin_HEXAGON_V6_vmpyewuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyewuh.64.128B + __builtin_HEXAGON_V6_vmpyewuh_64_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyh.128B + __builtin_HEXAGON_V6_vmpyh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyh.acc.128B + __builtin_HEXAGON_V6_vmpyh_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyhsat.acc.128B + __builtin_HEXAGON_V6_vmpyhsat_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyhsrs.128B + __builtin_HEXAGON_V6_vmpyhsrs_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyhss.128B + __builtin_HEXAGON_V6_vmpyhss_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyhus.128B + __builtin_HEXAGON_V6_vmpyhus_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyhus.acc.128B + __builtin_HEXAGON_V6_vmpyhus_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyhv.128B + __builtin_HEXAGON_V6_vmpyhv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyhv.acc.128B + __builtin_HEXAGON_V6_vmpyhv_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyhvsrs.128B + __builtin_HEXAGON_V6_vmpyhvsrs_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyieoh.128B + __builtin_HEXAGON_V6_vmpyieoh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyiewh.acc.128B + __builtin_HEXAGON_V6_vmpyiewh_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyiewuh.128B + __builtin_HEXAGON_V6_vmpyiewuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc.128B + __builtin_HEXAGON_V6_vmpyiewuh_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyih.128B + __builtin_HEXAGON_V6_vmpyih_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyih.acc.128B + __builtin_HEXAGON_V6_vmpyih_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyihb.128B + __builtin_HEXAGON_V6_vmpyihb_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyihb.acc.128B + __builtin_HEXAGON_V6_vmpyihb_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiowh.128B + __builtin_HEXAGON_V6_vmpyiowh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyiwb.128B + __builtin_HEXAGON_V6_vmpyiwb_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwb.acc.128B + __builtin_HEXAGON_V6_vmpyiwb_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwh.128B + __builtin_HEXAGON_V6_vmpyiwh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwh.acc.128B + __builtin_HEXAGON_V6_vmpyiwh_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwub.128B + __builtin_HEXAGON_V6_vmpyiwub_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwub.acc.128B + __builtin_HEXAGON_V6_vmpyiwub_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyowh.128B + __builtin_HEXAGON_V6_vmpyowh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc.128B + __builtin_HEXAGON_V6_vmpyowh_64_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.128B + __builtin_HEXAGON_V6_vmpyowh_rnd_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc.128B + __builtin_HEXAGON_V6_vmpyowh_rnd_sacc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyowh.sacc.128B + __builtin_HEXAGON_V6_vmpyowh_sacc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyub.128B + __builtin_HEXAGON_V6_vmpyub_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyub.acc.128B + __builtin_HEXAGON_V6_vmpyub_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyubv.128B + __builtin_HEXAGON_V6_vmpyubv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyubv.acc.128B + __builtin_HEXAGON_V6_vmpyubv_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyuh.128B + __builtin_HEXAGON_V6_vmpyuh_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyuh.acc.128B + __builtin_HEXAGON_V6_vmpyuh_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhe.128B + __builtin_HEXAGON_V6_vmpyuhe_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhe.acc.128B + __builtin_HEXAGON_V6_vmpyuhe_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhv.128B + __builtin_HEXAGON_V6_vmpyuhv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpyuhv.acc.128B + __builtin_HEXAGON_V6_vmpyuhv_acc_128B(v256, v128, v128); + // CHECK: @llvm.hexagon.V6.vmux.128B + __builtin_HEXAGON_V6_vmux_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vnavgb.128B + __builtin_HEXAGON_V6_vnavgb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vnavgh.128B + __builtin_HEXAGON_V6_vnavgh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vnavgub.128B + __builtin_HEXAGON_V6_vnavgub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vnavgw.128B + __builtin_HEXAGON_V6_vnavgw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vnormamth.128B + __builtin_HEXAGON_V6_vnormamth_128B(v128); + // CHECK: @llvm.hexagon.V6.vnormamtw.128B + __builtin_HEXAGON_V6_vnormamtw_128B(v128); + // CHECK: @llvm.hexagon.V6.vnot.128B + __builtin_HEXAGON_V6_vnot_128B(v128); + // CHECK: @llvm.hexagon.V6.vor.128B + __builtin_HEXAGON_V6_vor_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackeb.128B + __builtin_HEXAGON_V6_vpackeb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackeh.128B + __builtin_HEXAGON_V6_vpackeh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackhb.sat.128B + __builtin_HEXAGON_V6_vpackhb_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackhub.sat.128B + __builtin_HEXAGON_V6_vpackhub_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackob.128B + __builtin_HEXAGON_V6_vpackob_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackoh.128B + __builtin_HEXAGON_V6_vpackoh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackwh.sat.128B + __builtin_HEXAGON_V6_vpackwh_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpackwuh.sat.128B + __builtin_HEXAGON_V6_vpackwuh_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vpopcounth.128B + __builtin_HEXAGON_V6_vpopcounth_128B(v128); + // CHECK: @llvm.hexagon.V6.vprefixqb.128B + __builtin_HEXAGON_V6_vprefixqb_128B(v128); + // CHECK: @llvm.hexagon.V6.vprefixqh.128B + __builtin_HEXAGON_V6_vprefixqh_128B(v128); + // CHECK: @llvm.hexagon.V6.vprefixqw.128B + __builtin_HEXAGON_V6_vprefixqw_128B(v128); + // CHECK: @llvm.hexagon.V6.vrdelta.128B + __builtin_HEXAGON_V6_vrdelta_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.128B + __builtin_HEXAGON_V6_vrmpybub_rtt_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc.128B + __builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpybus.128B + __builtin_HEXAGON_V6_vrmpybus_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpybus.acc.128B + __builtin_HEXAGON_V6_vrmpybus_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusi.128B + __builtin_HEXAGON_V6_vrmpybusi_128B(v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusi.acc.128B + __builtin_HEXAGON_V6_vrmpybusi_acc_128B(v256, v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusv.128B + __builtin_HEXAGON_V6_vrmpybusv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpybusv.acc.128B + __builtin_HEXAGON_V6_vrmpybusv_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpybv.128B + __builtin_HEXAGON_V6_vrmpybv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpybv.acc.128B + __builtin_HEXAGON_V6_vrmpybv_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpyub.128B + __builtin_HEXAGON_V6_vrmpyub_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.acc.128B + __builtin_HEXAGON_V6_vrmpyub_acc_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.128B + __builtin_HEXAGON_V6_vrmpyub_rtt_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc.128B + __builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B(v256, v128, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubi.128B + __builtin_HEXAGON_V6_vrmpyubi_128B(v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubi.acc.128B + __builtin_HEXAGON_V6_vrmpyubi_acc_128B(v256, v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubv.128B + __builtin_HEXAGON_V6_vrmpyubv_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrmpyubv.acc.128B + __builtin_HEXAGON_V6_vrmpyubv_acc_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vror.128B + __builtin_HEXAGON_V6_vror_128B(v128, 0); + // CHECK: @llvm.hexagon.V6.vroundhb.128B + __builtin_HEXAGON_V6_vroundhb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vroundhub.128B + __builtin_HEXAGON_V6_vroundhub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrounduhub.128B + __builtin_HEXAGON_V6_vrounduhub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrounduwuh.128B + __builtin_HEXAGON_V6_vrounduwuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vroundwh.128B + __builtin_HEXAGON_V6_vroundwh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vroundwuh.128B + __builtin_HEXAGON_V6_vroundwuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vrsadubi.128B + __builtin_HEXAGON_V6_vrsadubi_128B(v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vrsadubi.acc.128B + __builtin_HEXAGON_V6_vrsadubi_acc_128B(v256, v256, 0, 0); + // CHECK: @llvm.hexagon.V6.vsathub.128B + __builtin_HEXAGON_V6_vsathub_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsatuwuh.128B + __builtin_HEXAGON_V6_vsatuwuh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsatwh.128B + __builtin_HEXAGON_V6_vsatwh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsb.128B + __builtin_HEXAGON_V6_vsb_128B(v128); + // CHECK: @llvm.hexagon.V6.vscattermh.128B + __builtin_HEXAGON_V6_vscattermh_128B(0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vscattermh.add.128B + __builtin_HEXAGON_V6_vscattermh_add_128B(0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vscattermhq.128B + __builtin_HEXAGON_V6_vscattermhq_128B(v128, 0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vscattermhw.128B + __builtin_HEXAGON_V6_vscattermhw_128B(0, 0, v256, v128); + // CHECK: @llvm.hexagon.V6.vscattermhw.add.128B + __builtin_HEXAGON_V6_vscattermhw_add_128B(0, 0, v256, v128); + // CHECK: @llvm.hexagon.V6.vscattermhwq.128B + __builtin_HEXAGON_V6_vscattermhwq_128B(v128, 0, 0, v256, v128); + // CHECK: @llvm.hexagon.V6.vscattermw.128B + __builtin_HEXAGON_V6_vscattermw_128B(0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vscattermw.add.128B + __builtin_HEXAGON_V6_vscattermw_add_128B(0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vscattermwq.128B + __builtin_HEXAGON_V6_vscattermwq_128B(v128, 0, 0, v128, v128); + // CHECK: @llvm.hexagon.V6.vsh.128B + __builtin_HEXAGON_V6_vsh_128B(v128); + // CHECK: @llvm.hexagon.V6.vshufeh.128B + __builtin_HEXAGON_V6_vshufeh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vshuffb.128B + __builtin_HEXAGON_V6_vshuffb_128B(v128); + // CHECK: @llvm.hexagon.V6.vshuffeb.128B + __builtin_HEXAGON_V6_vshuffeb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vshuffh.128B + __builtin_HEXAGON_V6_vshuffh_128B(v128); + // CHECK: @llvm.hexagon.V6.vshuffob.128B + __builtin_HEXAGON_V6_vshuffob_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vshuffvdd.128B + __builtin_HEXAGON_V6_vshuffvdd_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vshufoeb.128B + __builtin_HEXAGON_V6_vshufoeb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vshufoeh.128B + __builtin_HEXAGON_V6_vshufoeh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vshufoh.128B + __builtin_HEXAGON_V6_vshufoh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubb.128B + __builtin_HEXAGON_V6_vsubb_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubb.dv.128B + __builtin_HEXAGON_V6_vsubb_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubbnq.128B + __builtin_HEXAGON_V6_vsubbnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubbq.128B + __builtin_HEXAGON_V6_vsubbq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubbsat.128B + __builtin_HEXAGON_V6_vsubbsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubbsat.dv.128B + __builtin_HEXAGON_V6_vsubbsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubcarry.128B + __builtin_HEXAGON_V6_vsubcarry_128B(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vsubh.128B + __builtin_HEXAGON_V6_vsubh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubh.dv.128B + __builtin_HEXAGON_V6_vsubh_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubhnq.128B + __builtin_HEXAGON_V6_vsubhnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubhq.128B + __builtin_HEXAGON_V6_vsubhq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubhsat.128B + __builtin_HEXAGON_V6_vsubhsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubhsat.dv.128B + __builtin_HEXAGON_V6_vsubhsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubhw.128B + __builtin_HEXAGON_V6_vsubhw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsububh.128B + __builtin_HEXAGON_V6_vsububh_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsububsat.128B + __builtin_HEXAGON_V6_vsububsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsububsat.dv.128B + __builtin_HEXAGON_V6_vsububsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubububb.sat.128B + __builtin_HEXAGON_V6_vsubububb_sat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubuhsat.128B + __builtin_HEXAGON_V6_vsubuhsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubuhsat.dv.128B + __builtin_HEXAGON_V6_vsubuhsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubuhw.128B + __builtin_HEXAGON_V6_vsubuhw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubuwsat.128B + __builtin_HEXAGON_V6_vsubuwsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubuwsat.dv.128B + __builtin_HEXAGON_V6_vsubuwsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubw.128B + __builtin_HEXAGON_V6_vsubw_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubw.dv.128B + __builtin_HEXAGON_V6_vsubw_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vsubwnq.128B + __builtin_HEXAGON_V6_vsubwnq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubwq.128B + __builtin_HEXAGON_V6_vsubwq_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vsubwsat.128B + __builtin_HEXAGON_V6_vsubwsat_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubwsat.dv.128B + __builtin_HEXAGON_V6_vsubwsat_dv_128B(v256, v256); + // CHECK: @llvm.hexagon.V6.vswap.128B + __builtin_HEXAGON_V6_vswap_128B(v128, v128, v128); + // CHECK: @llvm.hexagon.V6.vtmpyb.128B + __builtin_HEXAGON_V6_vtmpyb_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vtmpyb.acc.128B + __builtin_HEXAGON_V6_vtmpyb_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vtmpybus.128B + __builtin_HEXAGON_V6_vtmpybus_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vtmpybus.acc.128B + __builtin_HEXAGON_V6_vtmpybus_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vtmpyhb.128B + __builtin_HEXAGON_V6_vtmpyhb_128B(v256, 0); + // CHECK: @llvm.hexagon.V6.vtmpyhb.acc.128B + __builtin_HEXAGON_V6_vtmpyhb_acc_128B(v256, v256, 0); + // CHECK: @llvm.hexagon.V6.vunpackb.128B + __builtin_HEXAGON_V6_vunpackb_128B(v128); + // CHECK: @llvm.hexagon.V6.vunpackh.128B + __builtin_HEXAGON_V6_vunpackh_128B(v128); + // CHECK: @llvm.hexagon.V6.vunpackob.128B + __builtin_HEXAGON_V6_vunpackob_128B(v256, v128); + // CHECK: @llvm.hexagon.V6.vunpackoh.128B + __builtin_HEXAGON_V6_vunpackoh_128B(v256, v128); + // CHECK: @llvm.hexagon.V6.vunpackub.128B + __builtin_HEXAGON_V6_vunpackub_128B(v128); + // CHECK: @llvm.hexagon.V6.vunpackuh.128B + __builtin_HEXAGON_V6_vunpackuh_128B(v128); + // CHECK: @llvm.hexagon.V6.vxor.128B + __builtin_HEXAGON_V6_vxor_128B(v128, v128); + // CHECK: @llvm.hexagon.V6.vzb.128B + __builtin_HEXAGON_V6_vzb_128B(v128); + // CHECK: @llvm.hexagon.V6.vzh.128B + __builtin_HEXAGON_V6_vzh_128B(v128); +} diff --git a/test/CodeGen/builtins-hvx64.c b/test/CodeGen/builtins-hvx64.c new file mode 100644 index 0000000000..5f0d301040 --- /dev/null +++ b/test/CodeGen/builtins-hvx64.c @@ -0,0 +1,802 @@ +// REQUIRES: hexagon-registered-target +// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length64 -emit-llvm %s -o - | FileCheck %s + +void test() { + int v64 __attribute__((__vector_size__(64))); + int v128 __attribute__((__vector_size__(128))); + + // CHECK: @llvm.hexagon.V6.extractw + __builtin_HEXAGON_V6_extractw(v64, 0); + // CHECK: @llvm.hexagon.V6.hi + __builtin_HEXAGON_V6_hi(v128); + // CHECK: @llvm.hexagon.V6.lo + __builtin_HEXAGON_V6_lo(v128); + // CHECK: @llvm.hexagon.V6.lvsplatb + __builtin_HEXAGON_V6_lvsplatb(0); + // CHECK: @llvm.hexagon.V6.lvsplath + __builtin_HEXAGON_V6_lvsplath(0); + // CHECK: @llvm.hexagon.V6.lvsplatw + __builtin_HEXAGON_V6_lvsplatw(0); + // CHECK: @llvm.hexagon.V6.pred.and + __builtin_HEXAGON_V6_pred_and(v64, v64); + // CHECK: @llvm.hexagon.V6.pred.and.n + __builtin_HEXAGON_V6_pred_and_n(v64, v64); + // CHECK: @llvm.hexagon.V6.pred.not + __builtin_HEXAGON_V6_pred_not(v64); + // CHECK: @llvm.hexagon.V6.pred.or + __builtin_HEXAGON_V6_pred_or(v64, v64); + // CHECK: @llvm.hexagon.V6.pred.or.n + __builtin_HEXAGON_V6_pred_or_n(v64, v64); + // CHECK: @llvm.hexagon.V6.pred.scalar2 + __builtin_HEXAGON_V6_pred_scalar2(0); + // CHECK: @llvm.hexagon.V6.pred.scalar2v2 + __builtin_HEXAGON_V6_pred_scalar2v2(0); + // CHECK: @llvm.hexagon.V6.pred.xor + __builtin_HEXAGON_V6_pred_xor(v64, v64); + // CHECK: @llvm.hexagon.V6.shuffeqh + __builtin_HEXAGON_V6_shuffeqh(v64, v64); + // CHECK: @llvm.hexagon.V6.shuffeqw + __builtin_HEXAGON_V6_shuffeqw(v64, v64); + // CHECK: @llvm.hexagon.V6.vS32b.nqpred.ai + __builtin_HEXAGON_V6_vS32b_nqpred_ai(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vS32b.nt.nqpred.ai + __builtin_HEXAGON_V6_vS32b_nt_nqpred_ai(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vS32b.nt.qpred.ai + __builtin_HEXAGON_V6_vS32b_nt_qpred_ai(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vS32b.qpred.ai + __builtin_HEXAGON_V6_vS32b_qpred_ai(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vabsb + __builtin_HEXAGON_V6_vabsb(v64); + // CHECK: @llvm.hexagon.V6.vabsb.sat + __builtin_HEXAGON_V6_vabsb_sat(v64); + // CHECK: @llvm.hexagon.V6.vabsdiffh + __builtin_HEXAGON_V6_vabsdiffh(v64, v64); + // CHECK: @llvm.hexagon.V6.vabsdiffub + __builtin_HEXAGON_V6_vabsdiffub(v64, v64); + // CHECK: @llvm.hexagon.V6.vabsdiffuh + __builtin_HEXAGON_V6_vabsdiffuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vabsdiffw + __builtin_HEXAGON_V6_vabsdiffw(v64, v64); + // CHECK: @llvm.hexagon.V6.vabsh + __builtin_HEXAGON_V6_vabsh(v64); + // CHECK: @llvm.hexagon.V6.vabsh.sat + __builtin_HEXAGON_V6_vabsh_sat(v64); + // CHECK: @llvm.hexagon.V6.vabsw + __builtin_HEXAGON_V6_vabsw(v64); + // CHECK: @llvm.hexagon.V6.vabsw.sat + __builtin_HEXAGON_V6_vabsw_sat(v64); + // CHECK: @llvm.hexagon.V6.vaddb + __builtin_HEXAGON_V6_vaddb(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddb.dv + __builtin_HEXAGON_V6_vaddb_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddbnq + __builtin_HEXAGON_V6_vaddbnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddbq + __builtin_HEXAGON_V6_vaddbq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddbsat + __builtin_HEXAGON_V6_vaddbsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddbsat.dv + __builtin_HEXAGON_V6_vaddbsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddcarry + __builtin_HEXAGON_V6_vaddcarry(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vaddclbh + __builtin_HEXAGON_V6_vaddclbh(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddclbw + __builtin_HEXAGON_V6_vaddclbw(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddh + __builtin_HEXAGON_V6_vaddh(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddh.dv + __builtin_HEXAGON_V6_vaddh_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhnq + __builtin_HEXAGON_V6_vaddhnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddhq + __builtin_HEXAGON_V6_vaddhq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddhsat + __builtin_HEXAGON_V6_vaddhsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddhsat.dv + __builtin_HEXAGON_V6_vaddhsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddhw + __builtin_HEXAGON_V6_vaddhw(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddhw.acc + __builtin_HEXAGON_V6_vaddhw_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddubh + __builtin_HEXAGON_V6_vaddubh(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddubh.acc + __builtin_HEXAGON_V6_vaddubh_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddubsat + __builtin_HEXAGON_V6_vaddubsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddubsat.dv + __builtin_HEXAGON_V6_vaddubsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddububb.sat + __builtin_HEXAGON_V6_vaddububb_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vadduhsat + __builtin_HEXAGON_V6_vadduhsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vadduhsat.dv + __builtin_HEXAGON_V6_vadduhsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vadduhw + __builtin_HEXAGON_V6_vadduhw(v64, v64); + // CHECK: @llvm.hexagon.V6.vadduhw.acc + __builtin_HEXAGON_V6_vadduhw_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vadduwsat + __builtin_HEXAGON_V6_vadduwsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vadduwsat.dv + __builtin_HEXAGON_V6_vadduwsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddw + __builtin_HEXAGON_V6_vaddw(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddw.dv + __builtin_HEXAGON_V6_vaddw_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vaddwnq + __builtin_HEXAGON_V6_vaddwnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddwq + __builtin_HEXAGON_V6_vaddwq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vaddwsat + __builtin_HEXAGON_V6_vaddwsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vaddwsat.dv + __builtin_HEXAGON_V6_vaddwsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.valignb + __builtin_HEXAGON_V6_valignb(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.valignbi + __builtin_HEXAGON_V6_valignbi(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vand + __builtin_HEXAGON_V6_vand(v64, v64); + // CHECK: @llvm.hexagon.V6.vandnqrt + __builtin_HEXAGON_V6_vandnqrt(v64, 0); + // CHECK: @llvm.hexagon.V6.vandnqrt.acc + __builtin_HEXAGON_V6_vandnqrt_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vandqrt + __builtin_HEXAGON_V6_vandqrt(v64, 0); + // CHECK: @llvm.hexagon.V6.vandqrt.acc + __builtin_HEXAGON_V6_vandqrt_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vandvnqv + __builtin_HEXAGON_V6_vandvnqv(v64, v64); + // CHECK: @llvm.hexagon.V6.vandvqv + __builtin_HEXAGON_V6_vandvqv(v64, v64); + // CHECK: @llvm.hexagon.V6.vandvrt + __builtin_HEXAGON_V6_vandvrt(v64, 0); + // CHECK: @llvm.hexagon.V6.vandvrt.acc + __builtin_HEXAGON_V6_vandvrt_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vaslh + __builtin_HEXAGON_V6_vaslh(v64, 0); + // CHECK: @llvm.hexagon.V6.vaslh.acc + __builtin_HEXAGON_V6_vaslh_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vaslhv + __builtin_HEXAGON_V6_vaslhv(v64, v64); + // CHECK: @llvm.hexagon.V6.vaslw + __builtin_HEXAGON_V6_vaslw(v64, 0); + // CHECK: @llvm.hexagon.V6.vaslw.acc + __builtin_HEXAGON_V6_vaslw_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vaslwv + __builtin_HEXAGON_V6_vaslwv(v64, v64); + // CHECK: @llvm.hexagon.V6.vasrh + __builtin_HEXAGON_V6_vasrh(v64, 0); + // CHECK: @llvm.hexagon.V6.vasrh.acc + __builtin_HEXAGON_V6_vasrh_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrhbrndsat + __builtin_HEXAGON_V6_vasrhbrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrhbsat + __builtin_HEXAGON_V6_vasrhbsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrhubrndsat + __builtin_HEXAGON_V6_vasrhubrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrhubsat + __builtin_HEXAGON_V6_vasrhubsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrhv + __builtin_HEXAGON_V6_vasrhv(v64, v64); + // CHECK: @llvm.hexagon.V6.vasruhubrndsat + __builtin_HEXAGON_V6_vasruhubrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasruhubsat + __builtin_HEXAGON_V6_vasruhubsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasruwuhrndsat + __builtin_HEXAGON_V6_vasruwuhrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasruwuhsat + __builtin_HEXAGON_V6_vasruwuhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrw + __builtin_HEXAGON_V6_vasrw(v64, 0); + // CHECK: @llvm.hexagon.V6.vasrw.acc + __builtin_HEXAGON_V6_vasrw_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwh + __builtin_HEXAGON_V6_vasrwh(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwhrndsat + __builtin_HEXAGON_V6_vasrwhrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwhsat + __builtin_HEXAGON_V6_vasrwhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwuhrndsat + __builtin_HEXAGON_V6_vasrwuhrndsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwuhsat + __builtin_HEXAGON_V6_vasrwuhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vasrwv + __builtin_HEXAGON_V6_vasrwv(v64, v64); + // CHECK: @llvm.hexagon.V6.vassign + __builtin_HEXAGON_V6_vassign(v64); + // CHECK: @llvm.hexagon.V6.vassignp + __builtin_HEXAGON_V6_vassignp(v128); + // CHECK: @llvm.hexagon.V6.vavgb + __builtin_HEXAGON_V6_vavgb(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgbrnd + __builtin_HEXAGON_V6_vavgbrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgh + __builtin_HEXAGON_V6_vavgh(v64, v64); + // CHECK: @llvm.hexagon.V6.vavghrnd + __builtin_HEXAGON_V6_vavghrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgub + __builtin_HEXAGON_V6_vavgub(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgubrnd + __builtin_HEXAGON_V6_vavgubrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vavguh + __builtin_HEXAGON_V6_vavguh(v64, v64); + // CHECK: @llvm.hexagon.V6.vavguhrnd + __builtin_HEXAGON_V6_vavguhrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vavguw + __builtin_HEXAGON_V6_vavguw(v64, v64); + // CHECK: @llvm.hexagon.V6.vavguwrnd + __builtin_HEXAGON_V6_vavguwrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgw + __builtin_HEXAGON_V6_vavgw(v64, v64); + // CHECK: @llvm.hexagon.V6.vavgwrnd + __builtin_HEXAGON_V6_vavgwrnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vcl0h + __builtin_HEXAGON_V6_vcl0h(v64); + // CHECK: @llvm.hexagon.V6.vcl0w + __builtin_HEXAGON_V6_vcl0w(v64); + // CHECK: @llvm.hexagon.V6.vcombine + __builtin_HEXAGON_V6_vcombine(v64, v64); + // CHECK: @llvm.hexagon.V6.vd0 + __builtin_HEXAGON_V6_vd0(); + // CHECK: @llvm.hexagon.V6.vdd0 + __builtin_HEXAGON_V6_vdd0(); + // CHECK: @llvm.hexagon.V6.vdealb + __builtin_HEXAGON_V6_vdealb(v64); + // CHECK: @llvm.hexagon.V6.vdealb4w + __builtin_HEXAGON_V6_vdealb4w(v64, v64); + // CHECK: @llvm.hexagon.V6.vdealh + __builtin_HEXAGON_V6_vdealh(v64); + // CHECK: @llvm.hexagon.V6.vdealvdd + __builtin_HEXAGON_V6_vdealvdd(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vdelta + __builtin_HEXAGON_V6_vdelta(v64, v64); + // CHECK: @llvm.hexagon.V6.vdmpybus + __builtin_HEXAGON_V6_vdmpybus(v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.acc + __builtin_HEXAGON_V6_vdmpybus_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.dv + __builtin_HEXAGON_V6_vdmpybus_dv(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpybus.dv.acc + __builtin_HEXAGON_V6_vdmpybus_dv_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb + __builtin_HEXAGON_V6_vdmpyhb(v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.acc + __builtin_HEXAGON_V6_vdmpyhb_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.dv + __builtin_HEXAGON_V6_vdmpyhb_dv(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhb.dv.acc + __builtin_HEXAGON_V6_vdmpyhb_dv_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhisat + __builtin_HEXAGON_V6_vdmpyhisat(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhisat.acc + __builtin_HEXAGON_V6_vdmpyhisat_acc(v64, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsat + __builtin_HEXAGON_V6_vdmpyhsat(v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsat.acc + __builtin_HEXAGON_V6_vdmpyhsat_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsuisat + __builtin_HEXAGON_V6_vdmpyhsuisat(v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsuisat.acc + __builtin_HEXAGON_V6_vdmpyhsuisat_acc(v64, v128, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsusat + __builtin_HEXAGON_V6_vdmpyhsusat(v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhsusat.acc + __builtin_HEXAGON_V6_vdmpyhsusat_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vdmpyhvsat + __builtin_HEXAGON_V6_vdmpyhvsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vdmpyhvsat.acc + __builtin_HEXAGON_V6_vdmpyhvsat_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vdsaduh + __builtin_HEXAGON_V6_vdsaduh(v128, 0); + // CHECK: @llvm.hexagon.V6.vdsaduh.acc + __builtin_HEXAGON_V6_vdsaduh_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.veqb + __builtin_HEXAGON_V6_veqb(v64, v64); + // CHECK: @llvm.hexagon.V6.veqb.and + __builtin_HEXAGON_V6_veqb_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqb.or + __builtin_HEXAGON_V6_veqb_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqb.xor + __builtin_HEXAGON_V6_veqb_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqh + __builtin_HEXAGON_V6_veqh(v64, v64); + // CHECK: @llvm.hexagon.V6.veqh.and + __builtin_HEXAGON_V6_veqh_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqh.or + __builtin_HEXAGON_V6_veqh_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqh.xor + __builtin_HEXAGON_V6_veqh_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqw + __builtin_HEXAGON_V6_veqw(v64, v64); + // CHECK: @llvm.hexagon.V6.veqw.and + __builtin_HEXAGON_V6_veqw_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqw.or + __builtin_HEXAGON_V6_veqw_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.veqw.xor + __builtin_HEXAGON_V6_veqw_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgathermh + __builtin_HEXAGON_V6_vgathermh(0, 0, 0, v64); + // CHECK: @llvm.hexagon.V6.vgathermhq + __builtin_HEXAGON_V6_vgathermhq(0, v64, 0, 0, v64); + // CHECK: @llvm.hexagon.V6.vgathermhw + __builtin_HEXAGON_V6_vgathermhw(0, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgathermhwq + __builtin_HEXAGON_V6_vgathermhwq(0, v64, 0, 0, v128); + // CHECK: @llvm.hexagon.V6.vgathermw + __builtin_HEXAGON_V6_vgathermw(0, 0, 0, v64); + // CHECK: @llvm.hexagon.V6.vgathermwq + __builtin_HEXAGON_V6_vgathermwq(0, v64, 0, 0, v64); + // CHECK: @llvm.hexagon.V6.vgtb + __builtin_HEXAGON_V6_vgtb(v64, v64); + // CHECK: @llvm.hexagon.V6.vgtb.and + __builtin_HEXAGON_V6_vgtb_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtb.or + __builtin_HEXAGON_V6_vgtb_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtb.xor + __builtin_HEXAGON_V6_vgtb_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgth + __builtin_HEXAGON_V6_vgth(v64, v64); + // CHECK: @llvm.hexagon.V6.vgth.and + __builtin_HEXAGON_V6_vgth_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgth.or + __builtin_HEXAGON_V6_vgth_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgth.xor + __builtin_HEXAGON_V6_vgth_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtub + __builtin_HEXAGON_V6_vgtub(v64, v64); + // CHECK: @llvm.hexagon.V6.vgtub.and + __builtin_HEXAGON_V6_vgtub_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtub.or + __builtin_HEXAGON_V6_vgtub_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtub.xor + __builtin_HEXAGON_V6_vgtub_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuh + __builtin_HEXAGON_V6_vgtuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuh.and + __builtin_HEXAGON_V6_vgtuh_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuh.or + __builtin_HEXAGON_V6_vgtuh_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuh.xor + __builtin_HEXAGON_V6_vgtuh_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuw + __builtin_HEXAGON_V6_vgtuw(v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuw.and + __builtin_HEXAGON_V6_vgtuw_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuw.or + __builtin_HEXAGON_V6_vgtuw_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtuw.xor + __builtin_HEXAGON_V6_vgtuw_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtw + __builtin_HEXAGON_V6_vgtw(v64, v64); + // CHECK: @llvm.hexagon.V6.vgtw.and + __builtin_HEXAGON_V6_vgtw_and(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtw.or + __builtin_HEXAGON_V6_vgtw_or(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vgtw.xor + __builtin_HEXAGON_V6_vgtw_xor(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vinsertwr + __builtin_HEXAGON_V6_vinsertwr(v64, 0); + // CHECK: @llvm.hexagon.V6.vlalignb + __builtin_HEXAGON_V6_vlalignb(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlalignbi + __builtin_HEXAGON_V6_vlalignbi(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlsrb + __builtin_HEXAGON_V6_vlsrb(v64, 0); + // CHECK: @llvm.hexagon.V6.vlsrh + __builtin_HEXAGON_V6_vlsrh(v64, 0); + // CHECK: @llvm.hexagon.V6.vlsrhv + __builtin_HEXAGON_V6_vlsrhv(v64, v64); + // CHECK: @llvm.hexagon.V6.vlsrw + __builtin_HEXAGON_V6_vlsrw(v64, 0); + // CHECK: @llvm.hexagon.V6.vlsrwv + __builtin_HEXAGON_V6_vlsrwv(v64, v64); + // CHECK: @llvm.hexagon.V6.vlut4 + __builtin_HEXAGON_V6_vlut4(v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb + __builtin_HEXAGON_V6_vlutvvb(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.nm + __builtin_HEXAGON_V6_vlutvvb_nm(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.oracc + __builtin_HEXAGON_V6_vlutvvb_oracc(v64, v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvvb.oracci + __builtin_HEXAGON_V6_vlutvvb_oracci(v64, v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvvbi + __builtin_HEXAGON_V6_vlutvvbi(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh + __builtin_HEXAGON_V6_vlutvwh(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.nm + __builtin_HEXAGON_V6_vlutvwh_nm(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.oracc + __builtin_HEXAGON_V6_vlutvwh_oracc(v128, v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvwh.oracci + __builtin_HEXAGON_V6_vlutvwh_oracci(v128, v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vlutvwhi + __builtin_HEXAGON_V6_vlutvwhi(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmaskedstorenq + __builtin_HEXAGON_V6_vmaskedstorenq(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vmaskedstorentnq + __builtin_HEXAGON_V6_vmaskedstorentnq(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vmaskedstorentq + __builtin_HEXAGON_V6_vmaskedstorentq(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vmaskedstoreq + __builtin_HEXAGON_V6_vmaskedstoreq(v64, 0, v64); + // CHECK: @llvm.hexagon.V6.vmaxb + __builtin_HEXAGON_V6_vmaxb(v64, v64); + // CHECK: @llvm.hexagon.V6.vmaxh + __builtin_HEXAGON_V6_vmaxh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmaxub + __builtin_HEXAGON_V6_vmaxub(v64, v64); + // CHECK: @llvm.hexagon.V6.vmaxuh + __builtin_HEXAGON_V6_vmaxuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmaxw + __builtin_HEXAGON_V6_vmaxw(v64, v64); + // CHECK: @llvm.hexagon.V6.vminb + __builtin_HEXAGON_V6_vminb(v64, v64); + // CHECK: @llvm.hexagon.V6.vminh + __builtin_HEXAGON_V6_vminh(v64, v64); + // CHECK: @llvm.hexagon.V6.vminub + __builtin_HEXAGON_V6_vminub(v64, v64); + // CHECK: @llvm.hexagon.V6.vminuh + __builtin_HEXAGON_V6_vminuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vminw + __builtin_HEXAGON_V6_vminw(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpabus + __builtin_HEXAGON_V6_vmpabus(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpabus.acc + __builtin_HEXAGON_V6_vmpabus_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpabusv + __builtin_HEXAGON_V6_vmpabusv(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpabuu + __builtin_HEXAGON_V6_vmpabuu(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpabuu.acc + __builtin_HEXAGON_V6_vmpabuu_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpabuuv + __builtin_HEXAGON_V6_vmpabuuv(v128, v128); + // CHECK: @llvm.hexagon.V6.vmpahb + __builtin_HEXAGON_V6_vmpahb(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpahb.acc + __builtin_HEXAGON_V6_vmpahb_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpahhsat + __builtin_HEXAGON_V6_vmpahhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpauhb + __builtin_HEXAGON_V6_vmpauhb(v128, 0); + // CHECK: @llvm.hexagon.V6.vmpauhb.acc + __builtin_HEXAGON_V6_vmpauhb_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vmpauhuhsat + __builtin_HEXAGON_V6_vmpauhuhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpsuhuhsat + __builtin_HEXAGON_V6_vmpsuhuhsat(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpybus + __builtin_HEXAGON_V6_vmpybus(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpybus.acc + __builtin_HEXAGON_V6_vmpybus_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpybusv + __builtin_HEXAGON_V6_vmpybusv(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpybusv.acc + __builtin_HEXAGON_V6_vmpybusv_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpybv + __builtin_HEXAGON_V6_vmpybv(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpybv.acc + __builtin_HEXAGON_V6_vmpybv_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyewuh + __builtin_HEXAGON_V6_vmpyewuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyewuh.64 + __builtin_HEXAGON_V6_vmpyewuh_64(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyh + __builtin_HEXAGON_V6_vmpyh(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyh.acc + __builtin_HEXAGON_V6_vmpyh_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyhsat.acc + __builtin_HEXAGON_V6_vmpyhsat_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyhsrs + __builtin_HEXAGON_V6_vmpyhsrs(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyhss + __builtin_HEXAGON_V6_vmpyhss(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyhus + __builtin_HEXAGON_V6_vmpyhus(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyhus.acc + __builtin_HEXAGON_V6_vmpyhus_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyhv + __builtin_HEXAGON_V6_vmpyhv(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyhv.acc + __builtin_HEXAGON_V6_vmpyhv_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyhvsrs + __builtin_HEXAGON_V6_vmpyhvsrs(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyieoh + __builtin_HEXAGON_V6_vmpyieoh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyiewh.acc + __builtin_HEXAGON_V6_vmpyiewh_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyiewuh + __builtin_HEXAGON_V6_vmpyiewuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyiewuh.acc + __builtin_HEXAGON_V6_vmpyiewuh_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyih + __builtin_HEXAGON_V6_vmpyih(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyih.acc + __builtin_HEXAGON_V6_vmpyih_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyihb + __builtin_HEXAGON_V6_vmpyihb(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyihb.acc + __builtin_HEXAGON_V6_vmpyihb_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiowh + __builtin_HEXAGON_V6_vmpyiowh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyiwb + __builtin_HEXAGON_V6_vmpyiwb(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwb.acc + __builtin_HEXAGON_V6_vmpyiwb_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwh + __builtin_HEXAGON_V6_vmpyiwh(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwh.acc + __builtin_HEXAGON_V6_vmpyiwh_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwub + __builtin_HEXAGON_V6_vmpyiwub(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyiwub.acc + __builtin_HEXAGON_V6_vmpyiwub_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyowh + __builtin_HEXAGON_V6_vmpyowh(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyowh.64.acc + __builtin_HEXAGON_V6_vmpyowh_64_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyowh.rnd + __builtin_HEXAGON_V6_vmpyowh_rnd(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyowh.rnd.sacc + __builtin_HEXAGON_V6_vmpyowh_rnd_sacc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyowh.sacc + __builtin_HEXAGON_V6_vmpyowh_sacc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyub + __builtin_HEXAGON_V6_vmpyub(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyub.acc + __builtin_HEXAGON_V6_vmpyub_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyubv + __builtin_HEXAGON_V6_vmpyubv(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyubv.acc + __builtin_HEXAGON_V6_vmpyubv_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyuh + __builtin_HEXAGON_V6_vmpyuh(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyuh.acc + __builtin_HEXAGON_V6_vmpyuh_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhe + __builtin_HEXAGON_V6_vmpyuhe(v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhe.acc + __builtin_HEXAGON_V6_vmpyuhe_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vmpyuhv + __builtin_HEXAGON_V6_vmpyuhv(v64, v64); + // CHECK: @llvm.hexagon.V6.vmpyuhv.acc + __builtin_HEXAGON_V6_vmpyuhv_acc(v128, v64, v64); + // CHECK: @llvm.hexagon.V6.vmux + __builtin_HEXAGON_V6_vmux(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vnavgb + __builtin_HEXAGON_V6_vnavgb(v64, v64); + // CHECK: @llvm.hexagon.V6.vnavgh + __builtin_HEXAGON_V6_vnavgh(v64, v64); + // CHECK: @llvm.hexagon.V6.vnavgub + __builtin_HEXAGON_V6_vnavgub(v64, v64); + // CHECK: @llvm.hexagon.V6.vnavgw + __builtin_HEXAGON_V6_vnavgw(v64, v64); + // CHECK: @llvm.hexagon.V6.vnormamth + __builtin_HEXAGON_V6_vnormamth(v64); + // CHECK: @llvm.hexagon.V6.vnormamtw + __builtin_HEXAGON_V6_vnormamtw(v64); + // CHECK: @llvm.hexagon.V6.vnot + __builtin_HEXAGON_V6_vnot(v64); + // CHECK: @llvm.hexagon.V6.vor + __builtin_HEXAGON_V6_vor(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackeb + __builtin_HEXAGON_V6_vpackeb(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackeh + __builtin_HEXAGON_V6_vpackeh(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackhb.sat + __builtin_HEXAGON_V6_vpackhb_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackhub.sat + __builtin_HEXAGON_V6_vpackhub_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackob + __builtin_HEXAGON_V6_vpackob(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackoh + __builtin_HEXAGON_V6_vpackoh(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackwh.sat + __builtin_HEXAGON_V6_vpackwh_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vpackwuh.sat + __builtin_HEXAGON_V6_vpackwuh_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vpopcounth + __builtin_HEXAGON_V6_vpopcounth(v64); + // CHECK: @llvm.hexagon.V6.vprefixqb + __builtin_HEXAGON_V6_vprefixqb(v64); + // CHECK: @llvm.hexagon.V6.vprefixqh + __builtin_HEXAGON_V6_vprefixqh(v64); + // CHECK: @llvm.hexagon.V6.vprefixqw + __builtin_HEXAGON_V6_vprefixqw(v64); + // CHECK: @llvm.hexagon.V6.vrdelta + __builtin_HEXAGON_V6_vrdelta(v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpybub.rtt + __builtin_HEXAGON_V6_vrmpybub_rtt(v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpybub.rtt.acc + __builtin_HEXAGON_V6_vrmpybub_rtt_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpybus + __builtin_HEXAGON_V6_vrmpybus(v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpybus.acc + __builtin_HEXAGON_V6_vrmpybus_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusi + __builtin_HEXAGON_V6_vrmpybusi(v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusi.acc + __builtin_HEXAGON_V6_vrmpybusi_acc(v128, v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpybusv + __builtin_HEXAGON_V6_vrmpybusv(v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpybusv.acc + __builtin_HEXAGON_V6_vrmpybusv_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpybv + __builtin_HEXAGON_V6_vrmpybv(v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpybv.acc + __builtin_HEXAGON_V6_vrmpybv_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpyub + __builtin_HEXAGON_V6_vrmpyub(v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.acc + __builtin_HEXAGON_V6_vrmpyub_acc(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.rtt + __builtin_HEXAGON_V6_vrmpyub_rtt(v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpyub.rtt.acc + __builtin_HEXAGON_V6_vrmpyub_rtt_acc(v128, v64, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubi + __builtin_HEXAGON_V6_vrmpyubi(v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubi.acc + __builtin_HEXAGON_V6_vrmpyubi_acc(v128, v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vrmpyubv + __builtin_HEXAGON_V6_vrmpyubv(v64, v64); + // CHECK: @llvm.hexagon.V6.vrmpyubv.acc + __builtin_HEXAGON_V6_vrmpyubv_acc(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vror + __builtin_HEXAGON_V6_vror(v64, 0); + // CHECK: @llvm.hexagon.V6.vroundhb + __builtin_HEXAGON_V6_vroundhb(v64, v64); + // CHECK: @llvm.hexagon.V6.vroundhub + __builtin_HEXAGON_V6_vroundhub(v64, v64); + // CHECK: @llvm.hexagon.V6.vrounduhub + __builtin_HEXAGON_V6_vrounduhub(v64, v64); + // CHECK: @llvm.hexagon.V6.vrounduwuh + __builtin_HEXAGON_V6_vrounduwuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vroundwh + __builtin_HEXAGON_V6_vroundwh(v64, v64); + // CHECK: @llvm.hexagon.V6.vroundwuh + __builtin_HEXAGON_V6_vroundwuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vrsadubi + __builtin_HEXAGON_V6_vrsadubi(v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vrsadubi.acc + __builtin_HEXAGON_V6_vrsadubi_acc(v128, v128, 0, 0); + // CHECK: @llvm.hexagon.V6.vsathub + __builtin_HEXAGON_V6_vsathub(v64, v64); + // CHECK: @llvm.hexagon.V6.vsatuwuh + __builtin_HEXAGON_V6_vsatuwuh(v64, v64); + // CHECK: @llvm.hexagon.V6.vsatwh + __builtin_HEXAGON_V6_vsatwh(v64, v64); + // CHECK: @llvm.hexagon.V6.vsb + __builtin_HEXAGON_V6_vsb(v64); + // CHECK: @llvm.hexagon.V6.vscattermh + __builtin_HEXAGON_V6_vscattermh(0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vscattermh.add + __builtin_HEXAGON_V6_vscattermh_add(0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vscattermhq + __builtin_HEXAGON_V6_vscattermhq(v64, 0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vscattermhw + __builtin_HEXAGON_V6_vscattermhw(0, 0, v128, v64); + // CHECK: @llvm.hexagon.V6.vscattermhw.add + __builtin_HEXAGON_V6_vscattermhw_add(0, 0, v128, v64); + // CHECK: @llvm.hexagon.V6.vscattermhwq + __builtin_HEXAGON_V6_vscattermhwq(v64, 0, 0, v128, v64); + // CHECK: @llvm.hexagon.V6.vscattermw + __builtin_HEXAGON_V6_vscattermw(0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vscattermw.add + __builtin_HEXAGON_V6_vscattermw_add(0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vscattermwq + __builtin_HEXAGON_V6_vscattermwq(v64, 0, 0, v64, v64); + // CHECK: @llvm.hexagon.V6.vsh + __builtin_HEXAGON_V6_vsh(v64); + // CHECK: @llvm.hexagon.V6.vshufeh + __builtin_HEXAGON_V6_vshufeh(v64, v64); + // CHECK: @llvm.hexagon.V6.vshuffb + __builtin_HEXAGON_V6_vshuffb(v64); + // CHECK: @llvm.hexagon.V6.vshuffeb + __builtin_HEXAGON_V6_vshuffeb(v64, v64); + // CHECK: @llvm.hexagon.V6.vshuffh + __builtin_HEXAGON_V6_vshuffh(v64); + // CHECK: @llvm.hexagon.V6.vshuffob + __builtin_HEXAGON_V6_vshuffob(v64, v64); + // CHECK: @llvm.hexagon.V6.vshuffvdd + __builtin_HEXAGON_V6_vshuffvdd(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vshufoeb + __builtin_HEXAGON_V6_vshufoeb(v64, v64); + // CHECK: @llvm.hexagon.V6.vshufoeh + __builtin_HEXAGON_V6_vshufoeh(v64, v64); + // CHECK: @llvm.hexagon.V6.vshufoh + __builtin_HEXAGON_V6_vshufoh(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubb + __builtin_HEXAGON_V6_vsubb(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubb.dv + __builtin_HEXAGON_V6_vsubb_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubbnq + __builtin_HEXAGON_V6_vsubbnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubbq + __builtin_HEXAGON_V6_vsubbq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubbsat + __builtin_HEXAGON_V6_vsubbsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubbsat.dv + __builtin_HEXAGON_V6_vsubbsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubcarry + __builtin_HEXAGON_V6_vsubcarry(v64, v64, 0); + // CHECK: @llvm.hexagon.V6.vsubh + __builtin_HEXAGON_V6_vsubh(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubh.dv + __builtin_HEXAGON_V6_vsubh_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubhnq + __builtin_HEXAGON_V6_vsubhnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubhq + __builtin_HEXAGON_V6_vsubhq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubhsat + __builtin_HEXAGON_V6_vsubhsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubhsat.dv + __builtin_HEXAGON_V6_vsubhsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubhw + __builtin_HEXAGON_V6_vsubhw(v64, v64); + // CHECK: @llvm.hexagon.V6.vsububh + __builtin_HEXAGON_V6_vsububh(v64, v64); + // CHECK: @llvm.hexagon.V6.vsububsat + __builtin_HEXAGON_V6_vsububsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsububsat.dv + __builtin_HEXAGON_V6_vsububsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubububb.sat + __builtin_HEXAGON_V6_vsubububb_sat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubuhsat + __builtin_HEXAGON_V6_vsubuhsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubuhsat.dv + __builtin_HEXAGON_V6_vsubuhsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubuhw + __builtin_HEXAGON_V6_vsubuhw(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubuwsat + __builtin_HEXAGON_V6_vsubuwsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubuwsat.dv + __builtin_HEXAGON_V6_vsubuwsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubw + __builtin_HEXAGON_V6_vsubw(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubw.dv + __builtin_HEXAGON_V6_vsubw_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vsubwnq + __builtin_HEXAGON_V6_vsubwnq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubwq + __builtin_HEXAGON_V6_vsubwq(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vsubwsat + __builtin_HEXAGON_V6_vsubwsat(v64, v64); + // CHECK: @llvm.hexagon.V6.vsubwsat.dv + __builtin_HEXAGON_V6_vsubwsat_dv(v128, v128); + // CHECK: @llvm.hexagon.V6.vswap + __builtin_HEXAGON_V6_vswap(v64, v64, v64); + // CHECK: @llvm.hexagon.V6.vtmpyb + __builtin_HEXAGON_V6_vtmpyb(v128, 0); + // CHECK: @llvm.hexagon.V6.vtmpyb.acc + __builtin_HEXAGON_V6_vtmpyb_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vtmpybus + __builtin_HEXAGON_V6_vtmpybus(v128, 0); + // CHECK: @llvm.hexagon.V6.vtmpybus.acc + __builtin_HEXAGON_V6_vtmpybus_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vtmpyhb + __builtin_HEXAGON_V6_vtmpyhb(v128, 0); + // CHECK: @llvm.hexagon.V6.vtmpyhb.acc + __builtin_HEXAGON_V6_vtmpyhb_acc(v128, v128, 0); + // CHECK: @llvm.hexagon.V6.vunpackb + __builtin_HEXAGON_V6_vunpackb(v64); + // CHECK: @llvm.hexagon.V6.vunpackh + __builtin_HEXAGON_V6_vunpackh(v64); + // CHECK: @llvm.hexagon.V6.vunpackob + __builtin_HEXAGON_V6_vunpackob(v128, v64); + // CHECK: @llvm.hexagon.V6.vunpackoh + __builtin_HEXAGON_V6_vunpackoh(v128, v64); + // CHECK: @llvm.hexagon.V6.vunpackub + __builtin_HEXAGON_V6_vunpackub(v64); + // CHECK: @llvm.hexagon.V6.vunpackuh + __builtin_HEXAGON_V6_vunpackuh(v64); + // CHECK: @llvm.hexagon.V6.vxor + __builtin_HEXAGON_V6_vxor(v64, v64); + // CHECK: @llvm.hexagon.V6.vzb + __builtin_HEXAGON_V6_vzb(v64); + // CHECK: @llvm.hexagon.V6.vzh + __builtin_HEXAGON_V6_vzh(v64); +} -- GitLab From 6e54f66e13baad6b3d3753c25492439ab1d06f08 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Thu, 12 Jul 2018 19:53:15 +0000 Subject: [PATCH 0525/1023] [Driver] Conform warn_drv_object_size_disabled_O0 to DefaultWarnNoError This diagnostic triggers when -fsanitize=object-size is explicitly specified but will be a no-op (i.e, at -O0). This diagnostic should not fail a -Werror build because it's just an explanatory note to the user. It's not always actionable. For example, a user may not be able to simply disable object-size, because they want it enabled in optimized builds. rdar://42128447 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336937 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticDriverKinds.td | 2 +- test/Driver/fsanitize-object-size.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 5526ad4bd5..a6be0595e1 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -273,7 +273,7 @@ def warn_drv_disabling_vptr_no_rtti_default : Warning< InGroup; def warn_drv_object_size_disabled_O0 : Warning< "the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">, - InGroup; + InGroup, DefaultWarnNoWerror; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; diff --git a/test/Driver/fsanitize-object-size.c b/test/Driver/fsanitize-object-size.c index b96221e0fd..50c67838df 100644 --- a/test/Driver/fsanitize-object-size.c +++ b/test/Driver/fsanitize-object-size.c @@ -2,8 +2,9 @@ // // RUN: %clang -target x86_64-linux-gnu -fsanitize=object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE // RUN: %clang -target x86_64-linux-gnu -fsanitize=object-size %s -O0 -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE -// RUN: %clang -target x86_64-linux-gnu -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-NO-OSIZE -// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-NO-OSIZE-NO-WARNING +// RUN: %clang -target x86_64-linux-gnu -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE +// RUN: %clang -target x86_64-linux-gnu -Werror -fsanitize=null,object-size %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OSIZE-NO-WARNING // Check that the object size check is enabled at other optimization levels. // -- GitLab From 829882796ce575409bda1c0a9f026dbf82bc8086 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 12 Jul 2018 21:09:05 +0000 Subject: [PATCH 0526/1023] AttributeList de-listifying: Basically, "AttributeList" loses all list-like mechanisms, ParsedAttributes is switched to use a TinyPtrVector (and a ParsedAttributesView is created to have a non-allocating attributes list). DeclaratorChunk gets the later kind, Declarator/DeclSpec keep ParsedAttributes. Iterators are added to the ParsedAttribute types so that for-loops work. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336945 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 65 ++-- include/clang/Sema/AttributeList.h | 284 ++++++++------- include/clang/Sema/DeclSpec.h | 81 ++--- include/clang/Sema/Sema.h | 261 ++++++-------- lib/Parse/ParseCXXInlineMethods.cpp | 10 +- lib/Parse/ParseDecl.cpp | 203 ++++------- lib/Parse/ParseDeclCXX.cpp | 145 ++++---- lib/Parse/ParseExpr.cpp | 50 ++- lib/Parse/ParseExprCXX.cpp | 105 +++--- lib/Parse/ParseObjc.cpp | 99 ++---- lib/Parse/ParsePragma.cpp | 12 +- lib/Parse/ParseStmt.cpp | 14 +- lib/Parse/ParseTemplate.cpp | 58 ++- lib/Parse/Parser.cpp | 22 +- lib/Sema/AttributeList.cpp | 67 ++-- lib/Sema/DeclSpec.cpp | 11 +- lib/Sema/SemaAttr.cpp | 7 +- lib/Sema/SemaCUDA.cpp | 9 +- lib/Sema/SemaDecl.cpp | 78 ++--- lib/Sema/SemaDeclAttr.cpp | 87 ++--- lib/Sema/SemaDeclCXX.cpp | 137 +++----- lib/Sema/SemaDeclObjC.cpp | 90 ++--- lib/Sema/SemaLambda.cpp | 4 +- lib/Sema/SemaStmt.cpp | 2 +- lib/Sema/SemaStmtAttr.cpp | 7 +- lib/Sema/SemaTemplate.cpp | 96 ++--- lib/Sema/SemaTemplateInstantiate.cpp | 2 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 +- lib/Sema/SemaType.cpp | 429 ++++++++++------------- 29 files changed, 1061 insertions(+), 1380 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 416691ccc8..f4d9f0168f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1361,11 +1361,11 @@ private: }; NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc); + ParsedAttributes &AccessAttrs, + ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, + const VirtSpecifiers &VS, + SourceLocation PureSpecLoc); void ParseCXXNonStaticMemberInitializer(Decl *VarD); void ParseLexedAttributes(ParsingClass &Class); void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, @@ -1406,6 +1406,15 @@ private: SourceRange Range; }; + struct ParsedAttributesViewWithRange : ParsedAttributesView { + ParsedAttributesViewWithRange() : ParsedAttributesView() {} + void clearListOnly() { + ParsedAttributesView::clearListOnly(); + Range = SourceRange(); + } + + SourceRange Range; + }; DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = nullptr); @@ -1921,7 +1930,8 @@ private: void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); void ParseMicrosoftIfExistsExternalDeclaration(); void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS); + ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS); bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, bool &InitExprsOk); bool ParseAsmOperandsOpt(SmallVectorImpl &Names, @@ -2310,14 +2320,23 @@ private: DeclSpec &DS, Sema::TagUseKind TUK); // FixItLoc = possible correct location for the attributes - void ProhibitAttributes(ParsedAttributesWithRange &attrs, + void ProhibitAttributes(ParsedAttributesWithRange &Attrs, SourceLocation FixItLoc = SourceLocation()) { - if (!attrs.Range.isValid()) return; - DiagnoseProhibitedAttributes(attrs, FixItLoc); - attrs.clear(); + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clear(); } - void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - SourceLocation FixItLoc); + + void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs, + SourceLocation FixItLoc = SourceLocation()) { + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clearListOnly(); + } + void DiagnoseProhibitedAttributes(const SourceRange &Range, + SourceLocation FixItLoc); // Forbid C++11 and C2x attributes that appear on certain syntactic locations // which standard permits but we don't supported yet, for example, attributes @@ -2694,7 +2713,7 @@ private: void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D, VirtSpecifiers &VS); DeclGroupPtrTy ParseCXXClassMemberDeclaration( - AccessSpecifier AS, AttributeList *Attr, + AccessSpecifier AS, ParsedAttributes &Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas( @@ -2851,20 +2870,17 @@ private: // C++ 14.1: Template Parameters [temp.param] Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none, - AttributeList *AccessAttrs = nullptr); + SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, + AccessSpecifier AS = AS_none); Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs); + ParsedAttributes &AccessAttrs, + AccessSpecifier AS); Decl *ParseSingleDeclarationAfterTemplate( - DeclaratorContext Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromParams, - SourceLocation &DeclEnd, - AccessSpecifier AS=AS_none, - AttributeList *AccessAttrs = nullptr); + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); bool ParseTemplateParameters(unsigned Depth, SmallVectorImpl &TemplateParams, SourceLocation &LAngleLoc, @@ -2907,6 +2923,7 @@ private: SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); //===--------------------------------------------------------------------===// diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index dd15b7a2f5..70a0306f41 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -21,6 +21,7 @@ #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/VersionTuple.h" #include @@ -181,12 +182,6 @@ private: const Expr *MessageExpr; - /// The next attribute in the current position. - AttributeList *NextInPosition = nullptr; - - /// The next attribute allocated in the current Pool. - AttributeList *NextInPool = nullptr; - /// Arguments, if any, are stored immediately following the object. ArgsUnion *getArgsBuffer() { return reinterpret_cast(this + 1); } ArgsUnion const *getArgsBuffer() const { @@ -433,9 +428,6 @@ public: static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, Syntax SyntaxUsed); - AttributeList *getNext() const { return NextInPosition; } - void setNext(AttributeList *N) { NextInPosition = N; } - /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } @@ -555,6 +547,7 @@ public: unsigned getSemanticSpelling() const; }; +class AttributePool; /// A factory, from which one makes pools, from which one creates /// individual attributes which are deallocated with the pool. /// @@ -595,7 +588,8 @@ private: /// Free lists. The index is determined by the following formula: /// (size - sizeof(AttributeList)) / sizeof(void*) - SmallVector FreeLists; + SmallVector, InlineFreeListsCapacity> + FreeLists; // The following are the private interface used by AttributePool. friend class AttributePool; @@ -603,12 +597,14 @@ private: /// Allocate an attribute of the given size. void *allocate(size_t size); + void deallocate(AttributeList *AL); + /// Reclaim all the attributes in the given pool chain, which is /// non-empty. Note that the current implementation is safe /// against reclaiming things which were not actually allocated /// with the allocator, although of course it's important to make /// sure that their allocator lives at least as long as this one. - void reclaimPool(AttributeList *head); + void reclaimPool(AttributePool &head); public: AttributeFactory(); @@ -616,21 +612,26 @@ public: }; class AttributePool { + friend class AttributeFactory; AttributeFactory &Factory; - AttributeList *Head = nullptr; + llvm::TinyPtrVector Attrs; void *allocate(size_t size) { return Factory.allocate(size); } AttributeList *add(AttributeList *attr) { - // We don't care about the order of the pool. - attr->NextInPool = Head; - Head = attr; + Attrs.push_back(attr); return attr; } - void takePool(AttributeList *pool); + void remove(AttributeList *attr) { + assert(llvm::is_contained(Attrs, attr) && + "Can't take attribute from a pool that doesn't own it!"); + Attrs.erase(llvm::find(Attrs, attr)); + } + + void takePool(AttributePool &pool); public: /// Create a new pool for a factory. @@ -638,30 +639,22 @@ public: AttributePool(const AttributePool &) = delete; - ~AttributePool() { - if (Head) Factory.reclaimPool(Head); - } + ~AttributePool() { Factory.reclaimPool(*this); } /// Move the given pool's allocations to this pool. - AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) { - pool.Head = nullptr; - } + AttributePool(AttributePool &&pool) = default; AttributeFactory &getFactory() const { return Factory; } void clear() { - if (Head) { - Factory.reclaimPool(Head); - Head = nullptr; - } + Factory.reclaimPool(*this); + Attrs.clear(); } /// Take the given pool's allocations and add them to this pool. void takeAllFrom(AttributePool &pool) { - if (pool.Head) { - takePool(pool.Head); - pool.Head = nullptr; - } + takePool(pool); + pool.Attrs.clear(); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -669,12 +662,11 @@ public: ArgsUnion *args, unsigned numArgs, AttributeList::Syntax syntax, SourceLocation ellipsisLoc = SourceLocation()) { - void *memory = allocate(sizeof(AttributeList) - + numArgs * sizeof(ArgsUnion)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - args, numArgs, syntax, - ellipsisLoc)); + void *memory = + allocate(sizeof(AttributeList) + numArgs * sizeof(ArgsUnion)); + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, args, + numArgs, syntax, ellipsisLoc)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -683,133 +675,158 @@ public: const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *MessageExpr, - AttributeList::Syntax syntax, - SourceLocation strict, const Expr *ReplacementExpr) { + SourceLocation unavailable, const Expr *MessageExpr, + AttributeList::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, - syntax, strict, ReplacementExpr)); + return add(new (memory) AttributeList( + attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, - IdentifierLoc *Param2, - IdentifierLoc *Param3, - AttributeList::Syntax syntax) { + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, AttributeList::Syntax syntax) { size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); void *memory = allocate(size); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param1, Param2, Param3, - syntax)); - } - - AttributeList *createTypeTagForDatatype( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *argumentKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, - AttributeList::Syntax syntax) { + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax)); + } + + AttributeList * + createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *argumentKind, + ParsedType matchingCType, bool layoutCompatible, + bool mustBeNull, AttributeList::Syntax syntax) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - argumentKind, matchingCType, - layoutCompatible, mustBeNull, - syntax)); + return add(new (memory) AttributeList( + attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax)); } - AttributeList *createTypeAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { + AttributeList * + createTypeAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, AttributeList::Syntax syntaxUsed) { void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - typeArg, syntaxUsed)); + return add(new (memory) AttributeList(attrName, attrRange, scopeName, + scopeLoc, typeArg, syntaxUsed)); } - AttributeList *createPropertyAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { + AttributeList * + createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + AttributeList::Syntax syntaxUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - getterId, setterId, - syntaxUsed)); + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, + getterId, setterId, syntaxUsed)); } }; -/// ParsedAttributes - A collection of parsed attributes. Currently -/// we don't differentiate between the various attribute syntaxes, -/// which is basically silly. -/// -/// Right now this is a very lightweight container, but the expectation -/// is that this will become significantly more serious. -class ParsedAttributes { -public: - ParsedAttributes(AttributeFactory &factory) : pool(factory) {} - ParsedAttributes(const ParsedAttributes &) = delete; - - AttributePool &getPool() const { return pool; } +class ParsedAttributesView { + using VecTy = llvm::TinyPtrVector; + using SizeType = decltype(std::declval().size()); - bool empty() const { return list == nullptr; } +public: + bool empty() const { return AttrList.empty(); } + SizeType size() const { return AttrList.size(); } + AttributeList &operator[](SizeType pos) { return *AttrList[pos]; } + const AttributeList &operator[](SizeType pos) const { return *AttrList[pos]; } - void add(AttributeList *newAttr) { + void addAtStart(AttributeList *newAttr) { + assert(newAttr); + AttrList.insert(AttrList.begin(), newAttr); + } + void addAtEnd(AttributeList *newAttr) { assert(newAttr); - assert(newAttr->getNext() == nullptr); - newAttr->setNext(list); - list = newAttr; + AttrList.push_back(newAttr); + } + + void remove(AttributeList *ToBeRemoved) { + assert(is_contained(AttrList, ToBeRemoved) && + "Cannot remove attribute that isn't in the list"); + AttrList.erase(llvm::find(AttrList, ToBeRemoved)); } - void addAll(AttributeList *newList) { - if (!newList) return; + void clearListOnly() { AttrList.clear(); } - AttributeList *lastInNewList = newList; - while (AttributeList *next = lastInNewList->getNext()) - lastInNewList = next; + struct iterator : llvm::iterator_adaptor_base { + iterator() : iterator_adaptor_base(nullptr) {} + iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} + reference operator*() { return **I; } + friend class ParsedAttributesView; + }; + struct const_iterator + : llvm::iterator_adaptor_base { + const_iterator() : iterator_adaptor_base(nullptr) {} + const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} + + reference operator*() const { return **I; } + friend class ParsedAttributesView; + }; - lastInNewList->setNext(list); - list = newList; + void addAll(iterator B, iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); } - void addAllAtEnd(AttributeList *newList) { - if (!list) { - list = newList; - return; - } + void addAll(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); + } - AttributeList *lastInList = list; - while (AttributeList *next = lastInList->getNext()) - lastInList = next; + void addAllAtEnd(iterator B, iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); + } - lastInList->setNext(newList); + void addAllAtEnd(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); } - void set(AttributeList *newList) { - list = newList; + iterator begin() { return iterator(AttrList.begin()); } + const_iterator begin() const { return const_iterator(AttrList.begin()); } + iterator end() { return iterator(AttrList.end()); } + const_iterator end() const { return const_iterator(AttrList.end()); } + + bool hasAttribute(AttributeList::Kind K) const { + return llvm::any_of( + AttrList, [K](const AttributeList *AL) { return AL->getKind() == K; }); } +private: + VecTy AttrList; +}; + +/// ParsedAttributes - A collection of parsed attributes. Currently +/// we don't differentiate between the various attribute syntaxes, +/// which is basically silly. +/// +/// Right now this is a very lightweight container, but the expectation +/// is that this will become significantly more serious. +class ParsedAttributes : public ParsedAttributesView { +public: + ParsedAttributes(AttributeFactory &factory) : pool(factory) {} + ParsedAttributes(const ParsedAttributes &) = delete; + + AttributePool &getPool() const { return pool; } + void takeAllFrom(ParsedAttributes &attrs) { - addAll(attrs.list); - attrs.list = nullptr; + addAll(attrs.begin(), attrs.end()); + attrs.clearListOnly(); pool.takeAllFrom(attrs.pool); } - void clear() { list = nullptr; pool.clear(); } - AttributeList *getList() const { return list; } - - void clearListOnly() { list = nullptr; } - - /// Returns a reference to the attribute list. Try not to introduce - /// dependencies on this method, it may not be long-lived. - AttributeList *&getListRef() { return list; } + void clear() { + clearListOnly(); + pool.clear(); + } /// Add attribute with expression arguments. AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, @@ -820,7 +837,7 @@ public: AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, syntax, ellipsisLoc); - add(attr); + addAtStart(attr); return attr; } @@ -839,7 +856,7 @@ public: pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); - add(attr); + addAtStart(attr); return attr; } @@ -853,7 +870,7 @@ public: AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, Param1, Param2, Param3, syntax); - add(attr); + addAtStart(attr); return attr; } @@ -869,7 +886,7 @@ public: scopeName, scopeLoc, argumentKind, matchingCType, layoutCompatible, mustBeNull, syntax); - add(attr); + addAtStart(attr); return attr; } @@ -881,7 +898,7 @@ public: AttributeList *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, typeArg, syntaxUsed); - add(attr); + addAtStart(attr); return attr; } @@ -894,13 +911,12 @@ public: AttributeList *attr = pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed); - add(attr); + addAtStart(attr); return attr; } private: mutable AttributePool pool; - AttributeList *list = nullptr; }; /// These constants match the enumerated choices of diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9c72afb058..77e90a964f 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -739,8 +739,8 @@ public: /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// \endcode /// - void addAttributes(AttributeList *AL) { - Attrs.addAll(AL); + void addAttributes(ParsedAttributesView &AL) { + Attrs.addAll(AL.begin(), AL.end()); } bool hasAttributes() const { return !Attrs.empty(); } @@ -1147,11 +1147,9 @@ struct DeclaratorChunk { return SourceRange(Loc, EndLoc); } - struct TypeInfoCommon { - AttributeList *AttrList; - }; + ParsedAttributesView AttrList; - struct PointerTypeInfo : TypeInfoCommon { + struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict/unaligned/atomic. unsigned TypeQuals : 5; @@ -1174,7 +1172,7 @@ struct DeclaratorChunk { } }; - struct ReferenceTypeInfo : TypeInfoCommon { + struct ReferenceTypeInfo { /// The type qualifier: restrict. [GNU] C++ extension bool HasRestrict : 1; /// True if this is an lvalue reference, false if it's an rvalue reference. @@ -1183,7 +1181,7 @@ struct DeclaratorChunk { } }; - struct ArrayTypeInfo : TypeInfoCommon { + struct ArrayTypeInfo { /// The type qualifiers for the array: /// const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1234,7 +1232,7 @@ struct DeclaratorChunk { SourceRange Range; }; - struct FunctionTypeInfo : TypeInfoCommon { + struct FunctionTypeInfo { /// hasPrototype - This is true if the function had at least one typed /// parameter. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. @@ -1463,7 +1461,7 @@ struct DeclaratorChunk { ParsedType getTrailingReturnType() const { return TrailingReturnType; } }; - struct BlockPointerTypeInfo : TypeInfoCommon { + struct BlockPointerTypeInfo { /// For now, sema will catch these as invalid. /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1472,7 +1470,7 @@ struct DeclaratorChunk { } }; - struct MemberPointerTypeInfo : TypeInfoCommon { + struct MemberPointerTypeInfo { /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; // CXXScopeSpec has a constructor, so it can't be a direct member. @@ -1489,15 +1487,14 @@ struct DeclaratorChunk { } }; - struct PipeTypeInfo : TypeInfoCommon { - /// The access writes. - unsigned AccessWrites : 3; + struct PipeTypeInfo { + /// The access writes. + unsigned AccessWrites : 3; - void destroy() {} + void destroy() {} }; union { - TypeInfoCommon Common; PointerTypeInfo Ptr; ReferenceTypeInfo Ref; ArrayTypeInfo Arr; @@ -1522,13 +1519,8 @@ struct DeclaratorChunk { /// If there are attributes applied to this declaratorchunk, return /// them. - const AttributeList *getAttrs() const { - return Common.AttrList; - } - - AttributeList *&getAttrListRef() { - return Common.AttrList; - } + const ParsedAttributesView &getAttrs() const { return AttrList; } + ParsedAttributesView &getAttrs() { return AttrList; } /// Return a DeclaratorChunk for a pointer. static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, @@ -1546,7 +1538,6 @@ struct DeclaratorChunk { I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding(); I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding(); - I.Ptr.AttrList = nullptr; return I; } @@ -1558,7 +1549,6 @@ struct DeclaratorChunk { I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = nullptr; return I; } @@ -1570,7 +1560,6 @@ struct DeclaratorChunk { I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = nullptr; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1614,7 +1603,6 @@ struct DeclaratorChunk { I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1625,7 +1613,6 @@ struct DeclaratorChunk { I.Kind = Pipe; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1637,7 +1624,6 @@ struct DeclaratorChunk { I.Loc = SS.getBeginLoc(); I.EndLoc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = nullptr; new (I.Mem.ScopeMem) CXXScopeSpec(SS); return I; } @@ -1649,7 +1635,6 @@ struct DeclaratorChunk { I.Kind = Paren; I.Loc = LParenLoc; I.EndLoc = RParenLoc; - I.Common.AttrList = nullptr; return I; } @@ -2144,17 +2129,27 @@ public: /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. - void AddTypeInfo(const DeclaratorChunk &TI, - ParsedAttributes &attrs, + /// This function takes attrs by R-Value reference because it takes ownership + /// of those attributes from the parameter. + void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); - DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end()); getAttributePool().takeAllFrom(attrs.getPool()); if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to + /// EndLoc, which should be the last token of the chunk. + void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + DeclTypeInfo.push_back(TI); + + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + /// Add a new innermost chunk to this declarator. void AddInnermostTypeInfo(const DeclaratorChunk &TI) { DeclTypeInfo.insert(DeclTypeInfo.begin(), TI); @@ -2395,16 +2390,15 @@ public: SetRangeEnd(lastLoc); } - const AttributeList *getAttributes() const { return Attrs.getList(); } - AttributeList *getAttributes() { return Attrs.getList(); } - - AttributeList *&getAttrListRef() { return Attrs.getListRef(); } + const ParsedAttributes &getAttributes() const { return Attrs; } + ParsedAttributes &getAttributes() { return Attrs; } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { - if (getAttributes() || getDeclSpec().hasAttributes()) return true; + if (!getAttributes().empty() || getDeclSpec().hasAttributes()) + return true; for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) - if (getTypeObject(i).getAttrs()) + if (!getTypeObject(i).getAttrs().empty()) return true; return false; } @@ -2412,12 +2406,9 @@ public: /// Return a source range list of C++11 attributes associated /// with the declarator. void getCXX11AttributeRanges(SmallVectorImpl &Ranges) { - AttributeList *AttrList = Attrs.getList(); - while (AttrList) { - if (AttrList->isCXX11Attribute()) - Ranges.push_back(AttrList->getRange()); - AttrList = AttrList->getNext(); - } + for (const AttributeList &AL : Attrs) + if (AL.isCXX11Attribute()) + Ranges.push_back(AL.getRange()); } void setAsmLabel(Expr *E) { AsmLabel = E; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index c5f62bd400..12a38677e4 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2048,8 +2048,7 @@ public: SourceLocation RParenLoc); /// Handle a C++11 empty-declaration and attribute-declaration. - Decl *ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, SourceLocation SemiLoc); enum class ModuleDeclKind { @@ -2187,7 +2186,7 @@ public: Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr, + SourceLocation NameLoc, const ParsedAttributesView &Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, @@ -2197,9 +2196,9 @@ public: Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists); TypeResult ActOnDependentTag(Scope *S, @@ -2221,11 +2220,11 @@ public: InClassInitStyle InitStyle, AccessSpecifier AS); MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, - SourceLocation DeclStart, - Declarator &D, Expr *BitfieldWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr); + const AttributeList &MSPropertyAttr); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, @@ -2258,10 +2257,9 @@ public: tok::ObjCKeywordKind visibility); // This is used for both record definitions and ObjC interface declarations. - void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, - ArrayRef Fields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, + ArrayRef Fields, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList); /// ActOnTagStartDefinition - Invoked when we have entered the /// scope of a tag's definition (e.g., for an enumeration, class, @@ -2326,12 +2324,11 @@ public: Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attrs, SourceLocation EqualLoc, - Expr *Val); + const ParsedAttributesView &Attrs, + SourceLocation EqualLoc, Expr *Val); void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDecl, - ArrayRef Elements, - Scope *S, AttributeList *Attr); + Decl *EnumDecl, ArrayRef Elements, Scope *S, + const ParsedAttributesView &Attr); DeclContext *getContainingDC(DeclContext *DC); @@ -3322,11 +3319,13 @@ public: // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); // Helper for delayed processing of attributes. - void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); - void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, + void ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList); + void ProcessDeclAttributeList(Scope *S, Decl *D, + const ParsedAttributesView &AL, bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList); + const ParsedAttributesView &AttrList); void checkUnusedDeclAttributes(Declarator &D); @@ -3392,7 +3391,8 @@ public: bool allowArrayTypes); /// Stmt attributes - this routine is the top level dispatcher. - StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, + StmtResult ProcessStmtAttributes(Stmt *Stmt, + const ParsedAttributesView &Attrs, SourceRange Range); void WarnConflictingTypedMethods(ObjCMethodDecl *Method, @@ -4548,11 +4548,10 @@ public: // Act on C++ namespaces Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *Ident, + SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl * &UsingDecl); + const ParsedAttributesView &AttrList, + UsingDirectiveDecl *&UsingDecl); void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; @@ -4593,13 +4592,11 @@ public: /// defined in [dcl.init.list]p2. bool isInitListConstructor(const FunctionDecl *Ctor); - Decl *ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *NamespcName, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); @@ -4630,15 +4627,11 @@ public: const DeclarationNameInfo &NameInfo, SourceLocation NameLoc); - NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation); + NamedDecl *BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation); NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef Expansions); @@ -4651,22 +4644,16 @@ public: findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, ConstructorUsingShadowDecl *DerivedShadow); - Decl *ActOnUsingDeclaration(Scope *CurScope, - AccessSpecifier AS, + Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - SourceLocation EllipsisLoc, - AttributeList *AttrList); - Decl *ActOnAliasDeclaration(Scope *CurScope, - AccessSpecifier AS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, + UnqualifiedId &Name, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList); + Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, MultiTemplateParamsArg TemplateParams, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec); + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec); /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. @@ -5727,10 +5714,9 @@ public: const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); - bool ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, + bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs = nullptr); + const ParsedAttributesView &Attrs); NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, @@ -5869,11 +5855,10 @@ public: /// conditions that are needed for the attribute to have an effect. void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); - void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, + void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, + Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void ActOnFinishCXXMemberDecls(); void ActOnFinishCXXNonNestedClass(Decl *D); @@ -6207,17 +6192,14 @@ public: ArrayRef ParamLists, bool IsFriend, bool &IsMemberSpecialization, bool &Invalid); - DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, - SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, + SkipBodyInfo *SkipBody = nullptr); TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, @@ -6291,14 +6273,12 @@ public: const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, bool AllowInjectedClassName = false); - DeclResult - ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody = nullptr); bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, TemplateDecl *PrimaryTemplate, @@ -6331,30 +6311,19 @@ public: bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr); DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, @@ -7939,20 +7908,14 @@ public: SourceLocation rAngleLoc); void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); - Decl *ActOnStartClassInterface(Scope *S, - SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + Decl *ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); void ActOnSuperClassOfClassInterface(Scope *S, SourceLocation AtInterfaceLoc, @@ -7980,24 +7943,18 @@ public: const ObjCList &PList); Decl *ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - Decl * const *ProtoRefNames, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); - - Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, + unsigned NumProtoRefs, const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList); + + Decl *ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); Decl *ActOnStartClassImplementation( SourceLocation AtClassImplLoc, @@ -8020,9 +7977,10 @@ public: ArrayRef TypeParamLists, unsigned NumElts); - DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef IdentList, - AttributeList *attrList); + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef IdentList, + const ParsedAttributesView &attrList); void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, ArrayRef ProtocolId, @@ -8157,22 +8115,21 @@ public: ObjCDeclSpec DeclSpec; /// ArgAttrs - Attribute list for this argument. - AttributeList *ArgAttrs; + ParsedAttributesView ArgAttrs; }; Decl *ActOnMethodDeclaration( - Scope *S, - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, Selector Sel, - // optional arguments. The number of types/arguments is obtained - // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic, bool MethodDefinition); + Scope *S, + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic, bool MethodDefinition); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, @@ -10093,7 +10050,7 @@ public: /// will get it wrong. Returns CFT_Host if D is null. CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr); + CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); /// Gets the CUDA target for the current context. CUDAFunctionTarget CurrentCUDATarget() { diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 77f2dccfed..27d48be0e3 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -22,12 +22,10 @@ using namespace clang; /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. -NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc) { +NamedDecl *Parser::ParseCXXInlineMethodDef( + AccessSpecifier AS, ParsedAttributes &AccessAttrs, ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers &VS, + SourceLocation PureSpecLoc) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c580d1777d..4b6b2b3336 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -53,7 +53,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); if (Attrs) - DS.addAttributes(Attrs->getList()); + DS.addAttributes(*Attrs); ParseSpecifierQualifierList(DS, AS, DSC); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; @@ -422,7 +422,7 @@ unsigned Parser::ParseClangAttributeArgs( ScopeName, ScopeLoc, Syntax); break; } - return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0; + return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; } bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, @@ -560,8 +560,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, // If this attribute's args were parsed, and it was expected to have // arguments but none were provided, emit a diagnostic. - const AttributeList *Attr = Attrs.getList(); - if (Attr && Attr->getMaxArgs() && !NumArgs) { + if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) { Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; return false; } @@ -1437,9 +1436,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } - const AttributeList *AL = Attrs.getList(); - if (OnDefinition && AL && !AL->isCXX11Attribute() && - AL->isKnownToGCC()) + if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && + Attrs.begin()->isKnownToGCC()) Diag(Tok, diag::warn_attribute_on_function_definition) << &LA.AttrName; @@ -1570,29 +1568,27 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, << FixItHint::CreateRemoval(AttrRange); } -void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - const SourceLocation CorrectLocation) { +void Parser::DiagnoseProhibitedAttributes( + const SourceRange &Range, const SourceLocation CorrectLocation) { if (CorrectLocation.isValid()) { - CharSourceRange AttrRange(attrs.Range, true); + CharSourceRange AttrRange(Range, true); Diag(CorrectLocation, diag::err_attributes_misplaced) << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) << FixItHint::CreateRemoval(AttrRange); } else - Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; + Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range; } void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { - for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { - if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute()) + for (const AttributeList &AL : Attrs) { + if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; - if (Attr->getKind() == AttributeList::UnknownAttribute) - Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) - << Attr->getName(); + if (AL.getKind() == AttributeList::UnknownAttribute) + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); else { - Diag(Attr->getLoc(), DiagID) - << Attr->getName(); - Attr->setInvalid(); + Diag(AL.getLoc(), DiagID) << AL.getName(); + AL.setInvalid(); } } } @@ -1610,47 +1606,19 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, if (TUK == Sema::TUK_Reference) return; - ParsedAttributes &PA = DS.getAttributes(); - AttributeList *AL = PA.getList(); - AttributeList *Prev = nullptr; - AttributeList *TypeAttrHead = nullptr; - AttributeList *TypeAttrTail = nullptr; - while (AL) { - AttributeList *Next = AL->getNext(); - - if ((AL->getKind() == AttributeList::AT_Aligned && - AL->isDeclspecAttribute()) || - AL->isMicrosoftAttribute()) { - // Stitch the attribute into the tag's attribute list. - if (TypeAttrTail) - TypeAttrTail->setNext(AL); - else - TypeAttrHead = AL; - TypeAttrTail = AL; - TypeAttrTail->setNext(nullptr); - - // Remove the attribute from the variable's attribute list. - if (Prev) { - // Set the last variable attribute's next attribute to be the attribute - // after the current one. - Prev->setNext(Next); - } else { - // Removing the head of the list requires us to reset the head to the - // next attribute. - PA.set(Next); - } - } else { - Prev = AL; - } + llvm::SmallVector ToBeMoved; - AL = Next; + for (AttributeList &AL : DS.getAttributes()) { + if ((AL.getKind() == AttributeList::AT_Aligned && + AL.isDeclspecAttribute()) || + AL.isMicrosoftAttribute()) + ToBeMoved.push_back(&AL); } - // Find end of type attributes Attrs and add NewTypeAttributes in the same - // order they were in originally. (Remember, in AttributeList things earlier - // in source order are later in the list, since new attributes are added to - // the front of the list.) - Attrs.addAllAtEnd(TypeAttrHead); + for (AttributeList *AL : ToBeMoved) { + DS.getAttributes().remove(AL); + Attrs.addAtEnd(AL); + } } /// ParseDeclaration - Parse a full 'declaration', which consists of @@ -1682,7 +1650,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, case tok::kw_template: case tok::kw_export: ProhibitAttributes(attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd); + SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. @@ -4075,10 +4043,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); - Actions.ActOnFields(getCurScope(), - RecordLoc, TagDecl, FieldDecls, - T.getOpenLocation(), T.getCloseLocation(), - attrs.getList()); + Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, + T.getOpenLocation(), T.getCloseLocation(), attrs); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } @@ -4389,8 +4355,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, unsigned DiagID; Decl *TagDecl = Actions.ActOnTag( getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, - IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, + attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, @@ -4531,8 +4497,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // Install the enumerator constant into EnumDecl. Decl *EnumConstDecl = Actions.ActOnEnumConstant( - getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - attrs.getList(), EqualLoc, AssignedVal.get()); + getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs, + EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); @@ -4584,10 +4550,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - Actions.ActOnEnumBody(StartLoc, T.getRange(), - EnumDecl, EnumConstantDecls, - getCurScope(), - attrs.getList()); + Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls, + getCurScope(), attrs); // Now handle enum constant availability diagnostics. assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); @@ -5382,10 +5346,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. - D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - DS.getLocEnd()), - DS.getAttributes(), - /* Don't replace range end. */SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getMemberPointer( + SS, DS.getTypeQualifiers(), DS.getLocEnd()), + std::move(DS.getAttributes()), + /* Don't replace range end. */ SourceLocation()); return; } } @@ -5398,7 +5362,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.AddTypeInfo( DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), - DS.getAttributes(), SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } // Not a pointer, C++ reference, or block. @@ -5430,20 +5394,16 @@ void Parser::ParseDeclaratorInternal(Declarator &D, ParseDeclaratorInternal(D, DirectDeclParser); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, - DS.getConstSpecLoc(), - DS.getVolatileSpecLoc(), - DS.getRestrictSpecLoc(), - DS.getAtomicSpecLoc(), - DS.getUnalignedSpecLoc()), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getPointer( + DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), + DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(), + DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), + std::move(DS.getAttributes()), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo( + DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc), + std::move(DS.getAttributes()), SourceLocation()); } else { // Is a reference DeclSpec DS(AttrFactory); @@ -5498,8 +5458,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Remember that we parsed a reference type. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, Kind == tok::amp), - DS.getAttributes(), - SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } } @@ -6007,9 +5966,9 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. T.consumeClose(); - D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(), - T.getCloseLocation()), - attrs, T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()), + std::move(attrs), T.getCloseLocation()); D.setGroupingParens(hadGroupingParens); @@ -6239,28 +6198,19 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } // Remember that we parsed a function type, and remember the attributes. - D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, - IsAmbiguous, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - RefQualifierIsLValueRef, - RefQualifierLoc, ConstQualifierLoc, - VolatileQualifierLoc, - RestrictQualifierLoc, - /*MutableLoc=*/SourceLocation(), - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - ExceptionSpecTokens, - DeclsInPrototype, - StartLoc, LocalEndLoc, D, - TrailingReturnType), - FnAttrs, EndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), RefQualifierIsLValueRef, + RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, + RestrictQualifierLoc, + /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange, + DynamicExceptions.data(), DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + ExceptionSpecTokens, DeclsInPrototype, StartLoc, + LocalEndLoc, D, TrailingReturnType), + std::move(FnAttrs), EndLoc); } /// ParseRefQualifier - Parses a member function ref-qualifier. Returns @@ -6582,7 +6532,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr, T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -6595,11 +6545,10 @@ void Parser::ParseBracketDeclarator(Declarator &D) { MaybeParseCXX11Attributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, - ExprRes.get(), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(), T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::code_completion) { Actions.CodeCompleteBracketDeclarator(getCurScope()); @@ -6672,12 +6621,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) { MaybeParseCXX11Attributes(DS.getAttributes()); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), - StaticLoc.isValid(), isStar, - NumElements.get(), - T.getOpenLocation(), - T.getCloseLocation()), - DS.getAttributes(), T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), + isStar, NumElements.get(), T.getOpenLocation(), + T.getCloseLocation()), + std::move(DS.getAttributes()), T.getCloseLocation()); } /// Diagnose brackets before an identifier. @@ -6729,18 +6677,15 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { if (NeedParens) { // Create a DeclaratorChunk for the inserted parens. - ParsedAttributes attrs(AttrFactory); SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); - D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs, + D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), SourceLocation()); } // Adding back the bracket info to the end of the Declarator. for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) { const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i); - ParsedAttributes attrs(AttrFactory); - attrs.set(Chunk.Common.AttrList); - D.AddTypeInfo(Chunk, attrs, SourceLocation()); + D.AddTypeInfo(Chunk, SourceLocation()); } // The missing identifier would have been diagnosed in ParseDirectDeclarator. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index a969a0f849..166f7a8d23 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -183,10 +183,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, - IdentLoc, Ident, T.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, + T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -233,11 +232,10 @@ void Parser::ParseInnerNamespace(std::vector &IdentLoc, // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), - NamespaceLoc[index], IdentLoc[index], - Ident[index], Tracker.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], + Ident[index], Tracker.getOpenLocation(), attrs, + ImplicitUsingDirectiveDecl); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -543,7 +541,7 @@ Decl *Parser::ParseUsingDirective(DeclaratorContext Context, SkipUntil(tok::semi); return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, - IdentLoc, NamespcName, attrs.getList()); + IdentLoc, NamespcName, attrs); } /// Parse a using-declarator (or the identifier in a C++11 alias-declaration). @@ -711,7 +709,7 @@ Parser::ParseUsingDeclaration(DeclaratorContext Context, Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, D.TypenameLoc, D.SS, D.Name, - D.EllipsisLoc, Attrs.getList()); + D.EllipsisLoc, Attrs); if (UD) DeclsInGroup.push_back(UD); } @@ -813,8 +811,8 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( TemplateParams ? TemplateParams->data() : nullptr, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, D.Name, Attrs.getList(), - TypeAlias, DeclFromDeclSpec); + UsingLoc, D.Name, Attrs, TypeAlias, + DeclFromDeclSpec); } /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration. @@ -1752,24 +1750,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // This is an explicit instantiation of a class template. ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, - StartLoc, - SS, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - attrs.getList()); - - // Friend template-ids are treated as references unless - // they have template headers, in which case they're ill-formed - // (FIXME: "template friend class A::B;"). - // We diagnose this error in ActOnClassTemplateSpecialization. + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, TemplateId->Template, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, attrs); + + // Friend template-ids are treated as references unless + // they have template headers, in which case they're ill-formed + // (FIXME: "template friend class A::B;"). + // We diagnose this error in ActOnClassTemplateSpecialization. } else if (TUK == Sema::TUK_Reference || (TUK == Sema::TUK_Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { @@ -1825,7 +1815,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization( getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), - *TemplateId, attrs.getList(), + *TemplateId, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0), @@ -1840,24 +1830,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, StartLoc, SS, Name, - NameLoc, attrs.getList()); + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, Name, NameLoc, attrs); } else if (TUK == Sema::TUK_Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitAttributes(attrs); - TagOrTempResult = - Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(), - TagType, StartLoc, SS, - Name, NameLoc, attrs.getList(), - MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] - : nullptr, - TemplateParams? TemplateParams->size() : 0)); + TagOrTempResult = Actions.ActOnTemplatedFriendTag( + getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, + NameLoc, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, + TemplateParams ? TemplateParams->size() : 0)); } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) ProhibitAttributes(attrs); @@ -1885,9 +1869,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag( - getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, - IsDependent, SourceLocation(), false, clang::TypeResult(), + getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + SourceLocation(), false, clang::TypeResult(), DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, @@ -1929,7 +1913,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (!TagOrTempResult.isInvalid()) // Delayed processing of attributes. - Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); const char *PrevSpec = nullptr; unsigned DiagID; @@ -2300,12 +2284,10 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( if (!VS.isUnset()) { // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. - const AttributeList *Attr = DeclaratorInfo.getAttributes(); - while (Attr) { - if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute()) - Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); - Attr = Attr->getNext(); - } + for (const AttributeList &AL : DeclaratorInfo.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_gcc_attribute_location); + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); } } @@ -2424,7 +2406,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - AttributeList *AccessAttrs, + ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -2492,7 +2474,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( getCurScope(), AS, /*UsingLoc*/ SourceLocation(), /*TypenameLoc*/ SourceLocation(), SS, Name, - /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr))); + /*EllipsisLoc*/ SourceLocation(), + /*AttrList*/ ParsedAttributesView()))); } } @@ -2512,7 +2495,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation DeclEnd; return DeclGroupPtrTy::make( DeclGroupRef(ParseTemplateDeclarationOrSpecialization( - DeclaratorContext::MemberContext, DeclEnd, AS, AccessAttrs))); + DeclaratorContext::MemberContext, DeclEnd, AccessAttrs, AS))); } // Handle: member-declaration ::= '__extension__' member-declaration @@ -2525,12 +2508,12 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParsedAttributesWithRange attrs(AttrFactory); - ParsedAttributesWithRange FnAttrs(AttrFactory); + ParsedAttributesViewWithRange FnAttrs; // Optional C++11 attribute-specifier MaybeParseCXX11Attributes(attrs); // We need to keep these attributes for future diagnostic // before they are taken over by declaration specifier. - FnAttrs.addAll(attrs.getList()); + FnAttrs.addAll(attrs.begin(), attrs.end()); FnAttrs.Range = attrs.Range; MaybeParseMicrosoftAttributes(attrs); @@ -2777,7 +2760,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // initialize it. ThisDecl = VT->getTemplatedDecl(); - if (ThisDecl && AccessAttrs) + if (ThisDecl) Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } @@ -3014,7 +2997,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( switch (Tok.getKind()) { case tok::kw___if_exists: case tok::kw___if_not_exists: - ParseMicrosoftIfExistsClassDeclaration(TagType, AS); + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS); return nullptr; case tok::semi: @@ -3080,8 +3063,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected); } - if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, - AccessAttrs.getList())) { + if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) { // found another attribute than only annotations AccessAttrs.clear(); } @@ -3094,7 +3076,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( TagDecl); default: - return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3282,9 +3264,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, - T.getOpenLocation(), - T.getCloseLocation(), - attrs.getList()); + T.getOpenLocation(), + T.getCloseLocation(), attrs); // C++11 [class.mem]p2: // Within the class member-specification, the class is regarded as complete @@ -3893,25 +3874,26 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); - const AttributeList *Attr = Attrs.getList(); - if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + if (!Attrs.empty() && + IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + AttributeList &Attr = *Attrs.begin(); // If the attribute is a standard or built-in attribute and we are // parsing an argument list, we need to determine whether this attribute // was allowed to have an argument list (such as [[deprecated]]), and how // many arguments were parsed (so we can diagnose on [[deprecated()]]). - if (Attr->getMaxArgs() && !NumArgs) { + if (Attr.getMaxArgs() && !NumArgs) { // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - Attr->setInvalid(true); - } else if (!Attr->getMaxArgs()) { + Attr.setInvalid(true); + } else if (!Attr.getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the // presence of the argument list (even if empty) is diagnosed. Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - Attr->setInvalid(true); + Attr.setInvalid(true); } } return true; @@ -4221,8 +4203,9 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, } while (Tok.is(tok::l_square)); } -void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS) { +void Parser::ParseMicrosoftIfExistsClassDeclaration( + DeclSpec::TST TagType, ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS) { IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; @@ -4252,7 +4235,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, + AccessAttrs, CurAS); continue; } @@ -4269,7 +4253,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, SourceLocation ASLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(), + ParsedAttributesView{}); else Diag(Tok, diag::err_expected) << tok::colon; ConsumeToken(); @@ -4277,7 +4262,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, } // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, nullptr); + ParseCXXClassMemberDeclaration(CurAS, AccessAttrs); } Braces.consumeClose(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 619fd222fd..d96dc5b362 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2948,33 +2948,31 @@ ExprResult Parser::ParseBlockLiteralExpression() { ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). - ParsedAttributes attrs(AttrFactory); SourceLocation NoLoc; - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, - /*IsAmbiguous=*/false, - /*RParenLoc=*/NoLoc, - /*ArgInfo=*/nullptr, - /*NumArgs=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLvalueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - CaretLoc, CaretLoc, - ParamInfo), - attrs, CaretLoc); + ParamInfo.AddTypeInfo( + DeclaratorChunk::getFunction(/*HasProto=*/true, + /*IsAmbiguous=*/false, + /*RParenLoc=*/NoLoc, + /*ArgInfo=*/nullptr, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, CaretLoc, + CaretLoc, ParamInfo), + CaretLoc); MaybeParseGNUAttributes(ParamInfo); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 77f758b159..e23581d203 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1109,12 +1109,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // after '(...)'. nvcc doesn't accept this. auto WarnIfHasCUDATargetAttr = [&] { if (getLangOpts().CUDA) - for (auto *A = Attr.getList(); A != nullptr; A = A->getNext()) - if (A->getKind() == AttributeList::AT_CUDADevice || - A->getKind() == AttributeList::AT_CUDAHost || - A->getKind() == AttributeList::AT_CUDAGlobal) - Diag(A->getLoc(), diag::warn_cuda_attr_lambda_position) - << A->getName()->getName(); + for (const AttributeList &A : Attr) + if (A.getKind() == AttributeList::AT_CUDADevice || + A.getKind() == AttributeList::AT_CUDAHost || + A.getKind() == AttributeList::AT_CUDAGlobal) + Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) + << A.getName()->getName(); }; TypeResult TrailingReturnType; @@ -1197,29 +1197,23 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - /*ExceptionSpecTokens*/nullptr, - /*DeclsInPrototype=*/None, - LParenLoc, FunLocalRangeEnd, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, + ESpecRange, DynamicExceptions.data(), + DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/ nullptr, + /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, tok::kw_constexpr) || (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { @@ -1266,31 +1260,29 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - /*LParenLoc=*/NoLoc, - /*Params=*/nullptr, - /*NumParams=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - DeclLoc, DeclEndLoc, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*Params=*/nullptr, + /*NumParams=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using @@ -2889,10 +2881,9 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.get(), - T.getOpenLocation(), + Size.get(), T.getOpenLocation(), T.getCloseLocation()), - Attrs, T.getCloseLocation()); + std::move(Attrs), T.getCloseLocation()); if (T.getCloseLocation().isInvalid()) return; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 81b930a228..447eb9610b 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -287,7 +287,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, Decl *CategoryType = Actions.ActOnStartCategoryInterface( AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); @@ -353,17 +353,12 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.isNot(tok::less)) Actions.ActOnTypedefedProtocols(protocols, protocolLocs, superClassId, superClassLoc); - - Decl *ClsType = - Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc, - typeParameterList, superClassId, - superClassLoc, - typeArgs, - SourceRange(typeArgsLAngleLoc, - typeArgsRAngleLoc), - protocols.data(), protocols.size(), - protocolLocs.data(), - EndProtoLoc, attrs.getList()); + + Decl *ClsType = Actions.ActOnStartClassInterface( + getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, + superClassLoc, typeArgs, + SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), + protocols.size(), protocolLocs.data(), EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); @@ -389,15 +384,13 @@ static void addContextSensitiveTypeNullability(Parser &P, if (D.getNumTypeObjects() > 0) { // Add the attribute to the declarator chunk nearest the declarator. - auto nullabilityAttr = getNullabilityAttr(D.getAttributePool()); - DeclaratorChunk &chunk = D.getTypeObject(0); - nullabilityAttr->setNext(chunk.getAttrListRef()); - chunk.getAttrListRef() = nullabilityAttr; + D.getTypeObject(0).getAttrs().addAtStart( + getNullabilityAttr(D.getAttributePool())); } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().addAttributes( - getNullabilityAttr(D.getDeclSpec().getAttributePool())); + D.getMutableDeclSpec().getAttributes().addAtStart( + getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); addedToDeclSpec = true; } } @@ -1200,18 +1193,12 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, /// Take all the decl attributes out of the given list and add /// them to the given attribute set. -static void takeDeclAttributes(ParsedAttributes &attrs, - AttributeList *list) { - while (list) { - AttributeList *cur = list; - list = cur->getNext(); - - if (!cur->isUsedAsTypeAttr()) { - // Clear out the next pointer. We're really completely - // destroying the internal invariants of the declarator here, - // but it doesn't matter because we're done with it. - cur->setNext(nullptr); - attrs.add(cur); +static void takeDeclAttributes(ParsedAttributesView &attrs, + ParsedAttributesView &from) { + for (auto &AL : llvm::reverse(from)) { + if (!AL.isUsedAsTypeAttr()) { + from.remove(&AL); + attrs.addAtStart(&AL); } } } @@ -1225,11 +1212,10 @@ static void takeDeclAttributes(ParsedAttributes &attrs, attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); // Now actually move the attributes over. - takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); + takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes()); takeDeclAttributes(attrs, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) - takeDeclAttributes(attrs, - const_cast(D.getTypeObject(i).getAttrs())); + takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs()); } /// objc-type-name: @@ -1384,13 +1370,10 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, MaybeParseCXX11Attributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - selLoc, Sel, nullptr, - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), MethodImplKind, - false, MethodDefinition); + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, + selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, false, MethodDefinition); PD.complete(Result); return Result; } @@ -1421,7 +1404,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (getLangOpts().ObjC2) MaybeParseGNUAttributes(paramAttrs); MaybeParseCXX11Attributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); + ArgInfo.ArgAttrs = paramAttrs; // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { @@ -1511,14 +1494,11 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - KeyLocs, Sel, &ArgInfos[0], - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), - MethodImplKind, isVariadic, MethodDefinition); - + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, + Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, isVariadic, MethodDefinition); + PD.complete(Result); return Result; } @@ -1883,9 +1863,9 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. - Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, - AllIvarDecls, - T.getOpenLocation(), T.getCloseLocation(), nullptr); + Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), + ParsedAttributesView()); } /// objc-class-instance-variables: @@ -2035,8 +2015,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs); } CheckNestedObjCContexts(AtLoc); @@ -2063,8 +2042,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return nullptr; - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs); } // Last, and definitely not least, parse a protocol declaration. @@ -2078,12 +2056,9 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - Decl *ProtoType = - Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + Decl *ProtoType = Actions.ActOnStartProtocolInterface( + AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), + ProtocolLocs.data(), EndProtoLoc, attrs); ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); return Actions.ConvertDeclToDeclGroup(ProtoType); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index afd99b23a8..553b490f48 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -1410,26 +1410,26 @@ void Parser::HandlePragmaAttribute() { return; } - if (!Attrs.getList() || Attrs.getList()->isInvalid()) { + if (Attrs.empty() || Attrs.begin()->isInvalid()) { SkipToEnd(); return; } // Ensure that we don't have more than one attribute. - if (Attrs.getList()->getNext()) { - SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); + if (Attrs.size() > 1) { + SourceLocation Loc = Attrs[1].getLoc(); Diag(Loc, diag::err_pragma_attribute_multiple_attributes); SkipToEnd(); return; } - if (!Attrs.getList()->isSupportedByPragmaAttribute()) { + AttributeList &Attribute = *Attrs.begin(); + if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); + << Attribute.getName(); SkipToEnd(); return; } - AttributeList &Attribute = *Attrs.getList(); // Parse the subject-list. if (!TryConsumeToken(tok::comma)) { diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8dba6386d0..1127158a05 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -116,7 +116,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, if (Attrs.empty() || Res.isInvalid()) return Res; - return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range); + return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range); } namespace { @@ -610,8 +610,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) - SubStmt = Actions.ProcessStmtAttributes( - SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); + SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs, + TempAttrs.Range); } else { Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } @@ -627,10 +627,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); - if (AttributeList *Attrs = attrs.getList()) { - Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); - attrs.clear(); - } + Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs); + attrs.clear(); return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, SubStmt.get()); @@ -2269,7 +2267,7 @@ bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { if (Attrs.empty()) return true; - if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint) + if (Attrs.begin()->getKind() != AttributeList::AT_OpenCLUnrollHint) return true; if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index f701f4639c..f7a69c482e 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -23,24 +23,19 @@ using namespace clang; /// Parse a template declaration, explicit instantiation, or /// explicit specialization. -Decl * -Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseDeclarationStartingWithTemplate( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { ObjCDeclContextSwitch ObjCDC(*this); if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { - return ParseExplicitInstantiation(Context, - SourceLocation(), ConsumeToken(), - DeclEnd, AS); + return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(), + DeclEnd, AccessAttrs, AS); } - return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, - AccessAttrs); + return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs, + AS); } - - /// Parse a template declaration or an explicit specialization. /// /// Template declarations include one or more template parameter lists @@ -56,11 +51,9 @@ Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context, /// /// explicit-specialization: [ C++ temp.expl.spec] /// 'template' '<' '>' declaration -Decl * -Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseTemplateDeclarationOrSpecialization( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(Tok.isOneOf(tok::kw_export, tok::kw_template) && "Token does not start a template declaration."); @@ -149,12 +142,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); // Parse the actual template declaration. - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(&ParamLists, - isSpecialization, - LastParamListWasEmpty), - ParsingTemplateParams, - DeclEnd, AS, AccessAttrs); + return ParseSingleDeclarationAfterTemplate( + Context, + ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } /// Parse a single declaration that declares a template, @@ -167,14 +158,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, /// declaration. Will be AS_none for namespace-scope declarations. /// /// \returns the new declaration. -Decl * -Parser::ParseSingleDeclarationAfterTemplate( - DeclaratorContext Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromTParams, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseSingleDeclarationAfterTemplate( + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && "Template information required"); @@ -1342,16 +1329,15 @@ Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { // This isn't really required here. ParsingDeclRAIIObject ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent); - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(ExternLoc, - TemplateLoc), - ParsingTemplateParams, - DeclEnd, AS); + return ParseSingleDeclarationAfterTemplate( + Context, ParsedTemplateInfo(ExternLoc, TemplateLoc), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d1c35352ae..7bda21b551 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -698,9 +698,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return nullptr; case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. - SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), - attrs.getList(), - Tok.getLocation()); + SingleDecl = + Actions.ActOnEmptyDeclaration(getCurScope(), attrs, Tok.getLocation()); ConsumeExtraSemi(OutsideFunction); break; case tok::r_brace: @@ -829,8 +828,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; return Actions.ConvertDeclToDeclGroup( - ParseExplicitInstantiation(DeclaratorContext::FileContext, - ExternLoc, TemplateLoc, DeclEnd)); + ParseExplicitInstantiation(DeclaratorContext::FileContext, ExternLoc, + TemplateLoc, DeclEnd, attrs)); } goto dont_know; @@ -1090,15 +1089,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Check to make sure that any normal attributes are allowed to be on // a definition. Late parsed attributes are checked at the end. if (Tok.isNot(tok::equal)) { - AttributeList *DtorAttrs = D.getAttributes(); - while (DtorAttrs) { - if (DtorAttrs->isKnownToGCC() && - !DtorAttrs->isCXX11Attribute()) { - Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName(); - } - DtorAttrs = DtorAttrs->getNext(); - } + for (const AttributeList &AL : D.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) + << AL.getName(); } // In delayed template parsing mode, for function template we consume the diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 4cd32b361d..6d5c6a26ef 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -60,56 +60,41 @@ static size_t getFreeListIndexForSize(size_t size) { void *AttributeFactory::allocate(size_t size) { // Check for a previously reclaimed attribute. size_t index = getFreeListIndexForSize(size); - if (index < FreeLists.size()) { - if (AttributeList *attr = FreeLists[index]) { - FreeLists[index] = attr->NextInPool; - return attr; - } + if (index < FreeLists.size() && !FreeLists[index].empty()) { + AttributeList *attr = FreeLists[index].back(); + FreeLists[index].pop_back(); + return attr; } // Otherwise, allocate something new. return Alloc.Allocate(size, alignof(AttributeFactory)); } -void AttributeFactory::reclaimPool(AttributeList *cur) { - assert(cur && "reclaiming empty pool!"); - do { - // Read this here, because we're going to overwrite NextInPool - // when we toss 'cur' into the appropriate queue. - AttributeList *next = cur->NextInPool; - - size_t size = cur->allocated_size(); - size_t freeListIndex = getFreeListIndexForSize(size); - - // Expand FreeLists to the appropriate size, if required. - if (freeListIndex >= FreeLists.size()) - FreeLists.resize(freeListIndex+1); - - // Add 'cur' to the appropriate free-list. - cur->NextInPool = FreeLists[freeListIndex]; - FreeLists[freeListIndex] = cur; - - cur = next; - } while (cur); -} +void AttributeFactory::deallocate(AttributeList *Attr) { + size_t size = Attr->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); -void AttributePool::takePool(AttributeList *pool) { - assert(pool); + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex + 1); - // Fast path: this pool is empty. - if (!Head) { - Head = pool; - return; - } +#if !NDEBUG + // In debug mode, zero out the attribute to help find memory overwriting. + memset(Attr, 0, size); +#endif + + // Add 'Attr' to the appropriate free-list. + FreeLists[freeListIndex].push_back(Attr); +} + +void AttributeFactory::reclaimPool(AttributePool &cur) { + for (AttributeList *AL : cur.Attrs) + deallocate(AL); +} - // Reverse the pool onto the current head. This optimizes for the - // pattern of pulling a lot of pools into a single pool. - do { - AttributeList *next = pool->NextInPool; - pool->NextInPool = Head; - Head = pool; - pool = next; - } while (pool); +void AttributePool::takePool(AttributePool &pool) { + Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); + pool.Attrs.clear(); } #include "clang/Sema/AttrParsedAttrKinds.inc" diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index fe111a5dde..01c9bad16f 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -186,7 +186,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; - I.Fun.AttrList = nullptr; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; @@ -995,15 +994,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { writtenBS.Width = getTypeSpecWidth(); writtenBS.Type = getTypeSpecType(); // Search the list of attributes for the presence of a mode attribute. - writtenBS.ModeAttr = false; - AttributeList* attrs = getAttributes().getList(); - while (attrs) { - if (attrs->getKind() == AttributeList::AT_Mode) { - writtenBS.ModeAttr = true; - break; - } - attrs = attrs->getNext(); - } + writtenBS.ModeAttr = getAttributes().hasAttribute(AttributeList::AT_Mode); } /// Finish - This does final analysis of the declspec, rejecting things like diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 64f12f3f5e..cc155b7ff6 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -645,7 +645,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (PragmaAttributeStack.empty()) return; for (auto &Entry : PragmaAttributeStack) { - const AttributeList *Attribute = Entry.Attribute; + AttributeList *Attribute = Entry.Attribute; assert(Attribute && "Expected an attribute"); // Ensure that the attribute can be applied to the given declaration. @@ -659,9 +659,10 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (!Applies) continue; Entry.IsUsed = true; - assert(!Attribute->getNext() && "Expected just one attribute"); PragmaAttributeCurrentTargetDecl = D; - ProcessDeclAttributeList(S, D, Attribute); + ParsedAttributesView Attrs; + Attrs.addAtStart(Attribute); + ProcessDeclAttributeList(S, D, Attrs); PragmaAttributeCurrentTargetDecl = nullptr; } } diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp index a44eeb47c1..5b81eb3a43 100644 --- a/lib/Sema/SemaCUDA.cpp +++ b/lib/Sema/SemaCUDA.cpp @@ -55,13 +55,14 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, /*IsExecConfig=*/true); } -Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) { +Sema::CUDAFunctionTarget +Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; bool HasInvalidTargetAttr = false; - while (Attr) { - switch(Attr->getKind()){ + for (const AttributeList &AL : Attrs) { + switch (AL.getKind()) { case AttributeList::AT_CUDAGlobal: HasGlobalAttr = true; break; @@ -77,8 +78,8 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) { default: break; } - Attr = Attr->getNext(); } + if (HasInvalidTargetAttr) return CFT_InvalidTarget; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 13ef46b541..1e63fd3bfe 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4447,10 +4447,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (AttributeList* attrs = DS.getAttributes().getList(); attrs; - attrs = attrs->getNext()) - Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) - << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); + for (const AttributeList &AL : DS.getAttributes()) + Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) + << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } } @@ -6204,29 +6203,21 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } -static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, - AttributeList::Kind Kind) { - for (const AttributeList *L = AttrList; L; L = L->getNext()) - if (L->getKind() == Kind) - return true; - return false; -} - static bool hasParsedAttr(Scope *S, const Declarator &PD, AttributeList::Kind Kind) { // Check decl attributes on the DeclSpec. - if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) + if (PD.getDeclSpec().getAttributes().hasAttribute(Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type // position to the decl itself. for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { - if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) + if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind)) return true; } // Finally, check attributes on the decl itself. - return hasParsedAttr(S, PD.getAttributes(), Kind); + return PD.getAttributes().hasAttribute(Kind); } /// Adjust the \c DeclContext for a function or variable that might be a @@ -11340,8 +11331,8 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, D.takeAttributes(Attrs, AttrEnd); ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); - D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), - EmptyAttrs, IdentLoc); + D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false), + IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); @@ -12944,7 +12935,7 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, // Always attach attributes to the underlying decl. if (TemplateDecl *TD = dyn_cast(D)) D = TD->getTemplatedDecl(); - ProcessDeclAttributeList(S, D, Attrs.getList()); + ProcessDeclAttributeList(S, D, Attrs); if (CXXMethodDecl *Method = dyn_cast_or_null(D)) if (Method->isStatic()) @@ -13046,18 +13037,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, + /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - Loc, Loc, D), - DS.getAttributes(), - SourceLocation()); + /*DeclsInPrototype=*/None, Loc, + Loc, D), + std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. @@ -13529,13 +13518,12 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, + const ParsedAttributesView &Attrs, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. @@ -13574,14 +13562,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return nullptr; OwnedDecl = false; - DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, - SS, Name, NameLoc, Attr, - TemplateParams, AS, - ModulePrivateLoc, - /*FriendLoc*/SourceLocation(), - TemplateParameterLists.size()-1, - TemplateParameterLists.data(), - SkipBody); + DeclResult Result = CheckClassTemplate( + S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, + AS, ModulePrivateLoc, + /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, + TemplateParameterLists.data(), SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. @@ -14047,7 +14032,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If this is a use, just return the declaration we found, unless // we have attributes. if (TUK == TUK_Reference || TUK == TUK_Friend) { - if (Attr) { + if (!Attrs.empty()) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. } else if (TUK == TUK_Reference && @@ -14407,8 +14392,7 @@ CreateNewDecl: if (TUK == TUK_Definition) New->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. @@ -15227,7 +15211,8 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef Fields, SourceLocation LBrac, - SourceLocation RBrac, AttributeList *Attr) { + SourceLocation RBrac, + const ParsedAttributesView &Attrs) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -15545,8 +15530,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->completeDefinition(); // Handle attributes before checking the layout. - if (Attr) - ProcessDeclAttributeList(S, Record, Attr); + ProcessDeclAttributeList(S, Record, Attrs); // We may have deferred checking for a deleted destructor. Check now. if (CXXRecordDecl *CXXRecord = dyn_cast(Record)) { @@ -15924,7 +15908,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attr, + const ParsedAttributesView &Attrs, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast(theEnumDecl); EnumConstantDecl *LastEnumConst = @@ -15975,7 +15959,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, } // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. @@ -16167,14 +16151,12 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDeclX, - ArrayRef Elements, - Scope *S, AttributeList *Attr) { + Decl *EnumDeclX, ArrayRef Elements, Scope *S, + const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast(EnumDeclX); QualType EnumType = Context.getTypeDeclType(Enum); - if (Attr) - ProcessDeclAttributeList(S, Enum, Attr); + ProcessDeclAttributeList(S, Enum, Attrs); if (Enum->isDependentType()) { for (unsigned i = 0, e = Elements.size(); i != e; ++i) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 022d9fe8b8..d352015a51 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -5820,8 +5820,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, if (AL.getKind() == AttributeList::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { S.Diag(AL.getLoc(), AL.isDeclspecAttribute() - ? diag::warn_unhandled_ms_attribute_ignored - : diag::warn_unknown_attribute_ignored) + ? diag::warn_unhandled_ms_attribute_ignored + : diag::warn_unknown_attribute_ignored) << AL.getName(); return; } @@ -5992,8 +5992,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, AL); break; case AttributeList::AT_CUDAHost: - handleSimpleAttributeWithExclusions(S, D, - AL); + handleSimpleAttributeWithExclusions(S, D, AL); break; case AttributeList::AT_GNUInline: handleGNUInlineAttr(S, D, AL); @@ -6095,8 +6094,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleObjCRuntimeName(S, D, AL); break; case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute(S, D, AL); - break; + handleSimpleAttribute(S, D, AL); + break; case AttributeList::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; @@ -6177,12 +6176,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute(S, D, AL); break; case AttributeList::AT_NotTailCalled: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions( + S, D, AL); break; case AttributeList::AT_DisableTailCalls: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions(S, D, + AL); break; case AttributeList::AT_Used: handleSimpleAttribute(S, D, AL); @@ -6458,18 +6457,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, - const AttributeList *AttrList, + const ParsedAttributesView &AttrList, bool IncludeCXX11Attributes) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); + if (AttrList.empty()) + return; + + for (const AttributeList &AL : AttrList) + ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); // FIXME: We should be able to handle these cases in TableGen. // GCC accepts // static int a9 __attribute__((weakref)); // but that looks really pointless. We reject it. if (D->hasAttr() && !D->hasAttr()) { - Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) - << cast(D); + Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) + << cast(D); D->dropAttr(); return; } @@ -6517,44 +6519,46 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } // Helper for delayed processing TransparentUnion attribute. -void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { - for (const AttributeList *AL = AttrList; AL; AL = AL->getNext()) - if (AL->getKind() == AttributeList::AT_TransparentUnion) { - handleTransparentUnionAttr(*this, D, *AL); +void Sema::ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) + if (AL.getKind() == AttributeList::AT_TransparentUnion) { + handleTransparentUnionAttr(*this, D, AL); break; } } // Annotation attributes are the only attributes allowed after an access // specifier. -bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() == AttributeList::AT_Annotate) { - ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute()); +bool Sema::ProcessAccessDeclAttributeList( + AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) { + if (AL.getKind() == AttributeList::AT_Annotate) { + ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); } else { - Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); + Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); return true; } } - return false; } /// checkUnusedDeclAttributes - Check a list of attributes to see if it /// contains any decl attributes that we should warn about. -static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { - for ( ; A; A = A->getNext()) { +static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { + for (const AttributeList &AL : A) { // Only warn if the attribute is an unignored, non-type attribute. - if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; - if (A->getKind() == AttributeList::IgnoredAttribute) continue; + if (AL.isUsedAsTypeAttr() || AL.isInvalid()) + continue; + if (AL.getKind() == AttributeList::IgnoredAttribute) + continue; - if (A->getKind() == AttributeList::UnknownAttribute) { - S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) - << A->getName() << A->getRange(); + if (AL.getKind() == AttributeList::UnknownAttribute) { + S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL.getName() << AL.getRange(); } else { - S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) - << A->getName() << A->getRange(); + S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) + << AL.getName() << AL.getRange(); } } } @@ -6563,7 +6567,7 @@ static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { /// used to build a declaration, complain about any decl attributes /// which might be lying around on it. void Sema::checkUnusedDeclAttributes(Declarator &D) { - ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); + ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); ::checkUnusedDeclAttributes(*this, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); @@ -6670,20 +6674,19 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { /// specified in many different places, and we need to find and apply them all. void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. - if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, D, Attrs); + if (!PD.getDeclSpec().getAttributes().empty()) + ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes()); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: // int *__attr__(x)** D; // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) - if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); + ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), + /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. - if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(S, D, Attrs); + ProcessDeclAttributeList(S, D, PD.getAttributes()); // Apply additional attributes specified by '#pragma clang attribute'. AddPragmaAttributes(S, D); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 822d5ef254..6f411ca26d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2300,18 +2300,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. - if (!Attributes.empty()) { - for (AttributeList *Attr = Attributes.getList(); Attr; - Attr = Attr->getNext()) { - if (Attr->isInvalid() || - Attr->getKind() == AttributeList::IgnoredAttribute) - continue; - Diag(Attr->getLoc(), - Attr->getKind() == AttributeList::UnknownAttribute - ? diag::warn_unknown_attribute_ignored - : diag::err_base_specifier_attribute) - << Attr->getName(); - } + for (const AttributeList &AL : Attributes) { + if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) + continue; + Diag(AL.getLoc(), AL.getKind() == AttributeList::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << AL.getName(); } TypeSourceInfo *TInfo = nullptr; @@ -2691,10 +2686,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. -bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, +bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs) { + const ParsedAttributesView &Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); @@ -2822,10 +2816,14 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { return false; } -static AttributeList *getMSPropertyAttr(AttributeList *list) { - for (AttributeList *it = list; it != nullptr; it = it->getNext()) - if (it->isDeclspecPropertyAttribute()) - return it; +static const AttributeList * +getMSPropertyAttr(const ParsedAttributesView &list) { + ParsedAttributesView::const_iterator Itr = + llvm::find_if(list, [](const AttributeList &AL) { + return AL.isDeclspecPropertyAttribute(); + }); + if (Itr != list.end()) + return &*Itr; return nullptr; } @@ -2904,8 +2902,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); - AttributeList *MSPropertyAttr = - getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); + const AttributeList *MSPropertyAttr = + getMSPropertyAttr(D.getDeclSpec().getAttributes()); if (cast(CurContext)->isInterface()) { // The Microsoft extension __interface only permits public member functions @@ -3073,7 +3071,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (MSPropertyAttr) { Member = HandleMSProperty(S, cast(CurContext), Loc, D, - BitWidth, InitStyle, AS, MSPropertyAttr); + BitWidth, InitStyle, AS, *MSPropertyAttr); if (!Member) return nullptr; isInstField = false; @@ -7809,22 +7807,20 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { } } -void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList) { +void Sema::ActOnFinishCXXMemberSpecification( + Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList) { if (!TagDecl) return; AdjustDeclIfTemplate(TagDecl); - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() != AttributeList::AT_Visibility) + for (const AttributeList &AL : AttrList) { + if (AL.getKind() != AttributeList::AT_Visibility) continue; - l->setInvalid(); - Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) << - l->getName(); + AL.setInvalid(); + Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) + << AL.getName(); } ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( @@ -8751,14 +8747,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. -Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, - SourceLocation InlineLoc, - SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl *&UD) { +Decl *Sema::ActOnStartNamespaceDef( + Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, + SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, + const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -9273,13 +9265,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, return false; } -Decl *Sema::ActOnUsingDirective(Scope *S, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList) { +Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + const ParsedAttributesView &AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); @@ -9371,15 +9361,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { S->PushUsingDirective(UDir); } - -Decl *Sema::ActOnUsingDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList) { + const ParsedAttributesView &AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { @@ -9836,15 +9823,11 @@ private: /// \param IsInstantiation - Whether this call arises from an /// instantiation of an unresolved using declaration. We treat /// the lookup differently for these declarations. -NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation) { +NamedDecl *Sema::BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -10410,14 +10393,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } -Decl *Sema::ActOnAliasDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, MultiTemplateParamsArg TemplateParamLists, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec) { + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->isTemplateParamScope()) S = S->getParent(); @@ -13575,13 +13555,12 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, } Decl *Sema::ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const ParsedAttributesView &AttrList, SourceLocation SemiLoc) { Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); // Attribute declarations appertain to empty declaration so we handle // them here. - if (AttrList) - ProcessDeclAttributeList(S, ED, AttrList); + ProcessDeclAttributeList(S, ED, AttrList); CurContext->addDecl(ED); return ED; @@ -13920,10 +13899,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, /// templated. Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -14036,7 +14014,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, return Friend; } - /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// @@ -15407,11 +15384,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. /// MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, - SourceLocation DeclStart, - Declarator &D, Expr *BitWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr) { + const AttributeList &MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); @@ -15474,7 +15451,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); - const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData(); + const AttributeList::PropertyData &Data = MSPropertyAttr.getPropertyData(); MSPropertyDecl *NewPD = MSPropertyDecl::Create( Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); ProcessDeclAttributes(TUScope, NewPD, D); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8c621dfa40..e1b033ea82 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -948,16 +948,14 @@ static bool checkTypeParamListConsistency(Sema &S, return false; } -Decl *Sema:: -ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, AttributeList *AttrList) { +Decl *Sema::ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. @@ -1042,9 +1040,8 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, IDecl->setInvalidDecl(); } } - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + ProcessDeclAttributeList(TUScope, IDecl, AttrList); AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); @@ -1183,15 +1180,11 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( return res; } -Decl * -Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); @@ -1234,9 +1227,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } - - if (AttrList) - ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + ProcessDeclAttributeList(TUScope, PDecl, AttrList); AddPragmaAttributes(TUScope, PDecl); // Merge attributes from previous declarations. @@ -1567,14 +1559,12 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // add the '*'. if (type->getAs()) { SourceLocation starLoc = getLocForEndOfToken(loc); - ParsedAttributes parsedAttrs(attrFactory); D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation()), - parsedAttrs, starLoc); // Diagnose the missing '*'. @@ -1752,7 +1742,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ArrayRef IdentList, - AttributeList *attrList) { + const ParsedAttributesView &attrList) { SmallVector DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; @@ -1765,9 +1755,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, PushOnScopeChains(PDecl, TUScope); CheckObjCDeclScope(PDecl); - - if (attrList) - ProcessDeclAttributeList(TUScope, PDecl, attrList); + + ProcessDeclAttributeList(TUScope, PDecl, attrList); AddPragmaAttributes(TUScope, PDecl); if (PrevDecl) @@ -1779,17 +1768,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, return BuildDeclaratorGroup(DeclsInGroup); } -Decl *Sema:: -ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); @@ -1858,8 +1843,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, // Process the attributes before looking at protocols to ensure that the // availability attribute is attached to the category to provide availability // checking for protocol uses. - if (AttrList) - ProcessDeclAttributeList(TUScope, CDecl, AttrList); + ProcessDeclAttributeList(TUScope, CDecl, AttrList); AddPragmaAttributes(TUScope, CDecl); if (NumProtoRefs) { @@ -4516,17 +4500,14 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef, } Decl *Sema::ActOnMethodDeclaration( - Scope *S, - SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, - Selector Sel, + Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!CurContext->isObjCContainer()) { @@ -4634,8 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); - if (AttrList) - ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 5e69feceda..9e53beb449 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1170,7 +1170,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, Class->setInvalidDecl(); SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); PopFunctionScopeInfo(); @@ -1608,7 +1608,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Finalize the lambda class. SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index ccf25ee9eb..058a2cd4f2 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -4283,7 +4283,7 @@ void Sema::ActOnCapturedRegionError() { SmallVector Fields(Record->fields()); ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields, - SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); PopDeclContext(); PopFunctionScopeInfo(); diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index e55e20c282..dbd967cc93 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -313,11 +313,12 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, } } -StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList, +StmtResult Sema::ProcessStmtAttributes(Stmt *S, + const ParsedAttributesView &AttrList, SourceRange Range) { SmallVector Attrs; - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range)) + for (const AttributeList &AL : AttrList) { + if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range)) Attrs.push_back(a); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 68a5196f6b..276a617d1a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1263,17 +1263,13 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } -DeclResult -Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList** OuterTemplateParamLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -1613,8 +1609,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK == TUK_Definition) NewClass->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); if (PrevClassTemplate) mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); @@ -7401,16 +7396,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs( return false; } -DeclResult -Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, - TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg - TemplateParameterLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); CXXScopeSpec &SS = TemplateId.SS; @@ -7711,8 +7701,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -8564,19 +8553,12 @@ static void dllExportImportClassTemplateSpecialization( } // Explicit instantiation of a class template specialization -DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc, - AttributeList *Attr) { +DeclResult Sema::ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.get(); TemplateDecl *TD = Name.getAsTemplateDecl(); @@ -8617,11 +8599,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, if (TSK == TSK_ExplicitInstantiationDeclaration) { // Check for dllexport class template instantiation declarations. - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLExport) { + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLExport) { Diag(ExternLoc, diag::warn_attribute_dllexport_explicit_instantiation_decl); - Diag(A->getLoc(), diag::note_attribute); + Diag(AL.getLoc(), diag::note_attribute); break; } } @@ -8641,10 +8623,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Check for dllimport class template instantiation definitions. bool DLLImport = ClassTemplate->getTemplatedDecl()->getAttr(); - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLImport) + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLImport) DLLImport = true; - if (A->getKind() == AttributeList::AT_DLLExport) { + if (AL.getKind() == AttributeList::AT_DLLExport) { // dllexport trumps dllimport here. DLLImport = false; break; @@ -8754,8 +8736,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setBraceRange(SourceRange()); bool PreviouslyDLLExported = Specialization->hasAttr(); - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add the explicit instantiation into its lexical context. However, // since explicit instantiations are never found by name lookup, we @@ -8853,15 +8834,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Explicit instantiation of a member class of a class template. DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr) { +Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr) { bool Owned = false; bool IsDependent = false; @@ -9163,8 +9140,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (PrevTemplate) { // Merge attributes. - if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, Prev, Attr); + ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); } if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); @@ -9200,7 +9176,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // template. UnresolvedSet<8> TemplateMatches; FunctionDecl *NonTemplateMatch = nullptr; - AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { @@ -9248,7 +9223,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, /* IgnoreImplicitHDAttributes = */ true) != - IdentifyCUDATarget(Attr)) { + IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -9327,8 +9302,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, return (Decl*) nullptr; } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes()); // In MSVC mode, dllimported explicit instantiation definitions are treated as // instantiation declarations. diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2218bdd958..5a4a6bd033 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2125,7 +2125,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // Finish checking fields. ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields, - SourceLocation(), SourceLocation(), nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Instantiation); // Default arguments are parsed, if not instantiated. We can go instantiate diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 68857d972b..5109dc8290 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1118,8 +1118,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition( } SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, - Enumerators, - nullptr, nullptr); + Enumerators, nullptr, ParsedAttributesView()); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -2648,7 +2647,8 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, + ParsedAttributesView(), /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c7e251d35b..18c5ce75d1 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -195,10 +195,10 @@ namespace { chunkIndex = idx; } - AttributeList *&getCurrentAttrListRef() const { + ParsedAttributesView &getCurrentAttributes() const { if (isProcessingDeclSpec()) - return getMutableDeclSpec().getAttributes().getListRef(); - return declarator.getTypeObject(chunkIndex).getAttrListRef(); + return getMutableDeclSpec().getAttributes(); + return declarator.getTypeObject(chunkIndex).getAttrs(); } /// Save the current set of attributes on the DeclSpec. @@ -207,9 +207,8 @@ namespace { if (hasSavedAttrs) return; DeclSpec &spec = getMutableDeclSpec(); - for (AttributeList *attr = spec.getAttributes().getList(); attr; - attr = attr->getNext()) - savedAttrs.push_back(attr); + for (AttributeList &AL : spec.getAttributes()) + savedAttrs.push_back(&AL); trivial &= savedAttrs.empty(); hasSavedAttrs = true; } @@ -241,46 +240,18 @@ namespace { void restoreDeclSpecAttrs() { assert(hasSavedAttrs); - if (savedAttrs.empty()) { - getMutableDeclSpec().getAttributes().set(nullptr); - return; - } - - getMutableDeclSpec().getAttributes().set(savedAttrs[0]); - for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) - savedAttrs[i]->setNext(savedAttrs[i+1]); - savedAttrs.back()->setNext(nullptr); + getMutableDeclSpec().getAttributes().clearListOnly(); + for (AttributeList *AL : savedAttrs) + getMutableDeclSpec().getAttributes().addAtStart(AL); } }; } // end anonymous namespace -static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { - attr.setNext(head); - head = &attr; -} - -static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) { - if (head == &attr) { - head = attr.getNext(); - return; - } - - AttributeList *cur = head; - while (true) { - assert(cur && cur->getNext() && "ran out of attrs?"); - if (cur->getNext() == &attr) { - cur->setNext(attr.getNext()); - return; - } - cur = cur->getNext(); - } -} - static void moveAttrFromListToList(AttributeList &attr, - AttributeList *&fromList, - AttributeList *&toList) { - spliceAttrOutOfList(attr, fromList); - spliceAttrIntoList(attr, toList); + ParsedAttributesView &fromList, + ParsedAttributesView &toList) { + fromList.remove(&attr); + toList.addAtStart(&attr); } /// The location of a type attribute. @@ -293,9 +264,8 @@ enum TypeAttrLocation { TAL_DeclName }; -static void processTypeAttrs(TypeProcessingState &state, - QualType &type, TypeAttrLocation TAL, - AttributeList *attrs); +static void processTypeAttrs(TypeProcessingState &state, QualType &type, + TypeAttrLocation TAL, ParsedAttributesView &attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, AttributeList &attr, @@ -416,8 +386,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, /*onlyBlockPointers=*/true); if (!destChunk) destChunk = &chunk; - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - destChunk->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + destChunk->getAttrs()); return; } @@ -432,8 +402,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, if (DeclaratorChunk *dest = maybeMovePastReturnType( declarator, i, /*onlyBlockPointers=*/true)) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - dest->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + dest->getAttrs()); return; } } @@ -493,8 +463,8 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // attribute from being applied multiple times and gives // the source-location-filler something to work with. state.saveDeclSpecAttrs(); - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getMutableDeclSpec().getAttributes().getListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getMutableDeclSpec().getAttributes()); return; } } @@ -502,13 +472,13 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // Otherwise, if we found an appropriate chunk, splice the attribute // into it. if (innermost != -1U) { - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getTypeObject(innermost).getAttrListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getTypeObject(innermost).getAttrs()); return; } // Otherwise, diagnose when we're done building the type. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -527,8 +497,8 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, DeclaratorChunk &chunk = declarator.getTypeObject(i-1); switch (chunk.Kind) { case DeclaratorChunk::Function: - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return; case DeclaratorChunk::Paren: @@ -548,11 +518,9 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, /// Try to distribute a function type attribute to the innermost /// function chunk or type. Returns true if the attribute was /// distributed, false if no location was found. -static bool -distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, - AttributeList &attr, - AttributeList *&attrList, - QualType &declSpecType) { +static bool distributeFunctionTypeAttrToInnermost( + TypeProcessingState &state, AttributeList &attr, + ParsedAttributesView &attrList, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); // Put it on the innermost function chunk, if there is one. @@ -560,7 +528,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, DeclaratorChunk &chunk = declarator.getTypeObject(i); if (chunk.Kind != DeclaratorChunk::Function) continue; - moveAttrFromListToList(attr, attrList, chunk.getAttrListRef()); + moveAttrFromListToList(attr, attrList, chunk.getAttrs()); return true; } @@ -579,15 +547,14 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, // the declarators. Move them straight there. We don't support the // 'put them wherever you like' semantics we allow for GNU attributes. if (attr.isCXX11Attribute()) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - state.getDeclarator().getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + state.getDeclarator().getAttributes()); return; } // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - state.getCurrentAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, state.getCurrentAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is @@ -604,14 +571,13 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - declarator.getAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, declarator.getAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is // fully built. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -627,24 +593,25 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, QualType &declSpecType) { // Collect all the type attributes from the declarator itself. - assert(state.getDeclarator().getAttributes() && "declarator has no attrs!"); - AttributeList *attr = state.getDeclarator().getAttributes(); - AttributeList *next; - do { - next = attr->getNext(); - + assert(!state.getDeclarator().getAttributes().empty() && + "declarator has no attrs!"); + // The called functions in this loop actually remove things from the current + // list, so iterating over the existing list isn't possible. Instead, make a + // non-owning copy and iterate over that. + ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()}; + for (AttributeList &attr : AttrsCopy) { // Do not distribute C++11 attributes. They have strict rules for what // they appertain to. - if (attr->isCXX11Attribute()) + if (attr.isCXX11Attribute()) continue; - switch (attr->getKind()) { + switch (attr.getKind()) { OBJC_POINTER_TYPE_ATTRS_CASELIST: - distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType); break; FUNCTION_TYPE_ATTRS_CASELIST: - distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType); break; MS_TYPE_ATTRS_CASELIST: @@ -661,7 +628,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, default: break; } - } while ((attr = next)); + } } /// Add a synthetic '()' to a block-literal declarator if it is @@ -761,28 +728,18 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, return false; // Warn if we see type attributes for omitted return type on a block literal. - AttributeList *&attrs = - declarator.getMutableDeclSpec().getAttributes().getListRef(); - AttributeList *prev = nullptr; - for (AttributeList *cur = attrs; cur; cur = cur->getNext()) { - AttributeList &attr = *cur; - // Skip attributes that were marked to be invalid or non-type - // attributes. - if (attr.isInvalid() || !attr.isTypeAttr()) { - prev = cur; + SmallVector ToBeRemoved; + for (AttributeList &AL : declarator.getMutableDeclSpec().getAttributes()) { + if (AL.isInvalid() || !AL.isTypeAttr()) continue; - } - S.Diag(attr.getLoc(), + S.Diag(AL.getLoc(), diag::warn_block_literal_attributes_on_omitted_return_type) - << attr.getName(); - // Remove cur from the list. - if (prev) { - prev->setNext(cur->getNext()); - prev = cur; - } else { - attrs = cur->getNext(); - } + << AL.getName(); + ToBeRemoved.push_back(&AL); } + // Remove bad attributes from the list. + for (AttributeList *AL : ToBeRemoved) + declarator.getMutableDeclSpec().getAttributes().remove(AL); // Warn if we see type qualifiers for omitted return type on a block literal. const DeclSpec &DS = declarator.getDeclSpec(); @@ -1210,18 +1167,11 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( return CreateParsedType(Result, ResultTInfo); } -static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) { - if (Attrs) { - const AttributeList *Next = Attrs; - do { - const AttributeList &Attr = *Next; - Next = Attr.getNext(); - if (Attr.getKind() == AttributeList::AT_OpenCLAccess) { - return static_cast( - Attr.getSemanticSpelling()); - } - } while (Next); - } +static OpenCLAccessAttr::Spelling +getImageAccess(const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) + if (AL.getKind() == AttributeList::AT_OpenCLAccess) + return static_cast(AL.getSemanticSpelling()); return OpenCLAccessAttr::Keyword_read_only; } @@ -1237,7 +1187,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - const DeclSpec &DS = declarator.getDeclSpec(); + DeclSpec &DS = declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getLocStart(); @@ -1582,16 +1532,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; -#define GENERIC_IMAGE_TYPE(ImgType, Id) \ - case DeclSpec::TST_##ImgType##_t: \ - switch (getImageAccess(DS.getAttributes().getList())) { \ - case OpenCLAccessAttr::Keyword_write_only: \ - Result = Context.Id##WOTy; break; \ - case OpenCLAccessAttr::Keyword_read_write: \ - Result = Context.Id##RWTy; break; \ - case OpenCLAccessAttr::Keyword_read_only: \ - Result = Context.Id##ROTy; break; \ - } \ +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + switch (getImageAccess(DS.getAttributes())) { \ + case OpenCLAccessAttr::Keyword_write_only: \ + Result = Context.Id##WOTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_write: \ + Result = Context.Id##RWTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_only: \ + Result = Context.Id##ROTy; \ + break; \ + } \ break; #include "clang/Basic/OpenCLImageTypes.def" @@ -1644,7 +1597,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // attributes are pushed around. // pipe attributes will be handled later ( at GetFullTypeForDeclarator ) if (!DS.isTypeSpecPipe()) - processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); + processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes()); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -2646,9 +2599,8 @@ static void inferARCWriteback(TypeProcessingState &state, if (chunk.Kind != DeclaratorChunk::Pointer && chunk.Kind != DeclaratorChunk::BlockPointer) return; - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) + for (const AttributeList &AL : chunk.getAttrs()) + if (AL.getKind() == AttributeList::AT_ObjCOwnership) return; transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing, @@ -2813,7 +2765,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // "void" instead. T = SemaRef.Context.VoidTy; processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; case UnqualifiedIdKind::IK_DeductionGuideName: @@ -2830,7 +2782,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, break; } - if (D.getAttributes()) + if (!D.getAttributes().empty()) distributeTypeAttrsFromDeclarator(state, T); // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. @@ -3314,21 +3266,20 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { /// this is the outermost chunk, then we can determine the CC from the /// declarator context. If not, then this could be either a member function /// type or normal function type. -static CallingConv -getCCForDeclaratorChunk(Sema &S, Declarator &D, - const DeclaratorChunk::FunctionTypeInfo &FTI, - unsigned ChunkIndex) { +static CallingConv getCCForDeclaratorChunk( + Sema &S, Declarator &D, const ParsedAttributesView &AttrList, + const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) { assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); // Check for an explicit CC attribute. - for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) { - switch (Attr->getKind()) { - CALLING_CONV_ATTRS_CASELIST: { + for (const AttributeList &AL : AttrList) { + switch (AL.getKind()) { + CALLING_CONV_ATTRS_CASELIST : { // Ignore attributes that don't validate or can't apply to the // function type. We'll diagnose the failure to apply them in // handleFunctionTypeAttr. CallingConv CC; - if (!S.CheckCallingConvAttr(*Attr, CC) && + if (!S.CheckCallingConvAttr(AL, CC) && (!FTI.isVariadic || supportsVariadicCall(CC))) { return CC; } @@ -3384,9 +3335,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, // convention attribute. This is the simplest place to infer // calling convention for OpenCL kernels. if (S.getLangOpts().OpenCL) { - for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_OpenCLKernel) { CC = CC_OpenCLKernel; break; } @@ -3437,12 +3387,11 @@ IdentifierInfo *Sema::getNSErrorIdent() { /// Check whether there is a nullability attribute of any kind in the given /// attribute list. -static bool hasNullabilityAttr(const AttributeList *attrs) { - for (const AttributeList *attr = attrs; attr; - attr = attr->getNext()) { - if (attr->getKind() == AttributeList::AT_TypeNonNull || - attr->getKind() == AttributeList::AT_TypeNullable || - attr->getKind() == AttributeList::AT_TypeNullUnspecified) +static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { + for (const AttributeList &AL : attrs) { + if (AL.getKind() == AttributeList::AT_TypeNonNull || + AL.getKind() == AttributeList::AT_TypeNullable || + AL.getKind() == AttributeList::AT_TypeNullUnspecified) return true; } @@ -4044,19 +3993,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // On pointer-to-pointer parameters marked cf_returns_retained or // cf_returns_not_retained, if the outer pointer is explicit then // infer the inner pointer as _Nullable. - auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool { - while (NextAttr) { - if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained || - NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained) - return true; - NextAttr = NextAttr->getNext(); - } - return false; + auto hasCFReturnsAttr = + [](const ParsedAttributesView &AttrList) -> bool { + return AttrList.hasAttribute(AttributeList::AT_CFReturnsRetained) || + AttrList.hasAttribute( + AttributeList::AT_CFReturnsNotRetained); }; if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) { if (hasCFReturnsAttr(D.getAttributes()) || hasCFReturnsAttr(InnermostChunk->getAttrs()) || - hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) { + hasCFReturnsAttr(D.getDeclSpec().getAttributes())) { inferNullability = NullabilityKind::Nullable; inferNullabilityInnerOnly = true; } @@ -4112,10 +4058,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Local function that checks the nullability for a given pointer declarator. // Returns true if _Nonnull was inferred. - auto inferPointerNullability = [&](SimplePointerKind pointerKind, - SourceLocation pointerLoc, - SourceLocation pointerEndLoc, - AttributeList *&attrs) -> AttributeList * { + auto inferPointerNullability = + [&](SimplePointerKind pointerKind, SourceLocation pointerLoc, + SourceLocation pointerEndLoc, + ParsedAttributesView &attrs) -> AttributeList * { // We've seen a pointer. if (NumPointersRemaining > 0) --NumPointersRemaining; @@ -4137,7 +4083,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, nullptr, SourceLocation(), nullptr, 0, syntax); - spliceAttrIntoList(*nullabilityAttr, attrs); + attrs.addAtStart(nullabilityAttr); if (inferNullabilityCS) { state.getDeclarator().getMutableDeclSpec().getObjCQualifiers() @@ -4192,9 +4138,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, pointerKind = SimplePointerKind::MemberPointer; if (auto *attr = inferPointerNullability( - pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), - D.getDeclSpec().getLocEnd(), - D.getMutableDeclSpec().getAttributes().getListRef())) { + pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), + D.getDeclSpec().getLocEnd(), + D.getMutableDeclSpec().getAttributes())) { T = Context.getAttributedType( AttributedType::getNullabilityAttrKind(*inferNullability),T,T); attr->setUsedAsTypeAttr(); @@ -4232,7 +4178,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability. inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name); if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) { @@ -4254,7 +4200,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (LangOpts.ObjC1 && T->getAs()) { T = Context.getObjCObjectPointerType(T); @@ -4528,20 +4474,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SourceLocation AttrLoc; if (chunkIndex + 1 < D.getNumTypeObjects()) { DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); - for (const AttributeList *Attr = ReturnTypeChunk.getAttrs(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : ReturnTypeChunk.getAttrs()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } } if (AttrLoc.isInvalid()) { - for (const AttributeList *Attr - = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } @@ -4581,7 +4524,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); + FunctionType::ExtInfo EI( + getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus && !LangOpts.OpenCL) { @@ -4591,19 +4535,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // We allow a zero-parameter variadic function in C if the // function is marked with the "overloadable" attribute. Scan // for this attribute now. - if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) { - bool Overloadable = false; - for (const AttributeList *Attrs = D.getAttributes(); - Attrs; Attrs = Attrs->getNext()) { - if (Attrs->getKind() == AttributeList::AT_Overloadable) { - Overloadable = true; - break; - } - } - - if (!Overloadable) + if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) + if (!D.getAttributes().hasAttribute(AttributeList::AT_Overloadable)) S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param); - } if (FTI.NumParams && FTI.Params[0].Param == nullptr) { // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function @@ -4758,7 +4692,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability. inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (SS.isInvalid()) { // Avoid emitting extra errors if we already errored on the scope. @@ -4814,7 +4748,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::Pipe: { T = S.BuildReadPipeType(T, DeclType.Loc); processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; } } @@ -4825,8 +4759,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } // See if there are any attributes on this declarator chunk. - processTypeAttrs(state, T, TAL_DeclChunk, - const_cast(DeclType.getAttrs())); + processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs()); } // GNU warning -Wstrict-prototypes @@ -5091,10 +5024,8 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, // Look for an explicit lifetime attribute. DeclaratorChunk &chunk = D.getTypeObject(chunkIndex); - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) - return; + if (chunk.getAttrs().hasAttribute(AttributeList::AT_ObjCOwnership)) + return; const char *attrStr = nullptr; switch (ownership) { @@ -5117,8 +5048,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ nullptr, SourceLocation(), /*args*/ &Args, 1, AttributeList::AS_GNU); - spliceAttrIntoList(*attr, chunk.getAttrListRef()); - + chunk.getAttrs().addAtStart(attr); // TODO: mark whether we did this inference? } @@ -5262,39 +5192,19 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { llvm_unreachable("unexpected attribute kind!"); } -static void fillAttributedTypeLoc(AttributedTypeLoc TL, - const AttributeList *attrs, - const AttributeList *DeclAttrs = nullptr) { - // DeclAttrs and attrs cannot be both empty. - assert((attrs || DeclAttrs) && - "no type attributes in the expected location!"); - - AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); - // Try to search for an attribute of matching kind in attrs list. - while (attrs && attrs->getKind() != parsedKind) - attrs = attrs->getNext(); - if (!attrs) { - // No matching type attribute in attrs list found. - // Try searching through C++11 attributes in the declarator attribute list. - while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() || - DeclAttrs->getKind() != parsedKind)) - DeclAttrs = DeclAttrs->getNext(); - attrs = DeclAttrs; - } - - assert(attrs && "no matching type attribute in expected location!"); - - TL.setAttrNameLoc(attrs->getLoc()); +static void setAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList &attr) { + TL.setAttrNameLoc(attr.getLoc()); if (TL.hasAttrExprOperand()) { - assert(attrs->isArgExpr(0) && "mismatched attribute operand kind"); - TL.setAttrExprOperand(attrs->getArgAsExpr(0)); + assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); + TL.setAttrExprOperand(attr.getArgAsExpr(0)); } else if (TL.hasAttrEnumOperand()) { - assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) && + assert((attr.isArgIdent(0) || attr.isArgExpr(0)) && "unexpected attribute operand kind"); - if (attrs->isArgIdent(0)) - TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc); + if (attr.isArgIdent(0)) + TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc); else - TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc()); + TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc()); } // FIXME: preserve this information to here. @@ -5302,6 +5212,25 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, TL.setAttrOperandParensRange(SourceRange()); } +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const ParsedAttributesView &Attrs, + const ParsedAttributesView &DeclAttrs) { + // DeclAttrs and Attrs cannot be both empty. + assert((!Attrs.empty() || !DeclAttrs.empty()) && + "no type attributes in the expected location!"); + + AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); + // Try to search for an attribute of matching kind in Attrs list. + for (const AttributeList &AL : Attrs) + if (AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + + for (const AttributeList &AL : DeclAttrs) + if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + llvm_unreachable("no matching type attribute in expected location!"); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor { ASTContext &Context; @@ -5312,7 +5241,7 @@ namespace { : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { @@ -5484,7 +5413,7 @@ namespace { } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, Chunk.getAttrs()); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5617,16 +5546,20 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { ATL.setParensRange(SourceRange()); } -static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, - const AttributeList *Attrs) { - while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace) - Attrs = Attrs->getNext(); +static void +fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, + const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) { + if (AL.getKind() == AttributeList::AT_AddressSpace) { + DASTL.setAttrNameLoc(AL.getLoc()); + DASTL.setAttrExprOperand(AL.getArgAsExpr(0)); + DASTL.setAttrOperandParensRange(SourceRange()); + return; + } + } - assert(Attrs && "no address_space attribute found at the expected location!"); - - DASTL.setAttrNameLoc(Attrs->getLoc()); - DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0)); - DASTL.setAttrOperandParensRange(SourceRange()); + llvm_unreachable( + "no address_space attribute found at the expected location!"); } /// Create and instantiate a TypeSourceInfo with type source information. @@ -5642,7 +5575,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, TypeSourceInfo *ReturnTypeInfo) { TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); - const AttributeList *DeclAttrs = D.getAttributes(); // Handle parameter packs whose type is a pack expansion. if (isa(T)) { @@ -5666,7 +5598,8 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } while (AttributedTypeLoc TL = CurrTL.getAs()) { - fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), + D.getAttributes()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -6558,7 +6491,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool { // If there is already a nullability attribute there, don't add // one. - if (hasNullabilityAttr(chunk.getAttrListRef())) + if (hasNullabilityAttr(chunk.getAttrs())) return false; // Complain about the nullability qualifier being in the wrong @@ -6591,8 +6524,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, " " + attr.getName()->getName().str() + " "); } - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return true; }; @@ -7239,16 +7172,18 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - TypeAttrLocation TAL, AttributeList *attrs) { + TypeAttrLocation TAL, + ParsedAttributesView &attrs) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. - while (attrs) { - AttributeList &attr = *attrs; - attrs = attr.getNext(); // reset to the next here due to early loop continue - // stmts + // This loop modifies the list pretty frequently, but we still need to make + // sure we visit every element once. Copy the attributes list, and iterate + // over that. + ParsedAttributesView AttrsCopy{attrs}; + for (AttributeList &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. if (attr.isInvalid()) -- GitLab From 37d341d1f0d786e0df31a6983a80cf96c30d5faf Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Jul 2018 21:11:25 +0000 Subject: [PATCH 0527/1023] PR38141: check whether noexcept-specifications are equivalent in redeclarations git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336946 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExceptionSpec.cpp | 14 ++++++++++---- test/CXX/except/except.spec/p3.cpp | 10 ++++++++++ test/SemaCXX/cxx1z-noexcept-function-type.cpp | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 8dce6d59c6..df5bc9b82b 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -530,10 +530,16 @@ static bool CheckEquivalentExceptionSpecImpl( } } - // FIXME: We treat dependent noexcept specifications as compatible even if - // their expressions are not equivalent. - if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) - return false; + // C++14 [except.spec]p3: + // Two exception-specifications are compatible if [...] both have the form + // noexcept(constant-expression) and the constant-expressions are equivalent + if (OldEST == EST_DependentNoexcept && NewEST == EST_DependentNoexcept) { + llvm::FoldingSetNodeID OldFSN, NewFSN; + Old->getNoexceptExpr()->Profile(OldFSN, S.Context, true); + New->getNoexceptExpr()->Profile(NewFSN, S.Context, true); + if (OldFSN == NewFSN) + return false; + } // Dynamic exception specifications with the same set of adjusted types // are compatible. diff --git a/test/CXX/except/except.spec/p3.cpp b/test/CXX/except/except.spec/p3.cpp index 03f1d7626c..d5af465104 100644 --- a/test/CXX/except/except.spec/p3.cpp +++ b/test/CXX/except/except.spec/p3.cpp @@ -104,3 +104,13 @@ void* operator new(mysize_t); void* operator new[](mysize_t); void* operator new[](mysize_t) throw(std::bad_alloc); +template void equivalent() noexcept (X); +template void equivalent() noexcept (X); + +template void not_equivalent() noexcept (X); // expected-note {{previous}} +template void not_equivalent() noexcept (Y); // expected-error {{does not match}} + +template void missing() noexcept (X); // expected-note {{previous}} +// FIXME: The missing exception specification that we report here doesn't make +// sense in the context of this declaration. +template void missing(); // expected-error {{missing exception specification 'noexcept(X)'}} diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp index 814b04c6e4..82ed724e1b 100644 --- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -10,7 +10,7 @@ template void redecl1() noexcept(noexcept(T())); // ok, same type template void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}} template void redecl2() noexcept(A); // expected-note {{previous}} -template void redecl2() noexcept(B); // expected-error {{conflicting types}} +template void redecl2() noexcept(B); // expected-error {{does not match previous}} // These have the same canonical type, but are still different. template void redecl3() throw(A); // expected-note {{previous}} -- GitLab From 0e073980598008bb839173d40f1b1306b16bc902 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Thu, 12 Jul 2018 21:21:29 +0000 Subject: [PATCH 0528/1023] Support linking static PIE binaries on NetBSD git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336947 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/NetBSD.cpp | 4 ++++ test/Driver/netbsd.c | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp index cbf5908d10..02caafda16 100644 --- a/lib/Driver/ToolChains/NetBSD.cpp +++ b/lib/Driver/ToolChains/NetBSD.cpp @@ -122,6 +122,10 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); + if (Args.hasArg(options::OPT_pie)) { + Args.AddAllArgs(CmdArgs, options::OPT_pie); + CmdArgs.push_back("--no-dynamic-linker"); + } } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); diff --git a/test/Driver/netbsd.c b/test/Driver/netbsd.c index 06b5eadfca..34ad6e4157 100644 --- a/test/Driver/netbsd.c +++ b/test/Driver/netbsd.c @@ -5,6 +5,9 @@ // RUN: -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=PIE %s // RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \ +// RUN: -static -pie --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=STATIC-PIE %s +// RUN: %clang -no-canonical-prefixes -target x86_64--netbsd \ // RUN: -shared --sysroot=%S/Inputs/basic_netbsd_tree %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=SHARED %s @@ -139,6 +142,16 @@ // STATIC: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbegin.o" // STATIC: "{{.*}}/usr/lib{{/|\\\\}}crtend.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" +// STATIC-PIE: ld{{.*}}" "--eh-frame-hdr" +// STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so" +// STATIC-PIE-NOT: "-Bshareable" +// STATIC-PIE: "-pie" +// STATIC-PIE-NOT: "-dynamic-linker" "/libexec/ld.elf_so" +// STATIC-PIE-NOT: "-Bshareable" +// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crt0.o" +// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crti.o" "{{.*}}/usr/lib{{/|\\\\}}crtbeginS.o" +// STATIC-PIE: "{{.*}}/usr/lib{{/|\\\\}}crtendS.o" "{{.*}}/usr/lib{{/|\\\\}}crtn.o" + // SHARED: ld{{.*}}" "--eh-frame-hdr" // SHARED-NOT: "-pie" // SHARED-NOT: "-dynamic-linker" -- GitLab From fb6fe237ce9a38b43c0eb39bbd6afa63c01ac70f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Jul 2018 23:32:39 +0000 Subject: [PATCH 0529/1023] PR38136: improve handling of template argument deduction of non-trailing function parameter packs. This makes our handling of non-trailing function parameter packs consistent between the case of deduction at the top level in a function call and other cases where deduction encounters a non-trailing function parameter pack. Instead of treating a non-trailing pack and all later parameters as being non-deduced, we treat a non-trailing pack as exactly matching any explicitly-specified template arguments (or being an empty pack if there are no such arguments). This corresponds to the "never deduced" rule in [temp.deduct.call]p1, but generalized to all deduction contexts. Non-trailing template argument packs still result in the entire template argument list being treated as non-deduced, as specified in [temp.deduct.type]p9. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336962 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 80 ++++++++++++------- .../temp.deduct/temp.deduct.type/p5-0x.cpp | 18 ++++- .../temp.deduct/temp.deduct.type/p9-0x.cpp | 38 +++++++++ 3 files changed, 106 insertions(+), 30 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 8ae22136e1..3a480628a7 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -941,12 +941,6 @@ DeduceTemplateArguments(Sema &S, SmallVectorImpl &Deduced, unsigned TDF, bool PartialOrdering = false) { - // Fast-path check to see if we have too many/too few arguments. - if (NumParams != NumArgs && - !(NumParams && isa(Params[NumParams - 1])) && - !(NumArgs && isa(Args[NumArgs - 1]))) - return Sema::TDK_MiscellaneousDeductionFailure; - // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type // Pi of the respective parameter-type- list of P is compared with the @@ -983,13 +977,6 @@ DeduceTemplateArguments(Sema &S, continue; } - // C++0x [temp.deduct.type]p5: - // The non-deduced contexts are: - // - A function parameter pack that does not occur at the end of the - // parameter-declaration-clause. - if (ParamIdx + 1 < NumParams) - return Sema::TDK_Success; - // C++0x [temp.deduct.type]p10: // If the parameter-declaration corresponding to Pi is a function // parameter pack, then the type of its declarator- id is compared with @@ -1000,15 +987,41 @@ DeduceTemplateArguments(Sema &S, QualType Pattern = Expansion->getPattern(); PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern); - for (; ArgIdx < NumArgs; ++ArgIdx) { - // Deduce template arguments from the pattern. - if (Sema::TemplateDeductionResult Result - = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, - Args[ArgIdx], Info, Deduced, - TDF, PartialOrdering)) - return Result; + if (ParamIdx + 1 == NumParams) { + for (; ArgIdx < NumArgs; ++ArgIdx) { + // Deduce template arguments from the pattern. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, + Args[ArgIdx], Info, Deduced, + TDF, PartialOrdering)) + return Result; - PackScope.nextPackElement(); + PackScope.nextPackElement(); + } + } else { + // C++0x [temp.deduct.type]p5: + // The non-deduced contexts are: + // - A function parameter pack that does not occur at the end of the + // parameter-declaration-clause. + // + // FIXME: There is no wording to say what we should do in this case. We + // choose to resolve this by applying the same rule that is applied for a + // function call: that is, deduce all contained packs to their + // explicitly-specified values (or to <> if there is no such value). + // + // This is seemingly-arbitrarily different from the case of a template-id + // with a non-trailing pack-expansion in its arguments, which renders the + // entire template-argument-list a non-deduced context. + + // If the parameter type contains an explicitly-specified pack that we + // could not expand, skip the number of parameters notionally created + // by the expansion. + Optional NumExpansions = Expansion->getNumExpansions(); + if (NumExpansions && !PackScope.isPartiallyExpanded()) { + for (unsigned I = 0; I != *NumExpansions && ArgIdx < NumArgs; + ++I, ++ArgIdx) + PackScope.nextPackElement(); + } } // Build argument packs for each of the parameter packs expanded by this @@ -2195,10 +2208,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // template parameter packs expanded by Pi. TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern(); - // FIXME: If there are no remaining arguments, we can bail out early - // and set any deduced parameter packs to an empty argument pack. - // The latter part of this is a (minor) correctness issue. - // Prepare to deduce the packs within the pattern. PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern); @@ -5280,9 +5289,24 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, const FunctionProtoType *Proto = cast(T); MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth, Used); - for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) - MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, - Depth, Used); + for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) { + // C++17 [temp.deduct.type]p5: + // The non-deduced contexts are: [...] + // -- A function parameter pack that does not occur at the end of the + // parameter-declaration-list. + if (!OnlyDeduced || I + 1 == N || + !Proto->getParamType(I)->getAs()) { + MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, + Depth, Used); + } else { + // FIXME: C++17 [temp.deduct.call]p1: + // When a function parameter pack appears in a non-deduced context, + // the type of that pack is never deduced. + // + // We should also track a set of "never deduced" parameters, and + // subtract that from the list of deduced parameters after marking. + } + } if (auto *E = Proto->getNoexceptExpr()) MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used); break; diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp index d239a5e172..697412995b 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// expected-no-diagnostics // FIXME: More bullets to go! @@ -16,8 +15,23 @@ struct has_nondeduced_pack_test when processing the first argument, +// and then fail because 'int' doesn't match 'double, int'.) int check_nondeduced_pack_test0[ has_nondeduced_pack_test::value? 1 : -1]; + int(float, double)>::value? -1 : 1]; +template void has_non_trailing_pack(T ..., int); +void (*ptr_has_non_trailing_pack)(char, int) = has_non_trailing_pack; +template void has_non_trailing_pack_and_more(T ..., U); // expected-note {{failed}} +void (*ptr_has_non_trailing_pack_and_more_1)(float, double, int) = &has_non_trailing_pack_and_more; +void (*ptr_has_non_trailing_pack_and_more_2)(float, double, int) = &has_non_trailing_pack_and_more; // expected-error {{does not match}} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp index 54a54b0c48..fccac8f1e5 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -35,6 +35,44 @@ namespace PackExpansionNotAtEnd { struct UselessPartialSpec; // expected-error{{class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used}} } +// When a pack expansion occurs within a template argument list, the entire +// list is a non-deduced context. For the corresponding case in a function +// parameter list, only that parameter is non-deduced. +// +// FIXME: It's not clear that this difference is intended, but the wording is +// explicit. +namespace PackExpansionNotAtEndFunctionVersusTemplate { + template struct X {}; + template void f1(void(T..., U)); + // expected-note@+1 {{couldn't infer template argument 'U'}} + template void f2(X); // FIXME: ill-formed, U is not deducible + + void g(int, int, int); + X h; + void test() { + // This is deducible: the T... parameter is a non-deduced context, but + // that's OK because we don't need to deduce it. + f1(g); + // This is not deducible: the T... parameter renders the entire + // template-argument-list a non-deduced context, so U is not deducible. + f2(h); // expected-error {{no matching function}} + } + + template struct Y; + template + struct Y {}; // expected-error {{cannot be deduced}} + template // expected-note {{non-deducible template parameter 'U'}} + struct Y>; // expected-error {{cannot be deduced}} + // FIXME: T is not deducible here, due to [temp.deduct.call]p1: + // "When a function parameter pack appears in a non-deduced context, + // the type of that pack is never deduced." + template + struct Y {}; +} + namespace DeduceNonTypeTemplateArgsInArray { template struct split_arrays; -- GitLab From ad8d9be58ec32f09df665d328853f66373b0543a Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Fri, 13 Jul 2018 12:21:38 +0000 Subject: [PATCH 0530/1023] [analyzer][UninitializedObjectChecker] Support for MemberPointerTypes Differential Revision: https://reviews.llvm.org/D48325 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336994 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 40 +++++-------------- .../cxx-uninitialized-object-ptr-ref.cpp | 12 ++---- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index 016be6fed8..a44ae9cd8d 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -131,12 +131,10 @@ private: // - a non-union record // - a pointer/reference // - an array - // - of a member pointer type - // - of a primitive type, which we'll define as either a BuiltinType or - // EnumeralType. + // - of a primitive type, which we'll define later in a helper function. // * the parent of each node is the object that contains it - // * every leaf is an array, a primitive object, a member pointer, a nullptr - // or an undefined pointer. + // * every leaf is an array, a primitive object, a nullptr or an undefined + // pointer. // // Example: // @@ -163,8 +161,8 @@ private: // // From this we'll construct a vector of fieldchains, where each fieldchain // represents an uninitialized field. An uninitialized field may be a - // primitive object, a member pointer, a pointer, a pointee or a union without - // a single initialized field. + // primitive object, a pointer, a pointee or a union without a single + // initialized field. // In the above example, for the default constructor call we'll end up with // these fieldchains: // @@ -189,10 +187,6 @@ private: bool isPointerOrReferenceUninit(const FieldRegion *FR, FieldChainInfo LocalChain); - /// This method checks a region of MemberPointerType, and returns true if the - /// the pointer is uninitialized. - bool isMemberPointerUninit(const FieldRegion *FR, FieldChainInfo LocalChain); - /// This method returns true if the value of a primitive object is /// uninitialized. bool isPrimitiveUninit(const SVal &V); @@ -225,10 +219,13 @@ static bool isCalledByConstructor(const CheckerContext &Context); /// known, and thus FD can not be analyzed. static bool isVoidPointer(const FieldDecl *FD); -/// Returns true if T is a primitive type. We'll call a type primitive if it's -/// either a BuiltinType or an EnumeralType. +/// Returns true if T is a primitive type. We defined this type so that for +/// objects that we'd only like analyze as much as checking whether their +/// value is undefined or not, such as ints and doubles, can be analyzed with +/// ease. This also helps ensuring that every special field type is handled +/// correctly. static bool isPrimitiveType(const QualType &T) { - return T->isBuiltinType() || T->isEnumeralType(); + return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType(); } /// Constructs a note message for a given FieldChainInfo object. @@ -392,13 +389,6 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, continue; } - if (T->isMemberPointerType()) { - if (isMemberPointerUninit(FR, LocalChain)) - ContainsUninitField = true; - continue; - } - - // If this is a pointer or reference type. if (T->isPointerType() || T->isReferenceType()) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; @@ -542,14 +532,6 @@ bool FindUninitializedFields::isPointerOrReferenceUninit( return false; } -bool FindUninitializedFields::isMemberPointerUninit(const FieldRegion *FR, - FieldChainInfo LocalChain) { - assert(FR->getDecl()->getType()->isMemberPointerType() && - "This function only checks regions that hold MemberPointerTypes!"); - // TODO: Implement support for MemberPointerTypes. - return false; -} - bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) { if (V.isUndef()) return true; diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index e6c0b91a62..db025420d7 100644 --- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -416,14 +416,12 @@ struct UsefulFunctions { #ifdef PEDANTIC struct PointerToMemberFunctionTest1 { - // TODO: we'd expect the note {{uninitialized field 'this->f'}} - void (UsefulFunctions::*f)(void); // no-note + void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}} PointerToMemberFunctionTest1() {} }; void fPointerToMemberFunctionTest1() { - // TODO: we'd expect the warning {{1 uninitialized field}} - PointerToMemberFunctionTest1(); // no-warning + PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}} } struct PointerToMemberFunctionTest2 { @@ -460,14 +458,12 @@ void fMultiPointerToMemberFunctionTest2() { } struct PointerToMemberDataTest1 { - // TODO: we'd expect the note {{uninitialized field 'this->f'}} - int UsefulFunctions::*d; // no-note + int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}} PointerToMemberDataTest1() {} }; void fPointerToMemberDataTest1() { - // TODO: we'd expect the warning {{1 uninitialized field}} - PointerToMemberDataTest1(); // no-warning + PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}} } struct PointerToMemberDataTest2 { -- GitLab From 08b72986d5d53d57e461c87c49046f2728edcabe Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Fri, 13 Jul 2018 12:54:47 +0000 Subject: [PATCH 0531/1023] [analyzer][UninitializedObjectChecker] Fixed captured lambda variable name Differential Revision: https://reviews.llvm.org/D48291 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336995 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 39 +++++++------- test/Analysis/cxx-uninitialized-object.cpp | 51 +++++++++++++++++-- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index a44ae9cd8d..5c94a5bd33 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -232,6 +232,10 @@ static bool isPrimitiveType(const QualType &T) { static void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain); +/// Returns with Field's name. This is a helper function to get the correct name +/// even if Field is a captured lambda variable. +static StringRef getVariableName(const FieldDecl *Field); + //===----------------------------------------------------------------------===// // Methods for UninitializedObjectChecker. //===----------------------------------------------------------------------===// @@ -581,22 +585,6 @@ const FieldDecl *FieldChainInfo::getEndOfChain() const { // "uninitialized field 'this->x'", but we can't refer to 'x' directly, // we need an explicit namespace resolution whether the uninit field was // 'D1::x' or 'D2::x'. -// -// TODO: If a field in the fieldchain is a captured lambda parameter, this -// function constructs an empty string for it: -// -// template struct A { -// Callable c; -// A(const Callable &c, int) : c(c) {} -// }; -// -// int b; // say that this isn't zero initialized -// auto alwaysTrue = [&b](int a) { return true; }; -// -// A call with these parameters: A::A(alwaysTrue, int()) -// will emit a note with the message "uninitialized field: 'this->c.'". If -// possible, the lambda parameter name should be retrieved or be replaced with a -// "" or something similar. void FieldChainInfo::print(llvm::raw_ostream &Out) const { if (Chain.isEmpty()) return; @@ -604,7 +592,7 @@ void FieldChainInfo::print(llvm::raw_ostream &Out) const { const llvm::ImmutableListImpl *L = Chain.getInternalPointer(); printTail(Out, L->getTail()); - Out << L->getHead()->getDecl()->getNameAsString(); + Out << getVariableName(L->getHead()->getDecl()); } void FieldChainInfo::printTail( @@ -615,7 +603,7 @@ void FieldChainInfo::printTail( printTail(Out, L->getTail()); const FieldDecl *Field = L->getHead()->getDecl(); - Out << Field->getNameAsString(); + Out << getVariableName(Field); Out << (Field->getType()->isPointerType() ? "->" : "."); } @@ -676,6 +664,21 @@ static void printNoteMessage(llvm::raw_ostream &Out, Out << "'"; } +static StringRef getVariableName(const FieldDecl *Field) { + // If Field is a captured lambda variable, Field->getName() will return with + // an empty string. We can however acquire it's name from the lambda's + // captures. + const auto *CXXParent = dyn_cast(Field->getParent()); + + if (CXXParent && CXXParent->isLambda()) { + assert(CXXParent->captures_begin()); + auto It = CXXParent->captures_begin() + Field->getFieldIndex(); + return It->getCapturedVar()->getName(); + } + + return Field->getName(); +} + void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { auto Chk = Mgr.registerChecker(); Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption( diff --git a/test/Analysis/cxx-uninitialized-object.cpp b/test/Analysis/cxx-uninitialized-object.cpp index 617ac78f40..39d4a7f801 100644 --- a/test/Analysis/cxx-uninitialized-object.cpp +++ b/test/Analysis/cxx-uninitialized-object.cpp @@ -736,6 +736,22 @@ void fMemsetTest2() { // Lambda tests. //===----------------------------------------------------------------------===// +template +struct LambdaThisTest { + Callable functor; + + LambdaThisTest(const Callable &functor, int) : functor(functor) { + // All good! + } +}; + +struct HasCapturableThis { + void fLambdaThisTest() { + auto isEven = [this](int a) { return a % 2 == 0; }; // no-crash + LambdaThisTest(isEven, int()); + } +}; + template struct LambdaTest1 { Callable functor; @@ -760,7 +776,7 @@ struct LambdaTest2 { void fLambdaTest2() { int b; - auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.'}} + auto equals = [&b](int a) { return a == b; }; // expected-note{{uninitialized field 'this->functor.b'}} LambdaTest2(equals, int()); } #else @@ -782,8 +798,8 @@ void fLambdaTest2() { namespace LT3Detail { struct RecordType { - int x; // expected-note{{uninitialized field 'this->functor..x'}} - int y; // expected-note{{uninitialized field 'this->functor..y'}} + int x; // expected-note{{uninitialized field 'this->functor.rec1.x'}} + int y; // expected-note{{uninitialized field 'this->functor.rec1.y'}} }; } // namespace LT3Detail @@ -826,6 +842,35 @@ void fLambdaTest3() { } #endif //PEDANTIC +template +struct MultipleLambdaCapturesTest1 { + Callable functor; + int dontGetFilteredByNonPedanticMode = 0; + + MultipleLambdaCapturesTest1(const Callable &functor, int) : functor(functor) {} // expected-warning{{2 uninitialized field}} +}; + +void fMultipleLambdaCapturesTest1() { + int b1, b2 = 3, b3; + auto equals = [&b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b1'}} + // expected-note@-1{{uninitialized field 'this->functor.b3'}} + MultipleLambdaCapturesTest1(equals, int()); +} + +template +struct MultipleLambdaCapturesTest2 { + Callable functor; + int dontGetFilteredByNonPedanticMode = 0; + + MultipleLambdaCapturesTest2(const Callable &functor, int) : functor(functor) {} // expected-warning{{1 uninitialized field}} +}; + +void fMultipleLambdaCapturesTest2() { + int b1, b2 = 3, b3; + auto equals = [b1, &b2, &b3](int a) { return a == b1 == b2 == b3; }; // expected-note{{uninitialized field 'this->functor.b3'}} + MultipleLambdaCapturesTest2(equals, int()); +} + //===----------------------------------------------------------------------===// // System header tests. //===----------------------------------------------------------------------===// -- GitLab From ff0bfffe182b84fdf08ee78d03df464a4191aaa0 Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Fri, 13 Jul 2018 13:44:44 +0000 Subject: [PATCH 0532/1023] [Analyzer] alpha.unix.cstring.OutOfBounds checker enable/disable fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was not possible to disable alpha.unix.cstring.OutOfBounds checker's reports since unix.Malloc checker always implicitly enabled the filter. Moreover if the checker was disabled from command line (-analyzer-disable-checker ..) the out of bounds warnings were nevertheless emitted under different checker names such as unix.cstring.NullArg, or unix.Malloc. This patch fixes the case sot that Malloc checker only enables implicitly the underlying modeling of strcpy, memcpy etc. but not the warning messages that would have been emmitted by alpha.unix.cstring.OutOfBounds Patch by: Dániel Krupp Differential Revision: https://reviews.llvm.org/D48831 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337000 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CStringChecker.cpp | 12 ++++----- test/Analysis/cstring-plist.c | 22 ++++++++++++++++ test/Analysis/malloc.c | 23 ++++++----------- test/Analysis/string.c | 25 ++++++++++++++++++- 4 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 test/Analysis/cstring-plist.c diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index a51bc062e1..278452ec99 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -305,10 +305,10 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false); if (StOutBound && !StInBound) { // These checks are either enabled by the CString out-of-bounds checker - // explicitly or the "basic" CStringNullArg checker support that Malloc - // checker enables. - assert(Filter.CheckCStringOutOfBounds || Filter.CheckCStringNullArg); - + // explicitly or implicitly by the Malloc checker. + // In the latter case we only do modeling but do not emit warning. + if (!Filter.CheckCStringOutOfBounds) + return nullptr; // Emit a bug report. if (warningMsg) { emitOutOfBoundsBug(C, StOutBound, S, warningMsg); @@ -1039,7 +1039,7 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, const Expr *CharE, std::tie(StateWholeReg, StateNotWholeReg) = State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL)); - // With the semantic of 'memset()', we should convert the CharVal to + // With the semantic of 'memset()', we should convert the CharVal to // unsigned char. CharVal = svalBuilder.evalCast(CharVal, Ctx.UnsignedCharTy, Ctx.IntTy); @@ -2418,5 +2418,5 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR, REGISTER_CHECKER(CStringNotNullTerm) void ento::registerCStringCheckerBasic(CheckerManager &Mgr) { - registerCStringNullArg(Mgr); + Mgr.registerChecker(); } diff --git a/test/Analysis/cstring-plist.c b/test/Analysis/cstring-plist.c new file mode 100644 index 0000000000..19d0e46fd3 --- /dev/null +++ b/test/Analysis/cstring-plist.c @@ -0,0 +1,22 @@ +// RUN: rm -f %t +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s +// RUN: FileCheck -input-file %t %s + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); +void free(void *); +char *strncpy(char *restrict s1, const char *restrict s2, size_t n); + + + +void cstringchecker_bounds_nocrash() { + char *p = malloc(2); + strncpy(p, "AAA", sizeof("AAA")); // we don't expect warning as the checker is disabled + free(p); +} + +// CHECK: diagnostics +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index 50be4ef3ba..3e86c29a55 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -375,7 +375,7 @@ void CheckUseZeroReallocatedPathWarn(_Bool b) { // or inter-procedural analysis, this is a conservative answer. int *f3() { static int *p = 0; - p = malloc(12); + p = malloc(12); return p; // no-warning } @@ -384,7 +384,7 @@ int *f3() { // functions or inter-procedural analysis, this is a conservative answer. static int *p_f4 = 0; int *f4() { - p_f4 = malloc(12); + p_f4 = malloc(12); return p_f4; // no-warning } @@ -1232,7 +1232,7 @@ void radar10978247(int myValueSize) { if (myValueSize <= sizeof(stackBuffer)) buffer = stackBuffer; - else + else buffer = malloc(myValueSize); // do stuff with the buffer @@ -1246,7 +1246,7 @@ void radar10978247_positive(int myValueSize) { if (myValueSize <= sizeof(stackBuffer)) buffer = stackBuffer; - else + else buffer = malloc(myValueSize); // do stuff with the buffer @@ -1254,7 +1254,7 @@ void radar10978247_positive(int myValueSize) { return; else return; // expected-warning {{leak}} -} +} // Previously this triggered a false positive // because malloc() is known to return uninitialized memory and the binding // of 'o' to 'p->n' was not getting propertly handled. Now we report a leak. @@ -1698,7 +1698,7 @@ void testReallocEscaped(void **memory) { void *smallocNoWarn(size_t size) { if (size == 0) { return malloc(1); // this branch is never called - } + } else { return malloc(size); } @@ -1777,21 +1777,12 @@ void freeFunctionPtr() { free((void *)fnptr); // expected-warning {{Argument to free() is a function pointer}} } -// Enabling the malloc checker enables some of the buffer-checking portions -// of the C-string checker. -void cstringchecker_bounds_nocrash() { - char *p = malloc(2); - strncpy(p, "AAA", sizeof("AAA")); // expected-warning {{Size argument is greater than the length of the destination buffer}} - - free(p); -} - void allocateSomeMemory(void *offendingParameter, void **ptr) { *ptr = malloc(1); } void testNoCrashOnOffendingParameter() { - // "extern" is necessary to avoid unrelated warnings + // "extern" is necessary to avoid unrelated warnings // on passing uninitialized value. extern void *offendingParameter; void* ptr; diff --git a/test/Analysis/string.c b/test/Analysis/string.c index 72a08cc850..7e8a7361cd 100644 --- a/test/Analysis/string.c +++ b/test/Analysis/string.c @@ -31,6 +31,8 @@ typedef typeof(sizeof(int)) size_t; void clang_analyzer_eval(int); int scanf(const char *restrict format, ...); +void *malloc(size_t); +void free(void *); //===----------------------------------------------------------------------=== // strlen() @@ -110,7 +112,7 @@ void strlen_global() { if (a == 0) { clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} // Make sure clang_analyzer_eval does not invalidate globals. - clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}} } // Call a function with unknown effects, which should invalidate globals. @@ -309,11 +311,13 @@ void strcpy_effects(char *x, char *y) { clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}} } +#ifndef SUPPRESS_OUT_OF_BOUND void strcpy_overflow(char *y) { char x[4]; if (strlen(y) == 4) strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}} } +#endif void strcpy_no_overflow(char *y) { char x[4]; @@ -348,11 +352,13 @@ void stpcpy_effect(char *x, char *y) { clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} } +#ifndef SUPPRESS_OUT_OF_BOUND void stpcpy_overflow(char *y) { char x[4]; if (strlen(y) == 4) stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}} } +#endif void stpcpy_no_overflow(char *y) { char x[4]; @@ -403,6 +409,7 @@ void strcat_effects(char *y) { clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} } +#ifndef SUPPRESS_OUT_OF_BOUND void strcat_overflow_0(char *y) { char x[4] = "12"; if (strlen(y) == 4) @@ -420,6 +427,7 @@ void strcat_overflow_2(char *y) { if (strlen(y) == 2) strcat(x, y); // expected-warning{{String copy function overflows destination buffer}} } +#endif void strcat_no_overflow(char *y) { char x[5] = "12"; @@ -496,6 +504,15 @@ void strncpy_effects(char *x, char *y) { clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} } +#ifndef SUPPRESS_OUT_OF_BOUND +// Enabling the malloc checker enables some of the buffer-checking portions +// of the C-string checker. +void cstringchecker_bounds_nocrash() { + char *p = malloc(2); + strncpy(p, "AAA", sizeof("AAA")); // expected-warning {{Size argument is greater than the length of the destination buffer}} + free(p); +} + void strncpy_overflow(char *y) { char x[4]; if (strlen(y) == 4) @@ -516,6 +533,7 @@ void strncpy_no_overflow2(char *y, int n) { if (strlen(y) == 3) strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}} } +#endif void strncpy_truncate(char *y) { char x[4]; @@ -592,6 +610,7 @@ void strncat_effects(char *y) { clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} } +#ifndef SUPPRESS_OUT_OF_BOUND void strncat_overflow_0(char *y) { char x[4] = "12"; if (strlen(y) == 4) @@ -615,6 +634,8 @@ void strncat_overflow_3(char *y) { if (strlen(y) == 4) strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}} } +#endif + void strncat_no_overflow_1(char *y) { char x[5] = "12"; if (strlen(y) == 2) @@ -632,6 +653,7 @@ void strncat_symbolic_dst_length(char *dst) { clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} } +#ifndef SUPPRESS_OUT_OF_BOUND void strncat_symbolic_src_length(char *src) { char dst[8] = "1234"; strncat(dst, src, 3); @@ -649,6 +671,7 @@ void strncat_unknown_src_length(char *src, int offset) { char dst2[8] = "1234"; strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}} } +#endif // There is no strncat_unknown_dst_length because if we can't get a symbolic // length for the "before" strlen, we won't be able to set one for "after". -- GitLab From 74701fe1cf2b869b46435d5eebd4a01aefb1f056 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 13 Jul 2018 15:07:47 +0000 Subject: [PATCH 0533/1023] [NFC] Rename clang::AttributeList to clang::ParsedAttr Since The type no longer contains the 'next' item anymore, it isn't a list, so rename it to ParsedAttr to be more accurate. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337005 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/InternalsManual.rst | 12 +- include/clang/Basic/Attr.td | 2 +- include/clang/Parse/Parser.h | 37 +- include/clang/Sema/DeclSpec.h | 4 +- include/clang/Sema/LoopHint.h | 2 +- .../Sema/{AttributeList.h => ParsedAttr.h} | 322 +++--- include/clang/Sema/Sema.h | 28 +- lib/Parse/ParseDecl.cpp | 92 +- lib/Parse/ParseDeclCXX.cpp | 30 +- lib/Parse/ParseExprCXX.cpp | 8 +- lib/Parse/ParseObjc.cpp | 4 +- lib/Parse/ParsePragma.cpp | 15 +- lib/Parse/ParseStmt.cpp | 4 +- lib/Parse/Parser.cpp | 2 +- lib/Sema/CMakeLists.txt | 2 +- lib/Sema/DeclSpec.cpp | 2 +- .../{AttributeList.cpp => ParsedAttr.cpp} | 90 +- lib/Sema/SemaAttr.cpp | 4 +- lib/Sema/SemaCUDA.cpp | 10 +- lib/Sema/SemaDecl.cpp | 8 +- lib/Sema/SemaDeclAttr.cpp | 989 +++++++++--------- lib/Sema/SemaDeclCXX.cpp | 21 +- lib/Sema/SemaStmtAttr.cpp | 22 +- lib/Sema/SemaTemplate.cpp | 10 +- lib/Sema/SemaType.cpp | 443 ++++---- utils/TableGen/ClangAttrEmitter.cpp | 53 +- 26 files changed, 1073 insertions(+), 1143 deletions(-) rename include/clang/Sema/{AttributeList.h => ParsedAttr.h} (72%) rename lib/Sema/{AttributeList.cpp => ParsedAttr.cpp} (68%) diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst index 940d32004d..7d85d2be28 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -1664,15 +1664,15 @@ and then the semantic handling of the attribute. Parsing of the attribute is determined by the various syntactic forms attributes can take, such as GNU, C++11, and Microsoft style attributes, as well as other information provided by the table definition of the attribute. Ultimately, the -parsed representation of an attribute object is an ``AttributeList`` object. +parsed representation of an attribute object is an ``ParsedAttr`` object. These parsed attributes chain together as a list of parsed attributes attached to a declarator or declaration specifier. The parsing of attributes is handled automatically by Clang, except for attributes spelled as keywords. When implementing a keyword attribute, the parsing of the keyword and creation of the -``AttributeList`` object must be done manually. +``ParsedAttr`` object must be done manually. Eventually, ``Sema::ProcessDeclAttributeList()`` is called with a ``Decl`` and -an ``AttributeList``, at which point the parsed attribute can be transformed +an ``ParsedAttr``, at which point the parsed attribute can be transformed into a semantic attribute. The process by which a parsed attribute is converted into a semantic attribute depends on the attribute definition and semantic requirements of the attribute. The end result, however, is that the semantic @@ -1751,8 +1751,8 @@ subjects in the list, but a custom diagnostic parameter can also be specified in the ``SubjectList``. The diagnostics generated for subject list violations are either ``diag::warn_attribute_wrong_decl_type`` or ``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is found -in `include/clang/Sema/AttributeList.h -`_ +in `include/clang/Sema/ParsedAttr.h +`_ If a previously unused Decl node is added to the ``SubjectList``, the logic used to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp `_ @@ -1887,7 +1887,7 @@ requirements. To support this feature, an attribute inheriting from should be the same value between all arguments sharing a spelling, and corresponds to the parsed attribute's ``Kind`` enumerator. This allows attributes to share a parsed attribute kind, but have distinct semantic -attribute classes. For instance, ``AttributeList::AT_Interrupt`` is the shared +attribute classes. For instance, ``ParsedAttr`` is the shared parsed attribute kind, but ARMInterruptAttr and MSP430InterruptAttr are the semantic attributes generated. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index c2edbbd47d..0219c715d3 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -509,7 +509,7 @@ class TargetSpecificAttr { // "exists" for a given target. So two target-specific attributes can share // the same name when they exist in different targets. To support this, a // Kind can be explicitly specified for a target-specific attribute. This - // corresponds to the AttributeList::AT_* enum that is generated and it + // corresponds to the ParsedAttr::AT_* enum that is generated and it // should contain a shared value between the attributes. // // Target-specific attributes which use this feature should ensure that the diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f4d9f0168f..c6ffcde5a1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -238,7 +238,7 @@ class Parser : public CodeCompletionHandler { unsigned getDepth() const { return Depth; } }; - /// Factory object for creating AttributeList objects. + /// Factory object for creating ParsedAttr objects. AttributeFactory AttrFactory; /// Gathers and cleans up TemplateIdAnnotations when parsing of a @@ -2361,7 +2361,7 @@ private: ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void MaybeParseGNUAttributes(Declarator &D, LateParsedAttrList *LateAttrs = nullptr) { @@ -2384,19 +2384,16 @@ private: Declarator *D = nullptr); void ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - AttributeList::Syntax Syntax, - Declarator *D); + ParsedAttributes &Attrs, SourceLocation *EndLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + ParsedAttr::Syntax Syntax, Declarator *D); IdentifierLoc *ParseIdentifierLoc(); unsigned ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void MaybeParseCXX11Attributes(Declarator &D) { if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { @@ -2482,7 +2479,7 @@ private: SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); Optional ParseAvailabilitySpec(); ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc); @@ -2493,7 +2490,7 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, @@ -2501,7 +2498,7 @@ private: SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, @@ -2509,15 +2506,13 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); - - void ParseAttributeWithTypeArg(IdentifierInfo &AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); + + void + ParseAttributeWithTypeArg(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, ParsedAttributes &Attrs, + SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax); void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 77e90a964f..02afb093fd 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -29,8 +29,8 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/Token.h" -#include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -2406,7 +2406,7 @@ public: /// Return a source range list of C++11 attributes associated /// with the declarator. void getCXX11AttributeRanges(SmallVectorImpl &Ranges) { - for (const AttributeList &AL : Attrs) + for (const ParsedAttr &AL : Attrs) if (AL.isCXX11Attribute()) Ranges.push_back(AL.getRange()); } diff --git a/include/clang/Sema/LoopHint.h b/include/clang/Sema/LoopHint.h index 0da1136004..171435e69b 100644 --- a/include/clang/Sema/LoopHint.h +++ b/include/clang/Sema/LoopHint.h @@ -12,8 +12,8 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" namespace clang { diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/ParsedAttr.h similarity index 72% rename from include/clang/Sema/AttributeList.h rename to include/clang/Sema/ParsedAttr.h index 70a0306f41..3f29324778 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/ParsedAttr.h @@ -1,4 +1,4 @@ -//===- AttributeList.h - Parsed attribute sets ------------------*- C++ -*-===// +//======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the AttributeList class, which is used to collect +// This file defines the ParsedAttr class, which is used to collect // parsed attributes. // //===----------------------------------------------------------------------===// @@ -60,7 +60,7 @@ enum AvailabilitySlot { IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots }; -/// Describes the trailing object for Availability attribute in AttributeList. +/// Describes the trailing object for Availability attribute in ParsedAttr. struct AvailabilityData { AvailabilityChange Changes[NumAvailabilitySlots]; SourceLocation StrictLoc; @@ -89,11 +89,11 @@ struct IdentifierLoc { }; /// A union of the various pointer types that can be passed to an -/// AttributeList as an argument. +/// ParsedAttr as an argument. using ArgsUnion = llvm::PointerUnion; using ArgsVector = llvm::SmallVector; -/// AttributeList - Represents a syntactic attribute. +/// ParsedAttr - Represents a syntactic attribute. /// /// For a GNU attribute, there are four forms of this construct: /// @@ -102,7 +102,7 @@ using ArgsVector = llvm::SmallVector; /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class AttributeList { // TODO: This should really be called ParsedAttribute +class ParsedAttr { // TODO: This should really be called ParsedAttribute public: /// The style used to specify an attribute. enum Syntax { @@ -215,10 +215,10 @@ private: friend class AttributePool; /// Constructor for attributes with expression arguments. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - Syntax syntaxUsed, SourceLocation ellipsisLoc) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, + SourceLocation ellipsisLoc) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), @@ -229,15 +229,13 @@ private: } /// Constructor for availability attributes. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Parm, const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *messageExpr, - Syntax syntaxUsed, SourceLocation strict, - const Expr *replacementExpr) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Parm, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, SourceLocation unavailable, + const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, + const Expr *replacementExpr) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), @@ -252,12 +250,10 @@ private: } /// Constructor for objc_bridge_related attributes. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Parm1, - IdentifierLoc *Parm2, - IdentifierLoc *Parm3, - Syntax syntaxUsed) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, + Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), @@ -271,10 +267,10 @@ private: } /// Constructor for type_tag_for_datatype attribute. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *ArgKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *ArgKind, ParsedType matchingCType, + bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), @@ -290,9 +286,9 @@ private: } /// Constructor for attributes with a single type argument. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, Syntax syntaxUsed) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), @@ -303,13 +299,13 @@ private: } /// Constructor for microsoft __declspec(property) attribute. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - Syntax syntaxUsed) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), + ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), HasProcessingCache(false) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); @@ -350,9 +346,9 @@ private: size_t allocated_size() const; public: - AttributeList(const AttributeList &) = delete; - AttributeList &operator=(const AttributeList &) = delete; - ~AttributeList() = delete; + ParsedAttr(const ParsedAttr &) = delete; + ParsedAttr &operator=(const ParsedAttr &) = delete; + ~ParsedAttr() = delete; void operator delete(void *) = delete; @@ -559,18 +555,17 @@ public: /// The required allocation size of an availability attribute, /// which we want to ensure is a multiple of sizeof(void*). AvailabilityAllocSize = - sizeof(AttributeList) - + ((sizeof(AvailabilityData) + sizeof(void*) + sizeof(ArgsUnion) - 1) - / sizeof(void*) * sizeof(void*)), - TypeTagForDatatypeAllocSize = - sizeof(AttributeList) - + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + - sizeof(ArgsUnion) - 1) - / sizeof(void*) * sizeof(void*), + sizeof(ParsedAttr) + + ((sizeof(AvailabilityData) + sizeof(void *) + sizeof(ArgsUnion) - 1) / + sizeof(void *) * sizeof(void *)), + TypeTagForDatatypeAllocSize = sizeof(ParsedAttr) + + (sizeof(ParsedAttr::TypeTagForDatatypeData) + + sizeof(void *) + sizeof(ArgsUnion) - 1) / + sizeof(void *) * sizeof(void *), PropertyAllocSize = - sizeof(AttributeList) - + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) - / sizeof(void*) * sizeof(void*) + sizeof(ParsedAttr) + + (sizeof(ParsedAttr::PropertyData) + sizeof(void *) - 1) / + sizeof(void *) * sizeof(void *) }; private: @@ -581,15 +576,14 @@ private: /// attribute that needs more than that; on x86-64 you'd need 10 /// expression arguments, and on i386 you'd need 19. InlineFreeListsCapacity = - 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) + 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *) }; llvm::BumpPtrAllocator Alloc; /// Free lists. The index is determined by the following formula: - /// (size - sizeof(AttributeList)) / sizeof(void*) - SmallVector, InlineFreeListsCapacity> - FreeLists; + /// (size - sizeof(ParsedAttr)) / sizeof(void*) + SmallVector, InlineFreeListsCapacity> FreeLists; // The following are the private interface used by AttributePool. friend class AttributePool; @@ -597,7 +591,7 @@ private: /// Allocate an attribute of the given size. void *allocate(size_t size); - void deallocate(AttributeList *AL); + void deallocate(ParsedAttr *AL); /// Reclaim all the attributes in the given pool chain, which is /// non-empty. Note that the current implementation is safe @@ -614,18 +608,18 @@ public: class AttributePool { friend class AttributeFactory; AttributeFactory &Factory; - llvm::TinyPtrVector Attrs; + llvm::TinyPtrVector Attrs; void *allocate(size_t size) { return Factory.allocate(size); } - AttributeList *add(AttributeList *attr) { + ParsedAttr *add(ParsedAttr *attr) { Attrs.push_back(attr); return attr; } - void remove(AttributeList *attr) { + void remove(ParsedAttr *attr) { assert(llvm::is_contained(Attrs, attr) && "Can't take attribute from a pool that doesn't own it!"); Attrs.erase(llvm::find(Attrs, attr)); @@ -657,97 +651,93 @@ public: pool.Attrs.clear(); } - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - AttributeList::Syntax syntax, - SourceLocation ellipsisLoc = SourceLocation()) { - void *memory = - allocate(sizeof(AttributeList) + numArgs * sizeof(ArgsUnion)); - return add(new (memory) - AttributeList(attrName, attrRange, scopeName, scopeLoc, args, - numArgs, syntax, ellipsisLoc)); - } - - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param, - const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, const Expr *MessageExpr, - AttributeList::Syntax syntax, SourceLocation strict, - const Expr *ReplacementExpr) { + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, + ParsedAttr::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { + void *memory = allocate(sizeof(ParsedAttr) + numArgs * sizeof(ArgsUnion)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + args, numArgs, syntax, ellipsisLoc)); + } + + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, const Expr *MessageExpr, + ParsedAttr::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) AttributeList( + return add(new (memory) ParsedAttr( attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); } - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, IdentifierLoc *Param2, - IdentifierLoc *Param3, AttributeList::Syntax syntax) { - size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + size_t size = sizeof(ParsedAttr) + 3 * sizeof(ArgsUnion); void *memory = allocate(size); - return add(new (memory) - AttributeList(attrName, attrRange, scopeName, scopeLoc, - Param1, Param2, Param3, syntax)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax)); } - AttributeList * + ParsedAttr * createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *argumentKind, ParsedType matchingCType, bool layoutCompatible, - bool mustBeNull, AttributeList::Syntax syntax) { + bool mustBeNull, ParsedAttr::Syntax syntax) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); - return add(new (memory) AttributeList( - attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, - layoutCompatible, mustBeNull, syntax)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax)); } - AttributeList * - createTypeAttribute(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { - void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); - return add(new (memory) AttributeList(attrName, attrRange, scopeName, - scopeLoc, typeArg, syntaxUsed)); + ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, + SourceRange attrRange, + IdentifierInfo *scopeName, + SourceLocation scopeLoc, ParsedType typeArg, + ParsedAttr::Syntax syntaxUsed) { + void *memory = allocate(sizeof(ParsedAttr) + sizeof(void *)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + typeArg, syntaxUsed)); } - AttributeList * + ParsedAttr * createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { + ParsedAttr::Syntax syntaxUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); - return add(new (memory) - AttributeList(attrName, attrRange, scopeName, scopeLoc, - getterId, setterId, syntaxUsed)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + getterId, setterId, syntaxUsed)); } }; class ParsedAttributesView { - using VecTy = llvm::TinyPtrVector; + using VecTy = llvm::TinyPtrVector; using SizeType = decltype(std::declval().size()); public: bool empty() const { return AttrList.empty(); } SizeType size() const { return AttrList.size(); } - AttributeList &operator[](SizeType pos) { return *AttrList[pos]; } - const AttributeList &operator[](SizeType pos) const { return *AttrList[pos]; } + ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } + const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; } - void addAtStart(AttributeList *newAttr) { + void addAtStart(ParsedAttr *newAttr) { assert(newAttr); AttrList.insert(AttrList.begin(), newAttr); } - void addAtEnd(AttributeList *newAttr) { + void addAtEnd(ParsedAttr *newAttr) { assert(newAttr); AttrList.push_back(newAttr); } - void remove(AttributeList *ToBeRemoved) { + void remove(ParsedAttr *ToBeRemoved) { assert(is_contained(AttrList, ToBeRemoved) && "Cannot remove attribute that isn't in the list"); AttrList.erase(llvm::find(AttrList, ToBeRemoved)); @@ -757,7 +747,7 @@ public: struct iterator : llvm::iterator_adaptor_base { + ParsedAttr> { iterator() : iterator_adaptor_base(nullptr) {} iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} reference operator*() { return **I; } @@ -766,7 +756,7 @@ public: struct const_iterator : llvm::iterator_adaptor_base { + ParsedAttr> { const_iterator() : iterator_adaptor_base(nullptr) {} const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} @@ -795,9 +785,9 @@ public: iterator end() { return iterator(AttrList.end()); } const_iterator end() const { return const_iterator(AttrList.end()); } - bool hasAttribute(AttributeList::Kind K) const { + bool hasAttribute(ParsedAttr::Kind K) const { return llvm::any_of( - AttrList, [K](const AttributeList *AL) { return AL->getKind() == K; }); + AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; }); } private: @@ -829,86 +819,76 @@ public: } /// Add attribute with expression arguments. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - AttributeList::Syntax syntax, - SourceLocation ellipsisLoc = SourceLocation()) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, - syntax, ellipsisLoc); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, + ParsedAttr::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { + ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, + args, numArgs, syntax, ellipsisLoc); addAtStart(attr); return attr; } /// Add availability attribute. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param, - const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *MessageExpr, - AttributeList::Syntax syntax, - SourceLocation strict, const Expr *ReplacementExpr) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, - deprecated, obsoleted, unavailable, MessageExpr, syntax, - strict, ReplacementExpr); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, const Expr *MessageExpr, + ParsedAttr::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { + ParsedAttr *attr = pool.create( + attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); addAtStart(attr); return attr; } /// Add objc_bridge_related attribute. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, - IdentifierLoc *Param2, - IdentifierLoc *Param3, - AttributeList::Syntax syntax) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, - Param1, Param2, Param3, syntax); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax); addAtStart(attr); return attr; } /// Add type_tag_for_datatype attribute. - AttributeList *addNewTypeTagForDatatype( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *argumentKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, - AttributeList::Syntax syntax) { - AttributeList *attr = - pool.createTypeTagForDatatype(attrName, attrRange, - scopeName, scopeLoc, - argumentKind, matchingCType, - layoutCompatible, mustBeNull, syntax); + ParsedAttr * + addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *argumentKind, + ParsedType matchingCType, bool layoutCompatible, + bool mustBeNull, ParsedAttr::Syntax syntax) { + ParsedAttr *attr = pool.createTypeTagForDatatype( + attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax); addAtStart(attr); return attr; } /// Add an attribute with a single type argument. - AttributeList * - addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { - AttributeList *attr = - pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, - typeArg, syntaxUsed); + ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, + ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, + scopeLoc, typeArg, syntaxUsed); addAtStart(attr); return attr; } /// Add microsoft __delspec(property) attribute. - AttributeList * + ParsedAttr * addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { - AttributeList *attr = + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed); addAtStart(attr); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 12a38677e4..e4e1467b12 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -76,7 +76,7 @@ namespace clang { class ASTReader; class ASTWriter; class ArrayType; - class AttributeList; + class ParsedAttr; class BindingDecl; class BlockDecl; class CapturedDecl; @@ -494,7 +494,7 @@ public: /// \#pragma clang attribute. struct PragmaAttributeEntry { SourceLocation Loc; - AttributeList *Attribute; + ParsedAttr *Attribute; SmallVector MatchRules; bool IsUsed; }; @@ -2224,7 +2224,7 @@ public: Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - const AttributeList &MSPropertyAttr); + const ParsedAttr &MSPropertyAttr); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, @@ -3321,11 +3321,10 @@ public: // Helper for delayed processing of attributes. void ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList); - void ProcessDeclAttributeList(Scope *S, Decl *D, - const ParsedAttributesView &AL, - bool IncludeCXX11Attributes = true); + void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AL, + bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const ParsedAttributesView &AttrList); + const ParsedAttributesView &AttrList); void checkUnusedDeclAttributes(Declarator &D); @@ -3335,13 +3334,13 @@ public: /// type as valid. bool isValidPointerAttrType(QualType T, bool RefOkay = false); - bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); - bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value); + bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr); - bool CheckAttrTarget(const AttributeList &CurrAttr); - bool CheckAttrNoArgs(const AttributeList &CurrAttr); - bool checkStringLiteralArgumentAttr(const AttributeList &Attr, - unsigned ArgNum, StringRef &Str, + bool CheckAttrTarget(const ParsedAttr &CurrAttr); + bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); + bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, + StringRef &Str, SourceLocation *ArgLocation = nullptr); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); @@ -8446,8 +8445,7 @@ public: void AddCFAuditedAttribute(Decl *D); /// Called on well-formed '\#pragma clang attribute push'. - void ActOnPragmaAttributePush(AttributeList &Attribute, - SourceLocation PragmaLoc, + void ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules); /// Called on well-formed '\#pragma clang attribute pop'. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4b6b2b3336..9b552e1040 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -162,14 +162,14 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, if (Tok.isNot(tok::l_paren)) { attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); + ParsedAttr::AS_GNU); continue; } // Handle "parameterized" attributes if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, - SourceLocation(), AttributeList::AS_GNU, D); + SourceLocation(), ParsedAttr::AS_GNU, D); continue; } @@ -249,7 +249,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { BalancedDelimiterTracker Parens(*this, tok::l_paren); Parens.consumeOpen(); @@ -275,7 +275,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, unsigned Parser::ParseAttributeArgsCommon( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { // Ignore the left paren location for now. ConsumeParen(); @@ -283,13 +283,13 @@ unsigned Parser::ParseAttributeArgsCommon( if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(AttrName, ScopeName, Syntax); // If we don't know how to parse this attribute, but this is the only // token in this argument, assume it's meant to be an identifier. - if (AttrKind == AttributeList::UnknownAttribute || - AttrKind == AttributeList::IgnoredAttribute) { + if (AttrKind == ParsedAttr::UnknownAttribute || + AttrKind == ParsedAttr::IgnoredAttribute) { const Token &Next = NextToken(); IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma); } @@ -343,27 +343,27 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax, + ParsedAttr::Syntax Syntax, Declarator *D) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(AttrName, ScopeName, Syntax); - if (AttrKind == AttributeList::AT_Availability) { + if (AttrKind == ParsedAttr::AT_Availability) { ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { + } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) { ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) { + } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) { ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_TypeTagForDatatype) { + } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) { ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; @@ -395,29 +395,29 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, unsigned Parser::ParseClangAttributeArgs( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(AttrName, ScopeName, Syntax); switch (AttrKind) { default: return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); - case AttributeList::AT_ExternalSourceSymbol: + case ParsedAttr::AT_ExternalSourceSymbol: ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); break; - case AttributeList::AT_Availability: + case ParsedAttr::AT_Availability: ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); break; - case AttributeList::AT_ObjCBridgeRelated: + case ParsedAttr::AT_ObjCBridgeRelated: ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); break; - case AttributeList::AT_TypeTagForDatatype: + case ParsedAttr::AT_TypeTagForDatatype: ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); break; @@ -549,14 +549,14 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, if (!HasInvalidAccessor) Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(), AccessorNames[AK_Get], AccessorNames[AK_Put], - AttributeList::AS_Declspec); + ParsedAttr::AS_Declspec); T.skipToEnd(); return !HasInvalidAccessor; } unsigned NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, - SourceLocation(), AttributeList::AS_Declspec); + SourceLocation(), ParsedAttr::AS_Declspec); // If this attribute's args were parsed, and it was expected to have // arguments but none were provided, emit a diagnostic. @@ -631,7 +631,7 @@ void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, if (!AttrHandled) Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Declspec); + ParsedAttr::AS_Declspec); } T.consumeClose(); if (End) @@ -657,7 +657,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); break; } default: @@ -708,7 +708,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -718,7 +718,7 @@ void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -726,7 +726,7 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { @@ -742,7 +742,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { Diag(AttrNameLoc, diag::ext_nullability) << AttrName; attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); break; } default: @@ -905,7 +905,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; @@ -1122,7 +1122,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, void Parser::ParseExternalSourceSymbolAttribute( IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume()) @@ -1236,7 +1236,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { @@ -1415,7 +1415,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, Actions.ActOnReenterFunctionContext(Actions.CurScope, D); ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, nullptr); if (HasFunScope) { @@ -1429,7 +1429,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, // If there are multiple decls, then the decl cannot be within the // function scope. ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, nullptr); } } else { @@ -1459,7 +1459,7 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1581,10 +1581,10 @@ void Parser::DiagnoseProhibitedAttributes( void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { - for (const AttributeList &AL : Attrs) { + for (const ParsedAttr &AL : Attrs) { if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; - if (AL.getKind() == AttributeList::UnknownAttribute) + if (AL.getKind() == ParsedAttr::UnknownAttribute) Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); else { Diag(AL.getLoc(), DiagID) << AL.getName(); @@ -1606,16 +1606,16 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, if (TUK == Sema::TUK_Reference) return; - llvm::SmallVector ToBeMoved; + llvm::SmallVector ToBeMoved; - for (AttributeList &AL : DS.getAttributes()) { - if ((AL.getKind() == AttributeList::AT_Aligned && + for (ParsedAttr &AL : DS.getAttributes()) { + if ((AL.getKind() == ParsedAttr::AT_Aligned && AL.isDeclspecAttribute()) || AL.isMicrosoftAttribute()) ToBeMoved.push_back(&AL); } - for (AttributeList *AL : ToBeMoved) { + for (ParsedAttr *AL : ToBeMoved) { DS.getAttributes().remove(AL); Attrs.addAtEnd(AL); } @@ -2731,7 +2731,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, ArgsVector ArgExprs; ArgExprs.push_back(ArgExpr.get()); Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, - AttributeList::AS_Keyword, EllipsisLoc); + ParsedAttr::AS_Keyword, EllipsisLoc); } /// Determine whether we're looking at something that might be a declarator @@ -3321,7 +3321,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); break; } @@ -3364,7 +3364,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Objective-C 'kindof' types. case tok::kw___kindof: DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); (void)ConsumeToken(); continue; @@ -5195,7 +5195,7 @@ void Parser::ParseTypeQualifierListOpt( // Objective-C 'kindof' types. case tok::kw___kindof: DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); (void)ConsumeToken(); continue; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 166f7a8d23..7c4c83d032 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1206,7 +1206,7 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -2284,7 +2284,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( if (!VS.isUnset()) { // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. - for (const AttributeList &AL : DeclaratorInfo.getAttributes()) + for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) Diag(AL.getLoc(), diag::warn_gcc_attribute_location); @@ -3803,16 +3803,15 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { - switch (AttributeList::getKind(AttrName, ScopeName, - AttributeList::AS_CXX11)) { - case AttributeList::AT_CarriesDependency: - case AttributeList::AT_Deprecated: - case AttributeList::AT_FallThrough: - case AttributeList::AT_CXX11NoReturn: + switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { + case ParsedAttr::AT_CarriesDependency: + case ParsedAttr::AT_Deprecated: + case ParsedAttr::AT_FallThrough: + case ParsedAttr::AT_CXX11NoReturn: return true; - case AttributeList::AT_WarnUnusedResult: + case ParsedAttr::AT_WarnUnusedResult: return !ScopeName && AttrName->getName().equals("nodiscard"); - case AttributeList::AT_Unused: + case ParsedAttr::AT_Unused: return !ScopeName && AttrName->getName().equals("maybe_unused"); default: return false; @@ -3842,8 +3841,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); const LangOptions &LO = getLangOpts(); - AttributeList::Syntax Syntax = - LO.CPlusPlus ? AttributeList::AS_CXX11 : AttributeList::AS_C2x; + ParsedAttr::Syntax Syntax = + LO.CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x; // If the attribute isn't known, we will not attempt to parse any // arguments. @@ -3876,7 +3875,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, if (!Attrs.empty() && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { - AttributeList &Attr = *Attrs.begin(); + ParsedAttr &Attr = *Attrs.begin(); // If the attribute is a standard or built-in attribute and we are // parsing an argument list, we need to determine whether this attribute // was allowed to have an argument list (such as [[deprecated]]), and how @@ -4012,8 +4011,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), ScopeName, ScopeLoc, nullptr, 0, - getLangOpts().CPlusPlus ? AttributeList::AS_CXX11 - : AttributeList::AS_C2x); + getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x); if (TryConsumeToken(tok::ellipsis)) Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) @@ -4165,7 +4163,7 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) { if (!T.consumeClose()) { Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, SourceLocation(), ArgExprs.data(), ArgExprs.size(), - AttributeList::AS_Microsoft); + ParsedAttr::AS_Microsoft); } } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e23581d203..647069760d 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1109,10 +1109,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // after '(...)'. nvcc doesn't accept this. auto WarnIfHasCUDATargetAttr = [&] { if (getLangOpts().CUDA) - for (const AttributeList &A : Attr) - if (A.getKind() == AttributeList::AT_CUDADevice || - A.getKind() == AttributeList::AT_CUDAHost || - A.getKind() == AttributeList::AT_CUDAGlobal) + for (const ParsedAttr &A : Attr) + if (A.getKind() == ParsedAttr::AT_CUDADevice || + A.getKind() == ParsedAttr::AT_CUDAHost || + A.getKind() == ParsedAttr::AT_CUDAGlobal) Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) << A.getName()->getName(); }; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 447eb9610b..5c5b3cdfcf 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -376,10 +376,10 @@ static void addContextSensitiveTypeNullability(Parser &P, SourceLocation nullabilityLoc, bool &addedToDeclSpec) { // Create the attribute. - auto getNullabilityAttr = [&](AttributePool &Pool) -> AttributeList * { + auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * { return Pool.create(P.getNullabilityKeyword(nullability), SourceRange(nullabilityLoc), nullptr, SourceLocation(), - nullptr, 0, AttributeList::AS_ContextSensitiveKeyword); + nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword); }; if (D.getNumTypeObjects() > 0) { diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 553b490f48..9a25f9c25c 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -1271,7 +1271,7 @@ getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { /// suggests the possible attribute subject rules in a fix-it together with /// any other missing tokens. DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( - unsigned DiagID, AttributeList &Attribute, + unsigned DiagID, ParsedAttr &Attribute, MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { SourceLocation Loc = PRef.getEndOfPreviousToken(); if (Loc.isInvalid()) @@ -1371,12 +1371,11 @@ void Parser::HandlePragmaAttribute() { if (Tok.isNot(tok::l_paren)) Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); + ParsedAttr::AS_GNU); else ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, /*ScopeName=*/nullptr, - /*ScopeLoc=*/SourceLocation(), - AttributeList::AS_GNU, + /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU, /*Declarator=*/nullptr); if (ExpectAndConsume(tok::r_paren)) @@ -1390,9 +1389,9 @@ void Parser::HandlePragmaAttribute() { if (Tok.getIdentifierInfo()) { // If we suspect that this is an attribute suggest the use of // '__attribute__'. - if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - AttributeList::AS_GNU) != - AttributeList::UnknownAttribute) { + if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, + ParsedAttr::AS_GNU) != + ParsedAttr::UnknownAttribute) { SourceLocation InsertStartLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::l_paren)) { @@ -1423,7 +1422,7 @@ void Parser::HandlePragmaAttribute() { return; } - AttributeList &Attribute = *Attrs.begin(); + ParsedAttr &Attribute = *Attrs.begin(); if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) << Attribute.getName(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 1127158a05..b16ce4fde3 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1942,7 +1942,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, ArgsUnion(Hint.ValueExpr)}; TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr, Hint.PragmaNameLoc->Loc, ArgHints, 4, - AttributeList::AS_Pragma); + ParsedAttr::AS_Pragma); } // Get the next statement. @@ -2267,7 +2267,7 @@ bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { if (Attrs.empty()) return true; - if (Attrs.begin()->getKind() != AttributeList::AT_OpenCLUnrollHint) + if (Attrs.begin()->getKind() != ParsedAttr::AT_OpenCLUnrollHint) return true; if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 7bda21b551..7a0b29cbae 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1089,7 +1089,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Check to make sure that any normal attributes are allowed to be on // a definition. Late parsed attributes are checked at the end. if (Tok.isNot(tok::equal)) { - for (const AttributeList &AL : D.getAttributes()) + for (const ParsedAttr &AL : D.getAttributes()) if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) << AL.getName(); diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 7d9ae621c9..bad42a2ce2 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -9,13 +9,13 @@ endif() add_clang_library(clangSema AnalysisBasedWarnings.cpp - AttributeList.cpp CodeCompleteConsumer.cpp DeclSpec.cpp DelayedDiagnostic.cpp IdentifierResolver.cpp JumpDiagnostics.cpp MultiplexExternalSemaSource.cpp + ParsedAttr.cpp Scope.cpp ScopeInfo.cpp Sema.cpp diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 01c9bad16f..ccca5d37ea 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -994,7 +994,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { writtenBS.Width = getTypeSpecWidth(); writtenBS.Type = getTypeSpecType(); // Search the list of attributes for the presence of a mode attribute. - writtenBS.ModeAttr = getAttributes().hasAttribute(AttributeList::AT_Mode); + writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode); } /// Finish - This does final analysis of the declspec, rejecting things like diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/ParsedAttr.cpp similarity index 68% rename from lib/Sema/AttributeList.cpp rename to lib/Sema/ParsedAttr.cpp index 6d5c6a26ef..6509df9985 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/ParsedAttr.cpp @@ -1,4 +1,4 @@ -//===- AttributeList.cpp --------------------------------------------------===// +//======- ParsedAttr.cpp --------------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file defines the AttributeList class implementation +// This file defines the ParsedAttr class implementation // //===----------------------------------------------------------------------===// -#include "clang/Sema/AttributeList.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/IdentifierTable.h" @@ -34,15 +34,15 @@ IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, return Result; } -size_t AttributeList::allocated_size() const { +size_t ParsedAttr::allocated_size() const { if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; else if (IsTypeTagForDatatype) return AttributeFactory::TypeTagForDatatypeAllocSize; else if (IsProperty) return AttributeFactory::PropertyAllocSize; else if (HasParsedType) - return sizeof(AttributeList) + sizeof(void *); - return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); + return sizeof(ParsedAttr) + sizeof(void *); + return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion)); } AttributeFactory::AttributeFactory() { @@ -52,16 +52,16 @@ AttributeFactory::AttributeFactory() { AttributeFactory::~AttributeFactory() = default; static size_t getFreeListIndexForSize(size_t size) { - assert(size >= sizeof(AttributeList)); + assert(size >= sizeof(ParsedAttr)); assert((size % sizeof(void*)) == 0); - return ((size - sizeof(AttributeList)) / sizeof(void*)); + return ((size - sizeof(ParsedAttr)) / sizeof(void *)); } void *AttributeFactory::allocate(size_t size) { // Check for a previously reclaimed attribute. size_t index = getFreeListIndexForSize(size); if (index < FreeLists.size() && !FreeLists[index].empty()) { - AttributeList *attr = FreeLists[index].back(); + ParsedAttr *attr = FreeLists[index].back(); FreeLists[index].pop_back(); return attr; } @@ -70,7 +70,7 @@ void *AttributeFactory::allocate(size_t size) { return Alloc.Allocate(size, alignof(AttributeFactory)); } -void AttributeFactory::deallocate(AttributeList *Attr) { +void AttributeFactory::deallocate(ParsedAttr *Attr) { size_t size = Attr->allocated_size(); size_t freeListIndex = getFreeListIndexForSize(size); @@ -88,7 +88,7 @@ void AttributeFactory::deallocate(AttributeList *Attr) { } void AttributeFactory::reclaimPool(AttributePool &cur) { - for (AttributeList *AL : cur.Attrs) + for (ParsedAttr *AL : cur.Attrs) deallocate(AL); } @@ -100,12 +100,13 @@ void AttributePool::takePool(AttributePool &pool) { #include "clang/Sema/AttrParsedAttrKinds.inc" static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, - AttributeList::Syntax SyntaxUsed) { + ParsedAttr::Syntax SyntaxUsed) { // Normalize the attribute name, __foo__ becomes foo. This is only allowable // for GNU attributes. - bool IsGNU = SyntaxUsed == AttributeList::AS_GNU || - ((SyntaxUsed == AttributeList::AS_CXX11 || - SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu"); + bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU || + ((SyntaxUsed == ParsedAttr::AS_CXX11 || + SyntaxUsed == ParsedAttr::AS_C2x) && + ScopeName == "gnu"); if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && AttrName.endswith("__")) AttrName = AttrName.slice(2, AttrName.size() - 2); @@ -113,9 +114,9 @@ static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, return AttrName; } -AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, - const IdentifierInfo *ScopeName, - Syntax SyntaxUsed) { +ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name, + const IdentifierInfo *ScopeName, + Syntax SyntaxUsed) { StringRef AttrName = Name->getName(); SmallString<64> FullName; @@ -133,12 +134,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, return ::getAttrKind(FullName, SyntaxUsed); } -unsigned AttributeList::getAttributeSpellingListIndex() const { +unsigned ParsedAttr::getAttributeSpellingListIndex() const { // Both variables will be used in tablegen generated // attribute spell list index matching code. StringRef Scope = ScopeName ? ScopeName->getName() : ""; StringRef Name = normalizeAttrName(AttrName->getName(), Scope, - (AttributeList::Syntax)SyntaxUsed); + (ParsedAttr::Syntax)SyntaxUsed); #include "clang/Sema/AttrSpellingListIndex.inc" @@ -154,11 +155,10 @@ struct ParsedAttrInfo { unsigned IsKnownToGCC : 1; unsigned IsSupportedByPragmaAttribute : 1; - bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, - const Decl *); - bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); + bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *); + bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr); bool (*ExistsInTarget)(const TargetInfo &Target); - unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); + unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr); void (*GetPragmaAttributeMatchRules)( llvm::SmallVectorImpl> &Rules, const LangOptions &LangOpts); @@ -170,71 +170,63 @@ namespace { } // namespace -static const ParsedAttrInfo &getInfo(const AttributeList &A) { +static const ParsedAttrInfo &getInfo(const ParsedAttr &A) { return AttrInfoMap[A.getKind()]; } -unsigned AttributeList::getMinArgs() const { - return getInfo(*this).NumArgs; -} +unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; } -unsigned AttributeList::getMaxArgs() const { +unsigned ParsedAttr::getMaxArgs() const { return getMinArgs() + getInfo(*this).OptArgs; } -bool AttributeList::hasCustomParsing() const { +bool ParsedAttr::hasCustomParsing() const { return getInfo(*this).HasCustomParsing; } -bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { +bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { return getInfo(*this).DiagAppertainsToDecl(S, *this, D); } -bool AttributeList::appliesToDecl(const Decl *D, - attr::SubjectMatchRule MatchRule) const { +bool ParsedAttr::appliesToDecl(const Decl *D, + attr::SubjectMatchRule MatchRule) const { return checkAttributeMatchRuleAppliesTo(D, MatchRule); } -void AttributeList::getMatchRules( +void ParsedAttr::getMatchRules( const LangOptions &LangOpts, SmallVectorImpl> &MatchRules) const { return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); } -bool AttributeList::diagnoseLangOpts(Sema &S) const { +bool ParsedAttr::diagnoseLangOpts(Sema &S) const { return getInfo(*this).DiagLangOpts(S, *this); } -bool AttributeList::isTargetSpecificAttr() const { +bool ParsedAttr::isTargetSpecificAttr() const { return getInfo(*this).IsTargetSpecific; } -bool AttributeList::isTypeAttr() const { - return getInfo(*this).IsType; -} +bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; } -bool AttributeList::isStmtAttr() const { - return getInfo(*this).IsStmt; -} +bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; } -bool AttributeList::existsInTarget(const TargetInfo &Target) const { +bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { return getInfo(*this).ExistsInTarget(Target); } -bool AttributeList::isKnownToGCC() const { - return getInfo(*this).IsKnownToGCC; -} +bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } -bool AttributeList::isSupportedByPragmaAttribute() const { +bool ParsedAttr::isSupportedByPragmaAttribute() const { return getInfo(*this).IsSupportedByPragmaAttribute; } -unsigned AttributeList::getSemanticSpelling() const { +unsigned ParsedAttr::getSemanticSpelling() const { return getInfo(*this).SpellingIndexToSemanticSpelling(*this); } -bool AttributeList::hasVariadicArg() const { +bool ParsedAttr::hasVariadicArg() const { // If the attribute has the maximum number of optional arguments, we will // claim that as being variadic. If we someday get an attribute that // legitimately bumps up against that maximum, we can use another bit to track diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index cc155b7ff6..4f3cf4633c 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -520,7 +520,7 @@ attrMatcherRuleListToString(ArrayRef Rules) { } // end anonymous namespace -void Sema::ActOnPragmaAttributePush(AttributeList &Attribute, +void Sema::ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules) { SmallVector SubjectMatchRules; @@ -645,7 +645,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (PragmaAttributeStack.empty()) return; for (auto &Entry : PragmaAttributeStack) { - AttributeList *Attribute = Entry.Attribute; + ParsedAttr *Attribute = Entry.Attribute; assert(Attribute && "Expected an attribute"); // Ensure that the attribute can be applied to the given declaration. diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp index 5b81eb3a43..13dd8d936f 100644 --- a/lib/Sema/SemaCUDA.cpp +++ b/lib/Sema/SemaCUDA.cpp @@ -61,18 +61,18 @@ Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { bool HasDeviceAttr = false; bool HasGlobalAttr = false; bool HasInvalidTargetAttr = false; - for (const AttributeList &AL : Attrs) { + for (const ParsedAttr &AL : Attrs) { switch (AL.getKind()) { - case AttributeList::AT_CUDAGlobal: + case ParsedAttr::AT_CUDAGlobal: HasGlobalAttr = true; break; - case AttributeList::AT_CUDAHost: + case ParsedAttr::AT_CUDAHost: HasHostAttr = true; break; - case AttributeList::AT_CUDADevice: + case ParsedAttr::AT_CUDADevice: HasDeviceAttr = true; break; - case AttributeList::AT_CUDAInvalidTarget: + case ParsedAttr::AT_CUDAInvalidTarget: HasInvalidTargetAttr = true; break; default: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1e63fd3bfe..a754cc912d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4447,7 +4447,7 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (const AttributeList &AL : DS.getAttributes()) + for (const ParsedAttr &AL : DS.getAttributes()) Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } @@ -6204,7 +6204,7 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { } static bool hasParsedAttr(Scope *S, const Declarator &PD, - AttributeList::Kind Kind) { + ParsedAttr::Kind Kind) { // Check decl attributes on the DeclSpec. if (PD.getDeclSpec().getAttributes().hasAttribute(Kind)) return true; @@ -6372,8 +6372,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( // dllimport globals without explicit storage class are treated as extern. We // have to change the storage class this early to get the right DeclContext. if (SC == SC_None && !DC->isRecord() && - hasParsedAttr(S, D, AttributeList::AT_DLLImport) && - !hasParsedAttr(S, D, AttributeList::AT_DLLExport)) + hasParsedAttr(S, D, ParsedAttr::AT_DLLImport) && + !hasParsedAttr(S, D, ParsedAttr::AT_DLLExport)) SC = SC_Extern; DeclContext *OriginalDC = DC; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index d352015a51..47ef872e43 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -172,13 +172,13 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); } -static unsigned getNumAttributeArgs(const AttributeList &AL) { +static unsigned getNumAttributeArgs(const ParsedAttr &AL) { // FIXME: Include the type in the argument list. return AL.getNumArgs() + AL.hasParsedType(); } template -static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &AL, +static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, unsigned Num, unsigned Diag, Compare Comp) { if (Comp(getNumAttributeArgs(AL), Num)) { @@ -191,8 +191,7 @@ static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &AL, /// Check if the attribute has exactly as many args as Num. May /// output an error. -static bool checkAttributeNumArgs(Sema &S, const AttributeList &AL, - unsigned Num) { +static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) { return checkAttributeNumArgsImpl(S, AL, Num, diag::err_attribute_wrong_number_arguments, std::not_equal_to()); @@ -200,7 +199,7 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &AL, /// Check if the attribute has at least as many args as Num. May /// output an error. -static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &AL, +static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) { return checkAttributeNumArgsImpl(S, AL, Num, diag::err_attribute_too_few_arguments, @@ -209,34 +208,32 @@ static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &AL, /// Check if the attribute has at most as many args as Num. May /// output an error. -static bool checkAttributeAtMostNumArgs(Sema &S, const AttributeList &AL, - unsigned Num) { +static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL, + unsigned Num) { return checkAttributeNumArgsImpl(S, AL, Num, diag::err_attribute_too_many_arguments, std::greater()); } /// A helper function to provide Attribute Location for the Attr types -/// AND the AttributeList. +/// AND the ParsedAttr. template static typename std::enable_if::value, SourceLocation>::type getAttrLoc(const AttrInfo &AL) { return AL.getLocation(); } -static SourceLocation getAttrLoc(const AttributeList &AL) { - return AL.getLoc(); -} +static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); } /// A helper function to provide Attribute Name for the Attr types -/// AND the AttributeList. +/// AND the ParsedAttr. template static typename std::enable_if::value, const AttrInfo *>::type getAttrName(const AttrInfo &AL) { return &AL; } -static const IdentifierInfo *getAttrName(const AttributeList &AL) { +static const IdentifierInfo *getAttrName(const ParsedAttr &AL) { return AL.getName(); } @@ -355,8 +352,8 @@ static bool checkFunctionOrMethodParameterIndex( /// If not emit an error and return false. If the argument is an identifier it /// will emit an error with a fixit hint and treat it as if it was a string /// literal. -bool Sema::checkStringLiteralArgumentAttr(const AttributeList &AL, - unsigned ArgNum, StringRef &Str, +bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, + StringRef &Str, SourceLocation *ArgLocation) { // Look for identifiers. If we have one emit a hint to fix it to a literal. if (AL.isArgIdent(ArgNum)) { @@ -390,14 +387,14 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &AL, /// Applies the given attribute to the Decl without performing any /// additional semantic checking. template -static void handleSimpleAttribute(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } template static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { handleSimpleAttribute(S, D, AL); } @@ -406,7 +403,7 @@ static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, template static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName())) return; @@ -441,7 +438,7 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { /// Note that this function may produce an error message. /// \return true if the Decl is a pointer type; false otherwise static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { const auto *VD = cast(D); QualType QT = VD->getType(); if (QT->isAnyPointerType()) @@ -561,7 +558,7 @@ static bool isCapabilityExpr(Sema &S, const Expr *Ex) { /// \param ParamIdxOk Whether an argument can be indexing into a function /// parameter list. static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, - const AttributeList &AL, + const ParsedAttr &AL, SmallVectorImpl &Args, int Sidx = 0, bool ParamIdxOk = false) { @@ -637,8 +634,7 @@ static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, // Attribute Implementations //===----------------------------------------------------------------------===// -static void handlePtGuardedVarAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!threadSafetyCheckIsPointer(S, D, AL)) return; @@ -647,7 +643,7 @@ static void handlePtGuardedVarAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const AttributeList &AL, +static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, Expr *&Arg) { SmallVector Args; // check that all arguments are lockable objects @@ -661,7 +657,7 @@ static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const AttributeList &AL, return true; } -static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *Arg = nullptr; if (!checkGuardedByAttrCommon(S, D, AL, Arg)) return; @@ -670,8 +666,7 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex())); } -static void handlePtGuardedByAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *Arg = nullptr; if (!checkGuardedByAttrCommon(S, D, AL, Arg)) return; @@ -683,8 +678,7 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D, AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex())); } -static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, - const AttributeList &AL, +static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl &Args) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return false; @@ -705,8 +699,7 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, return true; } -static void handleAcquiredAfterAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Args; if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) return; @@ -717,8 +710,7 @@ static void handleAcquiredAfterAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAcquiredBeforeAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Args; if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) return; @@ -729,8 +721,7 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static bool checkLockFunAttrCommon(Sema &S, Decl *D, - const AttributeList &AL, +static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl &Args) { // zero or more arguments ok // check that all arguments are lockable objects @@ -739,8 +730,7 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D, return true; } -static void handleAssertSharedLockAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Args; if (!checkLockFunAttrCommon(S, D, AL, Args)) return; @@ -753,7 +743,7 @@ static void handleAssertSharedLockAttr(Sema &S, Decl *D, } static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { SmallVector Args; if (!checkLockFunAttrCommon(S, D, AL, Args)) return; @@ -790,7 +780,7 @@ static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, return true; } -static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1) || !checkAttributeAtMostNumArgs(S, AL, 2)) return; @@ -828,8 +818,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, - const AttributeList &AL, +static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl &Args) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return false; @@ -847,7 +836,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, } static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { SmallVector Args; if (!checkTryLockFunAttrCommon(S, D, AL, Args)) return; @@ -858,7 +847,7 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, } static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { SmallVector Args; if (!checkTryLockFunAttrCommon(S, D, AL, Args)) return; @@ -868,8 +857,7 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, Args.size(), AL.getAttributeSpellingListIndex())); } -static void handleLockReturnedAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // check that the argument is lockable object SmallVector Args; checkAttrArgsAreCapabilityObjs(S, D, AL, Args); @@ -882,8 +870,7 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleLocksExcludedAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -900,8 +887,7 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static bool checkFunctionConditionAttr(Sema &S, Decl *D, - const AttributeList &AL, +static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL, Expr *&Cond, StringRef &Msg) { Cond = AL.getArgAsExpr(0); if (!Cond->isTypeDependent()) { @@ -930,7 +916,7 @@ static bool checkFunctionConditionAttr(Sema &S, Decl *D, return true; } -static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::ext_clang_enable_if); Expr *Cond; @@ -987,7 +973,7 @@ public: }; } -static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if); Expr *Cond; @@ -1014,8 +1000,7 @@ static void handleDiagnoseIfAttr(Sema &S, Decl *D, const AttributeList &AL) { cast(D), AL.getAttributeSpellingListIndex())); } -static void handlePassObjectSizeAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->hasAttr()) { S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter) << AL.getName(); @@ -1050,7 +1035,7 @@ static void handlePassObjectSizeAttr(Sema &S, Decl *D, AL.getRange(), S.Context, (int)Type, AL.getAttributeSpellingListIndex())); } -static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ConsumableAttr::ConsumedState DefaultState; if (AL.isArgIdent(0)) { @@ -1073,7 +1058,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &AL) { } static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, - const AttributeList &AL) { + const ParsedAttr &AL) { ASTContext &CurrContext = S.getASTContext(); QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); @@ -1089,8 +1074,7 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, return true; } -static void handleCallableWhenAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -1127,8 +1111,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D, States.size(), AL.getAttributeSpellingListIndex())); } -static void handleParamTypestateAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParamTypestateAttr::ConsumedState ParamState; if (AL.isArgIdent(0)) { @@ -1164,8 +1147,7 @@ static void handleParamTypestateAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleReturnTypestateAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ReturnTypestateAttr::ConsumedState ReturnState; if (AL.isArgIdent(0)) { @@ -1212,7 +1194,7 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkForConsumableClass(S, cast(D), AL)) return; @@ -1236,8 +1218,7 @@ static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleTestTypestateAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkForConsumableClass(S, cast(D), AL)) return; @@ -1261,12 +1242,12 @@ static void handleTestTypestateAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleExtVectorTypeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Remember this typedef decl, we will need it later for diagnostics. S.ExtVectorDecls.push_back(cast(D)); } -static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (auto *TD = dyn_cast(D)) TD->addAttr(::new (S.Context) PackedAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); @@ -1297,7 +1278,7 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &AL) { S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName(); } -static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &AL) { +static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { // The IBOutlet/IBOutletCollection attributes only apply to instance // variables or properties of Objective-C classes. The outlet must also // have an object reference type. @@ -1323,7 +1304,7 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &AL) { return true; } -static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &AL) { +static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkIBOutletCommon(S, D, AL)) return; @@ -1332,8 +1313,7 @@ static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleIBOutletCollection(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) { // The iboutletcollection attribute can have zero or one arguments. if (AL.getNumArgs() > 1) { @@ -1403,7 +1383,7 @@ bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { return T->isAnyPointerType() || T->isBlockPointerType(); } -static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &AL, +static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, SourceRange AttrParmRange, SourceRange TypeRange, bool isReturnValue = false) { @@ -1419,7 +1399,7 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &AL, return true; } -static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector NonNullArgs; for (unsigned I = 0; I < AL.getNumArgs(); ++I) { Expr *Ex = AL.getArgAsExpr(I); @@ -1465,7 +1445,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (AL.getNumArgs() > 0) { if (D->getFunctionType()) { handleNonNullAttr(S, D, AL); @@ -1486,8 +1466,7 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, AL.getAttributeSpellingListIndex())); } -static void handleReturnsNonNullAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType ResultType = getFunctionOrMethodResultType(D); SourceRange SR = getFunctionOrMethodResultSourceRange(D); if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, @@ -1499,7 +1478,7 @@ static void handleReturnsNonNullAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleNoEscapeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->isInvalidDecl()) return; @@ -1515,16 +1494,14 @@ static void handleNoEscapeAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } -static void handleAssumeAlignedAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *E = AL.getArgAsExpr(0), *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr; S.AddAssumeAlignedAttr(AL.getRange(), D, E, OE, AL.getAttributeSpellingListIndex()); } -static void handleAllocAlignAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.AddAllocAlignAttr(AL.getRange(), D, AL.getArgAsExpr(0), AL.getAttributeSpellingListIndex()); } @@ -1623,7 +1600,7 @@ static bool normalizeName(StringRef &AttrName) { return false; } -static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // This attribute must be applied to a function declaration. The first // argument to the attribute must be an identifier, the name of the resource, // for example: malloc. The following arguments must be argument indexes, the @@ -1730,7 +1707,7 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check the attribute arguments. if (AL.getNumArgs() > 1) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) @@ -1792,7 +1769,7 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Str; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) return; @@ -1808,7 +1785,7 @@ static void handleIFuncAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Str; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) return; @@ -1841,8 +1818,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleTLSModelAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Model; SourceLocation LiteralLoc; // Check that it is a string. @@ -1861,7 +1837,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType ResultType = getFunctionOrMethodResultType(D); if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) { D->addAttr(::new (S.Context) RestrictAttr( @@ -1873,7 +1849,7 @@ static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &AL) { << AL.getName() << getFunctionOrMethodResultSourceRange(D); } -static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) << AL.getName() << AttributeLangSupport::Cpp; @@ -1885,7 +1861,7 @@ static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &AL) { D->addAttr(CA); } -static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName())) return; @@ -1905,7 +1881,7 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) { +static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { if (hasDeclarator(D)) return; if (!isa(D)) { @@ -1918,14 +1894,14 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &Attrs) { Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); } -static void handleNoCfCheckAttr(Sema &S, Decl *D, const AttributeList &Attrs) { +static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { if (!S.getLangOpts().CFProtectionBranch) S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); else handleSimpleAttribute(S, D, Attrs); } -bool Sema::CheckAttrNoArgs(const AttributeList &Attrs) { +bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { if (!checkAttributeNumArgs(*this, Attrs, 0)) { Attrs.setInvalid(); return true; @@ -1934,7 +1910,7 @@ bool Sema::CheckAttrNoArgs(const AttributeList &Attrs) { return false; } -bool Sema::CheckAttrTarget(const AttributeList &AL) { +bool Sema::CheckAttrTarget(const ParsedAttr &AL) { // Check whether the attribute is valid on the current target. if (!AL.existsInTarget(Context.getTargetInfo())) { Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); @@ -1945,9 +1921,8 @@ bool Sema::CheckAttrTarget(const AttributeList &AL) { return false; } -static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, - const AttributeList &AL) { - +static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // The checking path for 'noreturn' and 'analyzer_noreturn' are different // because 'analyzer_noreturn' does not impact the type. if (!isFunctionOrMethodOrBlock(D)) { @@ -1968,30 +1943,31 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, } // PS3 PPU-specific. -static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &AL) { -/* - Returning a Vector Class in Registers - - According to the PPU ABI specifications, a class with a single member of - vector type is returned in memory when used as the return value of a function. - This results in inefficient code when implementing vector classes. To return - the value in a single vector register, add the vecreturn attribute to the - class definition. This attribute is also applicable to struct types. - - Example: - - struct Vector - { - __vector float xyzw; - } __attribute__((vecreturn)); - - Vector Add(Vector lhs, Vector rhs) - { - Vector result; - result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); - return result; // This will be returned in a register - } -*/ +static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + /* + Returning a Vector Class in Registers + + According to the PPU ABI specifications, a class with a single member of + vector type is returned in memory when used as the return value of a + function. + This results in inefficient code when implementing vector classes. To return + the value in a single vector register, add the vecreturn attribute to the + class definition. This attribute is also applicable to struct types. + + Example: + + struct Vector + { + __vector float xyzw; + } __attribute__((vecreturn)); + + Vector Add(Vector lhs, Vector rhs) + { + Vector result; + result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); + return result; // This will be returned in a register + } + */ if (VecReturnAttr *A = D->getAttr()) { S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A; return; @@ -2023,7 +1999,7 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (isa(D)) { // [[carries_dependency]] can only be applied to a parameter if it is a // parameter of a function declaration or lambda. @@ -2039,7 +2015,7 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName(); // If this is spelled as the standard C++17 attribute, but not in C++17, warn @@ -2051,7 +2027,7 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } -static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t priority = ConstructorAttr::DefaultPriority; if (AL.getNumArgs() && !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) @@ -2062,7 +2038,7 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t priority = DestructorAttr::DefaultPriority; if (AL.getNumArgs() && !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) @@ -2074,8 +2050,7 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &AL) { } template -static void handleAttrWithMessage(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) { // Handle the case where the attribute has a text message. StringRef Str; if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str)) @@ -2086,7 +2061,7 @@ static void handleAttrWithMessage(Sema &S, Decl *D, } static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!cast(D)->isThisDeclarationADefinition()) { S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) << AL.getName() << AL.getRange(); @@ -2319,8 +2294,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, return nullptr; } -static void handleAvailabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeNumArgs(S, AL, 1)) return; IdentifierLoc *Platform = AL.getArgAsIdent(0); @@ -2435,7 +2409,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, } static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; assert(checkAttributeAtMostNumArgs(S, AL, 3) && @@ -2484,7 +2458,7 @@ TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } -static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &AL, +static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, bool isTypeVisibility) { // Visibility attributes don't mean anything on a typedef. if (isa(D)) { @@ -2537,8 +2511,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &AL, D->addAttr(newAttr); } -static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *M = cast(D); if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) @@ -2566,7 +2539,7 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, AL.getRange(), S.Context, F, AL.getAttributeSpellingListIndex())); } -static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &AL) { +static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *TD = dyn_cast(D)) { QualType T = TD->getUnderlyingType(); if (!T->isCARCBridgableType()) { @@ -2595,7 +2568,7 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &AL) { +static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *TD = dyn_cast(D)) { QualType T = TD->getUnderlyingType(); if (!T->isObjCObjectPointerType()) { @@ -2611,7 +2584,7 @@ static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &AL AL.getAttributeSpellingListIndex())); } -static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName() << 1 << AANT_ArgumentIdentifier; @@ -2631,7 +2604,7 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; if (AL.getNumArgs() > 0) { Expr *E = AL.getArgAsExpr(0); @@ -2722,7 +2695,7 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &AL) { +static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->getFunctionType() && D->getFunctionType()->getReturnType()->isVoidType()) { S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) @@ -2747,7 +2720,7 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // weak_import only applies to variable & function declarations. bool isDef = false; if (!D->canBeWeakImported(isDef)) { @@ -2772,8 +2745,7 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &AL) { // Handles reqd_work_group_size and work_group_size_hint. template -static void handleWorkGroupSize(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t WGSize[3]; for (unsigned i = 0; i < 3; ++i) { const Expr *E = AL.getArgAsExpr(i); @@ -2798,7 +2770,7 @@ static void handleWorkGroupSize(Sema &S, Decl *D, } // Handles intel_reqd_sub_group_size. -static void handleSubGroupSize(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t SGSize; const Expr *E = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, E, SGSize)) @@ -2819,7 +2791,7 @@ static void handleSubGroupSize(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &AL) { +static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.hasParsedType()) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL.getName() << 1; @@ -2873,7 +2845,7 @@ bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { return true; } -static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Make sure that there is a string literal as the sections's single // argument. StringRef Str; @@ -2929,7 +2901,7 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { return false; } -static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Str; SourceLocation LiteralLoc; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || @@ -2942,7 +2914,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const AttributeList &AL) { D->addAttr(NewAttr); } -static void handleMinVectorWidthAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *E = AL.getArgAsExpr(0); uint32_t VecWidth; if (!checkUInt32Argument(S, AL, E, VecWidth)) { @@ -2961,7 +2933,7 @@ static void handleMinVectorWidthAttr(Sema &S, Decl *D, const AttributeList &AL) AL.getAttributeSpellingListIndex())); } -static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *E = AL.getArgAsExpr(0); SourceLocation Loc = E->getExprLoc(); FunctionDecl *FD = nullptr; @@ -3019,7 +2991,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleEnumExtensibilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName() << 0 << AANT_ArgumentIdentifier; @@ -3042,7 +3014,7 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D, /// Handle __attribute__((format_arg((idx)))) attribute based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { Expr *IdxExpr = AL.getArgAsExpr(0); ParamIdx Idx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx)) @@ -3108,8 +3080,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { /// Handle __attribute__((init_priority(priority))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html -static void handleInitPriorityAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.getLangOpts().CPlusPlus) { S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL.getName(); return; @@ -3170,7 +3141,7 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName() << 1 << AANT_ArgumentIdentifier; @@ -3292,8 +3263,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &AL) { D->addAttr(NewAttr); } -static void handleTransparentUnionAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Try to find the underlying union declaration. RecordDecl *RD = nullptr; const auto *TD = dyn_cast(D); @@ -3366,7 +3336,7 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Make sure that there is a string literal as the annotation's single // argument. StringRef Str; @@ -3384,8 +3354,7 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleAlignValueAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.AddAlignValueAttr(AL.getRange(), D, AL.getArgAsExpr(0), AL.getAttributeSpellingListIndex()); } @@ -3435,7 +3404,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, D->addAttr(::new (Context) AlignValueAttr(TmpAttr)); } -static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // check the attribute arguments. if (AL.getNumArgs() > 1) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) @@ -3715,7 +3684,7 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, /// Despite what would be logical, the mode attribute is a decl attribute, not a /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be /// HImode, not an intermediate pointer. -static void handleModeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // This attribute isn't documented, but glibc uses it. It changes // the width of an int or unsigned int to the specified size. if (!AL.isArgIdent(0)) { @@ -3871,7 +3840,7 @@ void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, ModeAttr(AttrRange, Context, Name, SpellingListIndex)); } -static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) NoDebugAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); @@ -3963,8 +3932,7 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } -static void handleAlwaysInlineAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName())) return; @@ -3975,20 +3943,19 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D, D->addAttr(Inline); } -static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (MinSizeAttr *MinSize = S.mergeMinSizeAttr( D, AL.getRange(), AL.getAttributeSpellingListIndex())) D->addAttr(MinSize); } -static void handleOptimizeNoneAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr( D, AL.getRange(), AL.getAttributeSpellingListIndex())) D->addAttr(Optnone); } -static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName())) return; @@ -4001,7 +3968,7 @@ static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } -static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName())) return; @@ -4021,7 +3988,7 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); } -static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL.getRange(), AL.getName()) || checkAttrMutualExclusion(S, D, AL.getRange(), @@ -4054,7 +4021,7 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *Fn = cast(D); if (!Fn->isInlineSpecified()) { S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); @@ -4066,7 +4033,7 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (hasDeclarator(D)) return; // Diagnostic is emitted elsewhere: here we store the (valid) AL @@ -4082,56 +4049,56 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &AL) { } switch (AL.getKind()) { - case AttributeList::AT_FastCall: + case ParsedAttr::AT_FastCall: D->addAttr(::new (S.Context) FastCallAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_StdCall: + case ParsedAttr::AT_StdCall: D->addAttr(::new (S.Context) StdCallAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_ThisCall: + case ParsedAttr::AT_ThisCall: D->addAttr(::new (S.Context) ThisCallAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_CDecl: + case ParsedAttr::AT_CDecl: D->addAttr(::new (S.Context) CDeclAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_Pascal: + case ParsedAttr::AT_Pascal: D->addAttr(::new (S.Context) PascalAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_SwiftCall: + case ParsedAttr::AT_SwiftCall: D->addAttr(::new (S.Context) SwiftCallAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_VectorCall: + case ParsedAttr::AT_VectorCall: D->addAttr(::new (S.Context) VectorCallAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_MSABI: + case ParsedAttr::AT_MSABI: D->addAttr(::new (S.Context) MSABIAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_SysVABI: + case ParsedAttr::AT_SysVABI: D->addAttr(::new (S.Context) SysVABIAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_RegCall: + case ParsedAttr::AT_RegCall: D->addAttr(::new (S.Context) RegCallAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_Pcs: { + case ParsedAttr::AT_Pcs: { PcsAttr::PCSType PCS; switch (CC) { case CC_AAPCS: @@ -4149,16 +4116,16 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); return; } - case AttributeList::AT_IntelOclBicc: + case ParsedAttr::AT_IntelOclBicc: D->addAttr(::new (S.Context) IntelOclBiccAttr(AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_PreserveMost: + case ParsedAttr::AT_PreserveMost: D->addAttr(::new (S.Context) PreserveMostAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_PreserveAll: + case ParsedAttr::AT_PreserveAll: D->addAttr(::new (S.Context) PreserveAllAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; @@ -4167,7 +4134,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &AL) { } } -static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -4187,7 +4154,7 @@ static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &AL) { DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex())); } -bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC, +bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, const FunctionDecl *FD) { if (Attrs.isInvalid()) return true; @@ -4197,7 +4164,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC, return false; } - unsigned ReqArgs = Attrs.getKind() == AttributeList::AT_Pcs ? 1 : 0; + unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0; if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) { Attrs.setInvalid(); return true; @@ -4205,23 +4172,39 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC, // TODO: diagnose uses of these conventions on the wrong target. switch (Attrs.getKind()) { - case AttributeList::AT_CDecl: CC = CC_C; break; - case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; - case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; - case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; - case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; - case AttributeList::AT_SwiftCall: CC = CC_Swift; break; - case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break; - case AttributeList::AT_RegCall: CC = CC_X86RegCall; break; - case AttributeList::AT_MSABI: + case ParsedAttr::AT_CDecl: + CC = CC_C; + break; + case ParsedAttr::AT_FastCall: + CC = CC_X86FastCall; + break; + case ParsedAttr::AT_StdCall: + CC = CC_X86StdCall; + break; + case ParsedAttr::AT_ThisCall: + CC = CC_X86ThisCall; + break; + case ParsedAttr::AT_Pascal: + CC = CC_X86Pascal; + break; + case ParsedAttr::AT_SwiftCall: + CC = CC_Swift; + break; + case ParsedAttr::AT_VectorCall: + CC = CC_X86VectorCall; + break; + case ParsedAttr::AT_RegCall: + CC = CC_X86RegCall; + break; + case ParsedAttr::AT_MSABI: CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : CC_Win64; break; - case AttributeList::AT_SysVABI: + case ParsedAttr::AT_SysVABI: CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : CC_C; break; - case AttributeList::AT_Pcs: { + case ParsedAttr::AT_Pcs: { StringRef StrRef; if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) { Attrs.setInvalid(); @@ -4239,9 +4222,15 @@ bool Sema::CheckCallingConvAttr(const AttributeList &Attrs, CallingConv &CC, Diag(Attrs.getLoc(), diag::err_invalid_pcs); return true; } - case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; - case AttributeList::AT_PreserveMost: CC = CC_PreserveMost; break; - case AttributeList::AT_PreserveAll: CC = CC_PreserveAll; break; + case ParsedAttr::AT_IntelOclBicc: + CC = CC_IntelOclBicc; + break; + case ParsedAttr::AT_PreserveMost: + CC = CC_PreserveMost; + break; + case ParsedAttr::AT_PreserveAll: + CC = CC_PreserveAll; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -4298,7 +4287,7 @@ static bool isValidSwiftErrorResultType(QualType Ty) { return isValidSwiftContextType(Ty); } -static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &Attrs, +static void handleParameterABIAttr(Sema &S, Decl *D, const ParsedAttr &Attrs, ParameterABI Abi) { S.AddParameterABIAttr(Attrs.getRange(), D, Abi, Attrs.getAttributeSpellingListIndex()); @@ -4357,7 +4346,7 @@ void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi, /// Checks a regparm attribute, returning true if it is ill-formed and /// otherwise setting numParams to the appropriate value. -bool Sema::CheckRegparmAttr(const AttributeList &AL, unsigned &numParams) { +bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { if (AL.isInvalid()) return true; @@ -4450,8 +4439,7 @@ void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex)); } -static void handleLaunchBoundsAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1) || !checkAttributeAtMostNumArgs(S, AL, 2)) return; @@ -4462,7 +4450,7 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, } static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; @@ -4495,7 +4483,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, } static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL.getName() << 1 << AANT_ArgumentIdentifier; @@ -4524,7 +4512,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleXRayLogArgsAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParamIdx ArgCount; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0), @@ -4556,9 +4544,9 @@ static bool isValidSubjectOfCFAttribute(Sema &S, QualType QT) { isValidSubjectOfNSAttribute(S, QT); } -static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNSConsumedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.AddNSConsumedAttr(AL.getRange(), D, AL.getAttributeSpellingListIndex(), - AL.getKind() == AttributeList::AT_NSConsumed, + AL.getKind() == ParsedAttr::AT_NSConsumed, /*template instantiation*/ false); } @@ -4605,13 +4593,13 @@ bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) { } static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { QualType ReturnType; if (const auto *MD = dyn_cast(D)) ReturnType = MD->getReturnType(); else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && - (AL.getKind() == AttributeList::AT_NSReturnsRetained)) + (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) return; // ignore: was handled as a type attribute else if (const auto *PD = dyn_cast(D)) ReturnType = PD->getType(); @@ -4631,14 +4619,14 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, AttributeDeclKind ExpectedDeclKind; switch (AL.getKind()) { default: llvm_unreachable("invalid ownership attribute"); - case AttributeList::AT_NSReturnsRetained: - case AttributeList::AT_NSReturnsAutoreleased: - case AttributeList::AT_NSReturnsNotRetained: + case ParsedAttr::AT_NSReturnsRetained: + case ParsedAttr::AT_NSReturnsAutoreleased: + case ParsedAttr::AT_NSReturnsNotRetained: ExpectedDeclKind = ExpectedFunctionOrMethod; break; - case AttributeList::AT_CFReturnsRetained: - case AttributeList::AT_CFReturnsNotRetained: + case ParsedAttr::AT_CFReturnsRetained: + case ParsedAttr::AT_CFReturnsNotRetained: ExpectedDeclKind = ExpectedFunctionMethodOrParameter; break; } @@ -4651,19 +4639,19 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, bool Cf; switch (AL.getKind()) { default: llvm_unreachable("invalid ownership attribute"); - case AttributeList::AT_NSReturnsRetained: + case ParsedAttr::AT_NSReturnsRetained: TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType); Cf = false; break; - - case AttributeList::AT_NSReturnsAutoreleased: - case AttributeList::AT_NSReturnsNotRetained: + + case ParsedAttr::AT_NSReturnsAutoreleased: + case ParsedAttr::AT_NSReturnsNotRetained: TypeOK = isValidSubjectOfNSAttribute(S, ReturnType); Cf = false; break; - case AttributeList::AT_CFReturnsRetained: - case AttributeList::AT_CFReturnsNotRetained: + case ParsedAttr::AT_CFReturnsRetained: + case ParsedAttr::AT_CFReturnsNotRetained: TypeOK = isValidSubjectOfCFAttribute(S, ReturnType); Cf = true; break; @@ -4698,23 +4686,23 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, switch (AL.getKind()) { default: llvm_unreachable("invalid ownership attribute"); - case AttributeList::AT_NSReturnsAutoreleased: + case ParsedAttr::AT_NSReturnsAutoreleased: D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_CFReturnsNotRetained: + case ParsedAttr::AT_CFReturnsNotRetained: D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_NSReturnsNotRetained: + case ParsedAttr::AT_NSReturnsNotRetained: D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_CFReturnsRetained: + case ParsedAttr::AT_CFReturnsRetained: D->addAttr(::new (S.Context) CFReturnsRetainedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; - case AttributeList::AT_NSReturnsRetained: + case ParsedAttr::AT_NSReturnsRetained: D->addAttr(::new (S.Context) NSReturnsRetainedAttr( AL.getRange(), S.Context, AL.getAttributeSpellingListIndex())); return; @@ -4722,7 +4710,7 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, } static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, - const AttributeList &Attrs) { + const ParsedAttr &Attrs) { const int EP_ObjCMethod = 1; const int EP_ObjCProperty = 2; @@ -4750,7 +4738,7 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, } static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, - const AttributeList &Attrs) { + const ParsedAttr &Attrs) { const auto *Method = cast(D); const DeclContext *DC = Method->getDeclContext(); @@ -4770,7 +4758,7 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); } -static void handleObjCBridgeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; if (!Parm) { @@ -4800,7 +4788,7 @@ static void handleObjCBridgeAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleObjCBridgeMutableAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; if (!Parm) { @@ -4814,7 +4802,7 @@ static void handleObjCBridgeMutableAttr(Sema &S, Decl *D, } static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { IdentifierInfo *RelatedClass = AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; if (!RelatedClass) { @@ -4832,7 +4820,7 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, } static void handleObjCDesignatedInitializer(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { ObjCInterfaceDecl *IFace; if (auto *CatDecl = dyn_cast(D->getDeclContext())) IFace = CatDecl->getClassInterface(); @@ -4848,8 +4836,7 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleObjCRuntimeName(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef MetaDataName; if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName)) return; @@ -4863,7 +4850,7 @@ static void handleObjCRuntimeName(Sema &S, Decl *D, // but they don't have access to the declaration (legacy/third-party code) // then they can 'enable' this feature with a typedef: // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; -static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &AL) { +static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) { bool notify = false; auto *RD = dyn_cast(D); @@ -4886,8 +4873,7 @@ static void handleObjCBoxable(Sema &S, Decl *D, const AttributeList &AL) { } } -static void handleObjCOwnershipAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (hasDeclarator(D)) return; S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) @@ -4895,7 +4881,7 @@ static void handleObjCOwnershipAttr(Sema &S, Decl *D, } static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { const auto *VD = cast(D); QualType QT = VD->getType(); @@ -4952,7 +4938,7 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex); } -static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) << AL.getName() << AttributeLangSupport::C; @@ -5002,7 +4988,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &AL) { D->addAttr(UA); } -static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) << AL.getName() << AttributeLangSupport::C; @@ -5018,8 +5004,7 @@ static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &AL) { } } -static void handleDeclspecThreadAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *VD = cast(D); if (!S.Context.getTargetInfo().isTLSSupported()) { S.Diag(AL.getLoc(), diag::err_thread_unsupported); @@ -5037,7 +5022,7 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Tags; for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { StringRef Tag; @@ -5069,8 +5054,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleARMInterruptAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Check the attribute arguments. if (AL.getNumArgs() > 1) { S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) @@ -5098,8 +5082,7 @@ static void handleARMInterruptAttr(Sema &S, Decl *D, ARMInterruptAttr(AL.getLoc(), S.Context, Kind, Index)); } -static void handleMSP430InterruptAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeNumArgs(S, AL, 1)) return; @@ -5134,8 +5117,7 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, D->addAttr(UsedAttr::CreateImplicit(S.Context)); } -static void handleMipsInterruptAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Only one optional argument permitted. if (AL.getNumArgs() > 1) { S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) @@ -5193,8 +5175,7 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex())); } -static void handleAnyX86InterruptAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Semantic checks for a function with the 'interrupt' attribute. // a) Must be a function. // b) Must have the 'void' return type. @@ -5259,7 +5240,7 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D, D->addAttr(UsedAttr::CreateImplicit(S.Context)); } -static void handleAVRInterruptAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!isFunctionOrMethod(D)) { S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) << "'interrupt'" << ExpectedFunction; @@ -5272,7 +5253,7 @@ static void handleAVRInterruptAttr(Sema &S, Decl *D, const AttributeList &AL) { handleSimpleAttribute(S, D, AL); } -static void handleAVRSignalAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!isFunctionOrMethod(D)) { S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) << "'signal'" << ExpectedFunction; @@ -5285,7 +5266,7 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const AttributeList &AL) { handleSimpleAttribute(S, D, AL); } -static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Dispatch the interrupt attribute based on the current target. switch (S.Context.getTargetInfo().getTriple().getArch()) { case llvm::Triple::msp430: @@ -5309,7 +5290,7 @@ static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { uint32_t Min = 0; Expr *MinExpr = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, MinExpr, Min)) @@ -5336,8 +5317,7 @@ static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t Min = 0; Expr *MinExpr = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, MinExpr, Min)) @@ -5366,8 +5346,7 @@ static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t NumSGPR = 0; Expr *NumSGPRExpr = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR)) @@ -5378,8 +5357,7 @@ static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t NumVGPR = 0; Expr *NumVGPRExpr = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR)) @@ -5391,7 +5369,7 @@ static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, } static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, - const AttributeList& AL) { + const ParsedAttr &AL) { // If we try to apply it to a function pointer, don't warn, but don't // do anything, either. It doesn't matter anyway, because there's nothing // special about calling a force_align_arg_pointer function. @@ -5415,7 +5393,7 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleLayoutVersion(Sema &S, Decl *D, const AttributeList &AL) { +static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) { uint32_t Version; Expr *VersionExpr = static_cast(AL.getArgAsExpr(0)); if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version)) @@ -5459,7 +5437,7 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex); } -static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) { +static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) @@ -5468,7 +5446,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) { } if (const auto *FD = dyn_cast(D)) { - if (FD->isInlined() && A.getKind() == AttributeList::AT_DLLImport && + if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) @@ -5486,7 +5464,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) { } unsigned Index = A.getAttributeSpellingListIndex(); - Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport + Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index) : (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index); if (NewAttr) @@ -5529,7 +5507,7 @@ Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase, MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex); } -static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // The capability attributes take a single string parameter for the name of // the capability they represent. The lockable attribute does not take any // parameters. However, semantically, both attributes represent the same @@ -5540,7 +5518,7 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &AL) { // literal will be considered a "mutex." StringRef N("mutex"); SourceLocation LiteralLoc; - if (AL.getKind() == AttributeList::AT_Capability && + if (AL.getKind() == ParsedAttr::AT_Capability && !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc)) return; @@ -5553,8 +5531,7 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &AL) { AL.getAttributeSpellingListIndex())); } -static void handleAssertCapabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Args; if (!checkLockFunAttrCommon(S, D, AL, Args)) return; @@ -5565,7 +5542,7 @@ static void handleAssertCapabilityAttr(Sema &S, Decl *D, } static void handleAcquireCapabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { SmallVector Args; if (!checkLockFunAttrCommon(S, D, AL, Args)) return; @@ -5577,7 +5554,7 @@ static void handleAcquireCapabilityAttr(Sema &S, Decl *D, } static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { SmallVector Args; if (!checkTryLockFunAttrCommon(S, D, AL, Args)) return; @@ -5591,7 +5568,7 @@ static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D, } static void handleReleaseCapabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { // Check that all arguments are lockable objects. SmallVector Args; checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true); @@ -5602,7 +5579,7 @@ static void handleReleaseCapabilityAttr(Sema &S, Decl *D, } static void handleRequiresCapabilityAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -5619,7 +5596,7 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D, D->addAttr(RCA); } -static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (const auto *NSD = dyn_cast(D)) { if (NSD->isAnonymousNamespace()) { S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace); @@ -5659,7 +5636,7 @@ static bool isGlobalVar(const Decl *D) { return false; } -static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!checkAttributeAtLeastNumArgs(S, AL, 1)) return; @@ -5686,7 +5663,7 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &AL) { } static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { StringRef AttrName = AL.getName()->getName(); normalizeName(AttrName); StringRef SanitizerName = llvm::StringSwitch(AttrName) @@ -5702,15 +5679,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleInternalLinkageAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL.getRange(), AL.getName(), AL.getAttributeSpellingListIndex())) D->addAttr(Internal); } -static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &AL) { +static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.LangOpts.OpenCLVersion != 200) S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version) << AL.getName() << "2.0" << 0; @@ -5723,13 +5699,13 @@ static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &AL) { /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. static bool handleCommonAttributeFeatures(Sema &S, Decl *D, - const AttributeList &AL) { + const ParsedAttr &AL) { // Several attributes carry different semantics than the parsing requires, so // those are opted out of the common argument checks. // // We also bail on unknown and ignored attributes because those are handled // as part of the target-specific handling logic. - if (AL.getKind() == AttributeList::UnknownAttribute) + if (AL.getKind() == ParsedAttr::UnknownAttribute) return false; // Check whether the attribute requires specific language extensions to be // enabled. @@ -5762,8 +5738,7 @@ static bool handleCommonAttributeFeatures(Sema &S, Decl *D, return false; } -static void handleOpenCLAccessAttr(Sema &S, Decl *D, - const AttributeList &AL) { +static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->isInvalidDecl()) return; @@ -5804,9 +5779,9 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it if a GNU attribute. static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, - const AttributeList &AL, + const ParsedAttr &AL, bool IncludeCXX11Attributes) { - if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) + if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) return; // Ignore C++11 attributes on declarator chunks: they appertain to the type @@ -5817,7 +5792,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, // Unknown attributes are automatically warned on. Target-specific attributes // which do not apply to the current target architecture are treated as // though they were unknown attributes. - if (AL.getKind() == AttributeList::UnknownAttribute || + if (AL.getKind() == ParsedAttr::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { S.Diag(AL.getLoc(), AL.isDeclspecAttribute() ? diag::warn_unhandled_ms_attribute_ignored @@ -5839,616 +5814,616 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) << AL.getName() << D->getLocation(); break; - case AttributeList::AT_Interrupt: + case ParsedAttr::AT_Interrupt: handleInterruptAttr(S, D, AL); break; - case AttributeList::AT_X86ForceAlignArgPointer: + case ParsedAttr::AT_X86ForceAlignArgPointer: handleX86ForceAlignArgPointerAttr(S, D, AL); break; - case AttributeList::AT_DLLExport: - case AttributeList::AT_DLLImport: + case ParsedAttr::AT_DLLExport: + case ParsedAttr::AT_DLLImport: handleDLLAttr(S, D, AL); break; - case AttributeList::AT_Mips16: + case ParsedAttr::AT_Mips16: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_NoMips16: + case ParsedAttr::AT_NoMips16: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_MicroMips: + case ParsedAttr::AT_MicroMips: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_NoMicroMips: + case ParsedAttr::AT_NoMicroMips: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_MipsLongCall: + case ParsedAttr::AT_MipsLongCall: handleSimpleAttributeWithExclusions( S, D, AL); break; - case AttributeList::AT_MipsShortCall: + case ParsedAttr::AT_MipsShortCall: handleSimpleAttributeWithExclusions( S, D, AL); break; - case AttributeList::AT_AMDGPUFlatWorkGroupSize: + case ParsedAttr::AT_AMDGPUFlatWorkGroupSize: handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL); break; - case AttributeList::AT_AMDGPUWavesPerEU: + case ParsedAttr::AT_AMDGPUWavesPerEU: handleAMDGPUWavesPerEUAttr(S, D, AL); break; - case AttributeList::AT_AMDGPUNumSGPR: + case ParsedAttr::AT_AMDGPUNumSGPR: handleAMDGPUNumSGPRAttr(S, D, AL); break; - case AttributeList::AT_AMDGPUNumVGPR: + case ParsedAttr::AT_AMDGPUNumVGPR: handleAMDGPUNumVGPRAttr(S, D, AL); break; - case AttributeList::AT_AVRSignal: + case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; - case AttributeList::AT_IBAction: + case ParsedAttr::AT_IBAction: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_IBOutlet: + case ParsedAttr::AT_IBOutlet: handleIBOutlet(S, D, AL); break; - case AttributeList::AT_IBOutletCollection: + case ParsedAttr::AT_IBOutletCollection: handleIBOutletCollection(S, D, AL); break; - case AttributeList::AT_IFunc: + case ParsedAttr::AT_IFunc: handleIFuncAttr(S, D, AL); break; - case AttributeList::AT_Alias: + case ParsedAttr::AT_Alias: handleAliasAttr(S, D, AL); break; - case AttributeList::AT_Aligned: + case ParsedAttr::AT_Aligned: handleAlignedAttr(S, D, AL); break; - case AttributeList::AT_AlignValue: + case ParsedAttr::AT_AlignValue: handleAlignValueAttr(S, D, AL); break; - case AttributeList::AT_AllocSize: + case ParsedAttr::AT_AllocSize: handleAllocSizeAttr(S, D, AL); break; - case AttributeList::AT_AlwaysInline: + case ParsedAttr::AT_AlwaysInline: handleAlwaysInlineAttr(S, D, AL); break; - case AttributeList::AT_Artificial: + case ParsedAttr::AT_Artificial: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_AnalyzerNoReturn: + case ParsedAttr::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, AL); break; - case AttributeList::AT_TLSModel: + case ParsedAttr::AT_TLSModel: handleTLSModelAttr(S, D, AL); break; - case AttributeList::AT_Annotate: + case ParsedAttr::AT_Annotate: handleAnnotateAttr(S, D, AL); break; - case AttributeList::AT_Availability: + case ParsedAttr::AT_Availability: handleAvailabilityAttr(S, D, AL); break; - case AttributeList::AT_CarriesDependency: + case ParsedAttr::AT_CarriesDependency: handleDependencyAttr(S, scope, D, AL); break; - case AttributeList::AT_Common: + case ParsedAttr::AT_Common: handleCommonAttr(S, D, AL); break; - case AttributeList::AT_CUDAConstant: + case ParsedAttr::AT_CUDAConstant: handleConstantAttr(S, D, AL); break; - case AttributeList::AT_PassObjectSize: + case ParsedAttr::AT_PassObjectSize: handlePassObjectSizeAttr(S, D, AL); break; - case AttributeList::AT_Constructor: + case ParsedAttr::AT_Constructor: handleConstructorAttr(S, D, AL); break; - case AttributeList::AT_CXX11NoReturn: + case ParsedAttr::AT_CXX11NoReturn: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Deprecated: + case ParsedAttr::AT_Deprecated: handleDeprecatedAttr(S, D, AL); break; - case AttributeList::AT_Destructor: + case ParsedAttr::AT_Destructor: handleDestructorAttr(S, D, AL); break; - case AttributeList::AT_EnableIf: + case ParsedAttr::AT_EnableIf: handleEnableIfAttr(S, D, AL); break; - case AttributeList::AT_DiagnoseIf: + case ParsedAttr::AT_DiagnoseIf: handleDiagnoseIfAttr(S, D, AL); break; - case AttributeList::AT_ExtVectorType: + case ParsedAttr::AT_ExtVectorType: handleExtVectorTypeAttr(S, D, AL); break; - case AttributeList::AT_ExternalSourceSymbol: + case ParsedAttr::AT_ExternalSourceSymbol: handleExternalSourceSymbolAttr(S, D, AL); break; - case AttributeList::AT_MinSize: + case ParsedAttr::AT_MinSize: handleMinSizeAttr(S, D, AL); break; - case AttributeList::AT_OptimizeNone: + case ParsedAttr::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, AL); break; - case AttributeList::AT_FlagEnum: + case ParsedAttr::AT_FlagEnum: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_EnumExtensibility: + case ParsedAttr::AT_EnumExtensibility: handleEnumExtensibilityAttr(S, D, AL); break; - case AttributeList::AT_Flatten: + case ParsedAttr::AT_Flatten: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Format: + case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); break; - case AttributeList::AT_FormatArg: + case ParsedAttr::AT_FormatArg: handleFormatArgAttr(S, D, AL); break; - case AttributeList::AT_CUDAGlobal: + case ParsedAttr::AT_CUDAGlobal: handleGlobalAttr(S, D, AL); break; - case AttributeList::AT_CUDADevice: + case ParsedAttr::AT_CUDADevice: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_CUDAHost: + case ParsedAttr::AT_CUDAHost: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_GNUInline: + case ParsedAttr::AT_GNUInline: handleGNUInlineAttr(S, D, AL); break; - case AttributeList::AT_CUDALaunchBounds: + case ParsedAttr::AT_CUDALaunchBounds: handleLaunchBoundsAttr(S, D, AL); break; - case AttributeList::AT_Restrict: + case ParsedAttr::AT_Restrict: handleRestrictAttr(S, D, AL); break; - case AttributeList::AT_MayAlias: + case ParsedAttr::AT_MayAlias: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Mode: + case ParsedAttr::AT_Mode: handleModeAttr(S, D, AL); break; - case AttributeList::AT_NoAlias: + case ParsedAttr::AT_NoAlias: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoCommon: + case ParsedAttr::AT_NoCommon: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoSplitStack: + case ParsedAttr::AT_NoSplitStack: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NonNull: + case ParsedAttr::AT_NonNull: if (auto *PVD = dyn_cast(D)) handleNonNullAttrParameter(S, PVD, AL); else handleNonNullAttr(S, D, AL); break; - case AttributeList::AT_ReturnsNonNull: + case ParsedAttr::AT_ReturnsNonNull: handleReturnsNonNullAttr(S, D, AL); break; - case AttributeList::AT_NoEscape: + case ParsedAttr::AT_NoEscape: handleNoEscapeAttr(S, D, AL); break; - case AttributeList::AT_AssumeAligned: + case ParsedAttr::AT_AssumeAligned: handleAssumeAlignedAttr(S, D, AL); break; - case AttributeList::AT_AllocAlign: + case ParsedAttr::AT_AllocAlign: handleAllocAlignAttr(S, D, AL); break; - case AttributeList::AT_Overloadable: + case ParsedAttr::AT_Overloadable: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Ownership: + case ParsedAttr::AT_Ownership: handleOwnershipAttr(S, D, AL); break; - case AttributeList::AT_Cold: + case ParsedAttr::AT_Cold: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_Hot: + case ParsedAttr::AT_Hot: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_Naked: + case ParsedAttr::AT_Naked: handleNakedAttr(S, D, AL); break; - case AttributeList::AT_NoReturn: + case ParsedAttr::AT_NoReturn: handleNoReturnAttr(S, D, AL); break; - case AttributeList::AT_AnyX86NoCfCheck: + case ParsedAttr::AT_AnyX86NoCfCheck: handleNoCfCheckAttr(S, D, AL); break; - case AttributeList::AT_NoThrow: + case ParsedAttr::AT_NoThrow: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_CUDAShared: + case ParsedAttr::AT_CUDAShared: handleSharedAttr(S, D, AL); break; - case AttributeList::AT_VecReturn: + case ParsedAttr::AT_VecReturn: handleVecReturnAttr(S, D, AL); break; - case AttributeList::AT_ObjCOwnership: + case ParsedAttr::AT_ObjCOwnership: handleObjCOwnershipAttr(S, D, AL); break; - case AttributeList::AT_ObjCPreciseLifetime: + case ParsedAttr::AT_ObjCPreciseLifetime: handleObjCPreciseLifetimeAttr(S, D, AL); break; - case AttributeList::AT_ObjCReturnsInnerPointer: + case ParsedAttr::AT_ObjCReturnsInnerPointer: handleObjCReturnsInnerPointerAttr(S, D, AL); break; - case AttributeList::AT_ObjCRequiresSuper: + case ParsedAttr::AT_ObjCRequiresSuper: handleObjCRequiresSuperAttr(S, D, AL); break; - case AttributeList::AT_ObjCBridge: + case ParsedAttr::AT_ObjCBridge: handleObjCBridgeAttr(S, D, AL); break; - case AttributeList::AT_ObjCBridgeMutable: + case ParsedAttr::AT_ObjCBridgeMutable: handleObjCBridgeMutableAttr(S, D, AL); break; - case AttributeList::AT_ObjCBridgeRelated: + case ParsedAttr::AT_ObjCBridgeRelated: handleObjCBridgeRelatedAttr(S, D, AL); break; - case AttributeList::AT_ObjCDesignatedInitializer: + case ParsedAttr::AT_ObjCDesignatedInitializer: handleObjCDesignatedInitializer(S, D, AL); break; - case AttributeList::AT_ObjCRuntimeName: + case ParsedAttr::AT_ObjCRuntimeName: handleObjCRuntimeName(S, D, AL); break; - case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute(S, D, AL); - break; - case AttributeList::AT_ObjCBoxable: + case ParsedAttr::AT_ObjCRuntimeVisible: + handleSimpleAttribute(S, D, AL); + break; + case ParsedAttr::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; - case AttributeList::AT_CFAuditedTransfer: + case ParsedAttr::AT_CFAuditedTransfer: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_CFUnknownTransfer: + case ParsedAttr::AT_CFUnknownTransfer: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_CFConsumed: - case AttributeList::AT_NSConsumed: + case ParsedAttr::AT_CFConsumed: + case ParsedAttr::AT_NSConsumed: handleNSConsumedAttr(S, D, AL); break; - case AttributeList::AT_NSConsumesSelf: + case ParsedAttr::AT_NSConsumesSelf: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NSReturnsAutoreleased: - case AttributeList::AT_NSReturnsNotRetained: - case AttributeList::AT_CFReturnsNotRetained: - case AttributeList::AT_NSReturnsRetained: - case AttributeList::AT_CFReturnsRetained: + case ParsedAttr::AT_NSReturnsAutoreleased: + case ParsedAttr::AT_NSReturnsNotRetained: + case ParsedAttr::AT_CFReturnsNotRetained: + case ParsedAttr::AT_NSReturnsRetained: + case ParsedAttr::AT_CFReturnsRetained: handleNSReturnsRetainedAttr(S, D, AL); break; - case AttributeList::AT_WorkGroupSizeHint: + case ParsedAttr::AT_WorkGroupSizeHint: handleWorkGroupSize(S, D, AL); break; - case AttributeList::AT_ReqdWorkGroupSize: + case ParsedAttr::AT_ReqdWorkGroupSize: handleWorkGroupSize(S, D, AL); break; - case AttributeList::AT_OpenCLIntelReqdSubGroupSize: + case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize: handleSubGroupSize(S, D, AL); break; - case AttributeList::AT_VecTypeHint: + case ParsedAttr::AT_VecTypeHint: handleVecTypeHint(S, D, AL); break; - case AttributeList::AT_RequireConstantInit: + case ParsedAttr::AT_RequireConstantInit: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_InitPriority: + case ParsedAttr::AT_InitPriority: handleInitPriorityAttr(S, D, AL); break; - case AttributeList::AT_Packed: + case ParsedAttr::AT_Packed: handlePackedAttr(S, D, AL); break; - case AttributeList::AT_Section: + case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; - case AttributeList::AT_Target: + case ParsedAttr::AT_Target: handleTargetAttr(S, D, AL); break; - case AttributeList::AT_MinVectorWidth: + case ParsedAttr::AT_MinVectorWidth: handleMinVectorWidthAttr(S, D, AL); break; - case AttributeList::AT_Unavailable: + case ParsedAttr::AT_Unavailable: handleAttrWithMessage(S, D, AL); break; - case AttributeList::AT_ArcWeakrefUnavailable: + case ParsedAttr::AT_ArcWeakrefUnavailable: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_ObjCRootClass: + case ParsedAttr::AT_ObjCRootClass: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_ObjCSubclassingRestricted: + case ParsedAttr::AT_ObjCSubclassingRestricted: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_ObjCExplicitProtocolImpl: + case ParsedAttr::AT_ObjCExplicitProtocolImpl: handleObjCSuppresProtocolAttr(S, D, AL); break; - case AttributeList::AT_ObjCRequiresPropertyDefs: + case ParsedAttr::AT_ObjCRequiresPropertyDefs: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Unused: + case ParsedAttr::AT_Unused: handleUnusedAttr(S, D, AL); break; - case AttributeList::AT_ReturnsTwice: + case ParsedAttr::AT_ReturnsTwice: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NotTailCalled: + case ParsedAttr::AT_NotTailCalled: handleSimpleAttributeWithExclusions( S, D, AL); break; - case AttributeList::AT_DisableTailCalls: + case ParsedAttr::AT_DisableTailCalls: handleSimpleAttributeWithExclusions(S, D, AL); break; - case AttributeList::AT_Used: + case ParsedAttr::AT_Used: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Visibility: + case ParsedAttr::AT_Visibility: handleVisibilityAttr(S, D, AL, false); break; - case AttributeList::AT_TypeVisibility: + case ParsedAttr::AT_TypeVisibility: handleVisibilityAttr(S, D, AL, true); break; - case AttributeList::AT_WarnUnused: + case ParsedAttr::AT_WarnUnused: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_WarnUnusedResult: + case ParsedAttr::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, AL); break; - case AttributeList::AT_Weak: + case ParsedAttr::AT_Weak: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_WeakRef: + case ParsedAttr::AT_WeakRef: handleWeakRefAttr(S, D, AL); break; - case AttributeList::AT_WeakImport: + case ParsedAttr::AT_WeakImport: handleWeakImportAttr(S, D, AL); break; - case AttributeList::AT_TransparentUnion: + case ParsedAttr::AT_TransparentUnion: handleTransparentUnionAttr(S, D, AL); break; - case AttributeList::AT_ObjCException: + case ParsedAttr::AT_ObjCException: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_ObjCMethodFamily: + case ParsedAttr::AT_ObjCMethodFamily: handleObjCMethodFamilyAttr(S, D, AL); break; - case AttributeList::AT_ObjCNSObject: + case ParsedAttr::AT_ObjCNSObject: handleObjCNSObject(S, D, AL); break; - case AttributeList::AT_ObjCIndependentClass: + case ParsedAttr::AT_ObjCIndependentClass: handleObjCIndependentClass(S, D, AL); break; - case AttributeList::AT_Blocks: + case ParsedAttr::AT_Blocks: handleBlocksAttr(S, D, AL); break; - case AttributeList::AT_Sentinel: + case ParsedAttr::AT_Sentinel: handleSentinelAttr(S, D, AL); break; - case AttributeList::AT_Const: + case ParsedAttr::AT_Const: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Pure: + case ParsedAttr::AT_Pure: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Cleanup: + case ParsedAttr::AT_Cleanup: handleCleanupAttr(S, D, AL); break; - case AttributeList::AT_NoDebug: + case ParsedAttr::AT_NoDebug: handleNoDebugAttr(S, D, AL); break; - case AttributeList::AT_NoDuplicate: + case ParsedAttr::AT_NoDuplicate: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Convergent: + case ParsedAttr::AT_Convergent: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoInline: + case ParsedAttr::AT_NoInline: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. + case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg. handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoStackProtector: + case ParsedAttr::AT_NoStackProtector: // Interacts with -fstack-protector options. handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_StdCall: - case AttributeList::AT_CDecl: - case AttributeList::AT_FastCall: - case AttributeList::AT_ThisCall: - case AttributeList::AT_Pascal: - case AttributeList::AT_RegCall: - case AttributeList::AT_SwiftCall: - case AttributeList::AT_VectorCall: - case AttributeList::AT_MSABI: - case AttributeList::AT_SysVABI: - case AttributeList::AT_Pcs: - case AttributeList::AT_IntelOclBicc: - case AttributeList::AT_PreserveMost: - case AttributeList::AT_PreserveAll: + case ParsedAttr::AT_StdCall: + case ParsedAttr::AT_CDecl: + case ParsedAttr::AT_FastCall: + case ParsedAttr::AT_ThisCall: + case ParsedAttr::AT_Pascal: + case ParsedAttr::AT_RegCall: + case ParsedAttr::AT_SwiftCall: + case ParsedAttr::AT_VectorCall: + case ParsedAttr::AT_MSABI: + case ParsedAttr::AT_SysVABI: + case ParsedAttr::AT_Pcs: + case ParsedAttr::AT_IntelOclBicc: + case ParsedAttr::AT_PreserveMost: + case ParsedAttr::AT_PreserveAll: handleCallConvAttr(S, D, AL); break; - case AttributeList::AT_Suppress: + case ParsedAttr::AT_Suppress: handleSuppressAttr(S, D, AL); break; - case AttributeList::AT_OpenCLKernel: + case ParsedAttr::AT_OpenCLKernel: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_OpenCLAccess: + case ParsedAttr::AT_OpenCLAccess: handleOpenCLAccessAttr(S, D, AL); break; - case AttributeList::AT_OpenCLNoSVM: + case ParsedAttr::AT_OpenCLNoSVM: handleOpenCLNoSVMAttr(S, D, AL); break; - case AttributeList::AT_SwiftContext: + case ParsedAttr::AT_SwiftContext: handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext); break; - case AttributeList::AT_SwiftErrorResult: + case ParsedAttr::AT_SwiftErrorResult: handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult); break; - case AttributeList::AT_SwiftIndirectResult: + case ParsedAttr::AT_SwiftIndirectResult: handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult); break; - case AttributeList::AT_InternalLinkage: + case ParsedAttr::AT_InternalLinkage: handleInternalLinkageAttr(S, D, AL); break; - case AttributeList::AT_LTOVisibilityPublic: + case ParsedAttr::AT_LTOVisibilityPublic: handleSimpleAttribute(S, D, AL); break; // Microsoft attributes: - case AttributeList::AT_EmptyBases: + case ParsedAttr::AT_EmptyBases: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_LayoutVersion: + case ParsedAttr::AT_LayoutVersion: handleLayoutVersion(S, D, AL); break; - case AttributeList::AT_TrivialABI: + case ParsedAttr::AT_TrivialABI: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_MSNoVTable: + case ParsedAttr::AT_MSNoVTable: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_MSStruct: + case ParsedAttr::AT_MSStruct: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Uuid: + case ParsedAttr::AT_Uuid: handleUuidAttr(S, D, AL); break; - case AttributeList::AT_MSInheritance: + case ParsedAttr::AT_MSInheritance: handleMSInheritanceAttr(S, D, AL); break; - case AttributeList::AT_SelectAny: + case ParsedAttr::AT_SelectAny: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_Thread: + case ParsedAttr::AT_Thread: handleDeclspecThreadAttr(S, D, AL); break; - case AttributeList::AT_AbiTag: + case ParsedAttr::AT_AbiTag: handleAbiTagAttr(S, D, AL); break; // Thread safety attributes: - case AttributeList::AT_AssertExclusiveLock: + case ParsedAttr::AT_AssertExclusiveLock: handleAssertExclusiveLockAttr(S, D, AL); break; - case AttributeList::AT_AssertSharedLock: + case ParsedAttr::AT_AssertSharedLock: handleAssertSharedLockAttr(S, D, AL); break; - case AttributeList::AT_GuardedVar: + case ParsedAttr::AT_GuardedVar: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_PtGuardedVar: + case ParsedAttr::AT_PtGuardedVar: handlePtGuardedVarAttr(S, D, AL); break; - case AttributeList::AT_ScopedLockable: + case ParsedAttr::AT_ScopedLockable: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_NoSanitize: + case ParsedAttr::AT_NoSanitize: handleNoSanitizeAttr(S, D, AL); break; - case AttributeList::AT_NoSanitizeSpecific: + case ParsedAttr::AT_NoSanitizeSpecific: handleNoSanitizeSpecificAttr(S, D, AL); break; - case AttributeList::AT_NoThreadSafetyAnalysis: + case ParsedAttr::AT_NoThreadSafetyAnalysis: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_GuardedBy: + case ParsedAttr::AT_GuardedBy: handleGuardedByAttr(S, D, AL); break; - case AttributeList::AT_PtGuardedBy: + case ParsedAttr::AT_PtGuardedBy: handlePtGuardedByAttr(S, D, AL); break; - case AttributeList::AT_ExclusiveTrylockFunction: + case ParsedAttr::AT_ExclusiveTrylockFunction: handleExclusiveTrylockFunctionAttr(S, D, AL); break; - case AttributeList::AT_LockReturned: + case ParsedAttr::AT_LockReturned: handleLockReturnedAttr(S, D, AL); break; - case AttributeList::AT_LocksExcluded: + case ParsedAttr::AT_LocksExcluded: handleLocksExcludedAttr(S, D, AL); break; - case AttributeList::AT_SharedTrylockFunction: + case ParsedAttr::AT_SharedTrylockFunction: handleSharedTrylockFunctionAttr(S, D, AL); break; - case AttributeList::AT_AcquiredBefore: + case ParsedAttr::AT_AcquiredBefore: handleAcquiredBeforeAttr(S, D, AL); break; - case AttributeList::AT_AcquiredAfter: + case ParsedAttr::AT_AcquiredAfter: handleAcquiredAfterAttr(S, D, AL); break; // Capability analysis attributes. - case AttributeList::AT_Capability: - case AttributeList::AT_Lockable: + case ParsedAttr::AT_Capability: + case ParsedAttr::AT_Lockable: handleCapabilityAttr(S, D, AL); break; - case AttributeList::AT_RequiresCapability: + case ParsedAttr::AT_RequiresCapability: handleRequiresCapabilityAttr(S, D, AL); break; - case AttributeList::AT_AssertCapability: + case ParsedAttr::AT_AssertCapability: handleAssertCapabilityAttr(S, D, AL); break; - case AttributeList::AT_AcquireCapability: + case ParsedAttr::AT_AcquireCapability: handleAcquireCapabilityAttr(S, D, AL); break; - case AttributeList::AT_ReleaseCapability: + case ParsedAttr::AT_ReleaseCapability: handleReleaseCapabilityAttr(S, D, AL); break; - case AttributeList::AT_TryAcquireCapability: + case ParsedAttr::AT_TryAcquireCapability: handleTryAcquireCapabilityAttr(S, D, AL); break; // Consumed analysis attributes. - case AttributeList::AT_Consumable: + case ParsedAttr::AT_Consumable: handleConsumableAttr(S, D, AL); break; - case AttributeList::AT_ConsumableAutoCast: + case ParsedAttr::AT_ConsumableAutoCast: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_ConsumableSetOnRead: + case ParsedAttr::AT_ConsumableSetOnRead: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_CallableWhen: + case ParsedAttr::AT_CallableWhen: handleCallableWhenAttr(S, D, AL); break; - case AttributeList::AT_ParamTypestate: + case ParsedAttr::AT_ParamTypestate: handleParamTypestateAttr(S, D, AL); break; - case AttributeList::AT_ReturnTypestate: + case ParsedAttr::AT_ReturnTypestate: handleReturnTypestateAttr(S, D, AL); break; - case AttributeList::AT_SetTypestate: + case ParsedAttr::AT_SetTypestate: handleSetTypestateAttr(S, D, AL); break; - case AttributeList::AT_TestTypestate: + case ParsedAttr::AT_TestTypestate: handleTestTypestateAttr(S, D, AL); break; // Type safety attributes. - case AttributeList::AT_ArgumentWithTypeTag: + case ParsedAttr::AT_ArgumentWithTypeTag: handleArgumentWithTypeTagAttr(S, D, AL); break; - case AttributeList::AT_TypeTagForDatatype: + case ParsedAttr::AT_TypeTagForDatatype: handleTypeTagForDatatypeAttr(S, D, AL); break; - case AttributeList::AT_AnyX86NoCallerSavedRegisters: + case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_RenderScriptKernel: + case ParsedAttr::AT_RenderScriptKernel: handleSimpleAttribute(S, D, AL); break; // XRay attributes. - case AttributeList::AT_XRayInstrument: + case ParsedAttr::AT_XRayInstrument: handleSimpleAttribute(S, D, AL); break; - case AttributeList::AT_XRayLogArgs: + case ParsedAttr::AT_XRayLogArgs: handleXRayLogArgsAttr(S, D, AL); break; } @@ -6462,7 +6437,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, if (AttrList.empty()) return; - for (const AttributeList &AL : AttrList) + for (const ParsedAttr &AL : AttrList) ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); // FIXME: We should be able to handle these cases in TableGen. @@ -6521,8 +6496,8 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, // Helper for delayed processing TransparentUnion attribute. void Sema::ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList) { - for (const AttributeList &AL : AttrList) - if (AL.getKind() == AttributeList::AT_TransparentUnion) { + for (const ParsedAttr &AL : AttrList) + if (AL.getKind() == ParsedAttr::AT_TransparentUnion) { handleTransparentUnionAttr(*this, D, AL); break; } @@ -6532,8 +6507,8 @@ void Sema::ProcessDeclAttributeDelayed(Decl *D, // specifier. bool Sema::ProcessAccessDeclAttributeList( AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { - for (const AttributeList &AL : AttrList) { - if (AL.getKind() == AttributeList::AT_Annotate) { + for (const ParsedAttr &AL : AttrList) { + if (AL.getKind() == ParsedAttr::AT_Annotate) { ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); } else { Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); @@ -6546,14 +6521,14 @@ bool Sema::ProcessAccessDeclAttributeList( /// checkUnusedDeclAttributes - Check a list of attributes to see if it /// contains any decl attributes that we should warn about. static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { - for (const AttributeList &AL : A) { + for (const ParsedAttr &AL : A) { // Only warn if the attribute is an unignored, non-type attribute. if (AL.isUsedAsTypeAttr() || AL.isInvalid()) continue; - if (AL.getKind() == AttributeList::IgnoredAttribute) + if (AL.getKind() == ParsedAttr::IgnoredAttribute) continue; - if (AL.getKind() == AttributeList::UnknownAttribute) { + if (AL.getKind() == ParsedAttr::UnknownAttribute) { S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName() << AL.getRange(); } else { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6f411ca26d..63d01c9d85 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2300,10 +2300,10 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. - for (const AttributeList &AL : Attributes) { - if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) + for (const ParsedAttr &AL : Attributes) { + if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) continue; - Diag(AL.getLoc(), AL.getKind() == AttributeList::UnknownAttribute + Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute ? diag::warn_unknown_attribute_ignored : diag::err_base_specifier_attribute) << AL.getName(); @@ -2816,10 +2816,9 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { return false; } -static const AttributeList * -getMSPropertyAttr(const ParsedAttributesView &list) { +static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) { ParsedAttributesView::const_iterator Itr = - llvm::find_if(list, [](const AttributeList &AL) { + llvm::find_if(list, [](const ParsedAttr &AL) { return AL.isDeclspecPropertyAttribute(); }); if (Itr != list.end()) @@ -2902,7 +2901,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); - const AttributeList *MSPropertyAttr = + const ParsedAttr *MSPropertyAttr = getMSPropertyAttr(D.getDeclSpec().getAttributes()); if (cast(CurContext)->isInterface()) { @@ -7815,8 +7814,8 @@ void Sema::ActOnFinishCXXMemberSpecification( AdjustDeclIfTemplate(TagDecl); - for (const AttributeList &AL : AttrList) { - if (AL.getKind() != AttributeList::AT_Visibility) + for (const ParsedAttr &AL : AttrList) { + if (AL.getKind() != ParsedAttr::AT_Visibility) continue; AL.setInvalid(); Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) @@ -15388,7 +15387,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - const AttributeList &MSPropertyAttr) { + const ParsedAttr &MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); @@ -15451,7 +15450,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); - const AttributeList::PropertyData &Data = MSPropertyAttr.getPropertyData(); + const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData(); MSPropertyDecl *NewPD = MSPropertyDecl::Create( Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); ProcessDeclAttributes(TUScope, NewPD, D); diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index dbd967cc93..e39a65c6ce 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -23,7 +23,7 @@ using namespace clang; using namespace sema; -static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, +static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { FallThroughAttr Attr(A.getRange(), S.Context, A.getAttributeSpellingListIndex()); @@ -53,7 +53,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, return ::new (S.Context) auto(Attr); } -static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A, +static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { if (A.getNumArgs() < 1) { S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) @@ -78,7 +78,7 @@ static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A, DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex()); } -static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, +static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange) { IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0); IdentifierLoc *OptionLoc = A.getArgAsIdent(1); @@ -246,7 +246,7 @@ CheckForIncompatibleAttributes(Sema &S, } } -static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A, +static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { // Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's // useful for OpenCL 1.x too and doesn't require HW support. @@ -288,21 +288,21 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A, return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor); } -static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, +static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { switch (A.getKind()) { - case AttributeList::UnknownAttribute: + case ParsedAttr::UnknownAttribute: S.Diag(A.getLoc(), A.isDeclspecAttribute() ? diag::warn_unhandled_ms_attribute_ignored : diag::warn_unknown_attribute_ignored) << A.getName(); return nullptr; - case AttributeList::AT_FallThrough: + case ParsedAttr::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); - case AttributeList::AT_LoopHint: + case ParsedAttr::AT_LoopHint: return handleLoopHintAttr(S, St, A, Range); - case AttributeList::AT_OpenCLUnrollHint: + case ParsedAttr::AT_OpenCLUnrollHint: return handleOpenCLUnrollHint(S, St, A, Range); - case AttributeList::AT_Suppress: + case ParsedAttr::AT_Suppress: return handleSuppressAttr(S, St, A, Range); default: // if we're here, then we parsed a known attribute, but didn't recognize @@ -317,7 +317,7 @@ StmtResult Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributesView &AttrList, SourceRange Range) { SmallVector Attrs; - for (const AttributeList &AL : AttrList) { + for (const ParsedAttr &AL : AttrList) { if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range)) Attrs.push_back(a); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 276a617d1a..e78fd438dc 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -8599,8 +8599,8 @@ DeclResult Sema::ActOnExplicitInstantiation( if (TSK == TSK_ExplicitInstantiationDeclaration) { // Check for dllexport class template instantiation declarations. - for (const AttributeList &AL : Attr) { - if (AL.getKind() == AttributeList::AT_DLLExport) { + for (const ParsedAttr &AL : Attr) { + if (AL.getKind() == ParsedAttr::AT_DLLExport) { Diag(ExternLoc, diag::warn_attribute_dllexport_explicit_instantiation_decl); Diag(AL.getLoc(), diag::note_attribute); @@ -8623,10 +8623,10 @@ DeclResult Sema::ActOnExplicitInstantiation( // Check for dllimport class template instantiation definitions. bool DLLImport = ClassTemplate->getTemplatedDecl()->getAttr(); - for (const AttributeList &AL : Attr) { - if (AL.getKind() == AttributeList::AT_DLLImport) + for (const ParsedAttr &AL : Attr) { + if (AL.getKind() == ParsedAttr::AT_DLLImport) DLLImport = true; - if (AL.getKind() == AttributeList::AT_DLLExport) { + if (AL.getKind() == ParsedAttr::AT_DLLExport) { // dllexport trumps dllimport here. DLLImport = false; break; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 18c5ce75d1..641a2f5f06 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -64,13 +64,17 @@ static bool isOmittedBlockReturnType(const Declarator &D) { /// diagnoseBadTypeAttribute - Diagnoses a type attribute which /// doesn't apply to the given type. -static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, +static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, QualType type) { TypeDiagSelector WhichType; bool useExpansionLoc = true; switch (attr.getKind()) { - case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break; - case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break; + case ParsedAttr::AT_ObjCGC: + WhichType = TDS_Pointer; + break; + case ParsedAttr::AT_ObjCOwnership: + WhichType = TDS_ObjCObjOrBlock; + break; default: // Assume everything else was a function attribute. WhichType = TDS_Function; @@ -98,48 +102,48 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, // objc_gc applies to Objective-C pointers or, otherwise, to the // smallest available pointer type (i.e. 'void*' in 'void**'). -#define OBJC_POINTER_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_ObjCGC: \ - case AttributeList::AT_ObjCOwnership +#define OBJC_POINTER_TYPE_ATTRS_CASELIST \ + case ParsedAttr::AT_ObjCGC: \ + case ParsedAttr::AT_ObjCOwnership // Calling convention attributes. -#define CALLING_CONV_ATTRS_CASELIST \ - case AttributeList::AT_CDecl: \ - case AttributeList::AT_FastCall: \ - case AttributeList::AT_StdCall: \ - case AttributeList::AT_ThisCall: \ - case AttributeList::AT_RegCall: \ - case AttributeList::AT_Pascal: \ - case AttributeList::AT_SwiftCall: \ - case AttributeList::AT_VectorCall: \ - case AttributeList::AT_MSABI: \ - case AttributeList::AT_SysVABI: \ - case AttributeList::AT_Pcs: \ - case AttributeList::AT_IntelOclBicc: \ - case AttributeList::AT_PreserveMost: \ - case AttributeList::AT_PreserveAll +#define CALLING_CONV_ATTRS_CASELIST \ + case ParsedAttr::AT_CDecl: \ + case ParsedAttr::AT_FastCall: \ + case ParsedAttr::AT_StdCall: \ + case ParsedAttr::AT_ThisCall: \ + case ParsedAttr::AT_RegCall: \ + case ParsedAttr::AT_Pascal: \ + case ParsedAttr::AT_SwiftCall: \ + case ParsedAttr::AT_VectorCall: \ + case ParsedAttr::AT_MSABI: \ + case ParsedAttr::AT_SysVABI: \ + case ParsedAttr::AT_Pcs: \ + case ParsedAttr::AT_IntelOclBicc: \ + case ParsedAttr::AT_PreserveMost: \ + case ParsedAttr::AT_PreserveAll // Function type attributes. -#define FUNCTION_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_NSReturnsRetained: \ - case AttributeList::AT_NoReturn: \ - case AttributeList::AT_Regparm: \ - case AttributeList::AT_AnyX86NoCallerSavedRegisters: \ - case AttributeList::AT_AnyX86NoCfCheck: \ +#define FUNCTION_TYPE_ATTRS_CASELIST \ + case ParsedAttr::AT_NSReturnsRetained: \ + case ParsedAttr::AT_NoReturn: \ + case ParsedAttr::AT_Regparm: \ + case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: \ + case ParsedAttr::AT_AnyX86NoCfCheck: \ CALLING_CONV_ATTRS_CASELIST // Microsoft-specific type qualifiers. -#define MS_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_Ptr32: \ - case AttributeList::AT_Ptr64: \ - case AttributeList::AT_SPtr: \ - case AttributeList::AT_UPtr +#define MS_TYPE_ATTRS_CASELIST \ + case ParsedAttr::AT_Ptr32: \ + case ParsedAttr::AT_Ptr64: \ + case ParsedAttr::AT_SPtr: \ + case ParsedAttr::AT_UPtr // Nullability qualifiers. -#define NULLABILITY_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_TypeNonNull: \ - case AttributeList::AT_TypeNullable: \ - case AttributeList::AT_TypeNullUnspecified +#define NULLABILITY_TYPE_ATTRS_CASELIST \ + case ParsedAttr::AT_TypeNonNull: \ + case ParsedAttr::AT_TypeNullable: \ + case ParsedAttr::AT_TypeNullUnspecified namespace { /// An object which stores processing state for the entire @@ -162,11 +166,11 @@ namespace { bool hasSavedAttrs; /// The original set of attributes on the DeclSpec. - SmallVector savedAttrs; + SmallVector savedAttrs; /// A list of attributes to diagnose the uselessness of when the /// processing is complete. - SmallVector ignoredTypeAttrs; + SmallVector ignoredTypeAttrs; public: TypeProcessingState(Sema &sema, Declarator &declarator) @@ -207,7 +211,7 @@ namespace { if (hasSavedAttrs) return; DeclSpec &spec = getMutableDeclSpec(); - for (AttributeList &AL : spec.getAttributes()) + for (ParsedAttr &AL : spec.getAttributes()) savedAttrs.push_back(&AL); trivial &= savedAttrs.empty(); hasSavedAttrs = true; @@ -215,7 +219,7 @@ namespace { /// Record that we had nowhere to put the given type attribute. /// We will diagnose such attributes later. - void addIgnoredTypeAttr(AttributeList &attr) { + void addIgnoredTypeAttr(ParsedAttr &attr) { ignoredTypeAttrs.push_back(&attr); } @@ -241,13 +245,13 @@ namespace { assert(hasSavedAttrs); getMutableDeclSpec().getAttributes().clearListOnly(); - for (AttributeList *AL : savedAttrs) + for (ParsedAttr *AL : savedAttrs) getMutableDeclSpec().getAttributes().addAtStart(AL); } }; } // end anonymous namespace -static void moveAttrFromListToList(AttributeList &attr, +static void moveAttrFromListToList(ParsedAttr &attr, ParsedAttributesView &fromList, ParsedAttributesView &toList) { fromList.remove(&attr); @@ -267,25 +271,23 @@ enum TypeAttrLocation { static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, ParsedAttributesView &attrs); -static bool handleFunctionTypeAttr(TypeProcessingState &state, - AttributeList &attr, +static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, QualType &type); static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state, - AttributeList &attr, - QualType &type); + ParsedAttr &attr, QualType &type); -static bool handleObjCGCTypeAttr(TypeProcessingState &state, - AttributeList &attr, QualType &type); +static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, + QualType &type); static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, - AttributeList &attr, QualType &type); + ParsedAttr &attr, QualType &type); static bool handleObjCPointerTypeAttr(TypeProcessingState &state, - AttributeList &attr, QualType &type) { - if (attr.getKind() == AttributeList::AT_ObjCGC) + ParsedAttr &attr, QualType &type) { + if (attr.getKind() == ParsedAttr::AT_ObjCGC) return handleObjCGCTypeAttr(state, attr, type); - assert(attr.getKind() == AttributeList::AT_ObjCOwnership); + assert(attr.getKind() == ParsedAttr::AT_ObjCOwnership); return handleObjCOwnershipTypeAttr(state, attr, type); } @@ -367,8 +369,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator, /// didn't apply in whatever position it was written in, try to move /// it to a more appropriate position. static void distributeObjCPointerTypeAttr(TypeProcessingState &state, - AttributeList &attr, - QualType type) { + ParsedAttr &attr, QualType type) { Declarator &declarator = state.getDeclarator(); // Move it to the outermost normal or block pointer declarator. @@ -381,7 +382,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, // of a block. DeclaratorChunk *destChunk = nullptr; if (state.isProcessingDeclSpec() && - attr.getKind() == AttributeList::AT_ObjCOwnership) + attr.getKind() == ParsedAttr::AT_ObjCOwnership) destChunk = maybeMovePastReturnType(declarator, i - 1, /*onlyBlockPointers=*/true); if (!destChunk) destChunk = &chunk; @@ -398,7 +399,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, // We may be starting at the return type of a block. case DeclaratorChunk::Function: if (state.isProcessingDeclSpec() && - attr.getKind() == AttributeList::AT_ObjCOwnership) { + attr.getKind() == ParsedAttr::AT_ObjCOwnership) { if (DeclaratorChunk *dest = maybeMovePastReturnType( declarator, i, /*onlyBlockPointers=*/true)) { @@ -423,10 +424,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, /// Distribute an objc_gc type attribute that was written on the /// declarator. -static void -distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, - AttributeList &attr, - QualType &declSpecType) { +static void distributeObjCPointerTypeAttrFromDeclarator( + TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); // objc_gc goes on the innermost pointer to something that's not a @@ -487,8 +486,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, /// that it didn't apply in whatever position it was written in, try /// to move it to a more appropriate position. static void distributeFunctionTypeAttr(TypeProcessingState &state, - AttributeList &attr, - QualType type) { + ParsedAttr &attr, QualType type) { Declarator &declarator = state.getDeclarator(); // Try to push the attribute from the return type of a function to @@ -519,7 +517,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, /// function chunk or type. Returns true if the attribute was /// distributed, false if no location was found. static bool distributeFunctionTypeAttrToInnermost( - TypeProcessingState &state, AttributeList &attr, + TypeProcessingState &state, ParsedAttr &attr, ParsedAttributesView &attrList, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); @@ -537,10 +535,9 @@ static bool distributeFunctionTypeAttrToInnermost( /// A function type attribute was written in the decl spec. Try to /// apply it somewhere. -static void -distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, - AttributeList &attr, - QualType &declSpecType) { +static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType) { state.saveDeclSpecAttrs(); // C++11 attributes before the decl specifiers actually appertain to @@ -564,10 +561,9 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, /// A function type attribute was written on the declarator. Try to /// apply it somewhere. -static void -distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, - AttributeList &attr, - QualType &declSpecType) { +static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, + ParsedAttr &attr, + QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. @@ -599,7 +595,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, // list, so iterating over the existing list isn't possible. Instead, make a // non-owning copy and iterate over that. ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()}; - for (AttributeList &attr : AttrsCopy) { + for (ParsedAttr &attr : AttrsCopy) { // Do not distribute C++11 attributes. They have strict rules for what // they appertain to. if (attr.isCXX11Attribute()) @@ -622,7 +618,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, // Nullability specifiers cannot go after the declarator-id. // Objective-C __kindof does not get distributed. - case AttributeList::AT_ObjCKindOf: + case ParsedAttr::AT_ObjCKindOf: continue; default: @@ -728,8 +724,8 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, return false; // Warn if we see type attributes for omitted return type on a block literal. - SmallVector ToBeRemoved; - for (AttributeList &AL : declarator.getMutableDeclSpec().getAttributes()) { + SmallVector ToBeRemoved; + for (ParsedAttr &AL : declarator.getMutableDeclSpec().getAttributes()) { if (AL.isInvalid() || !AL.isTypeAttr()) continue; S.Diag(AL.getLoc(), @@ -738,7 +734,7 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, ToBeRemoved.push_back(&AL); } // Remove bad attributes from the list. - for (AttributeList *AL : ToBeRemoved) + for (ParsedAttr *AL : ToBeRemoved) declarator.getMutableDeclSpec().getAttributes().remove(AL); // Warn if we see type qualifiers for omitted return type on a block literal. @@ -1169,8 +1165,8 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( static OpenCLAccessAttr::Spelling getImageAccess(const ParsedAttributesView &Attrs) { - for (const AttributeList &AL : Attrs) - if (AL.getKind() == AttributeList::AT_OpenCLAccess) + for (const ParsedAttr &AL : Attrs) + if (AL.getKind() == ParsedAttr::AT_OpenCLAccess) return static_cast(AL.getSemanticSpelling()); return OpenCLAccessAttr::Keyword_read_only; } @@ -2599,8 +2595,8 @@ static void inferARCWriteback(TypeProcessingState &state, if (chunk.Kind != DeclaratorChunk::Pointer && chunk.Kind != DeclaratorChunk::BlockPointer) return; - for (const AttributeList &AL : chunk.getAttrs()) - if (AL.getKind() == AttributeList::AT_ObjCOwnership) + for (const ParsedAttr &AL : chunk.getAttrs()) + if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) return; transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing, @@ -3272,7 +3268,7 @@ static CallingConv getCCForDeclaratorChunk( assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); // Check for an explicit CC attribute. - for (const AttributeList &AL : AttrList) { + for (const ParsedAttr &AL : AttrList) { switch (AL.getKind()) { CALLING_CONV_ATTRS_CASELIST : { // Ignore attributes that don't validate or can't apply to the @@ -3335,8 +3331,8 @@ static CallingConv getCCForDeclaratorChunk( // convention attribute. This is the simplest place to infer // calling convention for OpenCL kernels. if (S.getLangOpts().OpenCL) { - for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { - if (AL.getKind() == AttributeList::AT_OpenCLKernel) { + for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == ParsedAttr::AT_OpenCLKernel) { CC = CC_OpenCLKernel; break; } @@ -3388,10 +3384,10 @@ IdentifierInfo *Sema::getNSErrorIdent() { /// Check whether there is a nullability attribute of any kind in the given /// attribute list. static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { - for (const AttributeList &AL : attrs) { - if (AL.getKind() == AttributeList::AT_TypeNonNull || - AL.getKind() == AttributeList::AT_TypeNullable || - AL.getKind() == AttributeList::AT_TypeNullUnspecified) + for (const ParsedAttr &AL : attrs) { + if (AL.getKind() == ParsedAttr::AT_TypeNonNull || + AL.getKind() == ParsedAttr::AT_TypeNullable || + AL.getKind() == ParsedAttr::AT_TypeNullUnspecified) return true; } @@ -3995,9 +3991,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // infer the inner pointer as _Nullable. auto hasCFReturnsAttr = [](const ParsedAttributesView &AttrList) -> bool { - return AttrList.hasAttribute(AttributeList::AT_CFReturnsRetained) || - AttrList.hasAttribute( - AttributeList::AT_CFReturnsNotRetained); + return AttrList.hasAttribute(ParsedAttr::AT_CFReturnsRetained) || + AttrList.hasAttribute(ParsedAttr::AT_CFReturnsNotRetained); }; if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) { if (hasCFReturnsAttr(D.getAttributes()) || @@ -4061,7 +4056,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, auto inferPointerNullability = [&](SimplePointerKind pointerKind, SourceLocation pointerLoc, SourceLocation pointerEndLoc, - ParsedAttributesView &attrs) -> AttributeList * { + ParsedAttributesView &attrs) -> ParsedAttr * { // We've seen a pointer. if (NumPointersRemaining > 0) --NumPointersRemaining; @@ -4072,16 +4067,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If we're supposed to infer nullability, do so now. if (inferNullability && !inferNullabilityInnerOnlyComplete) { - AttributeList::Syntax syntax - = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword - : AttributeList::AS_Keyword; - AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool() - .create( - S.getNullabilityKeyword( - *inferNullability), - SourceRange(pointerLoc), - nullptr, SourceLocation(), - nullptr, 0, syntax); + ParsedAttr::Syntax syntax = inferNullabilityCS + ? ParsedAttr::AS_ContextSensitiveKeyword + : ParsedAttr::AS_Keyword; + ParsedAttr *nullabilityAttr = + state.getDeclarator().getAttributePool().create( + S.getNullabilityKeyword(*inferNullability), + SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0, + syntax); attrs.addAtStart(nullabilityAttr); @@ -4474,16 +4467,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SourceLocation AttrLoc; if (chunkIndex + 1 < D.getNumTypeObjects()) { DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); - for (const AttributeList &AL : ReturnTypeChunk.getAttrs()) { - if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + for (const ParsedAttr &AL : ReturnTypeChunk.getAttrs()) { + if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) { AttrLoc = AL.getLoc(); break; } } } if (AttrLoc.isInvalid()) { - for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { - if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) { AttrLoc = AL.getLoc(); break; } @@ -4536,7 +4529,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // function is marked with the "overloadable" attribute. Scan // for this attribute now. if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) - if (!D.getAttributes().hasAttribute(AttributeList::AT_Overloadable)) + if (!D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable)) S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param); if (FTI.NumParams && FTI.Params[0].Param == nullptr) { @@ -5024,7 +5017,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, // Look for an explicit lifetime attribute. DeclaratorChunk &chunk = D.getTypeObject(chunkIndex); - if (chunk.getAttrs().hasAttribute(AttributeList::AT_ObjCOwnership)) + if (chunk.getAttrs().hasAttribute(ParsedAttr::AT_ObjCOwnership)) return; const char *attrStr = nullptr; @@ -5044,10 +5037,10 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, // If there wasn't one, add one (with an invalid source location // so that we don't make an AttributedType for it). - AttributeList *attr = D.getAttributePool() - .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), - /*scope*/ nullptr, SourceLocation(), - /*args*/ &Args, 1, AttributeList::AS_GNU); + ParsedAttr *attr = D.getAttributePool().create( + &S.Context.Idents.get("objc_ownership"), SourceLocation(), + /*scope*/ nullptr, SourceLocation(), + /*args*/ &Args, 1, ParsedAttr::AS_GNU); chunk.getAttrs().addAtStart(attr); // TODO: mark whether we did this inference? } @@ -5119,81 +5112,80 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo); } -/// Map an AttributedType::Kind to an AttributeList::Kind. -static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { +/// Map an AttributedType::Kind to an ParsedAttr::Kind. +static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) { switch (kind) { case AttributedType::attr_address_space: - return AttributeList::AT_AddressSpace; + return ParsedAttr::AT_AddressSpace; case AttributedType::attr_regparm: - return AttributeList::AT_Regparm; + return ParsedAttr::AT_Regparm; case AttributedType::attr_vector_size: - return AttributeList::AT_VectorSize; + return ParsedAttr::AT_VectorSize; case AttributedType::attr_neon_vector_type: - return AttributeList::AT_NeonVectorType; + return ParsedAttr::AT_NeonVectorType; case AttributedType::attr_neon_polyvector_type: - return AttributeList::AT_NeonPolyVectorType; + return ParsedAttr::AT_NeonPolyVectorType; case AttributedType::attr_objc_gc: - return AttributeList::AT_ObjCGC; + return ParsedAttr::AT_ObjCGC; case AttributedType::attr_objc_ownership: case AttributedType::attr_objc_inert_unsafe_unretained: - return AttributeList::AT_ObjCOwnership; + return ParsedAttr::AT_ObjCOwnership; case AttributedType::attr_noreturn: - return AttributeList::AT_NoReturn; + return ParsedAttr::AT_NoReturn; case AttributedType::attr_nocf_check: - return AttributeList::AT_AnyX86NoCfCheck; + return ParsedAttr::AT_AnyX86NoCfCheck; case AttributedType::attr_cdecl: - return AttributeList::AT_CDecl; + return ParsedAttr::AT_CDecl; case AttributedType::attr_fastcall: - return AttributeList::AT_FastCall; + return ParsedAttr::AT_FastCall; case AttributedType::attr_stdcall: - return AttributeList::AT_StdCall; + return ParsedAttr::AT_StdCall; case AttributedType::attr_thiscall: - return AttributeList::AT_ThisCall; + return ParsedAttr::AT_ThisCall; case AttributedType::attr_regcall: - return AttributeList::AT_RegCall; + return ParsedAttr::AT_RegCall; case AttributedType::attr_pascal: - return AttributeList::AT_Pascal; + return ParsedAttr::AT_Pascal; case AttributedType::attr_swiftcall: - return AttributeList::AT_SwiftCall; + return ParsedAttr::AT_SwiftCall; case AttributedType::attr_vectorcall: - return AttributeList::AT_VectorCall; + return ParsedAttr::AT_VectorCall; case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: - return AttributeList::AT_Pcs; + return ParsedAttr::AT_Pcs; case AttributedType::attr_inteloclbicc: - return AttributeList::AT_IntelOclBicc; + return ParsedAttr::AT_IntelOclBicc; case AttributedType::attr_ms_abi: - return AttributeList::AT_MSABI; + return ParsedAttr::AT_MSABI; case AttributedType::attr_sysv_abi: - return AttributeList::AT_SysVABI; + return ParsedAttr::AT_SysVABI; case AttributedType::attr_preserve_most: - return AttributeList::AT_PreserveMost; + return ParsedAttr::AT_PreserveMost; case AttributedType::attr_preserve_all: - return AttributeList::AT_PreserveAll; + return ParsedAttr::AT_PreserveAll; case AttributedType::attr_ptr32: - return AttributeList::AT_Ptr32; + return ParsedAttr::AT_Ptr32; case AttributedType::attr_ptr64: - return AttributeList::AT_Ptr64; + return ParsedAttr::AT_Ptr64; case AttributedType::attr_sptr: - return AttributeList::AT_SPtr; + return ParsedAttr::AT_SPtr; case AttributedType::attr_uptr: - return AttributeList::AT_UPtr; + return ParsedAttr::AT_UPtr; case AttributedType::attr_nonnull: - return AttributeList::AT_TypeNonNull; + return ParsedAttr::AT_TypeNonNull; case AttributedType::attr_nullable: - return AttributeList::AT_TypeNullable; + return ParsedAttr::AT_TypeNullable; case AttributedType::attr_null_unspecified: - return AttributeList::AT_TypeNullUnspecified; + return ParsedAttr::AT_TypeNullUnspecified; case AttributedType::attr_objc_kindof: - return AttributeList::AT_ObjCKindOf; + return ParsedAttr::AT_ObjCKindOf; case AttributedType::attr_ns_returns_retained: - return AttributeList::AT_NSReturnsRetained; + return ParsedAttr::AT_NSReturnsRetained; } llvm_unreachable("unexpected attribute kind!"); } -static void setAttributedTypeLoc(AttributedTypeLoc TL, - const AttributeList &attr) { +static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) { TL.setAttrNameLoc(attr.getLoc()); if (TL.hasAttrExprOperand()) { assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); @@ -5219,13 +5211,13 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, assert((!Attrs.empty() || !DeclAttrs.empty()) && "no type attributes in the expected location!"); - AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); + ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind()); // Try to search for an attribute of matching kind in Attrs list. - for (const AttributeList &AL : Attrs) + for (const ParsedAttr &AL : Attrs) if (AL.getKind() == parsedKind) return setAttributedTypeLoc(TL, AL); - for (const AttributeList &AL : DeclAttrs) + for (const ParsedAttr &AL : DeclAttrs) if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) return setAttributedTypeLoc(TL, AL); llvm_unreachable("no matching type attribute in expected location!"); @@ -5549,8 +5541,8 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, const ParsedAttributesView &Attrs) { - for (const AttributeList &AL : Attrs) { - if (AL.getKind() == AttributeList::AT_AddressSpace) { + for (const ParsedAttr &AL : Attrs) { + if (AL.getKind() == ParsedAttr::AT_AddressSpace) { DASTL.setAttrNameLoc(AL.getLoc()); DASTL.setAttrExprOperand(AL.getArgAsExpr(0)); DASTL.setAttrOperandParensRange(SourceRange()); @@ -5755,7 +5747,7 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, /// specified type. The attribute contains 1 argument, the id of the address /// space for the type. static void HandleAddressSpaceTypeAttribute(QualType &Type, - const AttributeList &Attr, Sema &S){ + const ParsedAttr &Attr, Sema &S) { // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be // qualified by an address-space qualifier." if (Type->isFunctionType()) { @@ -5765,7 +5757,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, } LangAS ASIdx; - if (Attr.getKind() == AttributeList::AT_AddressSpace) { + if (Attr.getKind() == ParsedAttr::AT_AddressSpace) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -5804,15 +5796,15 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, } else { // The keyword-based type attributes imply which address space to use. switch (Attr.getKind()) { - case AttributeList::AT_OpenCLGlobalAddressSpace: + case ParsedAttr::AT_OpenCLGlobalAddressSpace: ASIdx = LangAS::opencl_global; break; - case AttributeList::AT_OpenCLLocalAddressSpace: + case ParsedAttr::AT_OpenCLLocalAddressSpace: ASIdx = LangAS::opencl_local; break; - case AttributeList::AT_OpenCLConstantAddressSpace: + case ParsedAttr::AT_OpenCLConstantAddressSpace: ASIdx = LangAS::opencl_constant; break; - case AttributeList::AT_OpenCLGenericAddressSpace: + case ParsedAttr::AT_OpenCLGenericAddressSpace: ASIdx = LangAS::opencl_generic; break; - case AttributeList::AT_OpenCLPrivateAddressSpace: + case ParsedAttr::AT_OpenCLPrivateAddressSpace: ASIdx = LangAS::opencl_private; break; default: llvm_unreachable("Invalid address space"); @@ -5872,8 +5864,7 @@ static bool hasDirectOwnershipQualifier(QualType type) { /// /// Returns 'true' if the attribute was handled. static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, - AttributeList &attr, - QualType &type) { + ParsedAttr &attr, QualType &type) { bool NonObjCPointer = false; if (!type->isDependentType() && !type->isUndeducedType()) { @@ -6058,8 +6049,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, /// attribute on the specified type. Returns true to indicate that /// the attribute was handled, false to indicate that the type does /// not permit the attribute. -static bool handleObjCGCTypeAttr(TypeProcessingState &state, - AttributeList &attr, +static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, QualType &type) { Sema &S = state.getSema(); @@ -6251,11 +6241,10 @@ namespace { } // end anonymous namespace static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, - AttributeList &Attr, - QualType &Type) { + ParsedAttr &Attr, QualType &Type) { Sema &S = State.getSema(); - AttributeList::Kind Kind = Attr.getKind(); + ParsedAttr::Kind Kind = Attr.getKind(); QualType Desugared = Type; const AttributedType *AT = dyn_cast(Type); while (AT) { @@ -6272,16 +6261,16 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, // You cannot have both __sptr and __uptr on the same type, nor can you // have __ptr32 and __ptr64. if ((CurAttrKind == AttributedType::attr_ptr32 && - Kind == AttributeList::AT_Ptr64) || + Kind == ParsedAttr::AT_Ptr64) || (CurAttrKind == AttributedType::attr_ptr64 && - Kind == AttributeList::AT_Ptr32)) { + Kind == ParsedAttr::AT_Ptr32)) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "'__ptr32'" << "'__ptr64'"; return true; } else if ((CurAttrKind == AttributedType::attr_sptr && - Kind == AttributeList::AT_UPtr) || + Kind == ParsedAttr::AT_UPtr) || (CurAttrKind == AttributedType::attr_uptr && - Kind == AttributeList::AT_SPtr)) { + Kind == ParsedAttr::AT_SPtr)) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "'__sptr'" << "'__uptr'"; return true; @@ -6306,10 +6295,18 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, AttributedType::Kind TAK; switch (Kind) { default: llvm_unreachable("Unknown attribute kind"); - case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break; - case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break; - case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break; - case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break; + case ParsedAttr::AT_Ptr32: + TAK = AttributedType::attr_ptr32; + break; + case ParsedAttr::AT_Ptr64: + TAK = AttributedType::attr_ptr64; + break; + case ParsedAttr::AT_SPtr: + TAK = AttributedType::attr_sptr; + break; + case ParsedAttr::AT_UPtr: + TAK = AttributedType::attr_uptr; + break; } Type = S.Context.getAttributedType(TAK, Type, Type); @@ -6460,15 +6457,15 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { } /// Map a nullability attribute kind to a nullability kind. -static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) { +static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { switch (kind) { - case AttributeList::AT_TypeNonNull: + case ParsedAttr::AT_TypeNonNull: return NullabilityKind::NonNull; - case AttributeList::AT_TypeNullable: + case ParsedAttr::AT_TypeNullable: return NullabilityKind::Nullable; - case AttributeList::AT_TypeNullUnspecified: + case ParsedAttr::AT_TypeNullUnspecified: return NullabilityKind::Unspecified; default: @@ -6483,8 +6480,7 @@ static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) { /// \returns true if the nullability annotation was distributed, false /// otherwise. static bool distributeNullabilityTypeAttr(TypeProcessingState &state, - QualType type, - AttributeList &attr) { + QualType type, ParsedAttr &attr) { Declarator &declarator = state.getDeclarator(); /// Attempt to move the attribute to the specified chunk. @@ -6564,28 +6560,28 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, return false; } -static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { +static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) { assert(!Attr.isInvalid()); switch (Attr.getKind()) { default: llvm_unreachable("not a calling convention attribute"); - case AttributeList::AT_CDecl: + case ParsedAttr::AT_CDecl: return AttributedType::attr_cdecl; - case AttributeList::AT_FastCall: + case ParsedAttr::AT_FastCall: return AttributedType::attr_fastcall; - case AttributeList::AT_StdCall: + case ParsedAttr::AT_StdCall: return AttributedType::attr_stdcall; - case AttributeList::AT_ThisCall: + case ParsedAttr::AT_ThisCall: return AttributedType::attr_thiscall; - case AttributeList::AT_RegCall: + case ParsedAttr::AT_RegCall: return AttributedType::attr_regcall; - case AttributeList::AT_Pascal: + case ParsedAttr::AT_Pascal: return AttributedType::attr_pascal; - case AttributeList::AT_SwiftCall: + case ParsedAttr::AT_SwiftCall: return AttributedType::attr_swiftcall; - case AttributeList::AT_VectorCall: + case ParsedAttr::AT_VectorCall: return AttributedType::attr_vectorcall; - case AttributeList::AT_Pcs: { + case ParsedAttr::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // identifier as a string literal. The contents of the string are valid, // but the form may not be. @@ -6598,15 +6594,15 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { .Case("aapcs", AttributedType::attr_pcs) .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); } - case AttributeList::AT_IntelOclBicc: + case ParsedAttr::AT_IntelOclBicc: return AttributedType::attr_inteloclbicc; - case AttributeList::AT_MSABI: + case ParsedAttr::AT_MSABI: return AttributedType::attr_ms_abi; - case AttributeList::AT_SysVABI: + case ParsedAttr::AT_SysVABI: return AttributedType::attr_sysv_abi; - case AttributeList::AT_PreserveMost: + case ParsedAttr::AT_PreserveMost: return AttributedType::attr_preserve_most; - case AttributeList::AT_PreserveAll: + case ParsedAttr::AT_PreserveAll: return AttributedType::attr_preserve_all; } llvm_unreachable("unexpected attribute kind!"); @@ -6614,14 +6610,13 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { /// Process an individual function attribute. Returns true to /// indicate that the attribute was handled, false if it wasn't. -static bool handleFunctionTypeAttr(TypeProcessingState &state, - AttributeList &attr, +static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, QualType &type) { Sema &S = state.getSema(); FunctionTypeUnwrapper unwrapped(S, type); - if (attr.getKind() == AttributeList::AT_NoReturn) { + if (attr.getKind() == ParsedAttr::AT_NoReturn) { if (S.CheckAttrNoArgs(attr)) return true; @@ -6637,7 +6632,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, // ns_returns_retained is not always a type attribute, but if we got // here, we're treating it as one right now. - if (attr.getKind() == AttributeList::AT_NSReturnsRetained) { + if (attr.getKind() == ParsedAttr::AT_NSReturnsRetained) { if (attr.getNumArgs()) return true; // Delay if this is not a function type. @@ -6661,7 +6656,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } - if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) { + if (attr.getKind() == ParsedAttr::AT_AnyX86NoCallerSavedRegisters) { if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr)) return true; @@ -6675,7 +6670,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } - if (attr.getKind() == AttributeList::AT_AnyX86NoCfCheck) { + if (attr.getKind() == ParsedAttr::AT_AnyX86NoCfCheck) { if (!S.getLangOpts().CFProtectionBranch) { S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored); attr.setInvalid(); @@ -6696,7 +6691,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } - if (attr.getKind() == AttributeList::AT_Regparm) { + if (attr.getKind() == ParsedAttr::AT_Regparm) { unsigned value; if (S.CheckRegparmAttr(attr, value)) return true; @@ -6853,7 +6848,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, /// The raw attribute should contain precisely 1 argument, the vector size for /// the variable, measured in bytes. If curType and rawAttr are well formed, /// this routine will return a new vector type. -static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, +static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { // Check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -6912,8 +6907,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, /// Process the OpenCL-like ext_vector_type attribute when it occurs on /// a type. -static void HandleExtVectorTypeAttr(QualType &CurType, - const AttributeList &Attr, +static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -7002,9 +6996,8 @@ static bool isPermittedNeonBaseType(QualType &Ty, /// the argument to these Neon attributes is the number of vector elements, /// not the vector size in bytes. The vector width and element type must /// match one of the standard Neon vector types. -static void HandleNeonVectorTypeAttr(QualType& CurType, - const AttributeList &Attr, Sema &S, - VectorType::VectorKind VecKind) { +static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, + Sema &S, VectorType::VectorKind VecKind) { // Target must have NEON if (!S.Context.getTargetInfo().hasFeature("neon")) { S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName(); @@ -7050,7 +7043,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType, } /// Handle OpenCL Access Qualifier Attribute. -static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr, +static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type. if (!(CurType->isImageType() || CurType->isPipeType())) { @@ -7183,7 +7176,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // sure we visit every element once. Copy the attributes list, and iterate // over that. ParsedAttributesView AttrsCopy{attrs}; - for (AttributeList &attr : AttrsCopy) { + for (ParsedAttr &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. if (attr.isInvalid()) @@ -7224,27 +7217,27 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, } break; - case AttributeList::UnknownAttribute: + case ParsedAttr::UnknownAttribute: if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) state.getSema().Diag(attr.getLoc(), diag::warn_unknown_attribute_ignored) << attr.getName(); break; - case AttributeList::IgnoredAttribute: + case ParsedAttr::IgnoredAttribute: break; - case AttributeList::AT_MayAlias: + case ParsedAttr::AT_MayAlias: // FIXME: This attribute needs to actually be handled, but if we ignore // it it breaks large amounts of Linux software. attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_OpenCLPrivateAddressSpace: - case AttributeList::AT_OpenCLGlobalAddressSpace: - case AttributeList::AT_OpenCLLocalAddressSpace: - case AttributeList::AT_OpenCLConstantAddressSpace: - case AttributeList::AT_OpenCLGenericAddressSpace: - case AttributeList::AT_AddressSpace: + case ParsedAttr::AT_OpenCLPrivateAddressSpace: + case ParsedAttr::AT_OpenCLGlobalAddressSpace: + case ParsedAttr::AT_OpenCLLocalAddressSpace: + case ParsedAttr::AT_OpenCLConstantAddressSpace: + case ParsedAttr::AT_OpenCLGenericAddressSpace: + case ParsedAttr::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; @@ -7253,25 +7246,25 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, distributeObjCPointerTypeAttr(state, attr, type); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_VectorSize: + case ParsedAttr::AT_VectorSize: HandleVectorSizeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_ExtVectorType: + case ParsedAttr::AT_ExtVectorType: HandleExtVectorTypeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_NeonVectorType: + case ParsedAttr::AT_NeonVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonVector); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_NeonPolyVectorType: + case ParsedAttr::AT_NeonPolyVectorType: HandleNeonVectorTypeAttr(type, attr, state.getSema(), VectorType::NeonPolyVector); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_OpenCLAccess: + case ParsedAttr::AT_OpenCLAccess: HandleOpenCLAccessAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; @@ -7310,7 +7303,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, } break; - case AttributeList::AT_ObjCKindOf: + case ParsedAttr::AT_ObjCKindOf: // '__kindof' must be part of the decl-specifiers. switch (TAL) { case TAL_DeclSpec: diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 712a854627..bddd51e9d1 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -3132,7 +3132,7 @@ static void emitArgInfo(const Record &R, raw_ostream &OS) { } static void GenerateDefaultAppertainsTo(raw_ostream &OS) { - OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,"; + OS << "static bool defaultAppertainsTo(Sema &, const ParsedAttr &,"; OS << "const Decl *) {\n"; OS << " return true;\n"; OS << "}\n\n"; @@ -3270,7 +3270,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { // name of that check to the caller. std::string FnName = "check" + Attr.getName().str() + "AppertainsTo"; std::stringstream SS; - SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, "; + SS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr, "; SS << "const Decl *D) {\n"; SS << " if ("; for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { @@ -3342,7 +3342,7 @@ emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport, static void GenerateDefaultLangOptRequirements(raw_ostream &OS) { OS << "static bool defaultDiagnoseLangOpts(Sema &, "; - OS << "const AttributeList &) {\n"; + OS << "const ParsedAttr &) {\n"; OS << " return true;\n"; OS << "}\n\n"; } @@ -3381,7 +3381,7 @@ static std::string GenerateLangOptRequirements(const Record &R, if (I != CustomLangOptsSet.end()) return *I; - OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n"; + OS << "static bool " << FnName << "(Sema &S, const ParsedAttr &Attr) {\n"; OS << " if (" << Test << ")\n"; OS << " return true;\n\n"; OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; @@ -3414,7 +3414,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, // If there are other attributes which share the same parsed attribute kind, // such as target-specific attributes with a shared spelling, collapse the // duplicate architectures. This is required because a shared target-specific - // attribute has only one AttributeList::Kind enumeration value, but it + // attribute has only one ParsedAttr::Kind enumeration value, but it // applies to multiple target architectures. In order for the attribute to be // considered valid, all of its architectures need to be included. if (!Attr.isValueUnset("ParseKind")) { @@ -3451,7 +3451,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) { OS << "static unsigned defaultSpellingIndexToSemanticSpelling(" - << "const AttributeList &Attr) {\n"; + << "const ParsedAttr &Attr) {\n"; OS << " return UINT_MAX;\n"; OS << "}\n\n"; } @@ -3474,7 +3474,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); std::string Name = Attr.getName().str() + "AttrSpellingMap"; - OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n"; + OS << "static unsigned " << Name << "(const ParsedAttr &Attr) {\n"; OS << Enum; OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n"; WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS); @@ -3524,7 +3524,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { // the spellings are identical, and custom parsing rules match, etc. // We need to generate struct instances based off ParsedAttrInfo from - // AttributeList.cpp. + // ParsedAttr.cpp. SS << " { "; emitArgInfo(*I->second, SS); SS << ", " << I->second->getValueAsBit("HasCustomParsing"); @@ -3549,7 +3549,8 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { SS << " // AT_" << I->first << "\n"; } - OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; + OS << "static const ParsedAttrInfo AttrInfoMap[ParsedAttr::UnknownAttribute " + "+ 1] = {\n"; OS << SS.str(); OS << "};\n\n"; @@ -3577,7 +3578,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { // specific attribute, or MSP430-specific attribute. Additionally, an // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport"> // for the same semantic attribute. Ultimately, we need to map each of - // these to a single AttributeList::Kind value, but the StringMatcher + // these to a single ParsedAttr::Kind value, but the StringMatcher // class cannot handle duplicate match strings. So we generate a list of // string to match based on the syntax, and emit multiple string matchers // depending on the syntax used. @@ -3624,34 +3625,34 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { Spelling += RawSpelling; if (SemaHandler) - Matches->push_back(StringMatcher::StringPair(Spelling, - "return AttributeList::AT_" + AttrName + ";")); + Matches->push_back(StringMatcher::StringPair( + Spelling, "return ParsedAttr::AT_" + AttrName + ";")); else - Matches->push_back(StringMatcher::StringPair(Spelling, - "return AttributeList::IgnoredAttribute;")); + Matches->push_back(StringMatcher::StringPair( + Spelling, "return ParsedAttr::IgnoredAttribute;")); } } } - - OS << "static AttributeList::Kind getAttrKind(StringRef Name, "; - OS << "AttributeList::Syntax Syntax) {\n"; - OS << " if (AttributeList::AS_GNU == Syntax) {\n"; + + OS << "static ParsedAttr::Kind getAttrKind(StringRef Name, "; + OS << "ParsedAttr::Syntax Syntax) {\n"; + OS << " if (ParsedAttr::AS_GNU == Syntax) {\n"; StringMatcher("Name", GNU, OS).Emit(); - OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Declspec == Syntax) {\n"; StringMatcher("Name", Declspec, OS).Emit(); - OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Microsoft == Syntax) {\n"; StringMatcher("Name", Microsoft, OS).Emit(); - OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_CXX11 == Syntax) {\n"; StringMatcher("Name", CXX11, OS).Emit(); - OS << " } else if (AttributeList::AS_C2x == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_C2x == Syntax) {\n"; StringMatcher("Name", C2x, OS).Emit(); - OS << " } else if (AttributeList::AS_Keyword == Syntax || "; - OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Keyword == Syntax || "; + OS << "ParsedAttr::AS_ContextSensitiveKeyword == Syntax) {\n"; StringMatcher("Name", Keywords, OS).Emit(); - OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n"; + OS << " } else if (ParsedAttr::AS_Pragma == Syntax) {\n"; StringMatcher("Name", Pragma, OS).Emit(); OS << " }\n"; - OS << " return AttributeList::UnknownAttribute;\n" + OS << " return ParsedAttr::UnknownAttribute;\n" << "}\n"; } -- GitLab From 2fc21c4f2b507670706de3a256d48b39cd12fdc3 Mon Sep 17 00:00:00 2001 From: Gheorghe-Teodor Bercea Date: Fri, 13 Jul 2018 16:18:24 +0000 Subject: [PATCH 0534/1023] [OpenMP] Initialize data sharing stack for SPMD case Summary: In the SPMD case, we need to initialize the data sharing and globalization infrastructure. This covers the case when an SPMD region calls a function in a different compilation unit. Reviewers: ABataev, carlo.bertolli, caomhin Reviewed By: ABataev Subscribers: Hahnfeld, jholewinski, guansong, cfe-commits Differential Revision: https://reviews.llvm.org/D49188 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337015 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 20 ++++++++++++++----- test/OpenMP/nvptx_data_sharing.cpp | 2 +- test/OpenMP/nvptx_target_parallel_codegen.cpp | 2 ++ ...vptx_target_parallel_proc_bind_codegen.cpp | 3 +++ ...vptx_target_parallel_reduction_codegen.cpp | 3 +++ test/OpenMP/nvptx_target_teams_codegen.cpp | 1 + ..._teams_distribute_parallel_for_codegen.cpp | 4 ++++ ...s_distribute_parallel_for_simd_codegen.cpp | 8 ++++++-- 8 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 0ef093fd05..ba87e05908 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -81,6 +81,8 @@ enum OpenMPRTLFunctionNVPTX { OMPRTL_NVPTX__kmpc_end_reduce_nowait, /// Call to void __kmpc_data_sharing_init_stack(); OMPRTL_NVPTX__kmpc_data_sharing_init_stack, + /// Call to void __kmpc_data_sharing_init_stack_spmd(); + OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd, /// Call to void* __kmpc_data_sharing_push_stack(size_t size, /// int16_t UseSharedMemory); OMPRTL_NVPTX__kmpc_data_sharing_push_stack, @@ -1025,6 +1027,12 @@ void CGOpenMPRuntimeNVPTX::emitSPMDEntryHeader( /*RequiresDataSharing=*/Bld.getInt16(1)}; CGF.EmitRuntimeCall( createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_spmd_kernel_init), Args); + + // For data sharing, we need to initialize the stack. + CGF.EmitRuntimeCall( + createNVPTXRuntimeFunction( + OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd)); + CGF.EmitBranch(ExecuteBB); CGF.EmitBlock(ExecuteBB); @@ -1107,11 +1115,6 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF, // Wait for parallel work syncCTAThreads(CGF); - // For data sharing, we need to initialize the stack for workers. - CGF.EmitRuntimeCall( - createNVPTXRuntimeFunction( - OMPRTL_NVPTX__kmpc_data_sharing_init_stack)); - Address WorkFn = CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrTy, /*Name=*/"work_fn"); Address ExecStatus = @@ -1417,6 +1420,13 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack"); break; } + case OMPRTL_NVPTX__kmpc_data_sharing_init_stack_spmd: { + /// Build void __kmpc_data_sharing_init_stack_spmd(); + auto *FnTy = + llvm::FunctionType::get(CGM.VoidTy, llvm::None, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_data_sharing_init_stack_spmd"); + break; + } case OMPRTL_NVPTX__kmpc_data_sharing_push_stack: { // Build void *__kmpc_data_sharing_push_stack(size_t size, // int16_t UseSharedMemory); diff --git a/test/OpenMP/nvptx_data_sharing.cpp b/test/OpenMP/nvptx_data_sharing.cpp index eb0acde299..0acb119915 100644 --- a/test/OpenMP/nvptx_data_sharing.cpp +++ b/test/OpenMP/nvptx_data_sharing.cpp @@ -30,7 +30,7 @@ void test_ds(){ /// ========= In the worker function ========= /// // CK1: {{.*}}define internal void @__omp_offloading{{.*}}test_ds{{.*}}_worker() // CK1: call void @llvm.nvvm.barrier0() -// CK1: call void @__kmpc_data_sharing_init_stack +// CK1-NOT: call void @__kmpc_data_sharing_init_stack /// ========= In the kernel function ========= /// diff --git a/test/OpenMP/nvptx_target_parallel_codegen.cpp b/test/OpenMP/nvptx_target_parallel_codegen.cpp index d193174ce7..15611f6475 100644 --- a/test/OpenMP/nvptx_target_parallel_codegen.cpp +++ b/test/OpenMP/nvptx_target_parallel_codegen.cpp @@ -60,6 +60,7 @@ int bar(int n){ // CHECK: [[AA:%.+]] = load i16*, i16** [[AA_ADDR]], align // CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXEC:.+]] // // CHECK: [[EXEC]] @@ -102,6 +103,7 @@ int bar(int n){ // CHECK: [[B:%.+]] = load [10 x i32]*, [10 x i32]** [[B_ADDR]], align // CHECK: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXEC:.+]] // // CHECK: [[EXEC]] diff --git a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp index eb166b7dcd..1cdcb70417 100644 --- a/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp +++ b/test/OpenMP/nvptx_target_parallel_proc_bind_codegen.cpp @@ -48,6 +48,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l22}}( // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXEC:.+]] // // CHECK: [[EXEC]] @@ -69,6 +70,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l26}}( // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXEC:.+]] // // CHECK: [[EXEC]] @@ -89,6 +91,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l31}}( // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXEC:.+]] // // CHECK: [[EXEC]] diff --git a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp index f13e113db0..02676272b0 100644 --- a/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp +++ b/test/OpenMP/nvptx_target_parallel_reduction_codegen.cpp @@ -55,6 +55,7 @@ int bar(int n){ // CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l27}}( // // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXECUTE:.+]] // // CHECK: [[EXECUTE]] @@ -242,6 +243,7 @@ int bar(int n){ // CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l32}}( // // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXECUTE:.+]] // // CHECK: [[EXECUTE]] @@ -519,6 +521,7 @@ int bar(int n){ // CHECK: define {{.*}}void {{@__omp_offloading_.+template.+l38}}( // // CHECK: call void @__kmpc_spmd_kernel_init( + // CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: br label {{%?}}[[EXECUTE:.+]] // // CHECK: [[EXECUTE]] diff --git a/test/OpenMP/nvptx_target_teams_codegen.cpp b/test/OpenMP/nvptx_target_teams_codegen.cpp index aa054fffc4..c7667d83b9 100644 --- a/test/OpenMP/nvptx_target_teams_codegen.cpp +++ b/test/OpenMP/nvptx_target_teams_codegen.cpp @@ -228,6 +228,7 @@ int bar(int n){ // CHECK: define weak void @__omp_offloading_{{.*}}ftemplate{{.*}}_l37( // CHECK: call void @__kmpc_spmd_kernel_init( +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call i8* @__kmpc_data_sharing_push_stack( // CHECK-NOT: call void @__kmpc_serialized_parallel( // CHECK: call void [[L0:@.+]](i32* %{{.+}}, i32* %{{.+}}, i16* %{{.*}}) diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp index 195f428e0f..f74919fc82 100644 --- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp +++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp @@ -70,6 +70,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91, // CHECK: {{call|invoke}} void [[OUTL1:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -84,6 +85,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, // CHECK: {{call|invoke}} void [[OUTL2:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -98,6 +100,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, // CHECK: {{call|invoke}} void [[OUTL3:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -113,6 +116,7 @@ int bar(int n){ // CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}}, // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]], // CHECK: {{call|invoke}} void [[OUTL4:@.+]]( diff --git a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp index 051ccfe9c4..0b945a69b0 100644 --- a/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp @@ -22,7 +22,7 @@ tx ftemplate(int n) { tx a[N]; short aa[N]; tx b[10]; - tx c[M][M]; + tx c[M][M]; tx f = n; tx l; int k; @@ -47,7 +47,7 @@ tx ftemplate(int n) { for(int i = 0; i < M; i++) { for(int j = 0; j < M; j++) { k = M; - c[i][j] = i+j*f+k; + c[i][j] = i+j*f+k; } } @@ -65,6 +65,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 91, // CHECK: {{call|invoke}} void [[OUTL1:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -79,6 +80,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, // CHECK: {{call|invoke}} void [[OUTL2:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -93,6 +95,7 @@ int bar(int n){ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+}}( // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, // CHECK: {{call|invoke}} void [[OUTL3:@.+]]( // CHECK: call void @__kmpc_for_static_fini( @@ -108,6 +111,7 @@ int bar(int n){ // CHECK: store {{.+}} [[F_IN]], {{.+}}* {{.+}}, // CHECK-DAG: [[THREAD_LIMIT:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK: call void @__kmpc_spmd_kernel_init(i32 [[THREAD_LIMIT]], +// CHECK: call void @__kmpc_data_sharing_init_stack_spmd // CHECK: store {{.+}} 99, {{.+}}* [[COMB_UB:%.+]], align // CHECK: call void @__kmpc_for_static_init_4({{.+}}, {{.+}}, {{.+}} 92, {{.+}}, {{.+}}, {{.+}}* [[COMB_UB]], // CHECK: {{call|invoke}} void [[OUTL4:@.+]]( -- GitLab From d119a80874f84aed19417020a5ab04d4568f1743 Mon Sep 17 00:00:00 2001 From: Nicolas Lesser Date: Fri, 13 Jul 2018 16:27:45 +0000 Subject: [PATCH 0535/1023] Fix PR34668 - P0704R1 implementation is too permissive Summary: https://bugs.llvm.org/show_bug.cgi?id=34668 Pretty straightforward. Reviewers: rsmith, Rakete1111 Reviewed By: Rakete1111 Subscribers: Rakete1111, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D38075 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337017 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprCXX.cpp | 5 +++-- test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8ed795abbb..fbf572e398 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -5472,8 +5472,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, case RQ_LValue: if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) { - // C++2a allows functions with ref-qualifier & if they are also 'const'. - if (Proto->isConst()) + // C++2a allows functions with ref-qualifier & if their cv-qualifier-seq + // is (exactly) 'const'. + if (Proto->isConst() && !Proto->isVolatile()) Diag(Loc, getLangOpts().CPlusPlus2a ? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : diag::ext_pointer_to_const_ref_member_on_rvalue); diff --git a/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp b/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp index 0bc40c8179..7c709d905f 100644 --- a/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp +++ b/test/SemaCXX/cxx2a-pointer-to-const-ref-member.cpp @@ -3,12 +3,15 @@ struct X { void ref() & {} // expected-note{{'ref' declared here}} void cref() const& {} + void cvref() const volatile & {} // expected-note{{'cvref' declared here}} }; void test() { X{}.ref(); // expected-error{{'this' argument to member function 'ref' is an rvalue, but function has non-const lvalue ref-qualifier}} X{}.cref(); // expected-no-error + X{}.cvref(); // expected-error{{'this' argument to member function 'cvref' is an rvalue, but function has non-const lvalue ref-qualifier}} (X{}.*&X::ref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}} (X{}.*&X::cref)(); // expected-no-error + (X{}.*&X::cvref)(); // expected-error-re{{pointer-to-member function type 'void (X::*)() {{.*}}&' can only be called on an lvalue}} } -- GitLab From 12e2fde436d38782477f681dbf3fc83b8095e188 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 13 Jul 2018 19:46:04 +0000 Subject: [PATCH 0536/1023] PR15730/PR16986 Allow dependently typed vector_size types. As listed in the above PRs, vector_size doesn't allow dependent types/values. This patch introduces a new DependentVectorType to handle a VectorType that has a dependent size or type. In the future, ALL the vector-types should be able to create one of these to handle dependent types/sizes as well. For example, DependentSizedExtVectorType could likely be switched to just use this instead, though that is left as an exercise for the future. Differential Revision: https://reviews.llvm.org/D49045 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337036 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 6 ++ include/clang/AST/RecursiveASTVisitor.h | 12 +++ include/clang/AST/Type.h | 46 +++++++++ include/clang/AST/TypeLoc.h | 7 ++ include/clang/AST/TypeNodes.def | 1 + include/clang/Sema/Sema.h | 1 + include/clang/Serialization/ASTBitCodes.h | 85 ++++++++-------- lib/AST/ASTContext.cpp | 40 ++++++++ lib/AST/ASTStructuralEquivalence.cpp | 16 ++- lib/AST/ItaniumMangle.cpp | 44 ++++++++ lib/AST/MicrosoftMangle.cpp | 10 ++ lib/AST/Type.cpp | 22 ++++ lib/AST/TypePrinter.cpp | 51 +++++++++- lib/Lex/LiteralSupport.cpp | 2 +- lib/Sema/SemaTemplate.cpp | 5 + lib/Sema/SemaTemplateDeduction.cpp | 56 +++++++++++ lib/Sema/SemaType.cpp | 116 ++++++++++++++-------- lib/Sema/TreeTransform.h | 54 ++++++++++ lib/Serialization/ASTReader.cpp | 16 +++ lib/Serialization/ASTWriter.cpp | 13 +++ test/SemaCXX/vector.cpp | 43 ++++++++ tools/libclang/CIndex.cpp | 1 + 22 files changed, 560 insertions(+), 87 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ddfbdc2472..8d3cf760a5 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -168,6 +168,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet DependentAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; + mutable llvm::FoldingSet DependentVectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet FunctionProtoTypes; @@ -1321,6 +1322,11 @@ public: /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; + /// Return the unique reference to the type for a dependently sized vector of + /// the specified element type. + QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, + SourceLocation AttrLoc, + VectorType::VectorKind VecKind) const; /// Return the unique reference to an extended vector type /// of the specified element type and size. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 3e6090d312..0d2b670507 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DependentVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) +DEF_TRAVERSE_TYPELOC(DependentVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index dbe96a00f5..b21d9f4127 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1590,6 +1590,7 @@ protected: class VectorTypeBitfields { friend class VectorType; + friend class DependentVectorType; unsigned : NumTypeBits; @@ -3079,6 +3080,51 @@ public: } }; +/// Represents a vector type where either the type or size is dependent. +//// +/// For example: +/// \code +/// template +/// class vector { +/// typedef T __attribute__((vector_size(Size))) type; +/// } +/// \endcode +class DependentVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + QualType ElementType; + Expr *SizeExpr; + SourceLocation Loc; + + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, VectorType::VectorKind vecKind); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return Loc; } + VectorType::VectorKind getVectorKind() const { + return VectorType::VectorKind(VectorTypeBits.VecKind); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentVector; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, const Expr *SizeExpr, + VectorType::VectorKind VecKind); +}; + /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 53d5a1a627..73909e50ff 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1798,6 +1798,13 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc { }; +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class DependentVectorTypeLoc + : public InheritingConcreteTypeLoc {}; + // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc(T1); + const auto *Vec2 = cast(T2); + if (Vec1->getVectorKind() != Vec2->getVectorKind()) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(), + Vec2->getSizeExpr())) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), + Vec2->getElementType())) + return false; + break; + } + case Type::Vector: case Type::ExtVector: { const auto *Vec1 = cast(T1); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index d8c435991e..6f7efcbe1b 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -539,7 +539,9 @@ private: void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); + void mangleNeonVectorType(const DependentVectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); + void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExprBase(const Expr *base, bool isArrow); @@ -1930,6 +1932,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::VariableArray: case Type::DependentSizedArray: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -3000,6 +3003,14 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { Out << BaseName << EltName; } +void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent neon vector type yet"); + Diags.Report(T->getAttributeLoc(), DiagID); +} + static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { switch (EltType->getKind()) { case BuiltinType::SChar: @@ -3067,6 +3078,13 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str(); Out << TypeName.length() << TypeName; } +void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent neon vector type yet"); + Diags.Report(T->getAttributeLoc(), DiagID); +} // GNU extension: vector types // ::= @@ -3097,6 +3115,32 @@ void CXXNameMangler::mangleType(const VectorType *T) { else mangleType(T->getElementType()); } + +void CXXNameMangler::mangleType(const DependentVectorType *T) { + if ((T->getVectorKind() == VectorType::NeonVector || + T->getVectorKind() == VectorType::NeonPolyVector)) { + llvm::Triple Target = getASTContext().getTargetInfo().getTriple(); + llvm::Triple::ArchType Arch = + getASTContext().getTargetInfo().getTriple().getArch(); + if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) && + !Target.isOSDarwin()) + mangleAArch64NeonVectorType(T); + else + mangleNeonVectorType(T); + return; + } + + Out << "Dv"; + mangleExpression(T->getSizeExpr()); + Out << '_'; + if (T->getVectorKind() == VectorType::AltiVecPixel) + Out << 'p'; + else if (T->getVectorKind() == VectorType::AltiVecBool) + Out << 'b'; + else + mangleType(T->getElementType()); +} + void CXXNameMangler::mangleType(const ExtVectorType *T) { mangleType(static_cast(T)); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 32c26270ec..f9cd24ce9a 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2514,6 +2514,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers Quals, SourceRange Range) { mangleType(static_cast(T), Quals, Range); } + +void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T, + Qualifiers, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent-sized vector type yet"); + Diags.Report(Range.getBegin(), DiagID) << Range; +} + void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ddb45868ec..cd30bc16d0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -177,6 +177,27 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } +DependentVectorType::DependentVectorType( + const ASTContext &Context, QualType ElementType, QualType CanonType, + Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind) + : Type(DependentVector, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, + ElementType->isVariablyModifiedType(), + ElementType->containsUnexpandedParameterPack() || + (SizeExpr && SizeExpr->containsUnexpandedParameterPack())), + Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { + VectorTypeBits.VecKind = VecKind; +} + +void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType ElementType, const Expr *SizeExpr, + VectorType::VectorKind VecKind) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + ID.AddInteger(VecKind); + SizeExpr->Profile(ID, Context, true); +} + DependentSizedExtVectorType::DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, @@ -3783,6 +3804,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index b424b24574..c5e2244e26 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::RValueReference: case Type::MemberPointer: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -640,7 +641,55 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); -} +} + +void TypePrinter::printDependentVectorBefore( + const DependentVectorType *T, raw_ostream &OS) { + switch (T->getVectorKind()) { + case VectorType::AltiVecPixel: + OS << "__vector __pixel "; + break; + case VectorType::AltiVecBool: + OS << "__vector __bool "; + printBefore(T->getElementType(), OS); + break; + case VectorType::AltiVecVector: + OS << "__vector "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonVector: + OS << "__attribute__((neon_vector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonPolyVector: + OS << "__attribute__((neon_polyvector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::GenericVector: { + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + OS << "__attribute__((__vector_size__("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + OS << ")))) "; + printBefore(T->getElementType(), OS); + break; + } + } +} + +void TypePrinter::printDependentVectorAfter( + const DependentVectorType *T, raw_ostream &OS) { + printAfter(T->getElementType(), OS); +} void TypePrinter::printExtVectorBefore(const ExtVectorType *T, raw_ostream &OS) { diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index e414f85e02..c1be3b2a97 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -734,7 +734,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (!hadError && saw_fixed_point_suffix) { assert(isFract || isAccum); - assert(radix == 16 || radix == 10); + //assert(radix == 16 || radix == 10); } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index e78fd438dc..c1d8c24796 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5341,6 +5341,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType( + const DependentVectorType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 3a480628a7..51d2bae08c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1870,6 +1870,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; } + case Type::DependentVector: { + const auto *VectorParam = cast(Param); + + if (const auto *VectorArg = dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); + ArgSize = VectorArg->getNumElements(); + // Note that we use the "array bound" rules here; just like in that + // case, we don't have any particular type for the vector size, but + // we can provide one if necessary. + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize, + S.Context.UnsignedIntTy, true, + Info, Deduced); + } + + if (const auto *VectorArg = dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced); + } + + return Sema::TDK_NonDeducedMismatch; + } + // (clang extension) // // T __attribute__(((ext_vector_type(N)))) @@ -5264,6 +5312,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentVector: { + const auto *VecType = cast(T); + MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced, + Depth, Used); + MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth, + Used); + break; + } case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast(T); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 641a2f5f06..0736fabac3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2243,6 +2243,58 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } +QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, + SourceLocation AttrLoc) { + // The base type must be integer (not Boolean or enumeration) or float, and + // can't already be a vector. + if (!CurType->isDependentType() && + (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; + return QualType(); + } + + if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + llvm::APSInt VecSize(32); + if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_type) + << "vector_size" << AANT_ArgumentIntegerConstant + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (CurType->isDependentType()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + unsigned VectorSize = static_cast(VecSize.getZExtValue() * 8); + unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); + + if (VectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange(); + return QualType(); + } + + // vecSize is specified in bytes - convert to bits. + if (VectorSize % TypeSize) { + Diag(AttrLoc, diag::err_attribute_invalid_size) + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << SizeExpr->getSourceRange(); + return QualType(); + } + + return Context.getVectorType(CurType, VectorSize / TypeSize, + VectorType::GenericVector); +} + /// Build an ext-vector type. /// /// Run the required checks for the extended vector type. @@ -6857,52 +6909,30 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr, Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); - llvm::APSInt vecSize(32); - if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || - !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentIntegerConstant - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - // The base type must be integer (not Boolean or enumeration) or float, and - // can't already be a vector. - if (!CurType->isBuiltinType() || CurType->isBooleanType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; - Attr.setInvalid(); - return; - } - unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - // vecSize is specified in bytes - convert to bits. - unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); - // the vector size needs to be an integral multiple of the type size. - if (vectorSize % typeSize) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) { - S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; + Expr *SizeExpr; + // Special case where the argument is a template id. + if (Attr.isArgIdent(0)) { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Id; + Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); + + ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, + Id, false, false); + + if (Size.isInvalid()) + return; + SizeExpr = Size.get(); + } else { + SizeExpr = Attr.getArgAsExpr(0); } - // Success! Instantiate the vector type, the number of elements is > 0, and - // not required to be a power of 2, unlike GCC. - CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, - VectorType::GenericVector); + QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc()); + if (!T.isNull()) + CurType = T; + else + Attr.setInvalid(); } /// Process the OpenCL-like ext_vector_type attribute when it occurs on diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 6ee5eca75c..5ed92aea32 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -818,6 +818,15 @@ public: QualType RebuildVectorType(QualType ElementType, unsigned NumElements, VectorType::VectorKind VecKind); + /// Build a new potentially dependently-sized extended vector type + /// given the element type and number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr, + SourceLocation AttributeLoc, + VectorType::VectorKind); + /// Build a new extended vector type given the element type and /// number of elements. /// @@ -4750,6 +4759,44 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformDependentVectorType( + TypeLocBuilder &TLB, DependentVectorTypeLoc TL) { + const DependentVectorType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + Size = SemaRef.ActOnConstantExpression(Size); + if (Size.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() || + Size.get() != T->getSizeExpr()) { + Result = getDerived().RebuildDependentVectorType( + ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind()); + if (Result.isNull()) + return QualType(); + } + + // Result might be dependent or not. + if (isa(Result)) { + DependentVectorTypeLoc NewTL = + TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + VectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } + + return Result; +} + template QualType TreeTransform::TransformDependentSizedExtVectorType( TypeLocBuilder &TLB, @@ -12381,6 +12428,13 @@ TreeTransform::RebuildVectorType(QualType ElementType, return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); } +template +QualType TreeTransform::RebuildDependentVectorType( + QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc, + VectorType::VectorKind VecKind) { + return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc); +} + template QualType TreeTransform::RebuildExtVectorType(QualType ElementType, unsigned NumElements, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 3277243667..19b5af38df 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6369,6 +6369,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPipeType(ElementType, ReadOnly); } + case TYPE_DEPENDENT_SIZED_VECTOR: { + unsigned Idx = 0; + QualType ElementType = readType(*Loc.F, Record, Idx); + Expr *SizeExpr = ReadExpr(*Loc.F); + SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); + unsigned VecKind = Record[Idx]; + + return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, + (VectorType::VectorKind)VecKind); + } + case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { unsigned Idx = 0; @@ -6549,6 +6560,11 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } +void TypeLocReader::VisitDependentVectorTypeLoc( + DependentVectorTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation()); +} + void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index bc569d17f2..1a8d806e9d 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -455,6 +455,14 @@ ASTTypeWriter::VisitDependentSizedExtVectorType( Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } +void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { + Record.AddTypeRef(T->getElementType()); + Record.AddStmt(const_cast(T->getSizeExpr())); + Record.AddSourceLocation(T->getAttributeLoc()); + Record.push_back(T->getVectorKind()); + Code = TYPE_DEPENDENT_SIZED_VECTOR; +} + void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { @@ -676,6 +684,11 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitDependentVectorTypeLoc( + DependentVectorTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 8fe24a32c8..56a8a6db5b 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x; // PR12649 typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}} + +namespace Templates { +template +struct TemplateVectorType { + typedef Elt __attribute__((__vector_size__(Size))) type; +}; + +template +struct PR15730 { + typedef T __attribute__((vector_size(N * sizeof(T)))) type; + typedef T __attribute__((vector_size(8192))) type2; + typedef T __attribute__((vector_size(3))) type3; +}; + +void Init() { + const TemplateVectorType::type Works = {}; + const TemplateVectorType::type Works2 = {}; + // expected-error@298 {{invalid vector element type 'bool'}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoBool; + // expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoComplex; + // expected-error@298 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type BadSize; + // expected-error@298 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type TooLarge; + // expected-error@298 {{zero vector size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type Zero; + + // expected-error@304 {{vector size too large}} + // expected-error@305 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}} + const PR15730<8, int>::type PR15730_1 = {}; + // expected-error@304 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}} + const PR15730<8, char>::type2 PR15730_2 = {}; +} + +} // namespace Templates diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index b61dff3238..499d9abf9a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1772,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type) +DEFAULT_TYPELOC_IMPL(DependentVector, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) DEFAULT_TYPELOC_IMPL(Vector, Type) DEFAULT_TYPELOC_IMPL(ExtVector, VectorType) -- GitLab From 916476d8b9a8d80bc47bd5382764e270d1293fc1 Mon Sep 17 00:00:00 2001 From: Vlad Tsyrklevich Date: Fri, 13 Jul 2018 19:48:35 +0000 Subject: [PATCH 0537/1023] SafeStack: Add builtins to read unsafe stack top/bottom Summary: Introduce built-ins to read the unsafe stack top and bottom. The unsafe stack top is required to implement garbage collection scanning for Oilpan. Currently there is already a built-in 'get_unsafe_stack_start' to read the bottom of the unsafe stack, but I chose to duplicate this API because 'start' is ambiguous (e.g. Oilpan uses WTF::GetStackStart to read the safe stack top.) Reviewers: pcc Reviewed By: pcc Subscribers: llvm-commits, kcc Differential Revision: https://reviews.llvm.org/D49152 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337037 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/SafeStack.rst | 16 ++++++++++++++-- include/clang/Basic/Builtins.def | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/SafeStack.rst b/docs/SafeStack.rst index f01b75f5cb..866a8060aa 100644 --- a/docs/SafeStack.rst +++ b/docs/SafeStack.rst @@ -165,11 +165,23 @@ never be stored on the heap, as it would leak the location of the SafeStack. This builtin function returns current unsafe stack pointer of the current thread. +``__builtin___get_unsafe_stack_bottom()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This builtin function returns a pointer to the bottom of the unsafe stack of the +current thread. + +``__builtin___get_unsafe_stack_top()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This builtin function returns a pointer to the top of the unsafe stack of the +current thread. + ``__builtin___get_unsafe_stack_start()`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This builtin function returns a pointer to the start of the unsafe stack of the -current thread. +Deprecated: This builtin function is an alias for +``__builtin___get_unsafe_stack_bottom()``. Design ====== diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 39105a9b37..edd823754a 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -1412,6 +1412,8 @@ BUILTIN(__builtin_dump_struct, "ivC*v*", "tn") // Safestack builtins BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn") +BUILTIN(__builtin___get_unsafe_stack_bottom, "v*", "Fn") +BUILTIN(__builtin___get_unsafe_stack_top, "v*", "Fn") BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn") // Nontemporal loads/stores builtins -- GitLab From ed9cbc4e26f95eda92a878e83d662466c602a74b Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 13 Jul 2018 20:16:38 +0000 Subject: [PATCH 0538/1023] [X86] Change the rounding mode used when testing the sqrt_round intrinsics. Using CUR_DIRECTION is not a realistic scenario. That is equivalent to the intrinsic without rounding. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337040 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/avx512f-builtins.c | 54 ++++++++------------------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 8162da8b5c..17cbc62d61 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -5971,11 +5971,8 @@ __m512 test_mm512_maskz_shuffle_ps(__mmask16 __U, __m512 __M, __m512 __V) { __m128d test_mm_sqrt_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: @test_mm_sqrt_round_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_sqrt_round_sd(__A, __B, 4); + // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 -1, i32 8) + return _mm_sqrt_round_sd(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_mask_sqrt_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ @@ -5992,14 +5989,8 @@ __m128d test_mm_mask_sqrt_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B __m128d test_mm_mask_sqrt_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_mask_sqrt_round_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> - // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_mask_sqrt_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128d test_mm_maskz_sqrt_sd(__mmask8 __U, __m128d __A, __m128d __B){ @@ -6016,23 +6007,14 @@ __m128d test_mm_maskz_sqrt_sd(__mmask8 __U, __m128d __A, __m128d __B){ __m128d test_mm_maskz_sqrt_round_sd(__mmask8 __U, __m128d __A, __m128d __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_round_sd - // CHECK: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: call double @llvm.sqrt.f64(double %{{.*}}) - // CHECK-NEXT: extractelement <2 x double> %{{.*}}, i64 0 - // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> - // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK-NEXT: select i1 {{.*}}, double {{.*}}, double {{.*}} - // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double {{.*}}, i64 0 - return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <2 x double> @llvm.x86.avx512.mask.sqrt.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 %{{.*}}, i32 8) + return _mm_maskz_sqrt_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_sqrt_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: @test_mm_sqrt_round_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_sqrt_round_ss(__A, __B, 4); + // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 -1, i32 8) + return _mm_sqrt_round_ss(__A, __B, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_mask_sqrt_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ @@ -6049,14 +6031,8 @@ __m128 test_mm_mask_sqrt_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_mask_sqrt_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_mask_sqrt_round_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> - // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 {{.*}}, i32 8) + return _mm_mask_sqrt_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m128 test_mm_maskz_sqrt_ss(__mmask8 __U, __m128 __A, __m128 __B){ @@ -6073,14 +6049,8 @@ __m128 test_mm_maskz_sqrt_ss(__mmask8 __U, __m128 __A, __m128 __B){ __m128 test_mm_maskz_sqrt_round_ss(__mmask8 __U, __m128 __A, __m128 __B){ // CHECK-LABEL: @test_mm_maskz_sqrt_round_ss - // CHECK: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: call float @llvm.sqrt.f32(float %{{.*}}) - // CHECK-NEXT: extractelement <4 x float> %{{.*}}, i64 0 - // CHECK-NEXT: bitcast i8 %{{.*}} to <8 x i1> - // CHECK-NEXT: extractelement <8 x i1> %{{.*}}, i64 0 - // CHECK-NEXT: select i1 {{.*}}, float {{.*}}, float {{.*}} - // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float {{.*}}, i64 0 - return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); + // CHECK: call <4 x float> @llvm.x86.avx512.mask.sqrt.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 {{.*}}, i32 8) + return _mm_maskz_sqrt_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); } __m512 test_mm512_broadcast_f32x4(float const* __A) { -- GitLab From a06e85a92cc5b0e047599c0a481206ec941b5db5 Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Fri, 13 Jul 2018 20:33:23 +0000 Subject: [PATCH 0539/1023] CodeGen: specify alignment + inbounds for automatic variable initialization Summary: Automatic variable initialization was generating default-aligned stores (which are deprecated) instead of using the known alignment from the alloca. Further, they didn't specify inbounds. Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D49209 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337041 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuilder.h | 15 +++++++ lib/CodeGen/CGDecl.cpp | 17 ++++---- test/CodeGen/init.c | 50 +++++++++++------------ test/CodeGenOpenCL/partial_initializer.cl | 10 ++--- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/lib/CodeGen/CGBuilder.h b/lib/CodeGen/CGBuilder.h index 5b9c7a3c46..d2e5eb256d 100644 --- a/lib/CodeGen/CGBuilder.h +++ b/lib/CodeGen/CGBuilder.h @@ -244,6 +244,21 @@ public: Addr.getAlignment().alignmentAtOffset(Offset)); } + using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; + Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, + unsigned Idx1, const llvm::DataLayout &DL, + const llvm::Twine &Name = "") { + auto *GEP = cast(CreateConstInBoundsGEP2_32( + Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*IsSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue()))); + } + llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 1e9a7d5856..9350e88f2e 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -888,15 +888,17 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, /// emitStoresForInitAfterMemset - For inits that /// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar /// stores that would be required. -static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, - bool isVolatile, CGBuilderTy &Builder) { +static void emitStoresForInitAfterMemset(CodeGenModule &CGM, + llvm::Constant *Init, Address Loc, + bool isVolatile, + CGBuilderTy &Builder) { assert(!Init->isNullValue() && !isa(Init) && "called emitStoresForInitAfterMemset for zero or undef value."); if (isa(Init) || isa(Init) || isa(Init) || isa(Init) || isa(Init)) { - Builder.CreateDefaultAlignedStore(Init, Loc, isVolatile); + Builder.CreateStore(Init, Loc, isVolatile); return; } @@ -908,7 +910,8 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, // If necessary, get a pointer to the element and emit it. if (!Elt->isNullValue() && !isa(Elt)) emitStoresForInitAfterMemset( - Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i), + CGM, Elt, + Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), isVolatile, Builder); } return; @@ -923,7 +926,8 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, // If necessary, get a pointer to the element and emit it. if (!Elt->isNullValue() && !isa(Elt)) emitStoresForInitAfterMemset( - Elt, Builder.CreateConstGEP2_32(Init->getType(), Loc, 0, i), + CGM, Elt, + Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), isVolatile, Builder); } } @@ -1411,8 +1415,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { if (!constant->isNullValue() && !isa(constant)) { Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo(Loc.getAddressSpace())); - emitStoresForInitAfterMemset(constant, Loc.getPointer(), - isVolatile, Builder); + emitStoresForInitAfterMemset(CGM, constant, Loc, isVolatile, Builder); } } else { // Otherwise, create a temporary global with the initializer then diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index 8403320ec6..b539681010 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -86,25 +86,25 @@ struct Huge { char test8(int X) { char str[100000] = "abc"; // tail should be memset. return str[X]; -// CHECK: @test8( -// CHECK: call void @llvm.memset -// CHECK: store i8 97 -// CHECK: store i8 98 -// CHECK: store i8 99 -// CHECK-NOT: getelementptr -// CHECK: load + // CHECK-LABEL: @test8( + // CHECK: call void @llvm.memset + // CHECK: store i8 97, i8* %{{[0-9]*}}, align 1 + // CHECK: store i8 98, i8* %{{[0-9]*}}, align 1 + // CHECK: store i8 99, i8* %{{[0-9]*}}, align 1 + // CHECK-NOT: getelementptr + // CHECK: load } void bar(void*); // PR279 -int test9(int X) { +void test9(int X) { int Arr[100] = { X }; // Should use memset bar(Arr); -// CHECK: @test9 -// CHECK: call void @llvm.memset -// CHECK-NOT: store i32 0 -// CHECK: call void @bar + // CHECK-LABEL: @test9( + // CHECK: call void @llvm.memset + // CHECK-NOT: store i32 0 + // CHECK: call void @bar } struct a { @@ -115,11 +115,11 @@ struct b { struct a a,b,c,d,e,f,g; }; -int test10(int X) { +void test10(int X) { struct b S = { .a.a = X, .d.e = X, .f.e = 0, .f.f = 0, .f.p = 0 }; bar(&S); - // CHECK: @test10 + // CHECK-LABEL: @test10( // CHECK: call void @llvm.memset // CHECK-NOT: store i32 0 // CHECK: call void @bar @@ -132,11 +132,11 @@ struct test11S { }; void test11(struct test11S *P) { *P = (struct test11S) { .A = { [0 ... 3] = 4 } }; - // CHECK: @test11 - // CHECK: store i32 4 - // CHECK: store i32 4 - // CHECK: store i32 4 - // CHECK: store i32 4 + // CHECK-LABEL: @test11( + // CHECK: store i32 4, i32* %{{.*}}, align 4 + // CHECK: store i32 4, i32* %{{.*}}, align 4 + // CHECK: store i32 4, i32* %{{.*}}, align 4 + // CHECK: store i32 4, i32* %{{.*}}, align 4 // CHECK: ret void } @@ -151,11 +151,11 @@ struct test12 { void test13(int x) { struct X { int a; int b : 10; int c; }; struct X y = {.c = x}; - // CHECK: @test13 + // CHECK-LABEL: @test13( // CHECK: and i16 {{.*}}, -1024 } -// CHECK-LABEL: @PR20473 +// CHECK-LABEL: @PR20473( void PR20473() { // CHECK: memcpy{{.*}}getelementptr inbounds ([2 x i8], [2 x i8]* @ bar((char[2]) {""}); @@ -168,9 +168,9 @@ void PR20473() { struct S14 { int a[16]; }; void test14(struct S14 *s14) { -// CHECK-LABEL: @test14 -// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT14]] {{.*}}, i32 64, i1 false) -// CHECK-NOT: store -// CHECK: ret void + // CHECK-LABEL: @test14( + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT14]] {{.*}}, i32 64, i1 false) + // CHECK-NOT: store + // CHECK: ret void *s14 = (struct S14) { { [5 ... 11] = 17 } }; } diff --git a/test/CodeGenOpenCL/partial_initializer.cl b/test/CodeGenOpenCL/partial_initializer.cl index cdc469f7d6..ee6be919a7 100644 --- a/test/CodeGenOpenCL/partial_initializer.cl +++ b/test/CodeGenOpenCL/partial_initializer.cl @@ -38,11 +38,11 @@ void f(void) { // CHECK: %[[v0:.*]] = bitcast [6 x [6 x float]]* %A to i8* // CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[v0]], i8 0, i32 144, i1 false) // CHECK: %[[v1:.*]] = bitcast i8* %[[v0]] to [6 x [6 x float]]* - // CHECK: %[[v2:.*]] = getelementptr [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0 - // CHECK: %[[v3:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 0 - // CHECK: store float 1.000000e+00, float* %[[v3]] - // CHECK: %[[v4:.*]] = getelementptr [6 x float], [6 x float]* %[[v2]], i32 0, i32 1 - // CHECK: store float 2.000000e+00, float* %[[v4]] + // CHECK: %[[v2:.*]] = getelementptr inbounds [6 x [6 x float]], [6 x [6 x float]]* %[[v1]], i32 0, i32 0 + // CHECK: %[[v3:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 0 + // CHECK: store float 1.000000e+00, float* %[[v3]], align 4 + // CHECK: %[[v4:.*]] = getelementptr inbounds [6 x float], [6 x float]* %[[v2]], i32 0, i32 1 + // CHECK: store float 2.000000e+00, float* %[[v4]], align 4 float A[6][6] = {1.0f, 2.0f}; // CHECK: %[[v5:.*]] = bitcast %struct.StrucTy* %S to i8* -- GitLab From 130cf585e6ed502f101db8ff1f203719919d045d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 13 Jul 2018 21:07:42 +0000 Subject: [PATCH 0540/1023] Use external layout information to layout bit-fields for MS ABI. Patch by Aleksandr Urakov! Differential Revision: https://reviews.llvm.org/D49227 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337047 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 10 +++++++++- .../Inputs/override-bit-field-layout.layout | 16 +++++++++++++++ test/CodeGenCXX/override-bit-field-layout.cpp | 20 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/CodeGenCXX/Inputs/override-bit-field-layout.layout create mode 100644 test/CodeGenCXX/override-bit-field-layout.cpp diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 988b88b39b..b4b09c7cec 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2677,7 +2677,7 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { // Check to see if this bitfield fits into an existing allocation. Note: // MSVC refuses to pack bitfields of formal types with different sizes // into the same allocation. - if (!IsUnion && LastFieldIsNonZeroWidthBitfield && + if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield && CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) { placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField); RemainingBitsInField -= Width; @@ -2689,6 +2689,14 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { placeFieldAtOffset(CharUnits::Zero()); Size = std::max(Size, Info.Size); // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. + } else if (UseExternalLayout) { + auto FieldBitOffset = External.getExternalFieldOffset(FD); + placeFieldAtBitOffset(FieldBitOffset); + auto NewSize = Context.toCharUnitsFromBits( + llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth())); + assert(NewSize >= Size && "bit field offset already allocated"); + Size = NewSize; + Alignment = std::max(Alignment, Info.Alignment); } else { // Allocate a new block of memory and place the bitfield in it. CharUnits FieldOffset = Size.alignTo(Info.Alignment); diff --git a/test/CodeGenCXX/Inputs/override-bit-field-layout.layout b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout new file mode 100644 index 0000000000..8e67dce650 --- /dev/null +++ b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout @@ -0,0 +1,16 @@ + +*** Dumping AST Record Layout +Type: struct S1 + +Layout: + +*** Dumping AST Record Layout +Type: struct S2 + +Layout: diff --git a/test/CodeGenCXX/override-bit-field-layout.cpp b/test/CodeGenCXX/override-bit-field-layout.cpp new file mode 100644 index 0000000000..e84fcb0f45 --- /dev/null +++ b/test/CodeGenCXX/override-bit-field-layout.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-bit-field-layout.layout %s | FileCheck %s + +// CHECK: Type: struct S1 +// CHECK: FieldOffsets: [0, 11] +struct S1 { + short a : 3; + short b : 5; +}; + +// CHECK: Type: struct S2 +// CHECK: FieldOffsets: [64] +struct S2 { + virtual ~S2() = default; + short a : 3; +}; + +void use_structs() { + S1 s1s[sizeof(S1)]; + S2 s2s[sizeof(S2)]; +} -- GitLab From 2d34629f474b71d65adbb4e9e5f31ea00f64a4ec Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 13 Jul 2018 21:29:31 +0000 Subject: [PATCH 0541/1023] Make BuiltinType constructor private, and befriend ASTContext. This reflects the fact that only ASTContext should ever create an instance of BuiltinType, and matches what we do for all the other Type subclasses. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337048 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index b21d9f4127..9e024c12ff 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2253,7 +2253,9 @@ public: #include "clang/AST/BuiltinTypes.def" }; -public: +private: + friend class ASTContext; // ASTContext creates these. + BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), /*InstantiationDependent=*/(K == Dependent), @@ -2262,6 +2264,7 @@ public: BuiltinTypeBits.Kind = K; } +public: Kind getKind() const { return static_cast(BuiltinTypeBits.Kind); } StringRef getName(const PrintingPolicy &Policy) const; -- GitLab From ae0cb256078e9230a0f3c15360b32cde6e74b4ba Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 13 Jul 2018 21:32:33 +0000 Subject: [PATCH 0542/1023] [Hexagon] Fix hvx-length feature name in testcases git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337049 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/builtins-hvx128.c | 2 +- test/CodeGen/builtins-hvx64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CodeGen/builtins-hvx128.c b/test/CodeGen/builtins-hvx128.c index c482d7bd35..07d0e050dd 100644 --- a/test/CodeGen/builtins-hvx128.c +++ b/test/CodeGen/builtins-hvx128.c @@ -1,5 +1,5 @@ // REQUIRES: hexagon-registered-target -// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128b -emit-llvm %s -o - | FileCheck %s void test() { int v128 __attribute__((__vector_size__(128))); diff --git a/test/CodeGen/builtins-hvx64.c b/test/CodeGen/builtins-hvx64.c index 5f0d301040..5a53296e72 100644 --- a/test/CodeGen/builtins-hvx64.c +++ b/test/CodeGen/builtins-hvx64.c @@ -1,5 +1,5 @@ // REQUIRES: hexagon-registered-target -// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length64b -emit-llvm %s -o - | FileCheck %s void test() { int v64 __attribute__((__vector_size__(64))); -- GitLab From ee3e94b5688725c35a664a80c8f334aeeb401f36 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Fri, 13 Jul 2018 21:35:58 +0000 Subject: [PATCH 0543/1023] [ThinLTO] Ensure we always select the same function copy to import Clang change to reflect the FunctionsToImportTy type change in the llvm changes for D48670. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337051 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BackendUtil.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 2a02b838d2..226a27b216 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -1127,9 +1127,8 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, // e.g. record required linkage changes. if (Summary->modulePath() == M->getModuleIdentifier()) continue; - // Doesn't matter what value we plug in to the map, just needs an entry - // to provoke importing by thinBackend. - ImportList[Summary->modulePath()][GUID] = 1; + // Add an entry to provoke importing by thinBackend. + ImportList[Summary->modulePath()].insert(GUID); } std::vector> OwnedImports; -- GitLab From bdb4f6d2d659950de9b4a8b317c8d5e82821461d Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Sat, 14 Jul 2018 01:50:14 +0000 Subject: [PATCH 0544/1023] Revert "[ThinLTO] Ensure we always select the same function copy to import" This reverts commit r337051. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337082 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BackendUtil.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 226a27b216..2a02b838d2 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -1127,8 +1127,9 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, // e.g. record required linkage changes. if (Summary->modulePath() == M->getModuleIdentifier()) continue; - // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); + // Doesn't matter what value we plug in to the map, just needs an entry + // to provoke importing by thinBackend. + ImportList[Summary->modulePath()][GUID] = 1; } std::vector> OwnedImports; -- GitLab From 6ffcf589f0d7c4b5e293ccfd3cff77945d3679e8 Mon Sep 17 00:00:00 2001 From: Brian Gesiak Date: Sat, 14 Jul 2018 18:21:44 +0000 Subject: [PATCH 0545/1023] Add caching when looking up coroutine_traits Summary: Currently clang looks up the coroutine_traits ClassTemplateDecl everytime it looks up the promise type. This is unnecessary as coroutine_traits doesn't change between promise type lookups. This diff caches the coroutine_traits lookup. Patch by Tanoy Sinha! Test Plan: I added log statements in the new lookupCoroutineTraits function to ensure that LookupQualifiedName was only called once even when multiple coroutines existed in the source file. Reviewers: modocache, GorNishanov Reviewed By: modocache Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48981 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337103 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 6 ++++++ lib/Sema/Sema.cpp | 6 +++--- lib/Sema/SemaCoroutine.cpp | 38 +++++++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a818125760..ec60bb0bd6 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -824,6 +824,10 @@ public: /// \. ClassTemplateDecl *StdInitializerList; + /// The C++ "std::coroutine_traits" template, which is defined in + /// \ + ClassTemplateDecl *StdCoroutineTraitsCache; + /// The C++ "type_info" declaration, which is defined in \. RecordDecl *CXXTypeInfoDecl; @@ -8536,6 +8540,8 @@ public: bool buildCoroutineParameterMoves(SourceLocation Loc); VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc); //===--------------------------------------------------------------------===// // OpenCL extensions. diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b26cf3c043..55000e3e35 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -131,9 +131,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), - NSValueDecl(nullptr), NSStringDecl(nullptr), - StringWithUTF8StringMethod(nullptr), + StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr), + MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr), + NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index 658bdcbafc..1d5454ca77 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -60,20 +60,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, return QualType(); } - LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), - FuncLoc, Sema::LookupOrdinaryName); - if (!S.LookupQualifiedName(Result, StdExp)) { - S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) - << "std::experimental::coroutine_traits"; - return QualType(); - } - - ClassTemplateDecl *CoroTraits = Result.getAsSingle(); + ClassTemplateDecl *CoroTraits = S.lookupCoroutineTraits(KwLoc, FuncLoc); if (!CoroTraits) { - Result.suppressDiagnostics(); - // We found something weird. Complain about the first thing we found. - NamedDecl *Found = *Result.begin(); - S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); return QualType(); } @@ -1538,3 +1526,27 @@ StmtResult Sema::BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs Args) { return StmtError(); return Res; } + +ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc) { + if (!StdCoroutineTraitsCache) { + if (auto StdExp = lookupStdExperimentalNamespace()) { + LookupResult Result(*this, + &PP.getIdentifierTable().get("coroutine_traits"), + FuncLoc, LookupOrdinaryName); + if (!LookupQualifiedName(Result, StdExp)) { + Diag(KwLoc, diag::err_implied_coroutine_type_not_found) + << "std::experimental::coroutine_traits"; + return nullptr; + } + if (!(StdCoroutineTraitsCache = + Result.getAsSingle())) { + Result.suppressDiagnostics(); + NamedDecl *Found = *Result.begin(); + Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); + return nullptr; + } + } + } + return StdCoroutineTraitsCache; +} -- GitLab From 0d80d9512f02e4aa692ef2f3131da71cefa86194 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Sun, 15 Jul 2018 03:11:43 +0000 Subject: [PATCH 0546/1023] [CMake] Use libc++ and compiler-rt for sanitizers When building runtimes for Linux as part of Fuchsia toolchain, use libc++ and compiler-rt for sanitizers. Differential Revision: https://reviews.llvm.org/D49331 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337117 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index ae8658debd..7264f90d4e 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -57,6 +57,9 @@ elseif(UNIX) set(RUNTIMES_${target}-linux-gnu_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") set(RUNTIMES_${target}-linux-gnu_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI "libc++" CACHE STRING "") + set(RUNTIMES_${target}-linux-gnu_SANITIZER_CXX_ABI_INTREE ON CACHE BOOL "") + set(RUNTIMES_${target}-linux-gnu_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "") endif() endforeach() endif() @@ -100,7 +103,6 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") - set(RUNTIMES_${target}-fuchsia_SANITIZER_USE_COMPILER_RT ON CACHE BOOL "") endforeach() set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") -- GitLab From 27d1a66dffa9424bcdadc7cd52cf2ae019e49889 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Sun, 15 Jul 2018 12:08:52 +0000 Subject: [PATCH 0547/1023] Run thread safety tests with both lock and capability attributes; NFC to the analysis behavior. Patch thanks to Aaron Puchert. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337125 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/warn-thread-safety-analysis.cpp | 116 ++++++++++--------- 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index a0a592c681..2c59a518c4 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1,12 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 -DUSE_TRY_ACQUIRE_CAPABILITY %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s -#define LOCKABLE __attribute__((lockable)) #define SCOPED_LOCKABLE __attribute__((scoped_lockable)) #define GUARDED_BY(x) __attribute__((guarded_by(x))) #define GUARDED_VAR __attribute__((guarded_var)) @@ -14,42 +13,46 @@ #define PT_GUARDED_VAR __attribute__((pt_guarded_var)) #define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) #define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) -#if USE_ASSERT_CAPABILITY +#if USE_CAPABILITY +#define LOCKABLE __attribute__((capability("mutex"))) #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__))) #define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__))) -#else -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) -#endif - -#ifdef USE_TRY_ACQUIRE_CAPABILITY +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) #else +#define LOCKABLE __attribute__((lockable)) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) #endif #define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) -#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) -#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) #define LOCK_RETURNED(x) __attribute__((lock_returned(x))) #define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) #define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) class LOCKABLE Mutex { public: - void Lock() __attribute__((exclusive_lock_function)); - void ReaderLock() __attribute__((shared_lock_function)); - void Unlock() __attribute__((unlock_function)); + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void ReaderLock() SHARED_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); - void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); + void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION(); // for negative capabilities const Mutex& operator!() const { return *this; } @@ -80,11 +83,10 @@ class SCOPED_LOCKABLE ReleasableMutexLock { void Release() UNLOCK_FUNCTION(); }; -class __attribute__((scoped_lockable)) DoubleMutexLock { +class SCOPED_LOCKABLE DoubleMutexLock { public: - DoubleMutexLock(Mutex *mu1, Mutex *mu2) - __attribute__((exclusive_lock_function(mu1, mu2))); - ~DoubleMutexLock() __attribute__((unlock_function)); + DoubleMutexLock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); + ~DoubleMutexLock() UNLOCK_FUNCTION(); }; // The universal lock, written "*", allows checking to be selectively turned @@ -165,7 +167,7 @@ class MutexWrapper { public: Mutex mu; int x __attribute__((guarded_by(mu))); - void MyLock() __attribute__((exclusive_lock_function(mu))); + void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu); }; MutexWrapper sls_mw; @@ -378,8 +380,8 @@ Mutex aa_mu; class GlobalLocker { public: - void globalLock() __attribute__((exclusive_lock_function(aa_mu))); - void globalUnlock() __attribute__((unlock_function(aa_mu))); + void globalLock() EXCLUSIVE_LOCK_FUNCTION(aa_mu); + void globalUnlock() UNLOCK_FUNCTION(aa_mu); }; GlobalLocker glock; @@ -462,7 +464,7 @@ class GBFoo { // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}} } - void testNoAnal() __attribute__((no_thread_safety_analysis)) { + void testNoAnal() NO_THREAD_SAFETY_ANALYSIS { gb_field = 0; } }; @@ -556,7 +558,7 @@ public: int a __attribute__((guarded_by(mu))); int b; - void foo() __attribute__((exclusive_locks_required(mu))) { } + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu) { } void test() { a = 0; // \ @@ -738,18 +740,18 @@ void shared_bad_2() { // FIXME: Add support for functions (not only methods) class LRBar { public: - void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu))); - void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu))); + void aa_elr_fun() EXCLUSIVE_LOCKS_REQUIRED(aa_mu); + void aa_elr_fun_s() SHARED_LOCKS_REQUIRED(aa_mu); void le_fun() __attribute__((locks_excluded(sls_mu))); }; class LRFoo { public: - void test() __attribute__((exclusive_locks_required(sls_mu))); - void testShared() __attribute__((shared_locks_required(sls_mu2))); + void test() EXCLUSIVE_LOCKS_REQUIRED(sls_mu); + void testShared() SHARED_LOCKS_REQUIRED(sls_mu2); }; -void elr_fun() __attribute__((exclusive_locks_required(sls_mu))); +void elr_fun() EXCLUSIVE_LOCKS_REQUIRED(sls_mu); void elr_fun() {} LRFoo MyLRFoo; @@ -801,18 +803,18 @@ void es_fun_7() { sls_mu.Unlock(); } -void es_fun_8() __attribute__((no_thread_safety_analysis)); +void es_fun_8() NO_THREAD_SAFETY_ANALYSIS; void es_fun_8() { Bar.aa_elr_fun_s(); } -void es_fun_9() __attribute__((shared_locks_required(aa_mu))); +void es_fun_9() SHARED_LOCKS_REQUIRED(aa_mu); void es_fun_9() { Bar.aa_elr_fun_s(); } -void es_fun_10() __attribute__((exclusive_locks_required(aa_mu))); +void es_fun_10() EXCLUSIVE_LOCKS_REQUIRED(aa_mu); void es_fun_10() { Bar.aa_elr_fun_s(); } @@ -1538,23 +1540,23 @@ namespace substitution_test { public: Mutex mu; - void lockData() __attribute__((exclusive_lock_function(mu))); - void unlockData() __attribute__((unlock_function(mu))); + void lockData() EXCLUSIVE_LOCK_FUNCTION(mu); + void unlockData() UNLOCK_FUNCTION(mu); - void doSomething() __attribute__((exclusive_locks_required(mu))) { } + void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu) { } }; class DataLocker { public: - void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))); - void unlockData(MyData *d) __attribute__((unlock_function(d->mu))); + void lockData (MyData *d) EXCLUSIVE_LOCK_FUNCTION(d->mu); + void unlockData(MyData *d) UNLOCK_FUNCTION(d->mu); }; class Foo { public: - void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { } + void foo(MyData* d) EXCLUSIVE_LOCKS_REQUIRED(d->mu) { } void bar1(MyData* d) { d->lockData(); @@ -1595,8 +1597,8 @@ namespace constructor_destructor_tests { class Foo { public: - Foo() __attribute__((exclusive_lock_function(fooMu))) { } - ~Foo() __attribute__((unlock_function(fooMu))) { } + Foo() EXCLUSIVE_LOCK_FUNCTION(fooMu) { } + ~Foo() UNLOCK_FUNCTION(fooMu) { } }; void fooTest() { @@ -2027,9 +2029,9 @@ void test() { namespace GoingNative { - struct __attribute__((lockable)) mutex { - void lock() __attribute__((exclusive_lock_function)); - void unlock() __attribute__((unlock_function)); + struct LOCKABLE mutex { + void lock() EXCLUSIVE_LOCK_FUNCTION(); + void unlock() UNLOCK_FUNCTION(); // ... }; bool foo(); @@ -3560,7 +3562,7 @@ struct Cell { class Foo { public: template - void elr(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); + void elr(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); void test(); }; @@ -3576,7 +3578,7 @@ void Foo::test() { template -void globalELR(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); +void globalELR(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); template void globalELR(Cell* c1) { } @@ -3589,7 +3591,7 @@ void globalTest() { template -void globalELR2(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); +void globalELR2(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); // second declaration template @@ -3612,7 +3614,7 @@ void globalTest2() { template class FooT { public: - void elr(Cell* c) __attribute__((exclusive_locks_required(c->mu_))); + void elr(Cell* c) EXCLUSIVE_LOCKS_REQUIRED(c->mu_); }; template @@ -4422,7 +4424,7 @@ class A { (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}} } - void RunHelper() __attribute__((exclusive_locks_required(M))); + void RunHelper() EXCLUSIVE_LOCKS_REQUIRED(M); Mutex M; }; @@ -4649,8 +4651,8 @@ namespace NegativeThreadRoles { typedef int __attribute__((capability("role"))) ThreadRole; -void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {} -void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {} +void acquire(ThreadRole R) EXCLUSIVE_LOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {} +void release(ThreadRole R) UNLOCK_FUNCTION(R) NO_THREAD_SAFETY_ANALYSIS {} ThreadRole FlightControl, Logger; -- GitLab From e3f43c2ae1bd915046fe173d8ac32389672cad83 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Mon, 16 Jul 2018 05:42:25 +0000 Subject: [PATCH 0548/1023] [MinGW] Automatically mangle Windows-specific entry points as C This mangles entry points wmain, WinMain, wWinMain or DllMain as C functions, to match the ABI for these functions. We already did the same for these functions in MSVC mode, but we also should do the same in the Itanium ABI. This fixes PR38124. Differential Revision: https://reviews.llvm.org/D49354 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337146 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ItaniumMangle.cpp | 12 ++++++++++++ test/CodeGenCXX/mangle-mingw.cpp | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/CodeGenCXX/mangle-mingw.cpp diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 6f7efcbe1b..3b99a3d9af 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -592,6 +592,18 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (FD->isMain()) return false; + // The Windows ABI expects that we would never mangle "typical" + // user-defined entry points regardless of visibility or freestanding-ness. + // + // N.B. This is distinct from asking about "main". "main" has a lot of + // special rules associated with it in the standard while these + // user-defined entry points are outside of the purview of the standard. + // For example, there can be only one definition for "main" in a standards + // compliant program; however nothing forbids the existence of wmain and + // WinMain in the same translation unit. + if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) diff --git a/test/CodeGenCXX/mangle-mingw.cpp b/test/CodeGenCXX/mangle-mingw.cpp new file mode 100644 index 0000000000..90a9826455 --- /dev/null +++ b/test/CodeGenCXX/mangle-mingw.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain -- GitLab From b813e9608d5e93c65454d82760e26ea304f925cb Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Mon, 16 Jul 2018 07:23:47 +0000 Subject: [PATCH 0549/1023] [Sema] Add fixit for unused lambda captures This diff adds a fixit to suggest removing unused lambda captures in the appropriate diagnostic. Patch by Andrew Comminos! Test plan: make check-all Differential revision: https://reviews.llvm.org/D48845 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337148 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/DeclSpec.h | 13 ++- include/clang/Sema/ScopeInfo.h | 3 + include/clang/Sema/Sema.h | 6 +- lib/Parse/ParseExprCXX.cpp | 6 +- lib/Sema/SemaLambda.cpp | 48 +++++++++-- test/FixIt/fixit-unused-lambda-capture.cpp | 94 ++++++++++++++++++++++ 6 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 test/FixIt/fixit-unused-lambda-capture.cpp diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 02afb093fd..40e5269c15 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -2540,12 +2540,16 @@ struct LambdaIntroducer { LambdaCaptureInitKind InitKind; ExprResult Init; ParsedType InitCaptureType; + SourceRange ExplicitRange; + LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, IdentifierInfo *Id, SourceLocation EllipsisLoc, LambdaCaptureInitKind InitKind, ExprResult Init, - ParsedType InitCaptureType) + ParsedType InitCaptureType, + SourceRange ExplicitRange) : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), - InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType) {} + InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType), + ExplicitRange(ExplicitRange) {} }; SourceRange Range; @@ -2563,9 +2567,10 @@ struct LambdaIntroducer { SourceLocation EllipsisLoc, LambdaCaptureInitKind InitKind, ExprResult Init, - ParsedType InitCaptureType) { + ParsedType InitCaptureType, + SourceRange ExplicitRange) { Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, - InitCaptureType)); + InitCaptureType, ExplicitRange)); } }; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index fa1b1037a2..1074074c60 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -829,6 +829,9 @@ public: /// if the enclosing full-expression is instantiation dependent). llvm::SmallSet NonODRUsedCapturingExprs; + /// A map of explicit capture indices to their introducer source ranges. + llvm::DenseMap ExplicitCaptureRanges; + /// Contains all of the variables defined in this lambda that shadow variables /// that were defined in parent contexts. Used to avoid warnings when the /// shadowed variables are uncaptured by this lambda. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ec60bb0bd6..2425dff005 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5602,8 +5602,10 @@ public: /// Does copying/destroying the captured variable have side effects? bool CaptureHasSideEffects(const sema::Capture &From); - /// Diagnose if an explicit lambda capture is unused. - void DiagnoseUnusedLambdaCapture(const sema::Capture &From); + /// Diagnose if an explicit lambda capture is unused. Returns true if a + /// diagnostic is emitted. + bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const sema::Capture &From); /// Complete a lambda-expression having processed and attached the /// lambda body. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 647069760d..26e7599951 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -808,6 +808,7 @@ Optional Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; ExprResult Init; + SourceLocation LocStart = Tok.getLocation(); if (Tok.is(tok::star)) { Loc = ConsumeToken(); @@ -981,8 +982,11 @@ Optional Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr); Init = InitExpr; } + + SourceLocation LocEnd = PrevTokLocation; + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, - InitCaptureType); + InitCaptureType, SourceRange(LocStart, LocEnd)); } T.consumeClose(); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 9e53beb449..0b768cc9fa 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -993,6 +993,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; continue; } @@ -1139,6 +1141,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, TryCapture_ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; } finishLambdaExplicitCaptures(LSI); @@ -1478,12 +1482,13 @@ bool Sema::CaptureHasSideEffects(const Capture &From) { return false; } -void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { +bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const Capture &From) { if (CaptureHasSideEffects(From)) - return; + return false; if (From.isVLATypeCapture()) - return; + return false; auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); if (From.isThisCapture()) @@ -1491,6 +1496,8 @@ void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { else diag << From.getVariable(); diag << From.isNonODRUsed(); + diag << FixItHint::CreateRemoval(CaptureRange); + return true; } ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, @@ -1532,18 +1539,49 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Translate captures. auto CurField = Class->field_begin(); + // True if the current capture has a used capture or default before it. + bool CurHasPreviousCapture = CaptureDefault != LCD_None; + SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? + CaptureDefaultLoc : IntroducerRange.getBegin(); + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { const Capture &From = LSI->Captures[I]; + assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; + // Use source ranges of explicit captures for fixits where available. + SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I]; + // Warn about unused explicit captures. + bool IsCaptureUsed = true; if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { // Initialized captures that are non-ODR used may not be eliminated. bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); - if (!NonODRUsedInitCapture) - DiagnoseUnusedLambdaCapture(From); + if (!NonODRUsedInitCapture) { + bool IsLast = (I + 1) == LSI->NumExplicitCaptures; + SourceRange FixItRange; + if (CaptureRange.isValid()) { + if (!CurHasPreviousCapture && !IsLast) { + // If there are no captures preceding this capture, remove the + // following comma. + FixItRange = SourceRange(CaptureRange.getBegin(), + getLocForEndOfToken(CaptureRange.getEnd())); + } else { + // Otherwise, remove the comma since the last used capture. + FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc), + CaptureRange.getEnd()); + } + } + + IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From); + } + } + + if (CaptureRange.isValid()) { + CurHasPreviousCapture |= IsCaptureUsed; + PrevCaptureLoc = CaptureRange.getEnd(); } // Handle 'this' capture. diff --git a/test/FixIt/fixit-unused-lambda-capture.cpp b/test/FixIt/fixit-unused-lambda-capture.cpp new file mode 100644 index 0000000000..c3120093ed --- /dev/null +++ b/test/FixIt/fixit-unused-lambda-capture.cpp @@ -0,0 +1,94 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunused-lambda-capture -Wno-unused-value -std=c++1z -fixit %t +// RUN: grep -v CHECK %t | FileCheck %s + +void test() { + int i = 0; + int j = 0; + int k = 0; + int c = 10; + int a[c]; + + [i,j] { return i; }; + // CHECK: [i] { return i; }; + [i,j] { return j; }; + // CHECK: [j] { return j; }; + [&i,j] { return j; }; + // CHECK: [j] { return j; }; + [j,&i] { return j; }; + // CHECK: [j] { return j; }; + [i,j,k] {}; + // CHECK: [] {}; + [i,j,k] { return i + j; }; + // CHECK: [i,j] { return i + j; }; + [i,j,k] { return j + k; }; + // CHECK: [j,k] { return j + k; }; + [i,j,k] { return i + k; }; + // CHECK: [i,k] { return i + k; }; + [i,j,k] { return i + j + k; }; + // CHECK: [i,j,k] { return i + j + k; }; + [&,i] { return k; }; + // CHECK: [&] { return k; }; + [=,&i] { return k; }; + // CHECK: [=] { return k; }; + [=,&i,&j] { return j; }; + // CHECK: [=,&j] { return j; }; + [=,&i,&j] { return i; }; + // CHECK: [=,&i] { return i; }; + [z = i] {}; + // CHECK: [] {}; + [i,z = i] { return z; }; + // CHECK: [z = i] { return z; }; + [z = i,i] { return z; }; + // CHECK: [z = i] { return z; }; + [&a] {}; + // CHECK: [] {}; + [i,&a] { return i; }; + // CHECK: [i] { return i; }; + [&a,i] { return i; }; + // CHECK: [i] { return i; }; + + #define I_MACRO() i + #define I_REF_MACRO() &i + [I_MACRO()] {}; + // CHECK: [] {}; + [I_MACRO(),j] { return j; }; + // CHECK: [j] { return j; }; + [j,I_MACRO()] { return j; }; + // CHECK: [j] { return j; }; + [I_REF_MACRO(),j] { return j; }; + // CHECK: [j] { return j; }; + [j,I_REF_MACRO()] { return j; }; + // CHECK: [j] { return j; }; + + int n = 0; + [z = (n = i),j] {}; + // CHECK: [z = (n = i)] {}; + [j,z = (n = i)] {}; + // CHECK: [z = (n = i)] {}; +} + +class ThisTest { + void test() { + int i = 0; + + [this] {}; + // CHECK: [] {}; + [i,this] { return i; }; + // CHECK: [i] { return i; }; + [this,i] { return i; }; + // CHECK: [i] { return i; }; + [*this] {}; + // CHECK: [] {}; + [*this,i] { return i; }; + // CHECK: [i] { return i; }; + [i,*this] { return i; }; + // CHECK: [i] { return i; }; + [*this] { return this; }; + // CHECK: [*this] { return this; }; + [*this,i] { return this; }; + // CHECK: [*this] { return this; }; + [i,*this] { return this; }; + // CHECK: [*this] { return this; }; + } +}; -- GitLab From d7888b0fe44112d6620ef66f5d75d859cbace18d Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Mon, 16 Jul 2018 09:27:27 +0000 Subject: [PATCH 0550/1023] [Analyzer] Mark `SymbolData` parts of iterator position as live in program state maps Marking a symbolic expression as live is non-recursive. In our checkers we either use conjured symbols or conjured symbols plus/minus integers to represent abstract position of iterators, so in this latter case we also must mark the `SymbolData` part of these symbolic expressions as live to prevent them from getting reaped. Differential Revision: https://reviews.llvm.org/D48764 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337151 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/IteratorChecker.cpp | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp index 325e881a74..56c250cd16 100644 --- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -488,14 +488,18 @@ void IteratorChecker::checkLiveSymbols(ProgramStateRef State, // alive auto RegionMap = State->get(); for (const auto Reg : RegionMap) { - const auto Pos = Reg.second; - SR.markLive(Pos.getOffset()); + const auto Offset = Reg.second.getOffset(); + for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i) + if (isa(*i)) + SR.markLive(*i); } auto SymbolMap = State->get(); for (const auto Sym : SymbolMap) { - const auto Pos = Sym.second; - SR.markLive(Pos.getOffset()); + const auto Offset = Sym.second.getOffset(); + for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i) + if (isa(*i)) + SR.markLive(*i); } auto ContMap = State->get(); @@ -1157,21 +1161,31 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State, const IteratorPosition &Pos2, bool Equal) { auto &SVB = State->getStateManager().getSValBuilder(); + + // FIXME: This code should be reworked as follows: + // 1. Subtract the operands using evalBinOp(). + // 2. Assume that the result doesn't overflow. + // 3. Compare the result to 0. + // 4. Assume the result of the comparison. const auto comparison = SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()), - nonloc::SymbolVal(Pos2.getOffset()), SVB.getConditionType()) - .getAs(); - - if (comparison) { - auto NewState = State->assume(*comparison, Equal); - if (const auto CompSym = comparison->getAsSymbol()) { - return assumeNoOverflow(NewState, cast(CompSym)->getLHS(), 2); - } - - return NewState; + nonloc::SymbolVal(Pos2.getOffset()), + SVB.getConditionType()); + + assert(comparison.getAs() && + "Symbol comparison must be a `DefinedSVal`"); + + auto NewState = State->assume(comparison.castAs(), Equal); + if (const auto CompSym = comparison.getAsSymbol()) { + assert(isa(CompSym) && + "Symbol comparison must be a `SymIntExpr`"); + assert(BinaryOperator::isComparisonOp( + cast(CompSym)->getOpcode()) && + "Symbol comparison must be a comparison"); + return assumeNoOverflow(NewState, cast(CompSym)->getLHS(), 2); } - return State; + return NewState; } bool isZero(ProgramStateRef State, const NonLoc &Val) { @@ -1225,14 +1239,12 @@ bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2, auto &SVB = State->getStateManager().getSValBuilder(); const auto comparison = - SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType()) - .getAs(); + SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType()); - if (comparison) { - return !State->assume(*comparison, false); - } + assert(comparison.getAs() && + "Symbol comparison must be a `DefinedSVal`"); - return false; + return !State->assume(comparison.castAs(), false); } } // namespace -- GitLab From fd9658b9daae8d49632f151dce9354765ea2b190 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 16 Jul 2018 09:52:02 +0000 Subject: [PATCH 0551/1023] [Sema] Reword warning for constant captures that are not required This is one of the darker corners of C++, make it clear that this is about constants and rephrase it a bit. Before: lambda capture 'i' is not required to be captured for this use After: lambda capture of constant 'i' is not required for this use git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337152 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- test/SemaCXX/warn-unused-lambda-capture.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1915f7e3be..c32b5ea07a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -341,8 +341,8 @@ def warn_unneeded_member_function : Warning< InGroup, DefaultIgnore; def warn_unused_private_field: Warning<"private field %0 is not used">, InGroup, DefaultIgnore; -def warn_unused_lambda_capture: Warning<"lambda capture %0 is not " - "%select{used|required to be captured for this use}1">, +def warn_unused_lambda_capture: Warning<"lambda capture " + "%select{|of constant }1%0 is not %select{used|required for this use}1">, InGroup, DefaultIgnore; def warn_parameter_size: Warning< diff --git a/test/SemaCXX/warn-unused-lambda-capture.cpp b/test/SemaCXX/warn-unused-lambda-capture.cpp index 52ec390b0b..f1f0c9e2bc 100644 --- a/test/SemaCXX/warn-unused-lambda-capture.cpp +++ b/test/SemaCXX/warn-unused-lambda-capture.cpp @@ -41,9 +41,9 @@ void test() { auto explicit_by_value_used = [i] { return i + 1; }; auto explicit_by_value_used_void = [i] { (void)i; }; auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} - auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} - auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} - auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} + auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture of constant 'i' is not required for this use}} + auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture of constant 'i' is not required for this use}} + auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture of constant 'k' is not required for this use}} auto explicit_by_reference_used = [&i] { i++; }; auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} @@ -146,10 +146,10 @@ void test_templated() { auto explicit_by_value_used_void = [i] { (void)i; }; auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} - auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} + auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture of constant 'i' is not required for this use}} auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}} - auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} - auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} + auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture of constant 'k' is not required for this use}} + auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture of constant 'k' is not required for this use}} auto explicit_by_reference_used = [&i] { i++; }; auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} -- GitLab From 90809faeea5a4cf6c25dcff6a55a74248a7cac83 Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Mon, 16 Jul 2018 12:16:39 +0000 Subject: [PATCH 0552/1023] [ASTImporter] Import implicit methods of existing class. Summary: When an already existing class is encountered during import, check if it has implicit methods that are missing in the existing one, and import these. The to-be-imported code may use the same class in different way than the existing (before the import) code. This may result in that there are implicit methods that are not generated for the existing code. Reviewers: a.sidorin, a_sidorin Reviewed By: a_sidorin Subscribers: a_sidorin, martong, cfe-commits Differential Revision: https://reviews.llvm.org/D49245 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337162 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 26 ++++++- unittests/AST/ASTImporterTest.cpp | 111 ++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 56ca9bbae4..366c2064d4 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -228,6 +228,7 @@ namespace clang { void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + void ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); bool ImportCastPath(CastExpr *E, CXXCastPath &Path); @@ -1253,6 +1254,16 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { Importer.Import(From); } +void ASTNodeImporter::ImportImplicitMethods( + const CXXRecordDecl *From, CXXRecordDecl *To) { + assert(From->isCompleteDefinition() && To->getDefinition() == To && + "Import implicit methods to or from non-definition"); + + for (CXXMethodDecl *FromM : From->methods()) + if (FromM->isImplicit()) + Importer.Import(FromM); +} + static void setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, ASTImporter &Importer) { if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { @@ -2199,8 +2210,19 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. - // FIXME: For C++, we should also merge methods here. - return Importer.MapImported(D, FoundDef); + // FIXME: Structural equivalence check should check for same + // user-defined methods. + Importer.MapImported(D, FoundDef); + if (const auto *DCXX = dyn_cast(D)) { + auto *FoundCXX = dyn_cast(FoundDef); + assert(FoundCXX && "Record type mismatch"); + + if (D->isCompleteDefinition() && !Importer.isMinimalImport()) + // FoundDef may not have every implicit method that D has + // because implicit methods are created only if they are used. + ImportImplicitMethods(DCXX, FoundCXX); + } + return FoundDef; } } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index cd8254c0a0..8aff6b5df9 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -2343,6 +2343,117 @@ TEST_P(ImportExpr, UnresolvedMemberExpr) { compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))))); } +class ImportImplicitMethods : public ASTImporterTestBase { +public: + static constexpr auto DefaultCode = R"( + struct A { int x; }; + void f() { + A a; + A a1(a); + A a2(A{}); + a = a1; + a = A{}; + a.~A(); + })"; + + template + void testImportOf( + const MatcherType &MethodMatcher, const char *Code = DefaultCode) { + test(MethodMatcher, Code, /*ExpectedCount=*/1u); + } + + template + void testNoImportOf( + const MatcherType &MethodMatcher, const char *Code = DefaultCode) { + test(MethodMatcher, Code, /*ExpectedCount=*/0u); + } + +private: + template + void test(const MatcherType &MethodMatcher, + const char *Code, unsigned int ExpectedCount) { + auto ClassMatcher = cxxRecordDecl(unless(isImplicit())); + + Decl *ToTU = getToTuDecl(Code, Lang_CXX11); + auto *ToClass = FirstDeclMatcher().match( + ToTU, ClassMatcher); + + ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 1); + + { + CXXMethodDecl *Method = + FirstDeclMatcher().match(ToClass, MethodMatcher); + ToClass->removeDecl(Method); + } + + ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 0); + + Decl *ImportedClass = nullptr; + { + Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc"); + auto *FromClass = FirstDeclMatcher().match( + FromTU, ClassMatcher); + ImportedClass = Import(FromClass, Lang_CXX11); + } + + EXPECT_EQ(ToClass, ImportedClass); + EXPECT_EQ(DeclCounter().match(ToClass, MethodMatcher), + ExpectedCount); + } +}; + +TEST_P(ImportImplicitMethods, DefaultConstructor) { + testImportOf(cxxConstructorDecl(isDefaultConstructor())); +} + +TEST_P(ImportImplicitMethods, CopyConstructor) { + testImportOf(cxxConstructorDecl(isCopyConstructor())); +} + +TEST_P(ImportImplicitMethods, MoveConstructor) { + testImportOf(cxxConstructorDecl(isMoveConstructor())); +} + +TEST_P(ImportImplicitMethods, Destructor) { + testImportOf(cxxDestructorDecl()); +} + +TEST_P(ImportImplicitMethods, CopyAssignment) { + testImportOf(cxxMethodDecl(isCopyAssignmentOperator())); +} + +TEST_P(ImportImplicitMethods, MoveAssignment) { + testImportOf(cxxMethodDecl(isMoveAssignmentOperator())); +} + +TEST_P(ImportImplicitMethods, DoNotImportUserProvided) { + auto Code = R"( + struct A { A() { int x; } }; + )"; + testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); +} + +TEST_P(ImportImplicitMethods, DoNotImportDefault) { + auto Code = R"( + struct A { A() = default; }; + )"; + testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); +} + +TEST_P(ImportImplicitMethods, DoNotImportDeleted) { + auto Code = R"( + struct A { A() = delete; }; + )"; + testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); +} + +TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) { + auto Code = R"( + struct A { void f() { } }; + )"; + testNoImportOf(cxxMethodDecl(hasName("f")), Code); +} + TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) { Decl *ToR1; { -- GitLab From 6fda594059bd48b6b2ddcb34eda0a278aee2214e Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Mon, 16 Jul 2018 13:14:46 +0000 Subject: [PATCH 0553/1023] [analyzer] Fix constraint being dropped when analyzing a program without taint tracking enabled Summary: This patch removes the constraint dropping when taint tracking is disabled. It also voids the crash reported in D28953 by treating a SymSymExpr with non pointer symbols as an opaque expression. Updated the regressions and verifying the big projects now; I'll update here when they're done. Based on the discussion on the mailing list and the patches by @ddcc. Reviewers: george.karpenkov, NoQ, ddcc, baloghadamsoftware Reviewed By: george.karpenkov Subscribers: delcypher, llvm-commits, rnkovacs, xazax.hun, szepet, a.sidorin, ddcc Differential Revision: https://reviews.llvm.org/D48650 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337167 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 2 +- .../Core/RangedConstraintManager.cpp | 23 ++++++------ lib/StaticAnalyzer/Core/SValBuilder.cpp | 4 +-- test/Analysis/PR37855.c | 2 +- test/Analysis/bitwise-ops.c | 5 ++- test/Analysis/std-c-library-functions.c | 3 +- .../svalbuilder-rearrange-comparisons.c | 36 +++++++++---------- 7 files changed, 36 insertions(+), 39 deletions(-) diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 75c22a34ea..a4abb82e2a 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -390,7 +390,7 @@ unsigned AnalyzerOptions::getGraphTrimInterval() { unsigned AnalyzerOptions::getMaxSymbolComplexity() { if (!MaxSymbolComplexity.hasValue()) - MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 10000); + MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 25); return MaxSymbolComplexity.getValue(); } diff --git a/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp index 1499d49899..f99853f070 100644 --- a/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp @@ -52,17 +52,18 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State, assert(BinaryOperator::isComparisonOp(Op)); // For now, we only support comparing pointers. - assert(Loc::isLocType(SSE->getLHS()->getType())); - assert(Loc::isLocType(SSE->getRHS()->getType())); - QualType DiffTy = SymMgr.getContext().getPointerDiffType(); - SymbolRef Subtraction = - SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy); - - const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy); - Op = BinaryOperator::reverseComparisonOp(Op); - if (!Assumption) - Op = BinaryOperator::negateComparisonOp(Op); - return assumeSymRel(State, Subtraction, Op, Zero); + if (Loc::isLocType(SSE->getLHS()->getType()) && + Loc::isLocType(SSE->getRHS()->getType())) { + QualType DiffTy = SymMgr.getContext().getPointerDiffType(); + SymbolRef Subtraction = + SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy); + + const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy); + Op = BinaryOperator::reverseComparisonOp(Op); + if (!Assumption) + Op = BinaryOperator::negateComparisonOp(Op); + return assumeSymRel(State, Subtraction, Op, Zero); + } } // If we get here, there's nothing else we can do but treat the symbol as diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index febe7cdb83..f292dca8e9 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -379,11 +379,9 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State, BinaryOperator::Opcode Op, NonLoc LHS, NonLoc RHS, QualType ResultTy) { - if (!State->isTainted(RHS) && !State->isTainted(LHS)) - return UnknownVal(); - const SymExpr *symLHS = LHS.getAsSymExpr(); const SymExpr *symRHS = RHS.getAsSymExpr(); + // TODO: When the Max Complexity is reached, we should conjure a symbol // instead of generating an Unknown value and propagate the taint info to it. const unsigned MaxComp = StateMgr.getOwningEngine() diff --git a/test/Analysis/PR37855.c b/test/Analysis/PR37855.c index 24e34c0836..0779796531 100644 --- a/test/Analysis/PR37855.c +++ b/test/Analysis/PR37855.c @@ -20,5 +20,5 @@ void k(l, node) { nodep = n; } if (nodep) // expected-warning {{Branch condition evaluates to a garbage value}} - n[1].node->s; // expected-warning {{Dereference of undefined pointer value}} + n[1].node->s; } diff --git a/test/Analysis/bitwise-ops.c b/test/Analysis/bitwise-ops.c index 5cdb668867..fcd3d7dbc7 100644 --- a/test/Analysis/bitwise-ops.c +++ b/test/Analysis/bitwise-ops.c @@ -8,9 +8,8 @@ void testPersistentConstraints(int x, int y) { CHECK(x); // expected-warning{{TRUE}} CHECK(x & 1); // expected-warning{{TRUE}} - // False positives due to SValBuilder giving up on certain kinds of exprs. - CHECK(1 - x); // expected-warning{{UNKNOWN}} - CHECK(x & y); // expected-warning{{UNKNOWN}} + CHECK(1 - x); // expected-warning{{TRUE}} + CHECK(x & y); // expected-warning{{TRUE}} } int testConstantShifts_PR18073(int which) { diff --git a/test/Analysis/std-c-library-functions.c b/test/Analysis/std-c-library-functions.c index 042b035f8b..b8eb3e54bd 100644 --- a/test/Analysis/std-c-library-functions.c +++ b/test/Analysis/std-c-library-functions.c @@ -57,8 +57,7 @@ void test_fread_fwrite(FILE *fp, int *buf) { size_t y = fread(buf, sizeof(int), 10, fp); clang_analyzer_eval(y <= 10); // expected-warning{{TRUE}} size_t z = fwrite(buf, sizeof(int), y, fp); - // FIXME: should be TRUE once symbol-symbol constraint support is improved. - clang_analyzer_eval(z <= y); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(z <= y); // expected-warning{{TRUE}} } ssize_t getline(char **, size_t *, FILE *); diff --git a/test/Analysis/svalbuilder-rearrange-comparisons.c b/test/Analysis/svalbuilder-rearrange-comparisons.c index 720144c38a..2303ce693c 100644 --- a/test/Analysis/svalbuilder-rearrange-comparisons.c +++ b/test/Analysis/svalbuilder-rearrange-comparisons.c @@ -560,7 +560,7 @@ void compare_same_symbol_plus_left_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) == (conj_$2{int})}} } void compare_same_symbol_minus_left_int_equal_unsigned() { @@ -569,7 +569,7 @@ void compare_same_symbol_minus_left_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) == (conj_$2{int})}} } void compare_same_symbol_plus_right_int_equal_unsigned() { @@ -577,7 +577,7 @@ void compare_same_symbol_plus_right_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_right_int_equal_unsigned() { @@ -585,7 +585,7 @@ void compare_same_symbol_minus_right_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) == ((conj_$2{int}) - 1U)}} } void compare_same_symbol_plus_left_plus_right_int_equal_unsigned() { @@ -603,7 +603,7 @@ void compare_same_symbol_plus_left_minus_right_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) == ((conj_$2{int}) - 1U)}} } void compare_same_symbol_minus_left_plus_right_int_equal_unsigned() { @@ -612,7 +612,7 @@ void compare_same_symbol_minus_left_plus_right_int_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x == y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) == ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_left_minus_right_int_equal_unsigned() { @@ -710,7 +710,7 @@ void compare_same_symbol_plus_left_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) <= (conj_$2{int})}} } void compare_same_symbol_minus_left_int_less_or_equal_unsigned() { @@ -719,7 +719,7 @@ void compare_same_symbol_minus_left_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) <= (conj_$2{int})}} } void compare_same_symbol_plus_right_int_less_or_equal_unsigned() { @@ -727,7 +727,7 @@ void compare_same_symbol_plus_right_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_right_int_less_or_equal_unsigned() { @@ -735,7 +735,7 @@ void compare_same_symbol_minus_right_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) <= ((conj_$2{int}) - 1U)}} } void compare_same_symbol_plus_left_plus_right_int_less_or_equal_unsigned() { @@ -753,7 +753,7 @@ void compare_same_symbol_plus_left_minus_right_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) <= ((conj_$2{int}) - 1U)}} } void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned() { @@ -762,7 +762,7 @@ void compare_same_symbol_minus_left_plus_right_int_less_or_equal_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x <= y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) <= ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_left_minus_right_int_less_or_equal_unsigned() { @@ -860,7 +860,7 @@ void compare_same_symbol_plus_left_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) < (conj_$2{int})}} } void compare_same_symbol_minus_left_int_less_unsigned() { @@ -869,7 +869,7 @@ void compare_same_symbol_minus_left_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) < (conj_$2{int})}} } void compare_same_symbol_plus_right_int_less_unsigned() { @@ -877,7 +877,7 @@ void compare_same_symbol_plus_right_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_right_int_less_unsigned() { @@ -885,7 +885,7 @@ void compare_same_symbol_minus_right_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{conj_$2{int}}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{(conj_$2{int}) < ((conj_$2{int}) - 1U)}} } void compare_same_symbol_plus_left_plus_right_int_less_unsigned() { @@ -903,7 +903,7 @@ void compare_same_symbol_plus_left_minus_right_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) + 1U) < ((conj_$2{int}) - 1U)}} } void compare_same_symbol_minus_left_plus_right_int_less_unsigned() { @@ -912,7 +912,7 @@ void compare_same_symbol_minus_left_plus_right_int_less_unsigned() { clang_analyzer_dump(x); // expected-warning{{(conj_$2{int}) - 1}} clang_analyzer_dump(y); // expected-warning{{(conj_$2{int}) + 1}} clang_analyzer_dump(x < y); - // expected-warning@-1{{Unknown}} // FIXME: Can this be simplified? + // expected-warning@-1{{((conj_$2{int}) - 1U) < ((conj_$2{int}) + 1U)}} } void compare_same_symbol_minus_left_minus_right_int_less_unsigned() { -- GitLab From 0b743c472efca616f462b2423d3c667f96023965 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Mon, 16 Jul 2018 13:32:22 +0000 Subject: [PATCH 0554/1023] [analyzer] Fix the Z3 backend always generating unsigned APSInt Summary: In `toAPSInt`, the Z3 backend was not checking the variable `Int`'s type and was always generating unsigned `APSInt`s. This was found by accident when I removed: ``` llvm::APSInt ConvertedLHS, ConvertedRHS; QualType LTy, RTy; std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); - doIntTypePromotion( - ConvertedLHS, LTy, ConvertedRHS, RTy); return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); ``` And the `BasicValueFactory` started to complain about different `signedness`. Reviewers: george.karpenkov, NoQ, ddcc Reviewed By: ddcc Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49305 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337169 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 9e975676cc..721e17759f 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -681,12 +681,14 @@ public: Z3_get_numeral_uint64(Z3Context::ZC, AST, reinterpret_cast<__uint64 *>(&Value[0])); if (Sort.getBitvectorSortSize() <= 64) { - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), true); + Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), + Int.isUnsigned()); } else if (Sort.getBitvectorSortSize() == 128) { Z3Expr ASTHigh = Z3Expr(Z3_mk_extract(Z3Context::ZC, 127, 64, AST)); Z3_get_numeral_uint64(Z3Context::ZC, AST, reinterpret_cast<__uint64 *>(&Value[1])); - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), true); + Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), + Int.isUnsigned()); } else { assert(false && "Bitwidth not supported!"); return false; @@ -702,7 +704,7 @@ public: llvm::APInt(Int.getBitWidth(), Z3_get_bool_value(Z3Context::ZC, AST) == Z3_L_TRUE ? 1 : 0), - true); + Int.isUnsigned()); return true; } } -- GitLab From 1ab19fc539dac7a6a0713f0bb8ddd4180914b2bc Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Mon, 16 Jul 2018 14:05:18 +0000 Subject: [PATCH 0555/1023] [ASTImporter] Changed constant int to unsigned int in test code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337172 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/AST/ASTImporterTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 8aff6b5df9..cc8ed92faa 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -2378,7 +2378,7 @@ private: auto *ToClass = FirstDeclMatcher().match( ToTU, ClassMatcher); - ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 1); + ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 1u); { CXXMethodDecl *Method = @@ -2386,7 +2386,7 @@ private: ToClass->removeDecl(Method); } - ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 0); + ASSERT_EQ(DeclCounter().match(ToClass, MethodMatcher), 0u); Decl *ImportedClass = nullptr; { -- GitLab From 5d5f03678e836071629fbda98b7e88d907664dce Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Mon, 16 Jul 2018 15:30:36 +0000 Subject: [PATCH 0556/1023] Restore "[ThinLTO] Ensure we always select the same function copy to import" This reverts commit r337082, restoring r337051, since the LLVM side patch has been restored. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337185 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BackendUtil.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 2a02b838d2..226a27b216 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -1127,9 +1127,8 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, // e.g. record required linkage changes. if (Summary->modulePath() == M->getModuleIdentifier()) continue; - // Doesn't matter what value we plug in to the map, just needs an entry - // to provoke importing by thinBackend. - ImportList[Summary->modulePath()][GUID] = 1; + // Add an entry to provoke importing by thinBackend. + ImportList[Summary->modulePath()].insert(GUID); } std::vector> OwnedImports; -- GitLab From 953bf589829d89c785e316914f438c2c015dae32 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 16 Jul 2018 16:49:20 +0000 Subject: [PATCH 0557/1023] [OPENMP, NVPTX] Globalize only captured variables. Sometimes we can try to globalize non-variable declarations, which may lead to compiler crash. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337191 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 2 +- test/OpenMP/nvptx_target_codegen.cpp | 38 +++++++++++++++------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index ba87e05908..5aaebff8f7 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -204,7 +204,7 @@ class CheckVarsEscapingDeclContext final void markAsEscaped(const ValueDecl *VD) { // Do not globalize declare target variables. - if (isDeclareTargetDeclaration(VD)) + if (!isa(VD) || isDeclareTargetDeclaration(VD)) return; VD = cast(VD->getCanonicalDecl()); // Variables captured by value must be globalized. diff --git a/test/OpenMP/nvptx_target_codegen.cpp b/test/OpenMP/nvptx_target_codegen.cpp index d578035598..d4d9941bc4 100644 --- a/test/OpenMP/nvptx_target_codegen.cpp +++ b/test/OpenMP/nvptx_target_codegen.cpp @@ -9,12 +9,12 @@ #define HEADER // Check that the execution mode of all 6 target regions is set to Generic Mode. -// CHECK-DAG: {{@__omp_offloading_.+l102}}_exec_mode = weak constant i8 1 -// CHECK-DAG: {{@__omp_offloading_.+l179}}_exec_mode = weak constant i8 1 -// CHECK-DAG: {{@__omp_offloading_.+l289}}_exec_mode = weak constant i8 1 -// CHECK-DAG: {{@__omp_offloading_.+l326}}_exec_mode = weak constant i8 1 -// CHECK-DAG: {{@__omp_offloading_.+l344}}_exec_mode = weak constant i8 1 -// CHECK-DAG: {{@__omp_offloading_.+l309}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l103}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l180}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l290}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l328}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l346}}_exec_mode = weak constant i8 1 +// CHECK-DAG: {{@__omp_offloading_.+l311}}_exec_mode = weak constant i8 1 __thread int id; @@ -24,6 +24,7 @@ template struct TT{ tx X; ty Y; + tx &operator[](int i) { return X; } }; int foo(int n) { @@ -35,7 +36,7 @@ int foo(int n) { double cn[5][n]; TT d; - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l102}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l103}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: store i8* null, i8** [[OMP_WORK_FN]], @@ -66,7 +67,7 @@ int foo(int n) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l102]]() + // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l103]]() // CHECK-DAG: [[TID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() // CHECK-DAG: [[NTH:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() // CHECK-DAG: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() @@ -108,7 +109,7 @@ int foo(int n) { { } - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l179}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l180}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: store i8* null, i8** [[OMP_WORK_FN]], @@ -139,7 +140,7 @@ int foo(int n) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l179]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]]) + // CHECK: define {{.*}}void [[T2:@__omp_offloading_.+foo.+l180]](i[[SZ:32|64]] [[ARG1:%[a-zA-Z_]+]], i[[SZ:32|64]] [[ID:%[a-zA-Z_]+]]) // CHECK: [[AA_ADDR:%.+]] = alloca i[[SZ]], // CHECK: store i[[SZ]] [[ARG1]], i[[SZ]]* [[AA_ADDR]], // CHECK: [[AA_CADDR:%.+]] = bitcast i[[SZ]]* [[AA_ADDR]] to i16* @@ -182,7 +183,7 @@ int foo(int n) { id = aa; } - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l289}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l290}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: store i8* null, i8** [[OMP_WORK_FN]], @@ -213,7 +214,7 @@ int foo(int n) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l289]](i[[SZ]] + // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l290]](i[[SZ]] // Create local storage for each capture. // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] // CHECK: [[LOCAL_B:%.+]] = alloca [10 x float]* @@ -295,6 +296,7 @@ int foo(int n) { cn[1][3] += 1.0; d.X += 1; d.Y += 1; + d[0] += 1; } return a; @@ -373,7 +375,7 @@ int baz(int f, double &a) { return f; } - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+326}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+328}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: store i8* null, i8** [[OMP_WORK_FN]], @@ -404,7 +406,7 @@ int baz(int f, double &a) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l326]](i[[SZ]] + // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+static.+l328]](i[[SZ]] // Create local storage for each capture. // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]] @@ -459,7 +461,7 @@ int baz(int f, double &a) { - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l344}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l346}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @@ -493,7 +495,7 @@ int baz(int f, double &a) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l344]]( + // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+S1.+l346]]( // Create local storage for each capture. // CHECK: [[LOCAL_THIS:%.+]] = alloca [[S1:%struct.*]]* // CHECK: [[LOCAL_B:%.+]] = alloca i[[SZ]] @@ -597,7 +599,7 @@ int baz(int f, double &a) { // CHECK: ret i32 [[RES]] - // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l309}}_worker() + // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l311}}_worker() // CHECK-DAG: [[OMP_EXEC_STATUS:%.+]] = alloca i8, // CHECK-DAG: [[OMP_WORK_FN:%.+]] = alloca i8*, // CHECK: store i8* null, i8** [[OMP_WORK_FN]], @@ -628,7 +630,7 @@ int baz(int f, double &a) { // CHECK: [[EXIT]] // CHECK: ret void - // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l309]](i[[SZ]] + // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+template.+l311]](i[[SZ]] // Create local storage for each capture. // CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]] // CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]] -- GitLab From 54d71f0ca9e6bbb7f8688abadf9d1805b9babae8 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 16 Jul 2018 18:12:18 +0000 Subject: [PATCH 0558/1023] [OPENMP] Fix syntactic errors in error messages. Fixed spelling of the offloading error messages. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337196 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 4 ++-- test/OpenMP/target_messages.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 1e37c894ee..d348816040 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -3970,7 +3970,7 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { if (!CE->getID() || !CE->getAddress()) { unsigned DiagID = CGM.getDiags().getCustomDiagID( DiagnosticsEngine::Error, - "Offloading entry for target region is incorect: either the " + "Offloading entry for target region is incorrect: either the " "address or the ID is invalid."); CGM.getDiags().Report(DiagID); continue; @@ -3983,7 +3983,7 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { if (!CE->getAddress()) { unsigned DiagID = CGM.getDiags().getCustomDiagID( DiagnosticsEngine::Error, - "Offloading entry for declare target varible is inccorect: the " + "Offloading entry for declare target variable is incorrect: the " "address is invalid."); CGM.getDiags().Report(DiagID); continue; diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp index 52dbe4900d..c9dc80aca4 100644 --- a/test/OpenMP/target_messages.cpp +++ b/test/OpenMP/target_messages.cpp @@ -14,7 +14,7 @@ // RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -DREGION_HOST // RUN: not %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -DREGION_DEVICE 2>&1 | FileCheck %s --check-prefix NO-REGION -// NO-REGION: Offloading entry for target region is incorect: either the address or the ID is invalid. +// NO-REGION: Offloading entry for target region is incorrect: either the address or the ID is invalid. #if defined(REGION_HOST) || defined(REGION_DEVICE) void foo() { -- GitLab From 7acd2b806207042702f4cece726c377ce7c236ec Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Mon, 16 Jul 2018 20:05:25 +0000 Subject: [PATCH 0559/1023] [OPENMP] Fix checks for declare target link entries. If the declare target link entries are created but not used, the compiler will produce an error message. Patch improves handling of such situations + improves checks for possibly lost declare target variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337207 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 50 +++++++++++++++------ lib/CodeGen/CGOpenMPRuntime.h | 2 + test/OpenMP/declare_target_link_codegen.cpp | 7 +-- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index d348816040..5594dd4438 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -3980,16 +3980,39 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { } else if (const auto *CE = dyn_cast(E)) { - if (!CE->getAddress()) { - unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Offloading entry for declare target variable is incorrect: the " - "address is invalid."); - CGM.getDiags().Report(DiagID); - continue; + OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = + static_cast( + CE->getFlags()); + switch (Flags) { + case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { + if (!CE->getAddress()) { + unsigned DiagID = CGM.getDiags().getCustomDiagID( + DiagnosticsEngine::Error, + "Offloading entry for declare target variable is incorrect: the " + "address is invalid."); + CGM.getDiags().Report(DiagID); + continue; + } + break; + } + case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: + assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || + (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && + "Declaret target link address is set."); + if (CGM.getLangOpts().OpenMPIsDevice) + continue; + if (!CE->getAddress()) { + unsigned DiagID = CGM.getDiags().getCustomDiagID( + DiagnosticsEngine::Error, + "Offloading entry for declare target variable is incorrect: the " + "address is invalid."); + CGM.getDiags().Report(DiagID); + continue; + } + break; } createOffloadEntry(CE->getAddress(), CE->getAddress(), - CE->getVarSize().getQuantity(), CE->getFlags(), + CE->getVarSize().getQuantity(), Flags, CE->getLinkage()); } else { llvm_unreachable("Unsupported entry kind."); @@ -7889,14 +7912,15 @@ void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); break; case OMPDeclareTargetDeclAttr::MT_Link: - // Map type 'to' because we do not map the original variable but the - // reference. - Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; - if (!CGM.getLangOpts().OpenMPIsDevice) { + Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; + if (CGM.getLangOpts().OpenMPIsDevice) { + VarName = Addr->getName(); + Addr = nullptr; + } else { + VarName = getAddrOfDeclareTargetLink(VD).getName(); Addr = cast(getAddrOfDeclareTargetLink(VD).getPointer()); } - VarName = Addr->getName(); VarSize = CGM.getPointerSize(); Linkage = llvm::GlobalValue::WeakAnyLinkage; break; diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h index 599b3ba01f..01ff0c20fd 100644 --- a/lib/CodeGen/CGOpenMPRuntime.h +++ b/lib/CodeGen/CGOpenMPRuntime.h @@ -522,6 +522,8 @@ private: enum OMPTargetGlobalVarEntryKind : uint32_t { /// Mark the entry as a to declare target. OMPTargetGlobalVarEntryTo = 0x0, + /// Mark the entry as a to declare target link. + OMPTargetGlobalVarEntryLink = 0x1, }; /// Device global variable entries info. diff --git a/test/OpenMP/declare_target_link_codegen.cpp b/test/OpenMP/declare_target_link_codegen.cpp index b377408455..fdecd728ce 100644 --- a/test/OpenMP/declare_target_link_codegen.cpp +++ b/test/OpenMP/declare_target_link_codegen.cpp @@ -23,8 +23,9 @@ // HOST: @c_decl_tgt_link_ptr = global i32* @c // HOST: [[SIZES:@.+]] = private unnamed_addr constant [2 x i64] [i64 4, i64 4] // HOST: [[MAPTYPES:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 531] -// CHECK: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00" -// CHECK: @.omp_offloading.entry.c_decl_tgt_link_ptr = weak constant %struct.__tgt_offload_entry { i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name, i32 0, i32 0), i64 8, i32 0, i32 0 }, section ".omp_offloading.entries", align 1 +// HOST: @.omp_offloading.entry_name{{.*}} = internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00" +// HOST: @.omp_offloading.entry.c_decl_tgt_link_ptr = weak constant %struct.__tgt_offload_entry { i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @.omp_offloading.entry_name, i32 0, i32 0), i64 8, i32 1, i32 0 }, section ".omp_offloading.entries", align 1 +// DEVICE-NOT: internal unnamed_addr constant [{{[0-9]+}} x i8] c"c_decl_tgt_link_ptr\00" // CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (i32** @c_decl_tgt_link_ptr to i8*)] extern int c; @@ -64,5 +65,5 @@ int maini1() { // HOST: [[C:%.*]] = load i32, i32* @c, // HOST: store i32 [[C]], i32* % -// CHECK: !{i32 1, !"c_decl_tgt_link_ptr", i32 0, i32 {{[0-9]+}}} +// CHECK: !{i32 1, !"c_decl_tgt_link_ptr", i32 1, i32 {{[0-9]+}}} #endif // HEADER -- GitLab From a621a93addcd463c55ccd1e7e5f613de8e5f16e8 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 16 Jul 2018 20:22:12 +0000 Subject: [PATCH 0560/1023] [ASTMatchers] Introduce Objective-C matchers `hasReceiver` and `isInstanceMessage` for ObjCMessageExpr Differential Revision: https://reviews.llvm.org/D49333 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337209 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 25 +++++++++++++ include/clang/ASTMatchers/ASTMatchers.h | 35 +++++++++++++++++++ lib/ASTMatchers/Dynamic/Registry.cpp | 2 ++ .../ASTMatchers/ASTMatchersTraversalTest.cpp | 29 +++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 3f0ded2270..a41424d89a 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -3268,6 +3268,19 @@ represent an error condition in the tree!

+Matcher<ObjCMessageExpr>isInstanceMessage +
Returns true when the Objective-C message is sent to an instance.
+
+Example
+matcher = objcMessagaeExpr(isInstanceMessage())
+matches
+  NSString *x = @"hello";
+  [x containsString:@"h"]
+but not
+  [NSString stringWithFormat:@"format"]
+
+ + Matcher<ObjCMessageExpr>matchesSelectorstd::string RegExp
Matches ObjC selectors whose name contains
 a substring matched by the given RegExp.
@@ -5875,6 +5888,18 @@ Example matches y in x(y)
 
+Matcher<ObjCMessageExpr>hasReceiverMatcher<Expr> InnerMatcher +
Matches if the Objective-C message is sent to an instance,
+and the inner matcher matches on that instance.
+
+For example the method call in
+  NSString *x = @"hello";
+  [x containsString:@"h"]
+is matched by
+objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
+
+ + Matcher<ObjCMessageExpr>hasReceiverTypeMatcher<QualType> InnerMatcher
Matches on the receiver of an ObjectiveC Message expression.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 1c8d1da37f..938c99adfd 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -2736,6 +2736,41 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher,
   return InnerMatcher.matches(TypeDecl, Finder, Builder);
 }
 
+/// Returns true when the Objective-C message is sent to an instance.
+///
+/// Example
+/// matcher = objcMessagaeExpr(isInstanceMessage())
+/// matches
+/// \code
+///   NSString *x = @"hello";
+///   [x containsString:@"h"];
+/// \endcode
+/// but not
+/// \code
+///   [NSString stringWithFormat:@"format"];
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, isInstanceMessage) {
+  return Node.isInstanceMessage();
+}
+
+/// Matches if the Objective-C message is sent to an instance,
+/// and the inner matcher matches on that instance.
+///
+/// For example the method call in
+/// \code
+///   NSString *x = @"hello";
+///   [x containsString:@"h"];
+/// \endcode
+/// is matched by
+/// objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
+AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher,
+              InnerMatcher) {
+  const Expr *ReceiverNode = Node.getInstanceReceiver();
+  return (ReceiverNode != nullptr &&
+          InnerMatcher.matches(*ReceiverNode->IgnoreParenImpCasts(), Finder,
+                               Builder));
+}
+
 /// Matches when BaseName == Selector.getAsString()
 ///
 ///  matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 384dd8d4e3..769d985c05 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -283,6 +283,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasParent);
   REGISTER_MATCHER(hasQualifier);
   REGISTER_MATCHER(hasRangeInit);
+  REGISTER_MATCHER(hasReceiver);
   REGISTER_MATCHER(hasReceiverType);
   REGISTER_MATCHER(hasReplacementType);
   REGISTER_MATCHER(hasReturnValue);
@@ -349,6 +350,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isImplicit);
   REGISTER_MATCHER(isExpansionInFileMatching);
   REGISTER_MATCHER(isExpansionInMainFile);
+  REGISTER_MATCHER(isInstanceMessage);
   REGISTER_MATCHER(isInstantiated);
   REGISTER_MATCHER(isExpansionInSystemHeader);
   REGISTER_MATCHER(isInteger);
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index b18cd63130..85b22b245e 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -422,6 +422,35 @@ TEST(Matcher, AnyArgument) {
   EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument));
 }
 
+TEST(Matcher, HasReceiver) {
+  EXPECT_TRUE(matchesObjC(
+      "@interface NSString @end"
+      "void f(NSString *x) {"
+      "[x containsString]"
+      "}",
+      objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
+
+  EXPECT_FALSE(matchesObjC(
+      "@interface NSString +(NSString *) stringWithFormat; @end"
+      "void f() { [NSString stringWithFormat]; }",
+      objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
+}
+
+TEST(Matcher, isInstanceMessage) {
+  EXPECT_TRUE(matchesObjC(
+      "@interface NSString @end"
+      "void f(NSString *x) {"
+      "[x containsString]"
+      "}",
+      objcMessageExpr(isInstanceMessage())));
+
+  EXPECT_FALSE(matchesObjC(
+      "@interface NSString +(NSString *) stringWithFormat; @end"
+      "void f() { [NSString stringWithFormat]; }",
+      objcMessageExpr(isInstanceMessage())));
+
+}
+
 TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {
   StatementMatcher ArgumentY =
     declRefExpr(to(varDecl(hasName("y")))).bind("arg");
-- 
GitLab


From e75ddf8c13756ad41aafcb557b51a3f8e95913b9 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Mon, 16 Jul 2018 20:32:32 +0000
Subject: [PATCH 0561/1023] [analyzer] Provide a symmetric method for
 generating a PathDiagnosticLocation from Decl

Differential Revision: https://reviews.llvm.org/D49166

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337211 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../StaticAnalyzer/Core/BugReporter/PathDiagnostic.h     | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index cca977de88..b18d3c9b30 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -216,6 +216,15 @@ public:
   static PathDiagnosticLocation createBegin(const Decl *D,
                                             const SourceManager &SM);
 
+  /// Create a location for the beginning of the declaration.
+  /// The third argument is ignored, useful for generic treatment
+  /// of statements and declarations.
+  static PathDiagnosticLocation
+  createBegin(const Decl *D, const SourceManager &SM,
+              const LocationOrAnalysisDeclContext LAC) {
+    return createBegin(D, SM);
+  }
+
   /// Create a location for the beginning of the statement.
   static PathDiagnosticLocation createBegin(const Stmt *S,
                                             const SourceManager &SM,
-- 
GitLab


From 83baf9557f669f3c12debbf41827c1ae34bb2f43 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Mon, 16 Jul 2018 20:32:57 +0000
Subject: [PATCH 0562/1023] [analyzer] Fix GCDAntipatternChecker to only fire
 when the semaphore is initialized to zero

Initializing a semaphore with a different constant most likely signals a different intent

rdar://41802552

Differential Revision: https://reviews.llvm.org/D48911

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337212 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp |  4 +++-
 test/Analysis/gcdantipatternchecker_test.m            | 10 ++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
index 1b7ea53aea..5cb51b01f0 100644
--- a/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -93,7 +93,9 @@ static bool isTest(const Decl *D) {
 static auto findGCDAntiPatternWithSemaphore() -> decltype(compoundStmt()) {
 
   const char *SemaphoreBinding = "semaphore_name";
-  auto SemaphoreCreateM = callExpr(callsName("dispatch_semaphore_create"));
+  auto SemaphoreCreateM = callExpr(allOf(
+      callsName("dispatch_semaphore_create"),
+      hasArgument(0, ignoringParenCasts(integerLiteral(equals(0))))));
 
   auto SemaphoreBindingM = anyOf(
       forEachDescendant(
diff --git a/test/Analysis/gcdantipatternchecker_test.m b/test/Analysis/gcdantipatternchecker_test.m
index adc7a52bf5..24ffe8975d 100644
--- a/test/Analysis/gcdantipatternchecker_test.m
+++ b/test/Analysis/gcdantipatternchecker_test.m
@@ -333,3 +333,13 @@ void dispatch_group_and_semaphore_use(MyInterface1 *M) {
   }];
   dispatch_semaphore_wait(sema1, 100); // expected-warning{{Waiting on a callback using a semaphore}}
 }
+
+void no_warn_on_nonzero_semaphore(MyInterface1 *M) {
+  dispatch_semaphore_t sema1 = dispatch_semaphore_create(1);
+
+  [M acceptBlock:^{
+      dispatch_semaphore_signal(sema1);
+  }];
+  dispatch_semaphore_wait(sema1, 100); // no-warning
+}
+
-- 
GitLab


From 627e5ecaad1f7438f6a7f586de7c700f2a876643 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Mon, 16 Jul 2018 20:33:25 +0000
Subject: [PATCH 0563/1023] [analyzer] Bugfix for an overly eager suppression
 for null pointer return from macros.

Only suppress those cases where the null which came from the macro is
relevant to the bug, and was not overwritten in between.

rdar://41497323

Differential Revision: https://reviews.llvm.org/D48856

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337213 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../Core/BugReporterVisitors.cpp              | 99 +++++++++++--------
 .../macro-null-return-suppression.cpp         | 23 +++++
 2 files changed, 83 insertions(+), 39 deletions(-)

diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 025c2898ee..f17f41a7ac 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -228,6 +228,38 @@ static bool isFunctionMacroExpansion(SourceLocation Loc,
   return EInfo.isFunctionMacroExpansion();
 }
 
+/// \return Whether \c RegionOfInterest was modified at \p N,
+/// where \p ReturnState is a state associated with the return
+/// from the current frame.
+static bool wasRegionOfInterestModifiedAt(
+        const SubRegion *RegionOfInterest,
+        const ExplodedNode *N,
+        SVal ValueAfter) {
+  ProgramStateRef State = N->getState();
+  ProgramStateManager &Mgr = N->getState()->getStateManager();
+
+  if (!N->getLocationAs()
+      && !N->getLocationAs()
+      && !N->getLocationAs())
+    return false;
+
+  // Writing into region of interest.
+  if (auto PS = N->getLocationAs())
+    if (auto *BO = PS->getStmtAs())
+      if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
+            N->getSVal(BO->getLHS()).getAsRegion()))
+        return true;
+
+  // SVal after the state is possibly different.
+  SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
+  if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() &&
+      (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
+    return true;
+
+  return false;
+}
+
+
 namespace {
 
 /// Put a diagnostic on return statement of all inlined functions
@@ -346,7 +378,7 @@ private:
       FramesModifyingCalculated.insert(
         N->getLocationContext()->getStackFrame());
 
-      if (wasRegionOfInterestModifiedAt(N, LastReturnState, ValueAtReturn)) {
+      if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) {
         const StackFrameContext *SCtx = N->getStackFrame();
         while (!SCtx->inTopFrame()) {
           auto p = FramesModifyingRegion.insert(SCtx);
@@ -365,33 +397,6 @@ private:
     } while (N);
   }
 
-  /// \return Whether \c RegionOfInterest was modified at \p N,
-  /// where \p ReturnState is a state associated with the return
-  /// from the current frame.
-  bool wasRegionOfInterestModifiedAt(const ExplodedNode *N,
-                                     ProgramStateRef ReturnState,
-                                     SVal ValueAtReturn) {
-    if (!N->getLocationAs()
-        && !N->getLocationAs()
-        && !N->getLocationAs())
-      return false;
-
-    // Writing into region of interest.
-    if (auto PS = N->getLocationAs())
-      if (auto *BO = PS->getStmtAs())
-        if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
-                                        N->getSVal(BO->getLHS()).getAsRegion()))
-          return true;
-
-    // SVal after the state is possibly different.
-    SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
-    if (!ReturnState->areEqual(ValueAtN, ValueAtReturn).isConstrainedTrue() &&
-        (!ValueAtN.isUndef() || !ValueAtReturn.isUndef()))
-      return true;
-
-    return false;
-  }
-
   /// Get parameters associated with runtime definition in order
   /// to get the correct parameter name.
   ArrayRef getCallParameters(CallEventRef<> Call) {
@@ -524,25 +529,28 @@ private:
   }
 };
 
+/// Suppress null-pointer-dereference bugs where dereferenced null was returned
+/// the macro.
 class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor {
   const SubRegion *RegionOfInterest;
+  const SVal ValueAtDereference;
 
-public:
-  MacroNullReturnSuppressionVisitor(const SubRegion *R) : RegionOfInterest(R) {}
+  // Do not invalidate the reports where the value was modified
+  // after it got assigned to from the macro.
+  bool WasModified = false;
 
-  static void *getTag() {
-    static int Tag = 0;
-    return static_cast(&Tag);
-  }
-
-  void Profile(llvm::FoldingSetNodeID &ID) const override {
-    ID.AddPointer(getTag());
-  }
+public:
+  MacroNullReturnSuppressionVisitor(const SubRegion *R,
+                                    const SVal V) : RegionOfInterest(R),
+                                                    ValueAtDereference(V) {}
 
   std::shared_ptr VisitNode(const ExplodedNode *N,
                                                  const ExplodedNode *PrevN,
                                                  BugReporterContext &BRC,
                                                  BugReport &BR) override {
+    if (WasModified)
+      return nullptr;
+
     auto BugPoint = BR.getErrorNode()->getLocation().getAs();
     if (!BugPoint)
       return nullptr;
@@ -556,6 +564,10 @@ public:
           BR.markInvalid(getTag(), MacroName.c_str());
       }
     }
+
+    if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference))
+      WasModified = true;
+
     return nullptr;
   }
 
@@ -568,7 +580,16 @@ public:
     if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()
           && V.getAs())
       BR.addVisitor(llvm::make_unique(
-              R->getAs()));
+              R->getAs(), V));
+  }
+
+  void* getTag() const {
+    static int Tag = 0;
+    return static_cast(&Tag);
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const override {
+    ID.AddPointer(getTag());
   }
 
 private:
diff --git a/test/Analysis/diagnostics/macro-null-return-suppression.cpp b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
index 9a14f03a32..a2928f15c1 100644
--- a/test/Analysis/diagnostics/macro-null-return-suppression.cpp
+++ b/test/Analysis/diagnostics/macro-null-return-suppression.cpp
@@ -43,3 +43,26 @@ int testDivision(int a) {
 DEREF_IN_MACRO(0) // expected-warning{{Dereference of null pointer}}
                   // expected-note@-1{{'p' initialized to a null}}
                   // expected-note@-2{{Dereference of null pointer}}
+
+// Warning should not be suppressed if the null returned by the macro
+// is not related to the warning.
+#define RETURN_NULL() (0)
+extern int* returnFreshPointer();
+int noSuppressMacroUnrelated() {
+  int *x = RETURN_NULL();
+  x = returnFreshPointer();  // expected-note{{Value assigned to 'x'}}
+  if (x) {} // expected-note{{Taking false branch}}
+            // expected-note@-1{{Assuming 'x' is null}}
+  return *x; // expected-warning{{Dereference of null pointer}}
+             // expected-note@-1{{Dereference}}
+}
+
+// Value haven't changed by the assignment, but the null pointer
+// did not come from the macro.
+int noSuppressMacroUnrelatedOtherReason() {
+  int *x = RETURN_NULL();
+  x = returnFreshPointer();  
+  x = 0; // expected-note{{Null pointer value stored to 'x'}}
+  return *x; // expected-warning{{Dereference of null pointer}}
+             // expected-note@-1{{Dereference}}
+}
-- 
GitLab


From 51349a127b1549746455a2581dd87b526deb76e4 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Mon, 16 Jul 2018 20:42:37 +0000
Subject: [PATCH 0564/1023] [ASTMatchers] Quickfix for tests.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337214 91177308-0d34-0410-b5e6-96231b3b80d8
---
 unittests/ASTMatchers/ASTMatchersTraversalTest.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 85b22b245e..3b8f362101 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -424,28 +424,28 @@ TEST(Matcher, AnyArgument) {
 
 TEST(Matcher, HasReceiver) {
   EXPECT_TRUE(matchesObjC(
-      "@interface NSString @end"
+      "@interface NSString @end "
       "void f(NSString *x) {"
-      "[x containsString]"
+      "[x containsString];"
       "}",
       objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
 
   EXPECT_FALSE(matchesObjC(
-      "@interface NSString +(NSString *) stringWithFormat; @end"
+      "@interface NSString +(NSString *) stringWithFormat; @end "
       "void f() { [NSString stringWithFormat]; }",
       objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
 }
 
 TEST(Matcher, isInstanceMessage) {
   EXPECT_TRUE(matchesObjC(
-      "@interface NSString @end"
+      "@interface NSString @end "
       "void f(NSString *x) {"
-      "[x containsString]"
+      "[x containsString];"
       "}",
       objcMessageExpr(isInstanceMessage())));
 
   EXPECT_FALSE(matchesObjC(
-      "@interface NSString +(NSString *) stringWithFormat; @end"
+      "@interface NSString +(NSString *) stringWithFormat; @end "
       "void f() { [NSString stringWithFormat]; }",
       objcMessageExpr(isInstanceMessage())));
 
-- 
GitLab


From 3ad62f50a0a775140c6c35308ade2f2caea67ed1 Mon Sep 17 00:00:00 2001
From: Reka Kovacs 
Date: Mon, 16 Jul 2018 20:47:45 +0000
Subject: [PATCH 0565/1023] [analyzer] Make checkEndFunction() give access to
 the return statement.

Differential Revision: https://reviews.llvm.org/D49387

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337215 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/StaticAnalyzer/Core/Checker.h               | 4 ++--
 include/clang/StaticAnalyzer/Core/CheckerManager.h        | 8 +++++---
 lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp          | 4 ++--
 lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp      | 2 +-
 lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp | 5 +++--
 lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp        | 5 +++--
 lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp    | 5 +++--
 lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp   | 5 +++--
 lib/StaticAnalyzer/Checkers/TraversalChecker.cpp          | 5 +++--
 .../Checkers/UninitializedObjectChecker.cpp               | 4 ++--
 lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp        | 5 +++--
 lib/StaticAnalyzer/Core/CheckerManager.cpp                | 5 +++--
 lib/StaticAnalyzer/Core/ExprEngine.cpp                    | 4 ++--
 13 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index a7f9a12b2c..45b7a61139 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -254,9 +254,9 @@ public:
 
 class EndFunction {
   template 
-  static void _checkEndFunction(void *checker,
+  static void _checkEndFunction(void *checker, const ReturnStmt *RS,
                                 CheckerContext &C) {
-    ((const CHECKER *)checker)->checkEndFunction(C);
+    ((const CHECKER *)checker)->checkEndFunction(RS, C);
   }
 
 public:
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 99a8eb01fa..33a794061a 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -296,7 +296,8 @@ public:
   void runCheckersForEndFunction(NodeBuilderContext &BC,
                                  ExplodedNodeSet &Dst,
                                  ExplodedNode *Pred,
-                                 ExprEngine &Eng);
+                                 ExprEngine &Eng,
+                                 const ReturnStmt *RS);
 
   /// Run checkers for branch condition.
   void runCheckersForBranchCondition(const Stmt *condition,
@@ -438,7 +439,8 @@ public:
 
   using CheckBeginFunctionFunc = CheckerFn;
 
-  using CheckEndFunctionFunc = CheckerFn;
+  using CheckEndFunctionFunc =
+      CheckerFn;
   
   using CheckBranchConditionFunc =
       CheckerFn;
@@ -496,7 +498,7 @@ public:
 
   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
 
-  void _registerForBeginFunction(CheckEndFunctionFunc checkfn);
+  void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
 
   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index bfd4019ed8..f4d2e32cef 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -126,7 +126,7 @@ public:
                                      const CallEvent *Call,
                                      PointerEscapeKind Kind) const;
   void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &Ctx) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
 
 private:
   void diagnoseMissingReleases(CheckerContext &C) const;
@@ -398,7 +398,7 @@ void ObjCDeallocChecker::checkPostObjCMessage(
 /// Check for missing releases even when -dealloc does not call
 /// '[super dealloc]'.
 void ObjCDeallocChecker::checkEndFunction(
-    CheckerContext &C) const {
+    const ReturnStmt *RS, CheckerContext &C) const {
   diagnoseMissingReleases(C);
 }
 
diff --git a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 495486bf39..7862a4c256 100644
--- a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -192,7 +192,7 @@ public:
   /// level or is inlined.
   ///
   /// check::EndFunction
-  void checkEndFunction(CheckerContext &Ctx) const {}
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const {}
 
   /// Called after all the paths in the ExplodedGraph reach end of path
   /// - the symbolic execution graph is fully explored.
diff --git a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
index 258eb05ca7..19c1d077af 100644
--- a/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
@@ -46,7 +46,7 @@ class MisusedMovedObjectChecker
     : public Checker {
 public:
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
   void checkPreCall(const CallEvent &MC, CheckerContext &C) const;
   void checkPostCall(const CallEvent &MC, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
@@ -222,7 +222,8 @@ ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
 
 // Removing the function parameters' MemRegion from the state. This is needed
 // for PODs where the trivial destructor does not even created nor executed.
-void MisusedMovedObjectChecker::checkEndFunction(CheckerContext &C) const {
+void MisusedMovedObjectChecker::checkEndFunction(const ReturnStmt *RS,
+                                                 CheckerContext &C) const {
   auto State = C.getState();
   TrackedRegionMapTy Objects = State->get();
   if (Objects.isEmpty())
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 54e87d4094..2c1e139330 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -2743,7 +2743,7 @@ public:
 
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
   void checkBeginFunction(CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
 
   ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
                                RefVal V, ArgEffect E, RefVal::Kind &hasErr,
@@ -3991,7 +3991,8 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
   Ctx.addTransition(state);
 }
 
-void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
+void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
+                                          CheckerContext &Ctx) const {
   ProgramStateRef state = Ctx.getState();
   RefBindingsTy B = state->get();
   ExplodedNode *Pred = Ctx.getPredecessor();
diff --git a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 86936cadd5..feae9e59b3 100644
--- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -47,7 +47,7 @@ public:
 
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &Ctx) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;
 
 private:
   void checkReturnedBlockCaptures(const BlockDataRegion &B,
@@ -287,7 +287,8 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
   EmitStackError(C, R, RetE);
 }
 
-void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
+void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
+                                              CheckerContext &Ctx) const {
   if (!ChecksEnabled[CK_StackAddrEscapeChecker])
     return;
 
diff --git a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index eac743349d..f4c0edbab3 100644
--- a/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -85,7 +85,7 @@ class TestAfterDivZeroChecker
 public:
   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
   void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
   void setDivZeroMap(SVal Var, CheckerContext &C) const;
   bool hasDivZeroMap(SVal Var, const CheckerContext &C) const;
   bool isZero(SVal S, CheckerContext &C) const;
@@ -180,7 +180,8 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
   }
 }
 
-void TestAfterDivZeroChecker::checkEndFunction(CheckerContext &C) const {
+void TestAfterDivZeroChecker::checkEndFunction(const ReturnStmt *RS,
+                                               CheckerContext &C) const {
   ProgramStateRef State = C.getState();
 
   DivZeroMapTy DivZeroes = State->get();
diff --git a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
index 8ad962875b..ee185b8136 100644
--- a/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
@@ -30,7 +30,7 @@ class TraversalDumper : public Checker< check::BranchCondition,
 public:
   void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
   void checkBeginFunction(CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
 };
 }
 
@@ -56,7 +56,8 @@ void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
   llvm::outs() << "--BEGIN FUNCTION--\n";
 }
 
-void TraversalDumper::checkEndFunction(CheckerContext &C) const {
+void TraversalDumper::checkEndFunction(const ReturnStmt *RS,
+                                       CheckerContext &C) const {
   llvm::outs() << "--END FUNCTION--\n";
 }
 
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
index 5c94a5bd33..398228a9d8 100644
--- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
@@ -47,7 +47,7 @@ public:
 
   UninitializedObjectChecker()
       : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
 };
 
 /// Represents a field chain. A field chain is a vector of fields where the
@@ -241,7 +241,7 @@ static StringRef getVariableName(const FieldDecl *Field);
 //===----------------------------------------------------------------------===//
 
 void UninitializedObjectChecker::checkEndFunction(
-    CheckerContext &Context) const {
+    const ReturnStmt *RS, CheckerContext &Context) const {
 
   const auto *CtorDecl = dyn_cast_or_null(
       Context.getLocationContext()->getDecl());
diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index ec5afa5134..5b602468cd 100644
--- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -48,7 +48,7 @@ public:
   DefaultBool IsPureOnly;
 
   void checkBeginFunction(CheckerContext &C) const;
-  void checkEndFunction(CheckerContext &C) const;
+  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
 
 private:
@@ -167,7 +167,8 @@ void VirtualCallChecker::checkBeginFunction(CheckerContext &C) const {
 }
 
 // The EndFunction callback when leave a constructor or a destructor.
-void VirtualCallChecker::checkEndFunction(CheckerContext &C) const {
+void VirtualCallChecker::checkEndFunction(const ReturnStmt *RS,
+                                          CheckerContext &C) const {
   registerCtorDtorCallInState(false, C);
 }
 
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index e355fa28ea..712872a15d 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -439,7 +439,8 @@ void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
 void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
                                                ExplodedNodeSet &Dst,
                                                ExplodedNode *Pred,
-                                               ExprEngine &Eng) {
+                                               ExprEngine &Eng,
+                                               const ReturnStmt *RS) {
   // We define the builder outside of the loop bacause if at least one checkers
   // creates a sucsessor for Pred, we do not need to generate an
   // autotransition for it.
@@ -449,7 +450,7 @@ void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
                                           Pred->getLocationContext(),
                                           checkFn.Checker);
     CheckerContext C(Bldr, Eng, Pred, L);
-    checkFn(C);
+    checkFn(RS, C);
   }
 }
 
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 27f7553e7a..188316c096 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2297,9 +2297,9 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
 
     // Notify checkers.
     for (const auto I : AfterRemovedDead)
-      getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this);
+      getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);
   } else {
-    getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this);
+    getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);
   }
 
   Engine.enqueueEndOfFunction(Dst, RS);
-- 
GitLab


From bd8c87930bc3817282e4c040c16a90a66ca7f267 Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Tue, 17 Jul 2018 00:11:41 +0000
Subject: [PATCH 0566/1023] Restructure checking for, and warning on, lifetime
 extension.

This change implements C++ DR1696, which makes initialization of a
reference member of a class from a temporary object ill-formed. The
standard wording here is imprecise, but we interpret it as meaning that
any time a mem-initializer would result in lifetime extension, the
program is ill-formed.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337226 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticGroups.td       |   1 +
 include/clang/Basic/DiagnosticSemaKinds.td    |  40 +-
 include/clang/Sema/Initialization.h           |  34 +-
 include/clang/Sema/Sema.h                     |   5 +
 lib/Sema/SemaDeclCXX.cpp                      |   7 +-
 lib/Sema/SemaExprCXX.cpp                      |   7 -
 lib/Sema/SemaInit.cpp                         | 370 +++++++++++++-----
 test/Analysis/initializer.cpp                 |  23 --
 test/CXX/drs/dr16xx.cpp                       |  94 +++++
 test/CXX/drs/dr18xx.cpp                       |  11 +
 test/CXX/special/class.copy/p11.0x.copy.cpp   |  13 +-
 test/CXX/special/class.copy/p11.0x.move.cpp   |   2 +-
 test/CXX/special/class.ctor/p5-0x.cpp         |   6 +-
 test/CXX/temp/temp.param/p5.cpp               |  12 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |  30 --
 test/CodeGenCXX/temporaries.cpp               |  27 --
 test/SemaCXX/constant-expression-cxx11.cpp    |   9 +-
 test/SemaCXX/constexpr-default-arg.cpp        |   4 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |   9 +-
 test/SemaCXX/eval-crashes.cpp                 |   6 +-
 test/SemaCXX/member-init.cpp                  |   3 +-
 test/SemaCXX/warn-dangling-field.cpp          |   6 +-
 www/cxx_dr_status.html                        |   4 +-
 23 files changed, 483 insertions(+), 240 deletions(-)

diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index e021cf6975..e27dc0d764 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -272,6 +272,7 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
 def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
 def DanglingElse: DiagGroup<"dangling-else">;
 def DanglingField : DiagGroup<"dangling-field">;
+def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
 def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
 def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
 def FlagEnum : DiagGroup<"flag-enum">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c32b5ea07a..acfdd260cd 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2049,10 +2049,6 @@ def err_implied_std_initializer_list_not_found : Error<
   "not found; include ">;
 def err_malformed_std_initializer_list : Error<
   "std::initializer_list must be a class template with a single type parameter">;
-def warn_dangling_std_initializer_list : Warning<
-  "array backing the initializer list will be destroyed at the end of "
-  "%select{the full-expression|the constructor}0">,
-  InGroup>;
 def err_auto_init_list_from_c : Error<
   "cannot use __auto_type with initializer list in C">;
 def err_auto_bitfield : Error<
@@ -7844,13 +7840,39 @@ def warn_bind_ref_member_to_parameter : Warning<
 def warn_init_ptr_member_to_parameter_addr : Warning<
   "initializing pointer member %0 with the stack address of parameter %1">,
   InGroup;
-def warn_bind_ref_member_to_temporary : Warning<
-  "binding reference %select{|subobject of }1member %0 to a temporary value">,
-  InGroup;
 def note_ref_or_ptr_member_declared_here : Note<
   "%select{reference|pointer}0 member declared here">;
-def note_ref_subobject_of_member_declared_here : Note<
-  "member with reference subobject declared here">;
+
+def err_bind_ref_member_to_temporary : Error<
+  "%select{reference|backing array for 'std::initializer_list'}2 "
+  "%select{|subobject of }1member %0 "
+  "%select{binds to|is}2 a temporary object "
+  "whose lifetime would be shorter than the constructed object">;
+def note_lifetime_extending_member_declared_here : Note<
+  "%select{%select{reference|'std::initializer_list'}0 member|"
+  "member with %select{reference|'std::initializer_list'}0 subobject}1 "
+  "declared here">;
+def warn_new_dangling_reference : Warning<
+  "temporary bound to reference member of allocated object "
+  "will be destroyed at the end of the full-expression">,
+  InGroup;
+def warn_new_dangling_initializer_list : Warning<
+  "array backing "
+  "%select{initializer list subobject of the allocated object|"
+  "the allocated initializer list}0 "
+  "will be destroyed at the end of the full-expression">,
+  InGroup;
+def warn_default_member_init_temporary_not_extended : Warning<
+  "sorry, lifetime extension of temporary created by aggregate initialization "
+  "using default member initializer is not supported; lifetime of temporary "
+  "will end at the end of the full-expression">, InGroup;
+def warn_default_member_init_init_list_not_extended : Warning<
+  "sorry, lifetime extension of backing array of initializer list "
+  "created by aggregate initialization using default member initializer "
+  "is not supported; lifetime of backing array will end at the end of the "
+  "full-expression">, InGroup;
+def note_in_default_member_initalizer_here : Note<
+  "in default member initializer for field %0 used here">;
 
 // For non-floating point, expressions of the form x == x or x != x
 // should result in a warning, since these always evaluate to a constant.
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 1e6423c99d..774a2c9ff9 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -63,7 +63,7 @@ public:
     /// is being thrown.
     EK_Exception,
 
-    /// The entity being initialized is a non-static data member 
+    /// The entity being initialized is a non-static data member
     /// subobject.
     EK_Member,
 
@@ -123,7 +123,7 @@ public:
     // enum as an index for its first %select.  When modifying this list,
     // that diagnostic text needs to be updated as well.
   };
-  
+
 private:
   /// The kind of entity being initialized.
   EntityKind Kind;
@@ -158,6 +158,10 @@ private:
     /// initialization in a copy or move constructor. These can perform array
     /// copies.
     bool IsImplicitFieldInit;
+
+    /// When Kind == EK_Member, whether this is the initial initialization
+    /// check for a default member initializer.
+    bool IsDefaultMemberInit;
   };
 
   struct C {
@@ -203,7 +207,7 @@ private:
 
   /// Create the initialization entity for a variable.
   InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
-      : Kind(EK), Type(Var->getType()), Variable{Var, false} {}
+      : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
   
   /// Create the initialization entity for the result of a
   /// function, throwing an object, performing an explicit cast, or
@@ -217,9 +221,9 @@ private:
   
   /// Create the initialization entity for a member subobject.
   InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
-                    bool Implicit) 
+                    bool Implicit, bool DefaultMemberInit)
       : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
-        Variable{Member, Implicit} {}
+        Variable{Member, Implicit, DefaultMemberInit} {}
   
   /// Create the initialization entity for an array element.
   InitializedEntity(ASTContext &Context, unsigned Index, 
@@ -339,21 +343,27 @@ public:
   static InitializedEntity InitializeDelegation(QualType Type) {
     return InitializedEntity(EK_Delegating, SourceLocation(), Type);
   }
-  
+
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(FieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member, Parent, Implicit);
+    return InitializedEntity(Member, Parent, Implicit, false);
   }
-  
+
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(IndirectFieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member->getAnonField(), Parent, Implicit);
+    return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
+  }
+
+  /// Create the initialization entity for a default member initializer.
+  static InitializedEntity
+  InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
+    return InitializedEntity(Member, nullptr, false, true);
   }
 
   /// Create the initialization entity for an array element.
@@ -453,6 +463,12 @@ public:
     return getKind() == EK_Member && Variable.IsImplicitFieldInit;
   }
 
+  /// Is this the default member initializer of a member (specified inside
+  /// the class definition)?
+  bool isDefaultMemberInitializer() const {
+    return getKind() == EK_Member && Variable.IsDefaultMemberInit;
+  }
+
   /// Determine the location of the 'return' keyword when initializing
   /// the result of a function call.
   SourceLocation getReturnLoc() const {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 2425dff005..f13e423cef 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2582,6 +2582,11 @@ public:
                                                  NamedDecl *FoundDecl,
                                                  CXXMethodDecl *Method);
 
+  /// Check that the lifetime of the initializer (and its subobjects) is
+  /// sufficient for initializing the entity, and perform lifetime extension
+  /// (when permitted) if not.
+  void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
+
   ExprResult PerformContextuallyConvertToBool(Expr *From);
   ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 63d01c9d85..eda6e16195 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3621,7 +3621,8 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
 
   ExprResult Init = InitExpr;
   if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
-    InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
+    InitializedEntity Entity =
+        InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
     InitializationKind Kind =
         FD->getInClassInitStyle() == ICIS_ListInit
             ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
@@ -4646,6 +4647,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
         SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
     if (DIE.isInvalid())
       return true;
+
+    auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
+    SemaRef.checkInitializerLifetime(Entity, DIE.get());
+
     CXXCtorInitializer *Init;
     if (Indirect)
       Init = new (SemaRef.Context)
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fbf572e398..a7ad8e322d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1864,13 +1864,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
   if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
     return ExprError();
 
-  if (initStyle == CXXNewExpr::ListInit &&
-      isStdInitializerList(AllocType, nullptr)) {
-    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
-         diag::warn_dangling_std_initializer_list)
-        << /*at end of FE*/0 << Inits[0]->getSourceRange();
-  }
-
   // In ARC, infer 'retaining' for the allocated
   if (getLangOpts().ObjCAutoRefCount &&
       AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 320d93a99a..f94eabd671 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -572,6 +572,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
         hadError = true;
         return;
       }
+      SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
       if (Init < NumInits)
         ILE->setInit(Init, DIE.get());
       else {
@@ -6197,17 +6198,43 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
   llvm_unreachable("unknown entity kind");
 }
 
+namespace {
+enum LifetimeKind {
+  /// The lifetime of a temporary bound to this entity ends at the end of the
+  /// full-expression, and that's (probably) fine.
+  LK_FullExpression,
+
+  /// The lifetime of a temporary bound to this entity is extended to the
+  /// lifeitme of the entity itself.
+  LK_Extended,
+
+  /// The lifetime of a temporary bound to this entity probably ends too soon,
+  /// because the entity is allocated in a new-expression.
+  LK_New,
+
+  /// The lifetime of a temporary bound to this entity ends too soon, because
+  /// the entity is a return object.
+  LK_Return,
+
+  /// This is a mem-initializer: if it would extend a temporary (other than via
+  /// a default member initializer), the program is ill-formed.
+  LK_MemInitializer,
+};
+using LifetimeResult =
+    llvm::PointerIntPair;
+}
+
 /// Determine the declaration which an initialized entity ultimately refers to,
 /// for the purpose of lifetime-extending a temporary bound to a reference in
 /// the initialization of \p Entity.
-static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+static LifetimeResult getEntityForTemporaryLifetimeExtension(
     const InitializedEntity *Entity,
-    const InitializedEntity *FallbackDecl = nullptr) {
+    const InitializedEntity *InitField = nullptr) {
   // C++11 [class.temporary]p5:
   switch (Entity->getKind()) {
   case InitializedEntity::EK_Variable:
     //   The temporary [...] persists for the lifetime of the reference
-    return Entity;
+    return {Entity, LK_Extended};
 
   case InitializedEntity::EK_Member:
     // For subobjects, we look at the complete object.
@@ -6216,29 +6243,43 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
                                                     Entity);
 
     //   except:
-    //   -- A temporary bound to a reference member in a constructor's
-    //      ctor-initializer persists until the constructor exits.
-    return Entity;
+    // C++17 [class.base.init]p8:
+    //   A temporary expression bound to a reference member in a
+    //   mem-initializer is ill-formed.
+    // C++17 [class.base.init]p11:
+    //   A temporary expression bound to a reference member from a
+    //   default member initializer is ill-formed.
+    //
+    // The context of p11 and its example suggest that it's only the use of a
+    // default member initializer from a constructor that makes the program
+    // ill-formed, not its mere existence, and that it can even be used by
+    // aggregate initialization.
+    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
+                                                         : LK_MemInitializer};
 
   case InitializedEntity::EK_Binding:
     // Per [dcl.decomp]p3, the binding is treated as a variable of reference
     // type.
-    return Entity;
+    return {Entity, LK_Extended};
 
   case InitializedEntity::EK_Parameter:
   case InitializedEntity::EK_Parameter_CF_Audited:
     //   -- A temporary bound to a reference parameter in a function call
     //      persists until the completion of the full-expression containing
     //      the call.
+    return {nullptr, LK_FullExpression};
+
   case InitializedEntity::EK_Result:
     //   -- The lifetime of a temporary bound to the returned value in a
     //      function return statement is not extended; the temporary is
     //      destroyed at the end of the full-expression in the return statement.
+    return {nullptr, LK_Return};
+
   case InitializedEntity::EK_New:
     //   -- A temporary bound to a reference in a new-initializer persists
     //      until the completion of the full-expression containing the
     //      new-initializer.
-    return nullptr;
+    return {nullptr, LK_New};
 
   case InitializedEntity::EK_Temporary:
   case InitializedEntity::EK_CompoundLiteralInit:
@@ -6246,25 +6287,26 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
     // We don't yet know the storage duration of the surrounding temporary.
     // Assume it's got full-expression duration for now, it will patch up our
     // storage duration if that's not correct.
-    return nullptr;
+    return {nullptr, LK_FullExpression};
 
   case InitializedEntity::EK_ArrayElement:
     // For subobjects, we look at the complete object.
     return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                  FallbackDecl);
+                                                  InitField);
 
   case InitializedEntity::EK_Base:
     // For subobjects, we look at the complete object.
     if (Entity->getParent())
       return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                    Entity);
-    LLVM_FALLTHROUGH;
+                                                    InitField);
+    return {InitField, LK_MemInitializer};
+
   case InitializedEntity::EK_Delegating:
     // We can reach this case for aggregate initialization in a constructor:
     //   struct A { int &&r; };
     //   struct B : A { B() : A{0} {} };
-    // In this case, use the innermost field decl as the context.
-    return FallbackDecl;
+    // In this case, use the outermost field decl as the context.
+    return {InitField, LK_MemInitializer};
 
   case InitializedEntity::EK_BlockElement:
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -6272,30 +6314,54 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_ComplexElement:
-    return nullptr;
+    return {nullptr, LK_FullExpression};
   }
   llvm_unreachable("unknown entity kind");
 }
 
-static void performLifetimeExtension(Expr *Init,
-                                     const InitializedEntity *ExtendingEntity);
+namespace {
+enum ExtensionKind {
+  /// Lifetime would be extended by a reference binding to a temporary.
+  EK_ReferenceBinding,
+  /// Lifetime would be extended by a std::initializer_list object binding to
+  /// its backing array.
+  EK_StdInitializerList,
+};
+using IndirectTemporaryPathEntry =
+    llvm::PointerUnion;
+using IndirectTemporaryPath = llvm::SmallVectorImpl;
+
+struct RevertToOldSizeRAII {
+  IndirectTemporaryPath &Path;
+  unsigned OldSize = Path.size();
+  RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {}
+  ~RevertToOldSizeRAII() { Path.resize(OldSize); }
+};
+}
+
+template 
+static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
+                                                  Expr *Init,
+                                                  TemporaryVisitor Visit);
+
+/// Visit the temporaries whose lifetimes would be extended by binding a
+/// reference to the glvalue expression \c Init.
+template 
+static void
+visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,
+                                           Expr *Init, ExtensionKind EK,
+                                           TemporaryVisitor Visit) {
+  RevertToOldSizeRAII RAII(Path);
 
-/// Update a glvalue expression that is used as the initializer of a reference
-/// to note that its lifetime is extended.
-/// \return \c true if any temporary had its lifetime extended.
-static bool
-performReferenceExtension(Expr *Init,
-                          const InitializedEntity *ExtendingEntity) {
   // Walk past any constructs which we can lifetime-extend across.
   Expr *Old;
   do {
     Old = Init;
 
     if (InitListExpr *ILE = dyn_cast(Init)) {
-      if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
-        // This is just redundant braces around an initializer. Step over it.
+      // If this is just redundant braces around an initializer, step over it.
+      if (ILE->isTransparent())
         Init = ILE->getInit(0);
-      }
     }
 
     // Step over any subobject adjustments; we may have a materialized
@@ -6312,40 +6378,65 @@ performReferenceExtension(Expr *Init,
     // when performing lifetime extension.
     if (auto *ASE = dyn_cast(Init))
       Init = ASE->getBase();
+
+    // Step into CXXDefaultInitExprs so we can diagnose cases where a
+    // constructor inherits one as an implicit mem-initializer.
+    if (auto *DIE = dyn_cast(Init)) {
+      Path.push_back(DIE);
+      Init = DIE->getExpr();
+
+      if (auto *EWC = dyn_cast(Init))
+        Init = EWC->getSubExpr();
+    }
   } while (Init != Old);
 
-  if (MaterializeTemporaryExpr *ME = dyn_cast(Init)) {
-    // Update the storage duration of the materialized temporary.
-    // FIXME: Rebuild the expression instead of mutating it.
-    ME->setExtendingDecl(ExtendingEntity->getDecl(),
-                         ExtendingEntity->allocateManglingNumber());
-    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
-    return true;
+  if (auto *MTE = dyn_cast(Init)) {
+    if (Visit(Path, MTE, EK))
+      visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(),
+                                            Visit);
   }
-
-  return false;
 }
 
-/// Update a prvalue expression that is going to be materialized as a
-/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init,
-                                     const InitializedEntity *ExtendingEntity) {
+/// Visit the temporaries whose lifetimes would be extended by
+/// lifetime-extending the object initialized by the prvalue expression \c
+/// Init.
+template 
+static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
+                                                  Expr *Init,
+                                                  TemporaryVisitor Visit) {
+  RevertToOldSizeRAII RAII(Path);
+
+  // Step into CXXDefaultInitExprs so we can diagnose cases where a
+  // constructor inherits one as an implicit mem-initializer.
+  if (auto *DIE = dyn_cast(Init)) {
+    Path.push_back(DIE);
+    Init = DIE->getExpr();
+
+    if (auto *EWC = dyn_cast(Init))
+      Init = EWC->getSubExpr();
+  }
+
   // Dig out the expression which constructs the extended temporary.
   Init = const_cast(Init->skipRValueSubobjectAdjustments());
 
   if (CXXBindTemporaryExpr *BTE = dyn_cast(Init))
     Init = BTE->getSubExpr();
 
-  if (CXXStdInitializerListExpr *ILE =
-          dyn_cast(Init)) {
-    performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
-    return;
-  }
+  // C++17 [dcl.init.list]p6:
+  //   initializing an initializer_list object from the array extends the
+  //   lifetime of the array exactly like binding a reference to a temporary.
+  if (auto *ILE = dyn_cast(Init))
+    return visitTemporariesExtendedByReferenceBinding(
+        Path, ILE->getSubExpr(), EK_StdInitializerList, Visit);
 
   if (InitListExpr *ILE = dyn_cast(Init)) {
+    if (ILE->isTransparent())
+      return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),
+                                                   Visit);
+
     if (ILE->getType()->isArrayType()) {
       for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
-        performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
+        visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit);
       return;
     }
 
@@ -6357,7 +6448,8 @@ static void performLifetimeExtension(Expr *Init,
       // bound to temporaries, those temporaries are also lifetime-extended.
       if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
           ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
-        performReferenceExtension(ILE->getInit(0), ExtendingEntity);
+        visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0),
+                                                   EK_ReferenceBinding, Visit);
       else {
         unsigned Index = 0;
         for (const auto *I : RD->fields()) {
@@ -6367,13 +6459,13 @@ static void performLifetimeExtension(Expr *Init,
             continue;
           Expr *SubInit = ILE->getInit(Index);
           if (I->getType()->isReferenceType())
-            performReferenceExtension(SubInit, ExtendingEntity);
-          else if (isa(SubInit) ||
-                   isa(SubInit))
-            // This may be either aggregate-initialization of a member or
-            // initialization of a std::initializer_list object. Either way,
+            visitTemporariesExtendedByReferenceBinding(
+                Path, SubInit, EK_ReferenceBinding, Visit);
+          else
+            // This might be either aggregate-initialization of a member or
+            // initialization of a std::initializer_list object. Regardless,
             // we should recursively lifetime-extend that initializer.
-            performLifetimeExtension(SubInit, ExtendingEntity);
+            visitTemporariesExtendedByInitializer(Path, SubInit, Visit);
           ++Index;
         }
       }
@@ -6381,37 +6473,123 @@ static void performLifetimeExtension(Expr *Init,
   }
 }
 
-static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
-                                    const Expr *Init, bool IsInitializerList,
-                                    const ValueDecl *ExtendingDecl) {
-  // Warn if a field lifetime-extends a temporary.
-  if (isa(ExtendingDecl)) {
-    if (IsInitializerList) {
-      S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
-        << /*at end of constructor*/true;
-      return;
+/// Determine whether this is an indirect path to a temporary that we are
+/// supposed to lifetime-extend along (but don't).
+static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) {
+  for (auto Elem : Path) {
+    if (!Elem.is())
+      return false;
+  }
+  return true;
+}
+
+void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
+                                    Expr *Init) {
+  LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);
+  LifetimeKind LK = LR.getInt();
+  const InitializedEntity *ExtendingEntity = LR.getPointer();
+
+  // If this entity doesn't have an interesting lifetime, don't bother looking
+  // for temporaries within its initializer.
+  if (LK == LK_FullExpression)
+    return;
+
+  auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,
+                              MaterializeTemporaryExpr *MTE,
+                              ExtensionKind EK) -> bool {
+    switch (LK) {
+    case LK_FullExpression:
+      llvm_unreachable("already handled this");
+
+    case LK_Extended:
+      // Lifetime-extend the temporary.
+      if (Path.empty()) {
+        // Update the storage duration of the materialized temporary.
+        // FIXME: Rebuild the expression instead of mutating it.
+        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
+                              ExtendingEntity->allocateManglingNumber());
+        // Also visit the temporaries lifetime-extended by this initializer.
+        return true;
+      }
+
+      if (shouldLifetimeExtendThroughPath(Path)) {
+        // We're supposed to lifetime-extend the temporary along this path (per
+        // the resolution of DR1815), but we don't support that yet.
+        //
+        // FIXME: Properly handle this situation. Perhaps the easiest approach
+        // would be to clone the initializer expression on each use that would
+        // lifetime extend its temporaries.
+        Diag(MTE->getExprLoc(),
+             EK == EK_ReferenceBinding
+                 ? diag::warn_default_member_init_temporary_not_extended
+                 : diag::warn_default_member_init_init_list_not_extended);
+      } else {
+        llvm_unreachable("unexpected indirect temporary path");
+      }
+      break;
+
+    case LK_MemInitializer:
+      // Under C++ DR1696, if a mem-initializer (or a default member
+      // initializer used by the absence of one) would lifetime-extend a
+      // temporary, the program is ill-formed.
+      if (auto *ExtendingDecl = ExtendingEntity->getDecl()) {
+        bool IsSubobjectMember = ExtendingEntity != &Entity;
+        Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)
+            << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember
+            << EK;
+        // Don't bother adding a note pointing to the field if we're inside its
+        // default member initializer; our primary diagnostic points to the
+        // same place in that case.
+        if (Path.empty() || !Path.back().is()) {
+          Diag(ExtendingDecl->getLocation(),
+               diag::note_lifetime_extending_member_declared_here)
+              << EK << IsSubobjectMember;
+        }
+      } else {
+        // We have a mem-initializer but no particular field within it; this
+        // is either a base class or a delegating initializer directly
+        // initializing the base-class from something that doesn't live long
+        // enough. Either way, that can't happen.
+        // FIXME: Move CheckForDanglingReferenceOrPointer checks here.
+        llvm_unreachable(
+            "temporary initializer for base class / delegating ctor");
+      }
+      break;
+
+    case LK_New:
+      if (EK == EK_ReferenceBinding) {
+        Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);
+      } else {
+        Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)
+            << (ExtendingEntity != &Entity);
+      }
+      break;
+
+    case LK_Return:
+      // FIXME: Move -Wreturn-stack-address checks here.
+      return false;
     }
 
-    bool IsSubobjectMember = false;
-    for (const InitializedEntity *Ent = Entity.getParent(); Ent;
-         Ent = Ent->getParent()) {
-      if (Ent->getKind() != InitializedEntity::EK_Base) {
-        IsSubobjectMember = true;
-        break;
+    // FIXME: Model these as CodeSynthesisContexts to fix the note emission
+    // order.
+    for (auto Elem : llvm::reverse(Path)) {
+      if (auto *DIE = Elem.dyn_cast()) {
+        Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here)
+            << DIE->getField();
       }
     }
-    S.Diag(Init->getExprLoc(),
-           diag::warn_bind_ref_member_to_temporary)
-      << ExtendingDecl << Init->getSourceRange()
-      << IsSubobjectMember << IsInitializerList;
-    if (IsSubobjectMember)
-      S.Diag(ExtendingDecl->getLocation(),
-             diag::note_ref_subobject_of_member_declared_here);
-    else
-      S.Diag(ExtendingDecl->getLocation(),
-             diag::note_ref_or_ptr_member_declared_here)
-        << /*is pointer*/false;
-  }
+
+    // We didn't lifetime-extend, so don't go any further; we don't need more
+    // warnings or errors on inner temporaries within this one's initializer.
+    return false;
+  };
+
+  llvm::SmallVector Path;
+  if (Init->isGLValue())
+    visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding,
+                                               TemporaryVisitor);
+  else
+    visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);
 }
 
 static void DiagnoseNarrowingInInitList(Sema &S,
@@ -6838,14 +7016,9 @@ InitializationSequence::Perform(Sema &S,
       }
 
       // Even though we didn't materialize a temporary, the binding may still
-      // extend the lifetime of a temporary. This happens if we bind a reference
-      // to the result of a cast to reference type.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(CurInit.get(), ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/false,
-                                  ExtendingEntity->getDecl());
+      // extend the lifetime of a temporary. This happens if we bind a
+      // reference to the result of a cast to reference type.
+      S.checkInitializerLifetime(Entity, CurInit.get());
 
       CheckForNullPointerDereference(S, CurInit.get());
       break;
@@ -6861,23 +7034,17 @@ InitializationSequence::Perform(Sema &S,
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
           Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
+      CurInit = MTE;
 
       // Maybe lifetime-extend the temporary's subobjects to match the
       // entity's lifetime.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(MTE, ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/false,
-                                  ExtendingEntity->getDecl());
+      S.checkInitializerLifetime(Entity, CurInit.get());
 
       // If we're extending this temporary to automatic storage duration -- we
       // need to register its cleanup during the full-expression's cleanups.
       if (MTE->getStorageDuration() == SD_Automatic &&
           MTE->getType().isDestructedType())
         S.Cleanup.setExprNeedsCleanups(true);
-
-      CurInit = MTE;
       break;
     }
 
@@ -7320,18 +7487,13 @@ InitializationSequence::Perform(Sema &S,
           CurInit.get()->getType(), CurInit.get(),
           /*BoundToLvalueReference=*/false);
 
-      // Maybe lifetime-extend the array temporary's subobjects to match the
-      // entity's lifetime.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(MTE, ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/true,
-                                  ExtendingEntity->getDecl());
-
       // Wrap it in a construction of a std::initializer_list.
       CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
 
+      // Maybe lifetime-extend the array temporary's subobjects to match the
+      // entity's lifetime.
+      S.checkInitializerLifetime(Entity, CurInit.get());
+
       // Bind the result, in case the library has given initializer_list a
       // non-trivial destructor.
       if (shouldBindAsTemporary(Entity))
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index b73a94f1db..0cb68c4a97 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -178,29 +178,6 @@ namespace ReferenceInitialization {
     const MyStruct &myStruct(OtherStruct(5));
     myStruct.method(); // no-warning
   }
-
-  struct HasMyStruct {
-    const MyStruct &ms; // expected-note {{reference member declared here}}
-    const MyStruct &msWithCleanups; // expected-note {{reference member declared here}}
-
-    // clang's Sema issues a warning when binding a reference member to a
-    // temporary value.
-    HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {
-        // expected-warning@-1 {{binding reference member 'ms' to a temporary value}}
-        // expected-warning@-2 {{binding reference member 'msWithCleanups' to a temporary value}}
-
-      // At this point the members are not garbage so we should not expect an
-      // analyzer warning here even though binding a reference member
-      // to a member is a terrible idea.
-      ms.method(); // no-warning
-      msWithCleanups.method(); // no-warning
-    }
-  };
-
-  void referenceInitializeField() {
-    HasMyStruct hms;
-  }
-
 };
 
 namespace PR31592 {
diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp
index e0af95ac39..54648cfe96 100644
--- a/test/CXX/drs/dr16xx.cpp
+++ b/test/CXX/drs/dr16xx.cpp
@@ -9,6 +9,20 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+#if __cplusplus >= 201103L
+namespace std {
+  typedef decltype(sizeof(int)) size_t;
+
+  template class initializer_list {
+    const E *begin;
+    size_t size;
+
+  public:
+    initializer_list();
+  };
+} // std
+#endif
+
 namespace dr1611 { // dr1611: dup 1658
   struct A { A(int); };
   struct B : virtual A { virtual void f() = 0; };
@@ -269,3 +283,83 @@ namespace dr1687 { // dr1687: 7
   auto c = To() <=> To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}}
 #endif
 }
+
+namespace dr1696 { // dr1696: 7
+  namespace std_examples {
+#if __cplusplus >= 201402L
+    extern struct A a;
+    struct A {
+      const A &x = { A{a, a} };
+      const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}}
+    };
+    A a{a, a};
+#endif
+  }
+
+  struct A { A(); ~A(); };
+#if __cplusplus >= 201103L
+  struct B {
+    A &&a; // expected-note {{declared here}}
+    B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
+  } b;
+#endif
+
+  struct C {
+    C();
+    const A &a; // expected-note {{declared here}}
+  };
+  C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
+
+#if __cplusplus >= 201103L
+  // This is OK in C++14 onwards, per DR1815, though we don't support that yet:
+  //   D1 d1 = {};
+  // is equivalent to
+  //   D1 d1 = {A()};
+  // ... which lifetime-extends the A temporary.
+  struct D1 {
+    const A &a = A();
+#if __cplusplus < 201402L
+    // expected-error@-2 {{binds to a temporary}}
+    // expected-note@-4 {{here}}
+#else
+    // expected-warning-re@-5 {{sorry, lifetime extension {{.*}} not supported}}
+#endif
+  };
+  D1 d1 = {}; // expected-note {{here}}
+
+  struct D2 {
+    const A &a = A(); // expected-error {{binds to a temporary}}
+    D2() {} // expected-note {{used here}}
+  };
+
+  struct D3 { // expected-note {{used here}}
+    const A &a = A(); // expected-error {{binds to a temporary}}
+  };
+  D3 d3; // expected-note {{first required here}}
+
+  struct haslist1 {
+    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
+    haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+  };
+
+  struct haslist2 {
+    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
+    haslist2();
+  };
+  haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+
+  struct haslist3 {
+    std::initializer_list il = {1, 2, 3};
+  };
+
+  struct haslist4 { // expected-note {{in default member initializer}}
+    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+  };
+  haslist4 hl4; // expected-note {{in implicit default constructor}}
+
+  struct haslist5 {
+    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+    haslist5() {} // expected-note {{in default member initializer}}
+  };
+#endif
+}
diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp
index a0f470ed4a..f6a4676bc7 100644
--- a/test/CXX/drs/dr18xx.cpp
+++ b/test/CXX/drs/dr18xx.cpp
@@ -30,6 +30,17 @@ namespace dr1813 { // dr1813: 7
   static_assert(!__is_standard_layout(U), "");
 }
 
+namespace dr1815 { // dr1815: no
+#if __cplusplus >= 201402L
+  // FIXME: needs codegen test
+  struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}}
+  A a = {}; // expected-note {{here}}
+
+  struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{here}}
+  B b; // expected-note {{here}}
+#endif
+}
+
 namespace dr1881 { // dr1881: 7
   struct A { int a : 4; };
   struct B : A { int b : 3; };
diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp
index 1ca0143d09..a4d0cdcdc7 100644
--- a/test/CXX/special/class.copy/p11.0x.copy.cpp
+++ b/test/CXX/special/class.copy/p11.0x.copy.cpp
@@ -121,13 +121,22 @@ extern HasNoAccessDtorBase HNADBa;
 HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
 
 // -- a non-static data member of rvalue reference type
+int some_int;
 struct RValue {
-  int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
-  // expected-warning@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}}
+  int && ri = static_cast(some_int); // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
 };
 RValue RVa;
 RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
 
+// FIXME: The note on the class-name is attached to the location of the
+// constructor. This is not especially clear.
+struct RValueTmp { // expected-note {{used here}}
+  int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
+  // expected-error@-1 {{reference member 'ri' binds to a temporary}}
+};
+RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}}
+RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}}
+
 namespace PR13381 {
   struct S {
     S(const S&);
diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp
index ab4259548e..5b016836e9 100644
--- a/test/CXX/special/class.copy/p11.0x.move.cpp
+++ b/test/CXX/special/class.copy/p11.0x.move.cpp
@@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c
 // The restriction on rvalue reference members applies to only the copy
 // constructor.
 struct RValue {
-  int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
+  int &&ri = 1;
   RValue(RValue&&);
 };
 RValue::RValue(RValue&&) = default;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index 2360345a48..5558313ce7 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -43,8 +43,12 @@ class NotDeleted2a { int &a = n; };
 NotDeleted2a nd2a;
 class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
 NotDeleted2b nd2b;
-class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}
+class NotDeleted2c { int &&a = static_cast(n); };
 NotDeleted2c nd2c;
+// Note: this one does not have a deleted default constructor even though the
+// implicit default constructor is ill-formed!
+class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{here}}
+NotDeleted2d nd2d; // expected-note {{first required here}}
 
 // - any non-variant non-static data member of const qualified type (or array
 // thereof) with no brace-or-equal-initializer does not have a user-provided
diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp
index aa0d7e92b9..de902a5e4d 100644
--- a/test/CXX/temp/temp.param/p5.cpp
+++ b/test/CXX/temp/temp.param/p5.cpp
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -verify %s -std=c++14
 
-template struct S {
+template struct S { // expected-note {{in default member initializer}}
   decltype(I) n;
-  int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}
+  int &&r = I; // expected-error {{reference member 'r' binds to a temporary object}}
 };
-S<5> s; // expected-note {{instantiation}}
+S<5> s; // expected-note {{implicit default constructor}}
 
-template struct U {
+template struct U { // expected-note {{in default member initializer}}
   decltype(v) n;
-  int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}
+  int &&r = v; // expected-error {{reference member 'r' binds to a temporary object}}
 };
-U u; // expected-note {{instantiation}}
+U u; // expected-note {{implicit default constructor}}
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 3299763997..0184a1d6e7 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -236,36 +236,6 @@ void fn9() {
   // CHECK: ret void
 }
 
-struct haslist1 {
-  std::initializer_list il;
-  haslist1(int i);
-};
-
-// CHECK-LABEL: define void @_ZN8haslist1C2Ei
-haslist1::haslist1(int i)
-// CHECK: alloca [3 x i32]
-// CHECK: store i32 %
-// CHECK: store i32 2
-// CHECK: store i32 3
-  : il{i, 2, 3}
-{
-  destroyme2 dm2;
-}
-
-struct haslist2 {
-  std::initializer_list il;
-  haslist2();
-};
-
-// CHECK-LABEL: define void @_ZN8haslist2C2Ev
-haslist2::haslist2()
-  : il{destroyme1(), destroyme1()}
-{
-  destroyme2 dm2;
-  // CHECK: call void @_ZN10destroyme2D1Ev
-  // CHECK: call void @_ZN10destroyme1D1Ev
-}
-
 void fn10(int i) {
   // CHECK-LABEL: define void @_Z4fn10i
   // CHECK: alloca [3 x i32]
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index bad51ba353..21372effbc 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -198,20 +198,6 @@ B::B()
   f();
 }
   
-struct C {
-  C();
-  
-  const B& b;
-};
-
-C::C() 
-  // CHECK: call void @_ZN6PR50771BC1Ev
-  : b(B()) {
-  // CHECK: call void @_ZN6PR50771fEv
-  f();
-  
-  // CHECK: call void @_ZN6PR50771BD1Ev
-}
 }
 
 A f8() {
@@ -816,16 +802,3 @@ namespace PR14130 {
   // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
   // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
 }
-
-namespace Ctor {
-  struct A { A(); ~A(); };
-  void f();
-  struct B {
-    A &&a;
-    B() : a{} { f(); }
-  } b;
-  // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
-  // CHECK: call void @_ZN4Ctor1AC1Ev(
-  // CHECK: call void @_ZN4Ctor1fEv(
-  // CHECK: call void @_ZN4Ctor1AD1Ev(
-}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 4b4bd43634..e921634b1b 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1892,14 +1892,15 @@ namespace Lifetime {
   }
 
   constexpr int &get(int &&n) { return n; }
+  constexpr int &&get_rv(int &&n) { return static_cast(n); }
   struct S {
-    int &&r; // expected-note 2{{declared here}}
+    int &&r;
     int &s;
     int t;
-    constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}}
-    constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}}
+    constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}
+    constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}
   };
-  constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor
+  constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}
   constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
 }
 
diff --git a/test/SemaCXX/constexpr-default-arg.cpp b/test/SemaCXX/constexpr-default-arg.cpp
index 2fc873c3e5..165c31aab6 100644
--- a/test/SemaCXX/constexpr-default-arg.cpp
+++ b/test/SemaCXX/constexpr-default-arg.cpp
@@ -31,8 +31,8 @@ void test_default_arg2() {
 }
 
 // Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
-struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}}
+struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
 struct B { A x, y; };
-B b = {};
+B b = {}; // expected-note 2{{in default member initializer for field 'r' used here}}
 
 }
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index 860a4aa6c6..ece014d93a 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -153,13 +153,14 @@ void dangle() {
 }
 
 struct haslist1 {
-  std::initializer_list il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
-  std::initializer_list jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
+  std::initializer_list il // expected-note {{declared here}}
+    = {1, 2, 3}; // ok, unused
+  std::initializer_list jl{1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}
   haslist1();
 };
 
-haslist1::haslist1()
-: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
+haslist1::haslist1() // expected-note {{used here}}
+: il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
 {}
 
 namespace PR12119 {
diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp
index 23946845d8..33bde75de6 100644
--- a/test/SemaCXX/eval-crashes.cpp
+++ b/test/SemaCXX/eval-crashes.cpp
@@ -26,10 +26,10 @@ namespace pr33140_0b {
 
 namespace pr33140_2 {
   // FIXME: The declaration of 'b' below should lifetime-extend two int
-  // temporaries, invalidating this warning to some extent.
-  struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}}
+  // temporaries.
+  struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
   struct B { A x, y; };
-  B b = {};
+  B b = {}; // expected-note 2{{used here}}
 }
 
 namespace pr33140_3 {
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index ad4a8f15b2..8a13eca2f1 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -86,9 +86,8 @@ namespace PR14838 {
   };
   struct thing {};
   struct another {
-    another() : r(thing()) {}
+    another() : r(thing()) {} // expected-error {{binds to a temporary object}}
     // expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}}
-    // expected-warning@-2 {{binding reference member 'r' to a temporary value}}
     const function &r; // expected-note {{reference member declared here}}
   } af;
 }
diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp
index eb65bd0669..97d4331c1f 100644
--- a/test/SemaCXX/warn-dangling-field.cpp
+++ b/test/SemaCXX/warn-dangling-field.cpp
@@ -20,7 +20,7 @@ struct S {
 
 struct S2 {
   const X &x; // expected-note {{reference member declared here}}
-  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}
+  S2(int i) : x(i) {} // expected-error {{member 'x' binds to a temporary}}
 };
 
 struct S3 {
@@ -43,9 +43,9 @@ S5 s5 = { 0 }; // ok, lifetime-extended
 
 struct S6 {
   S5 s5; // expected-note {{here}}
-  S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}
+  S6() : s5 { 0 } {} // expected-error {{reference subobject of member 's5' binds to a temporary}}
 };
 
 struct S7 : S5 {
-  S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}
+  S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}}
 };
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index 93d4ee93fb..04dd0eae1c 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -9991,7 +9991,7 @@ and POD class
     1696
     CD4
     Temporary lifetime and non-static data member initializers
-    Unknown
+    SVN
   
   
     1697
@@ -10705,7 +10705,7 @@ and POD class
     1815
     CD4
     Lifetime extension in aggregate initialization
-    Unknown
+    No
   
   
     1816
-- 
GitLab


From 7ba800497502025d63e18a62d295af6c7971f492 Mon Sep 17 00:00:00 2001
From: Artem Dergachev 
Date: Tue, 17 Jul 2018 00:22:27 +0000
Subject: [PATCH 0567/1023] [analyzer] Assert that nonloc::SymbolVal always
 wraps a non-Loc-type symbol.

In the current SVal hierarchy there are multiple ways of representing certain
values but few are actually used and expected to be seen by the code.

In particular, a value of a symbolic pointer is always represented by a
loc::MemRegionVal that wraps a SymbolicRegion that wraps the pointer symbol
and never by a nonloc::SymbolVal that wraps that symbol directly.

Assert the aforementioned fact. Fix one minor violation of it.

Differential Revision: https://reviews.llvm.org/D48205


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337227 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h | 7 +++++--
 lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp           | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index f3f2aa3f8f..0fde63e9eb 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -343,11 +343,14 @@ private:
 
 namespace nonloc {
 
-/// Represents symbolic expression.
+/// Represents symbolic expression that isn't a location.
 class SymbolVal : public NonLoc {
 public:
   SymbolVal() = delete;
-  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); }
+  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {
+    assert(sym);
+    assert(!Loc::isLocType(sym->getType()));
+  }
 
   SymbolRef getSymbol() const {
     return (const SymExpr *) Data;
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index a73ffd6ec1..c08cbb09ba 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1238,7 +1238,7 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
 
     SVal VisitSymbolData(const SymbolData *S) {
       if (const llvm::APSInt *I =
-              SVB.getKnownValue(State, nonloc::SymbolVal(S)))
+              SVB.getKnownValue(State, SVB.makeSymbolVal(S)))
         return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
                                             : (SVal)SVB.makeIntVal(*I);
       return SVB.makeSymbolVal(S);
-- 
GitLab


From bf89e7dc6e314c1da0a1fd0c1ac732a774873268 Mon Sep 17 00:00:00 2001
From: Artem Dergachev 
Date: Tue, 17 Jul 2018 00:42:35 +0000
Subject: [PATCH 0568/1023] [analyzer] pr37802: Fix symbolic-pointer-to-boolean
 casts during load.

The canonical representation of pointer &SymRegion{$x} casted to boolean is
"$x != 0", not "$x". Assertion added in r337227 catches that.

Differential Revision: https://reviews.llvm.org/D48232


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337228 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp |   3 +-
 test/Analysis/casts.cpp                       |   6 +
 test/Analysis/pr37802.cpp                     | 106 ++++++++++++++++++
 3 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 test/Analysis/pr37802.cpp

diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index c08cbb09ba..7163e380e6 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -159,7 +159,8 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
               return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));
 
         if (const SymbolicRegion *SymR = R->getSymbolicBase())
-          return nonloc::SymbolVal(SymR->getSymbol());
+          return makeNonLoc(SymR->getSymbol(), BO_NE,
+                            BasicVals.getZeroWithPtrWidth(), castTy);
 
         // FALL-THROUGH
         LLVM_FALLTHROUGH;
diff --git a/test/Analysis/casts.cpp b/test/Analysis/casts.cpp
index 6499b20a79..757eb6da66 100644
--- a/test/Analysis/casts.cpp
+++ b/test/Analysis/casts.cpp
@@ -35,3 +35,9 @@ int *&&castToIntPtrRValueRef(char *p) {
 bool testCastToIntPtrRValueRef(char *p, int *s) {
   return castToIntPtrRValueRef(p) != s; // no-crash
 }
+
+bool retrievePointerFromBoolean(int *p) {
+  bool q;
+  *reinterpret_cast(&q) = p;
+  return q;
+}
diff --git a/test/Analysis/pr37802.cpp b/test/Analysis/pr37802.cpp
new file mode 100644
index 0000000000..647e389362
--- /dev/null
+++ b/test/Analysis/pr37802.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -verify %s
+
+// expected-no-diagnostics
+
+void *operator new(unsigned long, void *h) { return h; }
+
+// I've no idea what this code does, but it used to crash, so let's keep it.
+namespace pr37802_v1 {
+struct J {
+  int *p;
+};
+class X {
+  void *ar;
+
+public:
+  X(void *t) : ar(t) {}
+  template 
+  void f(const T &t) {
+    new (ar) T(t);
+  }
+};
+class Y {
+public:
+  template 
+  void f(T &&);
+  void f(J t) {
+    f(*t.p);
+  }
+};
+class Z {
+  int at() const {}
+
+public:
+  Z(const Z &other) {
+    other.au(X(this));
+  }
+  template 
+  void au(T t) const {
+    void *c = const_cast(this);
+    if (at()) {
+      t.f(*static_cast(c));
+    } else {
+      t.f(*static_cast(c));
+    }
+  }
+};
+Z g() {
+  Z az = g();
+  Z e = az;
+  Y d;
+  e.au(d);
+}
+} // namespace pr37802_v1
+
+
+// This slightly modified code crashed differently.
+namespace pr37802_v2 {
+struct J {
+  int *p;
+};
+
+class X {
+  void *ar;
+
+public:
+  X(void *t) : ar(t) {}
+  void f(const J &t) { new (ar) J(t); }
+  void f(const bool &t) { new (ar) bool(t); }
+};
+
+class Y {
+public:
+  void boolf(bool &&);
+  void f(J &&);
+  void f(J t) { boolf(*t.p); }
+};
+
+class Z {
+  int at() const {}
+
+public:
+  Z(const Z &other) { other.au(X(this)); }
+  void au(X t) const {
+    void *c = const_cast(this);
+    if (at()) {
+      t.f(*static_cast(c));
+    } else {
+      t.f(*static_cast(c));
+    }
+  }
+  void au(Y t) const {
+    void *c = const_cast(this);
+    if (at()) {
+      t.f(*static_cast(c));
+    } else {
+    }
+  }
+};
+
+Z g() {
+  Z az = g();
+  Z e = az;
+  Y d;
+  e.au(d);
+}
+} // namespace pr37802_v2
-- 
GitLab


From cfb8e36efb59fe347b21633166082c3c8328a727 Mon Sep 17 00:00:00 2001
From: Artem Dergachev 
Date: Tue, 17 Jul 2018 00:57:57 +0000
Subject: [PATCH 0569/1023] [CFG] [analyzer] Allow elidable copies to have more
 than one arguments.

Copy-constructors and move-constructors may have default arguments. It is
incorrect to assert that they only have one argument, i.e. the reference to the
object being copied or moved. Remove the assertion.

Differential Revision: https://reviews.llvm.org/D49215


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337229 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Analysis/CFG.cpp                    |  1 -
 test/Analysis/cfg-rich-constructors.cpp | 23 +++++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 62803f4ba5..b895087e51 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1263,7 +1263,6 @@ void CFGBuilder::findConstructionContexts(
     // Support pre-C++17 copy elision AST.
     auto *CE = cast(Child);
     if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
-      assert(CE->getNumArgs() == 1);
       findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
     }
 
diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp
index 3944141b92..ce3e5f84ba 100644
--- a/test/Analysis/cfg-rich-constructors.cpp
+++ b/test/Analysis/cfg-rich-constructors.cpp
@@ -878,3 +878,26 @@ void passArgumentWithDestructorByReference() {
   useDByReference(D());
 }
 } // end namespace argument_constructors
+
+namespace copy_elision_with_extra_arguments {
+class C {
+public:
+  C();
+  C(const C &c, int x = 0);
+};
+
+// CHECK: void testCopyElisionWhenCopyConstructorHasExtraArguments()
+// CHECK:        [B1]
+// CXX11-ELIDE-NEXT:     1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.3], [B1.5], class copy_elision_with_extra_arguments::C)
+// CXX11-NOELIDE-NEXT:     1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.3], class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT:     2: [B1.1] (ImplicitCastExpr, NoOp, const class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT:     3: [B1.2]
+// CXX11-NEXT:     4:
+// CXX11-NEXT:     5: [B1.3] (CXXConstructExpr, [B1.6], class copy_elision_with_extra_arguments::C)
+// CXX11-NEXT:     6: copy_elision_with_extra_arguments::C c = copy_elision_with_extra_arguments::C();
+// CXX17-NEXT:     1: copy_elision_with_extra_arguments::C() (CXXConstructExpr, [B1.2], class copy_elision_with_extra_arguments::C)
+// CXX17-NEXT:     2: copy_elision_with_extra_arguments::C c = copy_elision_with_extra_arguments::C();
+void testCopyElisionWhenCopyConstructorHasExtraArguments() {
+  C c = C();
+}
+} // namespace copy_elision_with_extra_arguments
-- 
GitLab


From d564b220e7a941b24f07708241f065dfee99b95e Mon Sep 17 00:00:00 2001
From: Artem Dergachev 
Date: Tue, 17 Jul 2018 01:39:25 +0000
Subject: [PATCH 0570/1023] [analyzer] Fix size_t in tests.

Should fix a buildbot. No functional change intended.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337231 91177308-0d34-0410-b5e6-96231b3b80d8
---
 test/Analysis/pr37802.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/test/Analysis/pr37802.cpp b/test/Analysis/pr37802.cpp
index 647e389362..9acfebaae8 100644
--- a/test/Analysis/pr37802.cpp
+++ b/test/Analysis/pr37802.cpp
@@ -2,7 +2,8 @@
 
 // expected-no-diagnostics
 
-void *operator new(unsigned long, void *h) { return h; }
+typedef __typeof(sizeof(int)) size_t;
+void *operator new(size_t, void *h) { return h; }
 
 // I've no idea what this code does, but it used to crash, so let's keep it.
 namespace pr37802_v1 {
-- 
GitLab


From e9dc5a4b17dadc764e5fe516128807803c1bc2a4 Mon Sep 17 00:00:00 2001
From: Jacob Bandes-Storch 
Date: Tue, 17 Jul 2018 04:56:22 +0000
Subject: [PATCH 0571/1023] [Driver] Add -fno-digraphs

Summary: Add a flag `-fno-digraphs` to disable digraphs in the lexer, similar to `-fno-operator-names` which disables alternative names for C++ operators.

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: rsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D48266

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337232 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Driver/Options.td     |  4 ++++
 lib/Driver/ToolChains/Clang.cpp     |  1 +
 lib/Frontend/CompilerInvocation.cpp |  2 ++
 test/Lexer/digraph.c                | 23 +++++++++++++++++++++--
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 5a7e5c9e4e..9035a91ce2 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -1335,6 +1335,10 @@ def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">,
 def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group;
 def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
     Flags<[CC1Option]>, Group;
+def fdigraphs : Flag<["-"], "fdigraphs">, Group, Flags<[CC1Option]>,
+  HelpText<"Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)">;
+def fno_digraphs : Flag<["-"], "fno-digraphs">, Group, Flags<[CC1Option]>,
+  HelpText<"Disallow alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:'">;
 def fno_declspec : Flag<["-"], "fno-declspec">, Group,
   HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
 def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group,
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 472a4163e5..853f9a422f 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -3925,6 +3925,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // Forward -f (flag) options which we can pass directly.
   Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
   Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
+  Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
   Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
   Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
                   options::OPT_fno_emulated_tls);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index f57f23a0d4..d62429dc78 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -2173,6 +2173,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
                                   Opts.GNUKeywords);
 
+  Opts.Digraphs = Args.hasFlag(OPT_fdigraphs, OPT_fno_digraphs, Opts.Digraphs);
+
   if (Args.hasArg(OPT_fno_operator_names))
     Opts.CXXOperatorNames = 0;
 
diff --git a/test/Lexer/digraph.c b/test/Lexer/digraph.c
index e940caf44f..5d8a77d539 100644
--- a/test/Lexer/digraph.c
+++ b/test/Lexer/digraph.c
@@ -1,6 +1,13 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -DDIGRAPHS=1 -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -DDIGRAPHS=1 -fno-digraphs -fdigraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -fdigraphs -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -std=c89 -DDIGRAPHS=1 -fdigraphs -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -std=c89 -fno-digraphs -fsyntax-only -verify -ffreestanding %s
+
+#if DIGRAPHS
 
+// expected-no-diagnostics
 %:include 
 
     %:ifndef BUFSIZE
@@ -14,3 +21,15 @@
             d<:len:> = s<:len:>;
         %>
     %>
+#else
+
+// expected-error@+1 {{expected identifier or '('}}
+%:include 
+;
+// expected-error@+1 {{expected ')'}} expected-note@+1{{to match this '('}}
+void copy(char d<::>);
+
+// expected-error@+1 {{expected function body}}
+void copy() <% %>
+
+#endif
-- 
GitLab


From de3003c4189d27f04678d5295dd6b4d4700f7d3f Mon Sep 17 00:00:00 2001
From: Roman Lebedev 
Date: Tue, 17 Jul 2018 07:12:08 +0000
Subject: [PATCH 0572/1023] Harden/relax clang/test/CodeGen/opt-record-MIR.c
 test

Summary:
If the build path is short, `Line` field can end up fitting on the same line as `File`,
but the `{{.*}}` would consume it. Keeping in mind rL293149, i think we can fix it,
while keeping it working when there are and there are not any quotations.
At least this fixes this test for me.

Reviewers: anemet, aaron.ballman, hfinkel

Reviewed By: anemet

Subscribers: cfe-commits, llvm-commits

Differential Revision: https://reviews.llvm.org/D49348

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337249 91177308-0d34-0410-b5e6-96231b3b80d8
---
 test/CodeGen/opt-record-MIR.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/test/CodeGen/opt-record-MIR.c b/test/CodeGen/opt-record-MIR.c
index 00b91ffdf3..37239281e9 100644
--- a/test/CodeGen/opt-record-MIR.c
+++ b/test/CodeGen/opt-record-MIR.c
@@ -21,8 +21,9 @@ void foo(float *p, int i) {
 // YAML: --- !Missed
 // YAML: Pass:            regalloc
 // YAML: Name:            LoopSpillReload
-// YAML: DebugLoc:        { File: {{.*}},
-// YAML:                    Line: 10, Column: 11 }
+// YAML: DebugLoc:        { File: {{[^,]+}},
+// YAML:                    Line: 10,
+// YAML:                    Column: 11 }
 // YAML: Function:        foo
 // YAML: Args:
 // YAML:   - NumSpills:       '{{.}}'
-- 
GitLab


From 28deda3b5839098b427e528ad93bcfa434806a74 Mon Sep 17 00:00:00 2001
From: Florian Hahn 
Date: Tue, 17 Jul 2018 09:23:31 +0000
Subject: [PATCH 0573/1023] Temporarily revert r337226 "Restructure checking
 for, and warning on, lifetime extension."

This change breaks on ARM because pointers to clang::InitializedEntity are only
4 byte aligned and do not have 3 bits to store values. A possible solution
would be to change the fields in clang::InitializedEntity to enforce a bigger
alignment requirement.

The error message is

llvm/include/llvm/ADT/PointerIntPair.h:132:3: error: static_assert failed "PointerIntPair with integer size too large for pointer"
  static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
include/llvm/ADT/PointerIntPair.h:73:13: note: in instantiation of template class 'llvm::PointerIntPairInfo >' requested here
    Value = Info::updateInt(Info::updatePointer(0, PtrVal),
llvm/include/llvm/ADT/PointerIntPair.h:51:5: note: in instantiation of member function 'llvm::PointerIntPair, llvm::PointerIntPairInfo > >::setPointerAndInt' requested here
    setPointerAndInt(PtrVal, IntVal);
    ^
llvm/tools/clang/lib/Sema/SemaInit.cpp:6237:12: note: in instantiation of member function 'llvm::PointerIntPair, llvm::PointerIntPairInfo > >::PointerIntPair' requested here
    return {Entity, LK_Extended};

Full log here:
http://lab.llvm.org:8011/builders/clang-cmake-armv7-global-isel/builds/1330
http://lab.llvm.org:8011/builders/clang-cmake-armv7-full/builds/1394




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337255 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticGroups.td       |   1 -
 include/clang/Basic/DiagnosticSemaKinds.td    |  40 +-
 include/clang/Sema/Initialization.h           |  34 +-
 include/clang/Sema/Sema.h                     |   5 -
 lib/Sema/SemaDeclCXX.cpp                      |   7 +-
 lib/Sema/SemaExprCXX.cpp                      |   7 +
 lib/Sema/SemaInit.cpp                         | 370 +++++-------------
 test/Analysis/initializer.cpp                 |  23 ++
 test/CXX/drs/dr16xx.cpp                       |  94 -----
 test/CXX/drs/dr18xx.cpp                       |  11 -
 test/CXX/special/class.copy/p11.0x.copy.cpp   |  13 +-
 test/CXX/special/class.copy/p11.0x.move.cpp   |   2 +-
 test/CXX/special/class.ctor/p5-0x.cpp         |   6 +-
 test/CXX/temp/temp.param/p5.cpp               |  12 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |  30 ++
 test/CodeGenCXX/temporaries.cpp               |  27 ++
 test/SemaCXX/constant-expression-cxx11.cpp    |   9 +-
 test/SemaCXX/constexpr-default-arg.cpp        |   4 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |   9 +-
 test/SemaCXX/eval-crashes.cpp                 |   6 +-
 test/SemaCXX/member-init.cpp                  |   3 +-
 test/SemaCXX/warn-dangling-field.cpp          |   6 +-
 www/cxx_dr_status.html                        |   4 +-
 23 files changed, 240 insertions(+), 483 deletions(-)

diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index e27dc0d764..e021cf6975 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -272,7 +272,6 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
 def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
 def DanglingElse: DiagGroup<"dangling-else">;
 def DanglingField : DiagGroup<"dangling-field">;
-def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
 def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
 def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
 def FlagEnum : DiagGroup<"flag-enum">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index acfdd260cd..c32b5ea07a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2049,6 +2049,10 @@ def err_implied_std_initializer_list_not_found : Error<
   "not found; include ">;
 def err_malformed_std_initializer_list : Error<
   "std::initializer_list must be a class template with a single type parameter">;
+def warn_dangling_std_initializer_list : Warning<
+  "array backing the initializer list will be destroyed at the end of "
+  "%select{the full-expression|the constructor}0">,
+  InGroup>;
 def err_auto_init_list_from_c : Error<
   "cannot use __auto_type with initializer list in C">;
 def err_auto_bitfield : Error<
@@ -7840,39 +7844,13 @@ def warn_bind_ref_member_to_parameter : Warning<
 def warn_init_ptr_member_to_parameter_addr : Warning<
   "initializing pointer member %0 with the stack address of parameter %1">,
   InGroup;
+def warn_bind_ref_member_to_temporary : Warning<
+  "binding reference %select{|subobject of }1member %0 to a temporary value">,
+  InGroup;
 def note_ref_or_ptr_member_declared_here : Note<
   "%select{reference|pointer}0 member declared here">;
-
-def err_bind_ref_member_to_temporary : Error<
-  "%select{reference|backing array for 'std::initializer_list'}2 "
-  "%select{|subobject of }1member %0 "
-  "%select{binds to|is}2 a temporary object "
-  "whose lifetime would be shorter than the constructed object">;
-def note_lifetime_extending_member_declared_here : Note<
-  "%select{%select{reference|'std::initializer_list'}0 member|"
-  "member with %select{reference|'std::initializer_list'}0 subobject}1 "
-  "declared here">;
-def warn_new_dangling_reference : Warning<
-  "temporary bound to reference member of allocated object "
-  "will be destroyed at the end of the full-expression">,
-  InGroup;
-def warn_new_dangling_initializer_list : Warning<
-  "array backing "
-  "%select{initializer list subobject of the allocated object|"
-  "the allocated initializer list}0 "
-  "will be destroyed at the end of the full-expression">,
-  InGroup;
-def warn_default_member_init_temporary_not_extended : Warning<
-  "sorry, lifetime extension of temporary created by aggregate initialization "
-  "using default member initializer is not supported; lifetime of temporary "
-  "will end at the end of the full-expression">, InGroup;
-def warn_default_member_init_init_list_not_extended : Warning<
-  "sorry, lifetime extension of backing array of initializer list "
-  "created by aggregate initialization using default member initializer "
-  "is not supported; lifetime of backing array will end at the end of the "
-  "full-expression">, InGroup;
-def note_in_default_member_initalizer_here : Note<
-  "in default member initializer for field %0 used here">;
+def note_ref_subobject_of_member_declared_here : Note<
+  "member with reference subobject declared here">;
 
 // For non-floating point, expressions of the form x == x or x != x
 // should result in a warning, since these always evaluate to a constant.
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 774a2c9ff9..1e6423c99d 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -63,7 +63,7 @@ public:
     /// is being thrown.
     EK_Exception,
 
-    /// The entity being initialized is a non-static data member
+    /// The entity being initialized is a non-static data member 
     /// subobject.
     EK_Member,
 
@@ -123,7 +123,7 @@ public:
     // enum as an index for its first %select.  When modifying this list,
     // that diagnostic text needs to be updated as well.
   };
-
+  
 private:
   /// The kind of entity being initialized.
   EntityKind Kind;
@@ -158,10 +158,6 @@ private:
     /// initialization in a copy or move constructor. These can perform array
     /// copies.
     bool IsImplicitFieldInit;
-
-    /// When Kind == EK_Member, whether this is the initial initialization
-    /// check for a default member initializer.
-    bool IsDefaultMemberInit;
   };
 
   struct C {
@@ -207,7 +203,7 @@ private:
 
   /// Create the initialization entity for a variable.
   InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
-      : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
+      : Kind(EK), Type(Var->getType()), Variable{Var, false} {}
   
   /// Create the initialization entity for the result of a
   /// function, throwing an object, performing an explicit cast, or
@@ -221,9 +217,9 @@ private:
   
   /// Create the initialization entity for a member subobject.
   InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
-                    bool Implicit, bool DefaultMemberInit)
+                    bool Implicit) 
       : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
-        Variable{Member, Implicit, DefaultMemberInit} {}
+        Variable{Member, Implicit} {}
   
   /// Create the initialization entity for an array element.
   InitializedEntity(ASTContext &Context, unsigned Index, 
@@ -343,27 +339,21 @@ public:
   static InitializedEntity InitializeDelegation(QualType Type) {
     return InitializedEntity(EK_Delegating, SourceLocation(), Type);
   }
-
+  
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(FieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member, Parent, Implicit, false);
+    return InitializedEntity(Member, Parent, Implicit);
   }
-
+  
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(IndirectFieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
-  }
-
-  /// Create the initialization entity for a default member initializer.
-  static InitializedEntity
-  InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
-    return InitializedEntity(Member, nullptr, false, true);
+    return InitializedEntity(Member->getAnonField(), Parent, Implicit);
   }
 
   /// Create the initialization entity for an array element.
@@ -463,12 +453,6 @@ public:
     return getKind() == EK_Member && Variable.IsImplicitFieldInit;
   }
 
-  /// Is this the default member initializer of a member (specified inside
-  /// the class definition)?
-  bool isDefaultMemberInitializer() const {
-    return getKind() == EK_Member && Variable.IsDefaultMemberInit;
-  }
-
   /// Determine the location of the 'return' keyword when initializing
   /// the result of a function call.
   SourceLocation getReturnLoc() const {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f13e423cef..2425dff005 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2582,11 +2582,6 @@ public:
                                                  NamedDecl *FoundDecl,
                                                  CXXMethodDecl *Method);
 
-  /// Check that the lifetime of the initializer (and its subobjects) is
-  /// sufficient for initializing the entity, and perform lifetime extension
-  /// (when permitted) if not.
-  void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
-
   ExprResult PerformContextuallyConvertToBool(Expr *From);
   ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index eda6e16195..63d01c9d85 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3621,8 +3621,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
 
   ExprResult Init = InitExpr;
   if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
-    InitializedEntity Entity =
-        InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
+    InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
     InitializationKind Kind =
         FD->getInClassInitStyle() == ICIS_ListInit
             ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
@@ -4647,10 +4646,6 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
         SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
     if (DIE.isInvalid())
       return true;
-
-    auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
-    SemaRef.checkInitializerLifetime(Entity, DIE.get());
-
     CXXCtorInitializer *Init;
     if (Indirect)
       Init = new (SemaRef.Context)
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index a7ad8e322d..fbf572e398 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1864,6 +1864,13 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
   if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
     return ExprError();
 
+  if (initStyle == CXXNewExpr::ListInit &&
+      isStdInitializerList(AllocType, nullptr)) {
+    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
+         diag::warn_dangling_std_initializer_list)
+        << /*at end of FE*/0 << Inits[0]->getSourceRange();
+  }
+
   // In ARC, infer 'retaining' for the allocated
   if (getLangOpts().ObjCAutoRefCount &&
       AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index f94eabd671..320d93a99a 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -572,7 +572,6 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
         hadError = true;
         return;
       }
-      SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
       if (Init < NumInits)
         ILE->setInit(Init, DIE.get());
       else {
@@ -6198,43 +6197,17 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
   llvm_unreachable("unknown entity kind");
 }
 
-namespace {
-enum LifetimeKind {
-  /// The lifetime of a temporary bound to this entity ends at the end of the
-  /// full-expression, and that's (probably) fine.
-  LK_FullExpression,
-
-  /// The lifetime of a temporary bound to this entity is extended to the
-  /// lifeitme of the entity itself.
-  LK_Extended,
-
-  /// The lifetime of a temporary bound to this entity probably ends too soon,
-  /// because the entity is allocated in a new-expression.
-  LK_New,
-
-  /// The lifetime of a temporary bound to this entity ends too soon, because
-  /// the entity is a return object.
-  LK_Return,
-
-  /// This is a mem-initializer: if it would extend a temporary (other than via
-  /// a default member initializer), the program is ill-formed.
-  LK_MemInitializer,
-};
-using LifetimeResult =
-    llvm::PointerIntPair;
-}
-
 /// Determine the declaration which an initialized entity ultimately refers to,
 /// for the purpose of lifetime-extending a temporary bound to a reference in
 /// the initialization of \p Entity.
-static LifetimeResult getEntityForTemporaryLifetimeExtension(
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
     const InitializedEntity *Entity,
-    const InitializedEntity *InitField = nullptr) {
+    const InitializedEntity *FallbackDecl = nullptr) {
   // C++11 [class.temporary]p5:
   switch (Entity->getKind()) {
   case InitializedEntity::EK_Variable:
     //   The temporary [...] persists for the lifetime of the reference
-    return {Entity, LK_Extended};
+    return Entity;
 
   case InitializedEntity::EK_Member:
     // For subobjects, we look at the complete object.
@@ -6243,43 +6216,29 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension(
                                                     Entity);
 
     //   except:
-    // C++17 [class.base.init]p8:
-    //   A temporary expression bound to a reference member in a
-    //   mem-initializer is ill-formed.
-    // C++17 [class.base.init]p11:
-    //   A temporary expression bound to a reference member from a
-    //   default member initializer is ill-formed.
-    //
-    // The context of p11 and its example suggest that it's only the use of a
-    // default member initializer from a constructor that makes the program
-    // ill-formed, not its mere existence, and that it can even be used by
-    // aggregate initialization.
-    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
-                                                         : LK_MemInitializer};
+    //   -- A temporary bound to a reference member in a constructor's
+    //      ctor-initializer persists until the constructor exits.
+    return Entity;
 
   case InitializedEntity::EK_Binding:
     // Per [dcl.decomp]p3, the binding is treated as a variable of reference
     // type.
-    return {Entity, LK_Extended};
+    return Entity;
 
   case InitializedEntity::EK_Parameter:
   case InitializedEntity::EK_Parameter_CF_Audited:
     //   -- A temporary bound to a reference parameter in a function call
     //      persists until the completion of the full-expression containing
     //      the call.
-    return {nullptr, LK_FullExpression};
-
   case InitializedEntity::EK_Result:
     //   -- The lifetime of a temporary bound to the returned value in a
     //      function return statement is not extended; the temporary is
     //      destroyed at the end of the full-expression in the return statement.
-    return {nullptr, LK_Return};
-
   case InitializedEntity::EK_New:
     //   -- A temporary bound to a reference in a new-initializer persists
     //      until the completion of the full-expression containing the
     //      new-initializer.
-    return {nullptr, LK_New};
+    return nullptr;
 
   case InitializedEntity::EK_Temporary:
   case InitializedEntity::EK_CompoundLiteralInit:
@@ -6287,26 +6246,25 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension(
     // We don't yet know the storage duration of the surrounding temporary.
     // Assume it's got full-expression duration for now, it will patch up our
     // storage duration if that's not correct.
-    return {nullptr, LK_FullExpression};
+    return nullptr;
 
   case InitializedEntity::EK_ArrayElement:
     // For subobjects, we look at the complete object.
     return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                  InitField);
+                                                  FallbackDecl);
 
   case InitializedEntity::EK_Base:
     // For subobjects, we look at the complete object.
     if (Entity->getParent())
       return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                    InitField);
-    return {InitField, LK_MemInitializer};
-
+                                                    Entity);
+    LLVM_FALLTHROUGH;
   case InitializedEntity::EK_Delegating:
     // We can reach this case for aggregate initialization in a constructor:
     //   struct A { int &&r; };
     //   struct B : A { B() : A{0} {} };
-    // In this case, use the outermost field decl as the context.
-    return {InitField, LK_MemInitializer};
+    // In this case, use the innermost field decl as the context.
+    return FallbackDecl;
 
   case InitializedEntity::EK_BlockElement:
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -6314,54 +6272,30 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension(
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_ComplexElement:
-    return {nullptr, LK_FullExpression};
+    return nullptr;
   }
   llvm_unreachable("unknown entity kind");
 }
 
-namespace {
-enum ExtensionKind {
-  /// Lifetime would be extended by a reference binding to a temporary.
-  EK_ReferenceBinding,
-  /// Lifetime would be extended by a std::initializer_list object binding to
-  /// its backing array.
-  EK_StdInitializerList,
-};
-using IndirectTemporaryPathEntry =
-    llvm::PointerUnion;
-using IndirectTemporaryPath = llvm::SmallVectorImpl;
-
-struct RevertToOldSizeRAII {
-  IndirectTemporaryPath &Path;
-  unsigned OldSize = Path.size();
-  RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {}
-  ~RevertToOldSizeRAII() { Path.resize(OldSize); }
-};
-}
-
-template 
-static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
-                                                  Expr *Init,
-                                                  TemporaryVisitor Visit);
-
-/// Visit the temporaries whose lifetimes would be extended by binding a
-/// reference to the glvalue expression \c Init.
-template 
-static void
-visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,
-                                           Expr *Init, ExtensionKind EK,
-                                           TemporaryVisitor Visit) {
-  RevertToOldSizeRAII RAII(Path);
+static void performLifetimeExtension(Expr *Init,
+                                     const InitializedEntity *ExtendingEntity);
 
+/// Update a glvalue expression that is used as the initializer of a reference
+/// to note that its lifetime is extended.
+/// \return \c true if any temporary had its lifetime extended.
+static bool
+performReferenceExtension(Expr *Init,
+                          const InitializedEntity *ExtendingEntity) {
   // Walk past any constructs which we can lifetime-extend across.
   Expr *Old;
   do {
     Old = Init;
 
     if (InitListExpr *ILE = dyn_cast(Init)) {
-      // If this is just redundant braces around an initializer, step over it.
-      if (ILE->isTransparent())
+      if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
+        // This is just redundant braces around an initializer. Step over it.
         Init = ILE->getInit(0);
+      }
     }
 
     // Step over any subobject adjustments; we may have a materialized
@@ -6378,65 +6312,40 @@ visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,
     // when performing lifetime extension.
     if (auto *ASE = dyn_cast(Init))
       Init = ASE->getBase();
-
-    // Step into CXXDefaultInitExprs so we can diagnose cases where a
-    // constructor inherits one as an implicit mem-initializer.
-    if (auto *DIE = dyn_cast(Init)) {
-      Path.push_back(DIE);
-      Init = DIE->getExpr();
-
-      if (auto *EWC = dyn_cast(Init))
-        Init = EWC->getSubExpr();
-    }
   } while (Init != Old);
 
-  if (auto *MTE = dyn_cast(Init)) {
-    if (Visit(Path, MTE, EK))
-      visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(),
-                                            Visit);
+  if (MaterializeTemporaryExpr *ME = dyn_cast(Init)) {
+    // Update the storage duration of the materialized temporary.
+    // FIXME: Rebuild the expression instead of mutating it.
+    ME->setExtendingDecl(ExtendingEntity->getDecl(),
+                         ExtendingEntity->allocateManglingNumber());
+    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
+    return true;
   }
-}
-
-/// Visit the temporaries whose lifetimes would be extended by
-/// lifetime-extending the object initialized by the prvalue expression \c
-/// Init.
-template 
-static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
-                                                  Expr *Init,
-                                                  TemporaryVisitor Visit) {
-  RevertToOldSizeRAII RAII(Path);
-
-  // Step into CXXDefaultInitExprs so we can diagnose cases where a
-  // constructor inherits one as an implicit mem-initializer.
-  if (auto *DIE = dyn_cast(Init)) {
-    Path.push_back(DIE);
-    Init = DIE->getExpr();
 
-    if (auto *EWC = dyn_cast(Init))
-      Init = EWC->getSubExpr();
-  }
+  return false;
+}
 
+/// Update a prvalue expression that is going to be materialized as a
+/// lifetime-extended temporary.
+static void performLifetimeExtension(Expr *Init,
+                                     const InitializedEntity *ExtendingEntity) {
   // Dig out the expression which constructs the extended temporary.
   Init = const_cast(Init->skipRValueSubobjectAdjustments());
 
   if (CXXBindTemporaryExpr *BTE = dyn_cast(Init))
     Init = BTE->getSubExpr();
 
-  // C++17 [dcl.init.list]p6:
-  //   initializing an initializer_list object from the array extends the
-  //   lifetime of the array exactly like binding a reference to a temporary.
-  if (auto *ILE = dyn_cast(Init))
-    return visitTemporariesExtendedByReferenceBinding(
-        Path, ILE->getSubExpr(), EK_StdInitializerList, Visit);
+  if (CXXStdInitializerListExpr *ILE =
+          dyn_cast(Init)) {
+    performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
+    return;
+  }
 
   if (InitListExpr *ILE = dyn_cast(Init)) {
-    if (ILE->isTransparent())
-      return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),
-                                                   Visit);
-
     if (ILE->getType()->isArrayType()) {
       for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
-        visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit);
+        performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
       return;
     }
 
@@ -6448,8 +6357,7 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
       // bound to temporaries, those temporaries are also lifetime-extended.
       if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
           ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
-        visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0),
-                                                   EK_ReferenceBinding, Visit);
+        performReferenceExtension(ILE->getInit(0), ExtendingEntity);
       else {
         unsigned Index = 0;
         for (const auto *I : RD->fields()) {
@@ -6459,13 +6367,13 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
             continue;
           Expr *SubInit = ILE->getInit(Index);
           if (I->getType()->isReferenceType())
-            visitTemporariesExtendedByReferenceBinding(
-                Path, SubInit, EK_ReferenceBinding, Visit);
-          else
-            // This might be either aggregate-initialization of a member or
-            // initialization of a std::initializer_list object. Regardless,
+            performReferenceExtension(SubInit, ExtendingEntity);
+          else if (isa(SubInit) ||
+                   isa(SubInit))
+            // This may be either aggregate-initialization of a member or
+            // initialization of a std::initializer_list object. Either way,
             // we should recursively lifetime-extend that initializer.
-            visitTemporariesExtendedByInitializer(Path, SubInit, Visit);
+            performLifetimeExtension(SubInit, ExtendingEntity);
           ++Index;
         }
       }
@@ -6473,123 +6381,37 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
   }
 }
 
-/// Determine whether this is an indirect path to a temporary that we are
-/// supposed to lifetime-extend along (but don't).
-static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) {
-  for (auto Elem : Path) {
-    if (!Elem.is())
-      return false;
-  }
-  return true;
-}
-
-void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
-                                    Expr *Init) {
-  LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);
-  LifetimeKind LK = LR.getInt();
-  const InitializedEntity *ExtendingEntity = LR.getPointer();
-
-  // If this entity doesn't have an interesting lifetime, don't bother looking
-  // for temporaries within its initializer.
-  if (LK == LK_FullExpression)
-    return;
-
-  auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,
-                              MaterializeTemporaryExpr *MTE,
-                              ExtensionKind EK) -> bool {
-    switch (LK) {
-    case LK_FullExpression:
-      llvm_unreachable("already handled this");
-
-    case LK_Extended:
-      // Lifetime-extend the temporary.
-      if (Path.empty()) {
-        // Update the storage duration of the materialized temporary.
-        // FIXME: Rebuild the expression instead of mutating it.
-        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
-                              ExtendingEntity->allocateManglingNumber());
-        // Also visit the temporaries lifetime-extended by this initializer.
-        return true;
-      }
-
-      if (shouldLifetimeExtendThroughPath(Path)) {
-        // We're supposed to lifetime-extend the temporary along this path (per
-        // the resolution of DR1815), but we don't support that yet.
-        //
-        // FIXME: Properly handle this situation. Perhaps the easiest approach
-        // would be to clone the initializer expression on each use that would
-        // lifetime extend its temporaries.
-        Diag(MTE->getExprLoc(),
-             EK == EK_ReferenceBinding
-                 ? diag::warn_default_member_init_temporary_not_extended
-                 : diag::warn_default_member_init_init_list_not_extended);
-      } else {
-        llvm_unreachable("unexpected indirect temporary path");
-      }
-      break;
-
-    case LK_MemInitializer:
-      // Under C++ DR1696, if a mem-initializer (or a default member
-      // initializer used by the absence of one) would lifetime-extend a
-      // temporary, the program is ill-formed.
-      if (auto *ExtendingDecl = ExtendingEntity->getDecl()) {
-        bool IsSubobjectMember = ExtendingEntity != &Entity;
-        Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)
-            << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember
-            << EK;
-        // Don't bother adding a note pointing to the field if we're inside its
-        // default member initializer; our primary diagnostic points to the
-        // same place in that case.
-        if (Path.empty() || !Path.back().is()) {
-          Diag(ExtendingDecl->getLocation(),
-               diag::note_lifetime_extending_member_declared_here)
-              << EK << IsSubobjectMember;
-        }
-      } else {
-        // We have a mem-initializer but no particular field within it; this
-        // is either a base class or a delegating initializer directly
-        // initializing the base-class from something that doesn't live long
-        // enough. Either way, that can't happen.
-        // FIXME: Move CheckForDanglingReferenceOrPointer checks here.
-        llvm_unreachable(
-            "temporary initializer for base class / delegating ctor");
-      }
-      break;
-
-    case LK_New:
-      if (EK == EK_ReferenceBinding) {
-        Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);
-      } else {
-        Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)
-            << (ExtendingEntity != &Entity);
-      }
-      break;
-
-    case LK_Return:
-      // FIXME: Move -Wreturn-stack-address checks here.
-      return false;
+static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
+                                    const Expr *Init, bool IsInitializerList,
+                                    const ValueDecl *ExtendingDecl) {
+  // Warn if a field lifetime-extends a temporary.
+  if (isa(ExtendingDecl)) {
+    if (IsInitializerList) {
+      S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
+        << /*at end of constructor*/true;
+      return;
     }
 
-    // FIXME: Model these as CodeSynthesisContexts to fix the note emission
-    // order.
-    for (auto Elem : llvm::reverse(Path)) {
-      if (auto *DIE = Elem.dyn_cast()) {
-        Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here)
-            << DIE->getField();
+    bool IsSubobjectMember = false;
+    for (const InitializedEntity *Ent = Entity.getParent(); Ent;
+         Ent = Ent->getParent()) {
+      if (Ent->getKind() != InitializedEntity::EK_Base) {
+        IsSubobjectMember = true;
+        break;
       }
     }
-
-    // We didn't lifetime-extend, so don't go any further; we don't need more
-    // warnings or errors on inner temporaries within this one's initializer.
-    return false;
-  };
-
-  llvm::SmallVector Path;
-  if (Init->isGLValue())
-    visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding,
-                                               TemporaryVisitor);
-  else
-    visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);
+    S.Diag(Init->getExprLoc(),
+           diag::warn_bind_ref_member_to_temporary)
+      << ExtendingDecl << Init->getSourceRange()
+      << IsSubobjectMember << IsInitializerList;
+    if (IsSubobjectMember)
+      S.Diag(ExtendingDecl->getLocation(),
+             diag::note_ref_subobject_of_member_declared_here);
+    else
+      S.Diag(ExtendingDecl->getLocation(),
+             diag::note_ref_or_ptr_member_declared_here)
+        << /*is pointer*/false;
+  }
 }
 
 static void DiagnoseNarrowingInInitList(Sema &S,
@@ -7016,9 +6838,14 @@ InitializationSequence::Perform(Sema &S,
       }
 
       // Even though we didn't materialize a temporary, the binding may still
-      // extend the lifetime of a temporary. This happens if we bind a
-      // reference to the result of a cast to reference type.
-      S.checkInitializerLifetime(Entity, CurInit.get());
+      // extend the lifetime of a temporary. This happens if we bind a reference
+      // to the result of a cast to reference type.
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(CurInit.get(), ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(),
+                                  /*IsInitializerList=*/false,
+                                  ExtendingEntity->getDecl());
 
       CheckForNullPointerDereference(S, CurInit.get());
       break;
@@ -7034,17 +6861,23 @@ InitializationSequence::Perform(Sema &S,
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
           Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
-      CurInit = MTE;
 
       // Maybe lifetime-extend the temporary's subobjects to match the
       // entity's lifetime.
-      S.checkInitializerLifetime(Entity, CurInit.get());
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(MTE, ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(),
+                                  /*IsInitializerList=*/false,
+                                  ExtendingEntity->getDecl());
 
       // If we're extending this temporary to automatic storage duration -- we
       // need to register its cleanup during the full-expression's cleanups.
       if (MTE->getStorageDuration() == SD_Automatic &&
           MTE->getType().isDestructedType())
         S.Cleanup.setExprNeedsCleanups(true);
+
+      CurInit = MTE;
       break;
     }
 
@@ -7487,12 +7320,17 @@ InitializationSequence::Perform(Sema &S,
           CurInit.get()->getType(), CurInit.get(),
           /*BoundToLvalueReference=*/false);
 
-      // Wrap it in a construction of a std::initializer_list.
-      CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
-
       // Maybe lifetime-extend the array temporary's subobjects to match the
       // entity's lifetime.
-      S.checkInitializerLifetime(Entity, CurInit.get());
+      if (const InitializedEntity *ExtendingEntity =
+              getEntityForTemporaryLifetimeExtension(&Entity))
+        if (performReferenceExtension(MTE, ExtendingEntity))
+          warnOnLifetimeExtension(S, Entity, CurInit.get(),
+                                  /*IsInitializerList=*/true,
+                                  ExtendingEntity->getDecl());
+
+      // Wrap it in a construction of a std::initializer_list.
+      CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
 
       // Bind the result, in case the library has given initializer_list a
       // non-trivial destructor.
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index 0cb68c4a97..b73a94f1db 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -178,6 +178,29 @@ namespace ReferenceInitialization {
     const MyStruct &myStruct(OtherStruct(5));
     myStruct.method(); // no-warning
   }
+
+  struct HasMyStruct {
+    const MyStruct &ms; // expected-note {{reference member declared here}}
+    const MyStruct &msWithCleanups; // expected-note {{reference member declared here}}
+
+    // clang's Sema issues a warning when binding a reference member to a
+    // temporary value.
+    HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {
+        // expected-warning@-1 {{binding reference member 'ms' to a temporary value}}
+        // expected-warning@-2 {{binding reference member 'msWithCleanups' to a temporary value}}
+
+      // At this point the members are not garbage so we should not expect an
+      // analyzer warning here even though binding a reference member
+      // to a member is a terrible idea.
+      ms.method(); // no-warning
+      msWithCleanups.method(); // no-warning
+    }
+  };
+
+  void referenceInitializeField() {
+    HasMyStruct hms;
+  }
+
 };
 
 namespace PR31592 {
diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp
index 54648cfe96..e0af95ac39 100644
--- a/test/CXX/drs/dr16xx.cpp
+++ b/test/CXX/drs/dr16xx.cpp
@@ -9,20 +9,6 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
-#if __cplusplus >= 201103L
-namespace std {
-  typedef decltype(sizeof(int)) size_t;
-
-  template class initializer_list {
-    const E *begin;
-    size_t size;
-
-  public:
-    initializer_list();
-  };
-} // std
-#endif
-
 namespace dr1611 { // dr1611: dup 1658
   struct A { A(int); };
   struct B : virtual A { virtual void f() = 0; };
@@ -283,83 +269,3 @@ namespace dr1687 { // dr1687: 7
   auto c = To() <=> To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}}
 #endif
 }
-
-namespace dr1696 { // dr1696: 7
-  namespace std_examples {
-#if __cplusplus >= 201402L
-    extern struct A a;
-    struct A {
-      const A &x = { A{a, a} };
-      const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}}
-    };
-    A a{a, a};
-#endif
-  }
-
-  struct A { A(); ~A(); };
-#if __cplusplus >= 201103L
-  struct B {
-    A &&a; // expected-note {{declared here}}
-    B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
-  } b;
-#endif
-
-  struct C {
-    C();
-    const A &a; // expected-note {{declared here}}
-  };
-  C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
-
-#if __cplusplus >= 201103L
-  // This is OK in C++14 onwards, per DR1815, though we don't support that yet:
-  //   D1 d1 = {};
-  // is equivalent to
-  //   D1 d1 = {A()};
-  // ... which lifetime-extends the A temporary.
-  struct D1 {
-    const A &a = A();
-#if __cplusplus < 201402L
-    // expected-error@-2 {{binds to a temporary}}
-    // expected-note@-4 {{here}}
-#else
-    // expected-warning-re@-5 {{sorry, lifetime extension {{.*}} not supported}}
-#endif
-  };
-  D1 d1 = {}; // expected-note {{here}}
-
-  struct D2 {
-    const A &a = A(); // expected-error {{binds to a temporary}}
-    D2() {} // expected-note {{used here}}
-  };
-
-  struct D3 { // expected-note {{used here}}
-    const A &a = A(); // expected-error {{binds to a temporary}}
-  };
-  D3 d3; // expected-note {{first required here}}
-
-  struct haslist1 {
-    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
-    haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
-  };
-
-  struct haslist2 {
-    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
-    haslist2();
-  };
-  haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
-
-  struct haslist3 {
-    std::initializer_list il = {1, 2, 3};
-  };
-
-  struct haslist4 { // expected-note {{in default member initializer}}
-    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
-  };
-  haslist4 hl4; // expected-note {{in implicit default constructor}}
-
-  struct haslist5 {
-    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
-    haslist5() {} // expected-note {{in default member initializer}}
-  };
-#endif
-}
diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp
index f6a4676bc7..a0f470ed4a 100644
--- a/test/CXX/drs/dr18xx.cpp
+++ b/test/CXX/drs/dr18xx.cpp
@@ -30,17 +30,6 @@ namespace dr1813 { // dr1813: 7
   static_assert(!__is_standard_layout(U), "");
 }
 
-namespace dr1815 { // dr1815: no
-#if __cplusplus >= 201402L
-  // FIXME: needs codegen test
-  struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}}
-  A a = {}; // expected-note {{here}}
-
-  struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{here}}
-  B b; // expected-note {{here}}
-#endif
-}
-
 namespace dr1881 { // dr1881: 7
   struct A { int a : 4; };
   struct B : A { int b : 3; };
diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp
index a4d0cdcdc7..1ca0143d09 100644
--- a/test/CXX/special/class.copy/p11.0x.copy.cpp
+++ b/test/CXX/special/class.copy/p11.0x.copy.cpp
@@ -121,22 +121,13 @@ extern HasNoAccessDtorBase HNADBa;
 HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
 
 // -- a non-static data member of rvalue reference type
-int some_int;
 struct RValue {
-  int && ri = static_cast(some_int); // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
+  int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
+  // expected-warning@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}}
 };
 RValue RVa;
 RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
 
-// FIXME: The note on the class-name is attached to the location of the
-// constructor. This is not especially clear.
-struct RValueTmp { // expected-note {{used here}}
-  int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
-  // expected-error@-1 {{reference member 'ri' binds to a temporary}}
-};
-RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}}
-RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}}
-
 namespace PR13381 {
   struct S {
     S(const S&);
diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp
index 5b016836e9..ab4259548e 100644
--- a/test/CXX/special/class.copy/p11.0x.move.cpp
+++ b/test/CXX/special/class.copy/p11.0x.move.cpp
@@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c
 // The restriction on rvalue reference members applies to only the copy
 // constructor.
 struct RValue {
-  int &&ri = 1;
+  int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
   RValue(RValue&&);
 };
 RValue::RValue(RValue&&) = default;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index 5558313ce7..2360345a48 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -43,12 +43,8 @@ class NotDeleted2a { int &a = n; };
 NotDeleted2a nd2a;
 class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
 NotDeleted2b nd2b;
-class NotDeleted2c { int &&a = static_cast(n); };
+class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}
 NotDeleted2c nd2c;
-// Note: this one does not have a deleted default constructor even though the
-// implicit default constructor is ill-formed!
-class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{here}}
-NotDeleted2d nd2d; // expected-note {{first required here}}
 
 // - any non-variant non-static data member of const qualified type (or array
 // thereof) with no brace-or-equal-initializer does not have a user-provided
diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp
index de902a5e4d..aa0d7e92b9 100644
--- a/test/CXX/temp/temp.param/p5.cpp
+++ b/test/CXX/temp/temp.param/p5.cpp
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -verify %s -std=c++14
 
-template struct S { // expected-note {{in default member initializer}}
+template struct S {
   decltype(I) n;
-  int &&r = I; // expected-error {{reference member 'r' binds to a temporary object}}
+  int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}
 };
-S<5> s; // expected-note {{implicit default constructor}}
+S<5> s; // expected-note {{instantiation}}
 
-template struct U { // expected-note {{in default member initializer}}
+template struct U {
   decltype(v) n;
-  int &&r = v; // expected-error {{reference member 'r' binds to a temporary object}}
+  int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}
 };
-U u; // expected-note {{implicit default constructor}}
+U u; // expected-note {{instantiation}}
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 0184a1d6e7..3299763997 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -236,6 +236,36 @@ void fn9() {
   // CHECK: ret void
 }
 
+struct haslist1 {
+  std::initializer_list il;
+  haslist1(int i);
+};
+
+// CHECK-LABEL: define void @_ZN8haslist1C2Ei
+haslist1::haslist1(int i)
+// CHECK: alloca [3 x i32]
+// CHECK: store i32 %
+// CHECK: store i32 2
+// CHECK: store i32 3
+  : il{i, 2, 3}
+{
+  destroyme2 dm2;
+}
+
+struct haslist2 {
+  std::initializer_list il;
+  haslist2();
+};
+
+// CHECK-LABEL: define void @_ZN8haslist2C2Ev
+haslist2::haslist2()
+  : il{destroyme1(), destroyme1()}
+{
+  destroyme2 dm2;
+  // CHECK: call void @_ZN10destroyme2D1Ev
+  // CHECK: call void @_ZN10destroyme1D1Ev
+}
+
 void fn10(int i) {
   // CHECK-LABEL: define void @_Z4fn10i
   // CHECK: alloca [3 x i32]
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index 21372effbc..bad51ba353 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -198,6 +198,20 @@ B::B()
   f();
 }
   
+struct C {
+  C();
+  
+  const B& b;
+};
+
+C::C() 
+  // CHECK: call void @_ZN6PR50771BC1Ev
+  : b(B()) {
+  // CHECK: call void @_ZN6PR50771fEv
+  f();
+  
+  // CHECK: call void @_ZN6PR50771BD1Ev
+}
 }
 
 A f8() {
@@ -802,3 +816,16 @@ namespace PR14130 {
   // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
   // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
 }
+
+namespace Ctor {
+  struct A { A(); ~A(); };
+  void f();
+  struct B {
+    A &&a;
+    B() : a{} { f(); }
+  } b;
+  // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
+  // CHECK: call void @_ZN4Ctor1AC1Ev(
+  // CHECK: call void @_ZN4Ctor1fEv(
+  // CHECK: call void @_ZN4Ctor1AD1Ev(
+}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index e921634b1b..4b4bd43634 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1892,15 +1892,14 @@ namespace Lifetime {
   }
 
   constexpr int &get(int &&n) { return n; }
-  constexpr int &&get_rv(int &&n) { return static_cast(n); }
   struct S {
-    int &&r;
+    int &&r; // expected-note 2{{declared here}}
     int &s;
     int t;
-    constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}
-    constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}
+    constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}}
+    constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}}
   };
-  constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}
+  constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor
   constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
 }
 
diff --git a/test/SemaCXX/constexpr-default-arg.cpp b/test/SemaCXX/constexpr-default-arg.cpp
index 165c31aab6..2fc873c3e5 100644
--- a/test/SemaCXX/constexpr-default-arg.cpp
+++ b/test/SemaCXX/constexpr-default-arg.cpp
@@ -31,8 +31,8 @@ void test_default_arg2() {
 }
 
 // Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
-struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
+struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}}
 struct B { A x, y; };
-B b = {}; // expected-note 2{{in default member initializer for field 'r' used here}}
+B b = {};
 
 }
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index ece014d93a..860a4aa6c6 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -153,14 +153,13 @@ void dangle() {
 }
 
 struct haslist1 {
-  std::initializer_list il // expected-note {{declared here}}
-    = {1, 2, 3}; // ok, unused
-  std::initializer_list jl{1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}
+  std::initializer_list il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
+  std::initializer_list jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
   haslist1();
 };
 
-haslist1::haslist1() // expected-note {{used here}}
-: il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+haslist1::haslist1()
+: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
 {}
 
 namespace PR12119 {
diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp
index 33bde75de6..23946845d8 100644
--- a/test/SemaCXX/eval-crashes.cpp
+++ b/test/SemaCXX/eval-crashes.cpp
@@ -26,10 +26,10 @@ namespace pr33140_0b {
 
 namespace pr33140_2 {
   // FIXME: The declaration of 'b' below should lifetime-extend two int
-  // temporaries.
-  struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
+  // temporaries, invalidating this warning to some extent.
+  struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}}
   struct B { A x, y; };
-  B b = {}; // expected-note 2{{used here}}
+  B b = {};
 }
 
 namespace pr33140_3 {
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index 8a13eca2f1..ad4a8f15b2 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -86,8 +86,9 @@ namespace PR14838 {
   };
   struct thing {};
   struct another {
-    another() : r(thing()) {} // expected-error {{binds to a temporary object}}
+    another() : r(thing()) {}
     // expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}}
+    // expected-warning@-2 {{binding reference member 'r' to a temporary value}}
     const function &r; // expected-note {{reference member declared here}}
   } af;
 }
diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp
index 97d4331c1f..eb65bd0669 100644
--- a/test/SemaCXX/warn-dangling-field.cpp
+++ b/test/SemaCXX/warn-dangling-field.cpp
@@ -20,7 +20,7 @@ struct S {
 
 struct S2 {
   const X &x; // expected-note {{reference member declared here}}
-  S2(int i) : x(i) {} // expected-error {{member 'x' binds to a temporary}}
+  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}
 };
 
 struct S3 {
@@ -43,9 +43,9 @@ S5 s5 = { 0 }; // ok, lifetime-extended
 
 struct S6 {
   S5 s5; // expected-note {{here}}
-  S6() : s5 { 0 } {} // expected-error {{reference subobject of member 's5' binds to a temporary}}
+  S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}
 };
 
 struct S7 : S5 {
-  S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}}
+  S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}
 };
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index 04dd0eae1c..93d4ee93fb 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -9991,7 +9991,7 @@ and POD class
     1696
     CD4
     Temporary lifetime and non-static data member initializers
-    SVN
+    Unknown
   
   
     1697
@@ -10705,7 +10705,7 @@ and POD class
     1815
     CD4
     Lifetime extension in aggregate initialization
-    No
+    Unknown
   
   
     1816
-- 
GitLab


From d0d3baaed339a76574fdfecc2f756e568bf58f53 Mon Sep 17 00:00:00 2001
From: Balazs Keri <1.int32@gmail.com>
Date: Tue, 17 Jul 2018 09:52:41 +0000
Subject: [PATCH 0574/1023] [ASTImporter] Import described template (if any) of
 function.

Summary:
When a function is imported, check if it has a described template.
The name lookup is corrected to find the templated entity in this case.
The described template of the function is imported too.

Reviewers: a.sidorin, a_sidorin

Reviewed By: a_sidorin

Subscribers: a_sidorin, martong, cfe-commits

Differential Revision: https://reviews.llvm.org/D49235

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337260 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/ASTImporter.cpp           | 14 ++++++++++++++
 unittests/AST/ASTImporterTest.cpp |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 366c2064d4..980ab478d5 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2539,6 +2539,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
     return ToD;
 
   const FunctionDecl *FoundByLookup = nullptr;
+  FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate();
 
   // If this is a function template specialization, then try to find the same
   // existing specialization in the "to" context. The localUncachedLookup
@@ -2565,6 +2566,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
       if (!FoundDecl->isInIdentifierNamespace(IDNS))
         continue;
 
+      // If template was found, look at the templated function.
+      if (FromFT) {
+        if (auto *Template = dyn_cast(FoundDecl))
+          FoundDecl = Template->getTemplatedDecl();
+        else
+          continue;
+      }
+
       if (auto *FoundFunction = dyn_cast(FoundDecl)) {
         if (FoundFunction->hasExternalFormalLinkage() &&
             D->hasExternalFormalLinkage()) {
@@ -2740,6 +2749,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
     ToFunction->setType(T);
   }
 
+  // Import the describing template function, if any.
+  if (FromFT)
+    if (!Importer.Import(FromFT))
+      return nullptr;
+
   if (D->doesThisDeclarationHaveABody()) {
     if (Stmt *FromBody = D->getBody()) {
       if (Stmt *ToBody = Importer.Import(FromBody)) {
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index cc8ed92faa..c59c2cd125 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -1185,7 +1185,7 @@ TEST_P(ASTImporterTestBase,
 }
 
 TEST_P(ASTImporterTestBase,
-       DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
+       ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
   Decl *FromTU = getTuDecl("template void f(){}", Lang_CXX);
   auto FromFT = FirstDeclMatcher().match(
       FromTU, functionTemplateDecl());
-- 
GitLab


From 24e7a5fe16c20695df235a84a6dfe19f09364c5b Mon Sep 17 00:00:00 2001
From: Gabor Marton 
Date: Tue, 17 Jul 2018 12:06:36 +0000
Subject: [PATCH 0575/1023] [ASTImporter] Fix import of unnamed structs

Summary:
D48773 simplified ASTImporter nicely, but it introduced a new error: Unnamed
structs are not imported correctly, if they appear in a recursive context.
This patch provides a fix for structural equivalency.

Reviewers: a.sidorin, a_sidorin, balazske, gerazo

Subscribers: rnkovacs, dkrupp, cfe-commits

Differential Revision: https://reviews.llvm.org/D49296

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337267 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/ASTStructuralEquivalence.cpp        |  2 +-
 unittests/AST/ASTImporterTest.cpp           | 42 ++++++++--
 unittests/AST/StructuralEquivalenceTest.cpp | 88 ++++++++++++++++++++-
 3 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index 77e0d9e61b..1da7b84948 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/lib/AST/ASTStructuralEquivalence.cpp
@@ -924,7 +924,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return false;
   }
 
-  if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) {
+  if (!D1->getDeclName() && !D2->getDeclName()) {
     // If both anonymous structs/unions are in a record context, make sure
     // they occur in the same location in the context records.
     if (Optional Index1 =
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index c59c2cd125..84bfdadae2 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -273,6 +273,11 @@ public:
   }
 };
 
+template  RecordDecl *getRecordDecl(T *D) {
+  auto *ET = cast(D->getType().getTypePtr());
+  return cast(ET->getNamedType().getTypePtr())->getDecl();
+};
+
 // This class provides generic methods to write tests which can check internal
 // attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
 // this fixture makes it possible to import from several "From" contexts.
@@ -1755,11 +1760,6 @@ TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
       )",
       Lang_CXX, "input0.cc");
 
-  auto getRecordDecl = [](VarDecl *VD) {
-    auto *ET = cast(VD->getType().getTypePtr());
-    return cast(ET->getNamedType().getTypePtr())->getDecl();
-  };
-
   auto *Obj0 =
       FirstDeclMatcher().match(FromTU, varDecl(hasName("object0")));
   auto *From0 = getRecordDecl(Obj0);
@@ -2580,6 +2580,38 @@ TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
   EXPECT_NE(ToM1, ToM2);
 }
 
+TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
+  Decl *FromTU = getTuDecl(
+      R"(
+      struct A {
+        struct {
+          struct A *next;
+        } entry0;
+        struct {
+          struct A *next;
+        } entry1;
+      };
+      )",
+      Lang_C, "input0.cc");
+  auto *From =
+      FirstDeclMatcher().match(FromTU, recordDecl(hasName("A")));
+
+  Import(From, Lang_C);
+
+  auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
+  auto *Entry0 =
+      FirstDeclMatcher().match(ToTU, fieldDecl(hasName("entry0")));
+  auto *Entry1 =
+      FirstDeclMatcher().match(ToTU, fieldDecl(hasName("entry1")));
+  auto *R0 = getRecordDecl(Entry0);
+  auto *R1 = getRecordDecl(Entry1);
+  EXPECT_NE(R0, R1);
+  EXPECT_TRUE(MatchVerifier().match(
+      R0, recordDecl(has(fieldDecl(hasName("next"))))));
+  EXPECT_TRUE(MatchVerifier().match(
+      R1, recordDecl(has(fieldDecl(hasName("next"))))));
+}
+
 struct DeclContextTest : ASTImporterTestBase {};
 
 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp
index 551986fc1c..19d2e334fc 100644
--- a/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/unittests/AST/StructuralEquivalenceTest.cpp
@@ -42,6 +42,21 @@ struct StructuralEquivalenceTest : ::testing::Test {
     return std::make_tuple(D0, D1);
   }
 
+  std::tuple makeTuDecls(
+      const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) {
+    this->Code0 = SrcCode0;
+    this->Code1 = SrcCode1;
+    ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+
+    const char *const InputFileName = "input.cc";
+
+    AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
+    AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
+
+    return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),
+                           AST1->getASTContext().getTranslationUnitDecl());
+  }
+
   // Get a pair of node pointers into the synthesized AST from the given code
   // snippets. The same matcher is used for both snippets.
   template 
@@ -62,7 +77,7 @@ struct StructuralEquivalenceTest : ::testing::Test {
     return makeDecls(SrcCode0, SrcCode1, Lang, Matcher);
   }
 
-  bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) {
+  bool testStructuralMatch(Decl *D0, Decl *D1) {
     llvm::DenseSet> NonEquivalentDecls;
     StructuralEquivalenceContext Ctx(
         D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
@@ -70,7 +85,7 @@ struct StructuralEquivalenceTest : ::testing::Test {
     return Ctx.IsStructurallyEquivalent(D0, D1);
   }
 
-  bool testStructuralMatch(std::tuple t) {
+  bool testStructuralMatch(std::tuple t) {
     return testStructuralMatch(get<0>(t), get<1>(t));
   }
 };
@@ -468,6 +483,11 @@ TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {
 }
 
 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {
+  // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!
+  RecordDecl *getRecordDecl(FieldDecl *FD) {
+    auto *ET = cast(FD->getType().getTypePtr());
+    return cast(ET->getNamedType().getTypePtr())->getDecl();
+  };
 };
 
 TEST_F(StructuralEquivalenceRecordTest, Name) {
@@ -535,6 +555,70 @@ TEST_F(StructuralEquivalenceRecordTest, Match) {
   EXPECT_TRUE(testStructuralMatch(t));
 }
 
+TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {
+  auto t = makeTuDecls(
+      R"(
+      struct A {
+        struct {
+          struct A *next;
+        } entry0;
+        struct {
+          struct A *next;
+        } entry1;
+      };
+      )",
+      "", Lang_C);
+  auto *TU = get<0>(t);
+  auto *Entry0 =
+      FirstDeclMatcher().match(TU, fieldDecl(hasName("entry0")));
+  auto *Entry1 =
+      FirstDeclMatcher().match(TU, fieldDecl(hasName("entry1")));
+  auto *R0 = getRecordDecl(Entry0);
+  auto *R1 = getRecordDecl(Entry1);
+
+  ASSERT_NE(R0, R1);
+  EXPECT_TRUE(testStructuralMatch(R0, R0));
+  EXPECT_TRUE(testStructuralMatch(R1, R1));
+  EXPECT_FALSE(testStructuralMatch(R0, R1));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+       UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {
+  auto Code =
+      R"(
+      struct A {
+        struct {
+          struct A *next;
+        } entry0;
+        struct {
+          struct A *next;
+        } entry1;
+      };
+      )";
+  auto t = makeTuDecls(Code, Code, Lang_C);
+
+  auto *FromTU = get<0>(t);
+  auto *Entry1 =
+      FirstDeclMatcher().match(FromTU, fieldDecl(hasName("entry1")));
+
+  auto *ToTU = get<1>(t);
+  auto *Entry0 =
+      FirstDeclMatcher().match(ToTU, fieldDecl(hasName("entry0")));
+  auto *A =
+      FirstDeclMatcher().match(ToTU, recordDecl(hasName("A")));
+  A->startDefinition(); // Set isBeingDefined, getDefinition() will return a
+                        // nullptr. This may be the case during ASTImport.
+
+  auto *R0 = getRecordDecl(Entry0);
+  auto *R1 = getRecordDecl(Entry1);
+
+  ASSERT_NE(R0, R1);
+  EXPECT_TRUE(testStructuralMatch(R0, R0));
+  EXPECT_TRUE(testStructuralMatch(R1, R1));
+  EXPECT_FALSE(testStructuralMatch(R0, R1));
+}
+
+
 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {
   auto t = makeNamedDecls(
       "struct A{ }; struct B{ }; void foo(A a, A b);",
-- 
GitLab


From d74a010716307cc509574849a864cadd00120d85 Mon Sep 17 00:00:00 2001
From: Joerg Sonnenberger 
Date: Tue, 17 Jul 2018 12:33:19 +0000
Subject: [PATCH 0576/1023] By popular demand, switch in64_t on NetBSD/AArch64
 and NetBSD/PowerPC64 to long for consistency with other 64bit platforms.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337271 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/Targets/AArch64.cpp |  7 ++----
 lib/Basic/Targets/PPC.h       |  4 ----
 test/Preprocessor/init.c      | 32 ++++++++++++++--------------
 test/Preprocessor/stdint.c    | 40 +++++++++++++++++------------------
 4 files changed, 38 insertions(+), 45 deletions(-)

diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 40b808d708..e55b606da9 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -35,14 +35,11 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
                                      const TargetOptions &Opts)
     : TargetInfo(Triple), ABI("aapcs") {
-  if (getTriple().getOS() == llvm::Triple::NetBSD ||
-      getTriple().getOS() == llvm::Triple::OpenBSD) {
-    // NetBSD apparently prefers consistency across ARM targets to
-    // consistency across 64-bit targets.
+  if (getTriple().getOS() == llvm::Triple::OpenBSD) {
     Int64Type = SignedLongLong;
     IntMaxType = SignedLongLong;
   } else {
-    if (!getTriple().isOSDarwin())
+    if (!getTriple().isOSDarwin() && getTriple().getOS() != llvm::Triple::NetBSD)
       WCharType = UnsignedInt;
 
     Int64Type = SignedLong;
diff --git a/lib/Basic/Targets/PPC.h b/lib/Basic/Targets/PPC.h
index d5ccdd1b11..439c73a0e3 100644
--- a/lib/Basic/Targets/PPC.h
+++ b/lib/Basic/Targets/PPC.h
@@ -366,10 +366,6 @@ public:
       LongDoubleWidth = LongDoubleAlign = 64;
       LongDoubleFormat = &llvm::APFloat::IEEEdouble();
       break;
-    case llvm::Triple::NetBSD:
-      IntMaxType = SignedLongLong;
-      Int64Type = SignedLongLong;
-      break;
     default:
       break;
     }
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 6dedf26a24..ac65f15acd 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -724,21 +724,21 @@
 // AARCH64-NETBSD:#define __INT32_FMTi__ "i"
 // AARCH64-NETBSD:#define __INT32_MAX__ 2147483647
 // AARCH64-NETBSD:#define __INT32_TYPE__ int
-// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ LL
-// AARCH64-NETBSD:#define __INT64_FMTd__ "lld"
-// AARCH64-NETBSD:#define __INT64_FMTi__ "lli"
-// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807LL
-// AARCH64-NETBSD:#define __INT64_TYPE__ long long int
+// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ L
+// AARCH64-NETBSD:#define __INT64_FMTd__ "ld"
+// AARCH64-NETBSD:#define __INT64_FMTi__ "li"
+// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807L
+// AARCH64-NETBSD:#define __INT64_TYPE__ long int
 // AARCH64-NETBSD:#define __INT8_C_SUFFIX__
 // AARCH64-NETBSD:#define __INT8_FMTd__ "hhd"
 // AARCH64-NETBSD:#define __INT8_FMTi__ "hhi"
 // AARCH64-NETBSD:#define __INT8_MAX__ 127
 // AARCH64-NETBSD:#define __INT8_TYPE__ signed char
-// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ LL
-// AARCH64-NETBSD:#define __INTMAX_FMTd__ "lld"
-// AARCH64-NETBSD:#define __INTMAX_FMTi__ "lli"
-// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807LL
-// AARCH64-NETBSD:#define __INTMAX_TYPE__ long long int
+// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ L
+// AARCH64-NETBSD:#define __INTMAX_FMTd__ "ld"
+// AARCH64-NETBSD:#define __INTMAX_FMTi__ "li"
+// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807L
+// AARCH64-NETBSD:#define __INTMAX_TYPE__ long int
 // AARCH64-NETBSD:#define __INTMAX_WIDTH__ 64
 // AARCH64-NETBSD:#define __INTPTR_FMTd__ "ld"
 // AARCH64-NETBSD:#define __INTPTR_FMTi__ "li"
@@ -824,15 +824,15 @@
 // AARCH64-NETBSD:#define __UINT32_C_SUFFIX__ U
 // AARCH64-NETBSD:#define __UINT32_MAX__ 4294967295U
 // AARCH64-NETBSD:#define __UINT32_TYPE__ unsigned int
-// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ ULL
-// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615ULL
-// AARCH64-NETBSD:#define __UINT64_TYPE__ long long unsigned int
+// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ UL
+// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615UL
+// AARCH64-NETBSD:#define __UINT64_TYPE__ long unsigned int
 // AARCH64-NETBSD:#define __UINT8_C_SUFFIX__
 // AARCH64-NETBSD:#define __UINT8_MAX__ 255
 // AARCH64-NETBSD:#define __UINT8_TYPE__ unsigned char
-// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ ULL
-// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL
-// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long long unsigned int
+// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ UL
+// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615UL
+// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long unsigned int
 // AARCH64-NETBSD:#define __UINTMAX_WIDTH__ 64
 // AARCH64-NETBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
 // AARCH64-NETBSD:#define __UINTPTR_TYPE__ long unsigned int
diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c
index 3b32346d5e..fc179b4ba5 100644
--- a/test/Preprocessor/stdint.c
+++ b/test/Preprocessor/stdint.c
@@ -636,8 +636,8 @@
 //
 // RUN: %clang_cc1 -E -ffreestanding -triple=powerpc64-none-netbsd %s | FileCheck -check-prefix PPC64-NETBSD %s
 //
-// PPC64-NETBSD:typedef long long int int64_t;
-// PPC64-NETBSD:typedef long long unsigned int uint64_t;
+// PPC64-NETBSD:typedef long int int64_t;
+// PPC64-NETBSD:typedef long unsigned int uint64_t;
 // PPC64-NETBSD:typedef int64_t int_least64_t;
 // PPC64-NETBSD:typedef uint64_t uint_least64_t;
 // PPC64-NETBSD:typedef int64_t int_fast64_t;
@@ -667,8 +667,8 @@
 // PPC64-NETBSD:typedef long int intptr_t;
 // PPC64-NETBSD:typedef long unsigned int uintptr_t;
 //
-// PPC64-NETBSD:typedef long long int intmax_t;
-// PPC64-NETBSD:typedef long long unsigned int uintmax_t;
+// PPC64-NETBSD:typedef long int intmax_t;
+// PPC64-NETBSD:typedef long unsigned int uintmax_t;
 //
 // PPC64-NETBSD:INT8_MAX_ 127
 // PPC64-NETBSD:INT8_MIN_ (-127 -1)
@@ -700,15 +700,15 @@
 // PPC64-NETBSD:INT_FAST32_MAX_ 2147483647
 // PPC64-NETBSD:UINT_FAST32_MAX_ 4294967295U
 //
-// PPC64-NETBSD:INT64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:INT64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:UINT64_MAX_ 18446744073709551615ULL
-// PPC64-NETBSD:INT_LEAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INT_LEAST64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINT_LEAST64_MAX_ 18446744073709551615ULL
-// PPC64-NETBSD:INT_FAST64_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INT_FAST64_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINT_FAST64_MAX_ 18446744073709551615ULL
+// PPC64-NETBSD:INT64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:INT64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:UINT64_MAX_ 18446744073709551615UL
+// PPC64-NETBSD:INT_LEAST64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INT_LEAST64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINT_LEAST64_MAX_ 18446744073709551615UL
+// PPC64-NETBSD:INT_FAST64_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INT_FAST64_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINT_FAST64_MAX_ 18446744073709551615UL
 //
 // PPC64-NETBSD:INTPTR_MIN_ (-9223372036854775807L -1)
 // PPC64-NETBSD:INTPTR_MAX_ 9223372036854775807L
@@ -717,9 +717,9 @@
 // PPC64-NETBSD:PTRDIFF_MAX_ 9223372036854775807L
 // PPC64-NETBSD:SIZE_MAX_ 18446744073709551615UL
 //
-// PPC64-NETBSD:INTMAX_MIN_ (-9223372036854775807LL -1)
-// PPC64-NETBSD:INTMAX_MAX_ 9223372036854775807LL
-// PPC64-NETBSD:UINTMAX_MAX_ 18446744073709551615ULL
+// PPC64-NETBSD:INTMAX_MIN_ (-9223372036854775807L -1)
+// PPC64-NETBSD:INTMAX_MAX_ 9223372036854775807L
+// PPC64-NETBSD:UINTMAX_MAX_ 18446744073709551615UL
 //
 // PPC64-NETBSD:SIG_ATOMIC_MIN_ (-2147483647 -1)
 // PPC64-NETBSD:SIG_ATOMIC_MAX_ 2147483647
@@ -735,11 +735,11 @@
 // PPC64-NETBSD:UINT16_C_(0) 0U
 // PPC64-NETBSD:INT32_C_(0) 0
 // PPC64-NETBSD:UINT32_C_(0) 0U
-// PPC64-NETBSD:INT64_C_(0) 0LL
-// PPC64-NETBSD:UINT64_C_(0) 0ULL
+// PPC64-NETBSD:INT64_C_(0) 0L
+// PPC64-NETBSD:UINT64_C_(0) 0UL
 //
-// PPC64-NETBSD:INTMAX_C_(0) 0LL
-// PPC64-NETBSD:UINTMAX_C_(0) 0ULL
+// PPC64-NETBSD:INTMAX_C_(0) 0L
+// PPC64-NETBSD:UINTMAX_C_(0) 0UL
 //
 // RUN: %clang_cc1 -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s
 //
-- 
GitLab


From 703ada1375c63916b557d509241769dd8b03f7b5 Mon Sep 17 00:00:00 2001
From: Joerg Sonnenberger 
Date: Tue, 17 Jul 2018 12:38:57 +0000
Subject: [PATCH 0577/1023] For NetBSD, unwind data is emitted by default, so
 also enable frame pointer optimisation by default when using optimisation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337274 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Driver/ToolChains/Clang.cpp  | 4 ++++
 test/Driver/frame-pointer-elim.c | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 853f9a422f..e7b15c7ad8 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -524,6 +524,10 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
     break;
   }
 
+  if (Triple.getOS() == llvm::Triple::NetBSD) {
+    return !areOptimizationsEnabled(Args);
+  }
+
   if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
     switch (Triple.getArch()) {
     // Don't use a frame pointer on linux if optimizing for certain targets.
diff --git a/test/Driver/frame-pointer-elim.c b/test/Driver/frame-pointer-elim.c
index e39499a55c..6fcd3eb75a 100644
--- a/test/Driver/frame-pointer-elim.c
+++ b/test/Driver/frame-pointer-elim.c
@@ -17,6 +17,15 @@
 // RUN:   FileCheck --check-prefix=CLOUDABI %s
 // CLOUDABI-NOT: "-momit-leaf-frame-pointer"
 
+// NetBSD follows the same rules as Linux.
+// RUN: %clang -### -target x86_64-unknown-netbsd -S -O1 %s 2>&1 | \
+// RUN:   FileCheck --check-prefix=NETBSD-OPT %s
+// NETBSD-OPT: "-momit-leaf-frame-pointer"
+
+// RUN: %clang -### -target x86_64-unknown-netbsd -S %s 2>&1 | \
+// RUN:   FileCheck --check-prefix=NETBSD %s
+// NETBSD-NOT: "-momit-leaf-frame-pointer"
+
 // Darwin disables omitting the leaf frame pointer even under optimization
 // unless the command lines are given.
 // RUN: %clang -### -target i386-apple-darwin -S %s 2>&1 | \
-- 
GitLab


From 7efce9a166c918c01e87e5234e016fac78da63d8 Mon Sep 17 00:00:00 2001
From: Gabor Marton 
Date: Tue, 17 Jul 2018 12:39:27 +0000
Subject: [PATCH 0578/1023] [ASTImporter] Fix poisonous structural equivalence
 cache

Summary:
Implementation functions call into the member functions of
ASTStructuralEquivalence, thus they can falsely alter the DeclsToCheck state
(they add decls).  This results that some leaf declarations can be stated as
inequivalent as a side effect of one inequivalent element in the DeclsToCheck
list.  And since we store the non-equivalencies, any (otherwise independent)
decls will be rendered as non-equivalent.  Solution: I tried to clearly
separate the implementation functions (the static ones) and the public
interface.  From now on, the implementation functions do not call any public
member functions, only other implementation functions.

Reviewers: a.sidorin, a_sidorin, r.stahl

Subscribers: rnkovacs, dkrupp, cfe-commits

Differential Revision: https://reviews.llvm.org/D49300

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337275 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/ASTStructuralEquivalence.h | 12 ++-
 lib/AST/ASTImporter.cpp                      | 35 ++++----
 lib/AST/ASTStructuralEquivalence.cpp         | 91 +++++++++++++++++---
 lib/Sema/SemaType.cpp                        |  2 +-
 unittests/AST/StructuralEquivalenceTest.cpp  |  2 +-
 5 files changed, 109 insertions(+), 33 deletions(-)

diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index c39d9d9dc1..d32f87d43e 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/include/clang/AST/ASTStructuralEquivalence.h
@@ -85,10 +85,18 @@ struct StructuralEquivalenceContext {
 
   /// Determine whether the two declarations are structurally
   /// equivalent.
-  bool IsStructurallyEquivalent(Decl *D1, Decl *D2);
+  /// Implementation functions (all static functions in
+  /// ASTStructuralEquivalence.cpp) must never call this function because that
+  /// will wreak havoc the internal state (\c DeclsToCheck and
+  /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+  bool IsEquivalent(Decl *D1, Decl *D2);
 
   /// Determine whether the two types are structurally equivalent.
-  bool IsStructurallyEquivalent(QualType T1, QualType T2);
+  /// Implementation functions (all static functions in
+  /// ASTStructuralEquivalence.cpp) must never call this function because that
+  /// will wreak havoc the internal state (\c DeclsToCheck and
+  /// \c TentativeEquivalences members) and can cause faulty equivalent results.
+  bool IsEquivalent(QualType T1, QualType T2);
 
   /// Find the index of the given anonymous struct/union within its
   /// context.
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 980ab478d5..0632da9c7f 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -295,6 +295,7 @@ namespace clang {
 
     bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
 
+    bool IsStructuralMatch(Decl *From, Decl *To, bool Complain);
     bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
                            bool Complain = true);
     bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
@@ -1592,7 +1593,15 @@ getStructuralEquivalenceKind(const ASTImporter &Importer) {
                                     : StructuralEquivalenceKind::Default;
 }
 
-bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, 
+bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) {
+  StructuralEquivalenceContext Ctx(
+      Importer.getFromContext(), Importer.getToContext(),
+      Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+      false, Complain);
+  return Ctx.IsEquivalent(From, To);
+}
+
+bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
                                         RecordDecl *ToRecord, bool Complain) {
   // Eliminate a potential failure point where we attempt to re-import
   // something we're trying to import while completing ToRecord.
@@ -1608,7 +1617,7 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
                                    Importer.getNonEquivalentDecls(),
                                    getStructuralEquivalenceKind(Importer),
                                    false, Complain);
-  return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
+  return Ctx.IsEquivalent(FromRecord, ToRecord);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
@@ -1617,14 +1626,14 @@ bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
       Importer.getFromContext(), Importer.getToContext(),
       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
       false, Complain);
-  return Ctx.IsStructurallyEquivalent(FromVar, ToVar);
+  return Ctx.IsEquivalent(FromVar, ToVar);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
   StructuralEquivalenceContext Ctx(
       Importer.getFromContext(), Importer.getToContext(),
       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer));
-  return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
+  return Ctx.IsEquivalent(FromEnum, ToEnum);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
@@ -1633,7 +1642,7 @@ bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
       Importer.getFromContext(), Importer.getToContext(),
       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
       false, false);
-  return Ctx.IsStructurallyEquivalent(From, To);
+  return Ctx.IsEquivalent(From, To);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) {
@@ -1641,7 +1650,7 @@ bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) {
       Importer.getFromContext(), Importer.getToContext(),
       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
       false, false);
-  return Ctx.IsStructurallyEquivalent(From, To);
+  return Ctx.IsEquivalent(From, To);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
@@ -1660,7 +1669,7 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From,
                                    Importer.getToContext(),
                                    Importer.getNonEquivalentDecls(),
                                    getStructuralEquivalenceKind(Importer));
-  return Ctx.IsStructurallyEquivalent(From, To);
+  return Ctx.IsEquivalent(From, To);
 }
 
 bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
@@ -1669,7 +1678,7 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
                                    Importer.getToContext(),
                                    Importer.getNonEquivalentDecls(),
                                    getStructuralEquivalenceKind(Importer));
-  return Ctx.IsStructurallyEquivalent(From, To);
+  return Ctx.IsEquivalent(From, To);
 }
 
 Decl *ASTNodeImporter::VisitDecl(Decl *D) {
@@ -2978,15 +2987,11 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
   // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
   auto *RD = cast(DC);
   FriendDecl *ImportedFriend = RD->getFirstFriend();
-  StructuralEquivalenceContext Context(
-      Importer.getFromContext(), Importer.getToContext(),
-      Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
-      false, false);
 
   while (ImportedFriend) {
     if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
-      if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
-                                           ImportedFriend->getFriendDecl()))
+      if (IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(),
+                            /*Complain=*/false))
         return Importer.MapImported(D, ImportedFriend);
 
     } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
@@ -7621,5 +7626,5 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
   StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
                                    getStructuralEquivalenceKind(*this), false,
                                    Complain);
-  return Ctx.IsStructurallyEquivalent(From, To);
+  return Ctx.IsEquivalent(From, To);
 }
diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp
index 1da7b84948..7853ab2881 100644
--- a/lib/AST/ASTStructuralEquivalence.cpp
+++ b/lib/AST/ASTStructuralEquivalence.cpp
@@ -10,6 +10,59 @@
 //  This file implement StructuralEquivalenceContext class and helper functions
 //  for layout matching.
 //
+// The structural equivalence check could have been implemented as a parallel
+// BFS on a pair of graphs.  That must have been the original approach at the
+// beginning.
+// Let's consider this simple BFS algorithm from the `s` source:
+// ```
+// void bfs(Graph G, int s)
+// {
+//   Queue queue = new Queue();
+//   marked[s] = true; // Mark the source
+//   queue.enqueue(s); // and put it on the queue.
+//   while (!q.isEmpty()) {
+//     int v = queue.dequeue(); // Remove next vertex from the queue.
+//     for (int w : G.adj(v))
+//       if (!marked[w]) // For every unmarked adjacent vertex,
+//       {
+//         marked[w] = true;
+//         queue.enqueue(w);
+//       }
+//   }
+// }
+// ```
+// Indeed, it has it's queue, which holds pairs of nodes, one from each graph,
+// this is the `DeclsToCheck` and it's pair is in `TentativeEquivalences`.
+// `TentativeEquivalences` also plays the role of the marking (`marked`)
+// functionality above, we use it to check whether we've already seen a pair of
+// nodes.
+//
+// We put in the elements into the queue only in the toplevel decl check
+// function:
+// ```
+// static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+//                                      Decl *D1, Decl *D2);
+// ```
+// The `while` loop where we iterate over the children is implemented in
+// `Finish()`.  And `Finish` is called only from the two **member** functions
+// which check the equivalency of two Decls or two Types. ASTImporter (and
+// other clients) call only these functions.
+//
+// The `static` implementation functions are called from `Finish`, these push
+// the children nodes to the queue via `static bool
+// IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1,
+// Decl *D2)`.  So far so good, this is almost like the BFS.  However, if we
+// let a static implementation function to call `Finish` via another **member**
+// function that means we end up with two nested while loops each of them
+// working on the same queue. This is wrong and nobody can reason about it's
+// doing. Thus, static implementation functions must not call the **member**
+// functions.
+//
+// So, now `TentativeEquivalences` plays two roles. It is used to store the
+// second half of the decls which we want to compare, plus it plays a role in
+// closing the recursion. On a long term, we could refactor structural
+// equivalency to be more alike to the traditional BFS.
+//
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTStructuralEquivalence.h"
@@ -184,10 +237,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return true;
 
   case TemplateArgument::Type:
-    return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType());
+    return IsStructurallyEquivalent(Context, Arg1.getAsType(), Arg2.getAsType());
 
   case TemplateArgument::Integral:
-    if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(),
+    if (!IsStructurallyEquivalent(Context, Arg1.getIntegralType(),
                                           Arg2.getIntegralType()))
       return false;
 
@@ -195,7 +248,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
                                      Arg2.getAsIntegral());
 
   case TemplateArgument::Declaration:
-    return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
+    return IsStructurallyEquivalent(Context, Arg1.getAsDecl(), Arg2.getAsDecl());
 
   case TemplateArgument::NullPtr:
     return true; // FIXME: Is this correct?
@@ -1205,8 +1258,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
       return false;
     }
 
-    if (!Context.IsStructurallyEquivalent(Params1->getParam(I),
-                                          Params2->getParam(I)))
+    if (!IsStructurallyEquivalent(Context, Params1->getParam(I),
+                                  Params2->getParam(I)))
       return false;
   }
 
@@ -1243,7 +1296,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
   }
 
   // Check types.
-  if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) {
+  if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) {
     if (Context.Complain) {
       Context.Diag2(D2->getLocation(),
                     diag::err_odr_non_type_parameter_type_inconsistent)
@@ -1294,8 +1347,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return false;
 
   // Check the templated declaration.
-  return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(),
-                                          D2->getTemplatedDecl());
+  return IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
+                                  D2->getTemplatedDecl());
 }
 
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
@@ -1306,8 +1359,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return false;
 
   // Check the templated declaration.
-  return Context.IsStructurallyEquivalent(D1->getTemplatedDecl()->getType(),
-                                          D2->getTemplatedDecl()->getType());
+  return IsStructurallyEquivalent(Context, D1->getTemplatedDecl()->getType(),
+                                  D2->getTemplatedDecl()->getType());
 }
 
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
@@ -1418,16 +1471,26 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
   return Index;
 }
 
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1,
-                                                            Decl *D2) {
+bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) {
+
+  // Ensure that the implementation functions (all static functions in this TU)
+  // never call the public ASTStructuralEquivalence::IsEquivalent() functions,
+  // because that will wreak havoc the internal state (DeclsToCheck and
+  // TentativeEquivalences members) and can cause faulty behaviour. For
+  // instance, some leaf declarations can be stated and cached as inequivalent
+  // as a side effect of one inequivalent element in the DeclsToCheck list.
+  assert(DeclsToCheck.empty());
+  assert(TentativeEquivalences.empty());
+
   if (!::IsStructurallyEquivalent(*this, D1, D2))
     return false;
 
   return !Finish();
 }
 
-bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1,
-                                                            QualType T2) {
+bool StructuralEquivalenceContext::IsEquivalent(QualType T1, QualType T2) {
+  assert(DeclsToCheck.empty());
+  assert(TentativeEquivalences.empty());
   if (!::IsStructurallyEquivalent(*this, T1, T2))
     return false;
 
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 0736fabac3..ac04cecaf7 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -7498,7 +7498,7 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
       StructuralEquivalenceKind::Default,
       false /*StrictTypeSpelling*/, true /*Complain*/,
       true /*ErrorOnTagTypeMismatch*/);
-  return Ctx.IsStructurallyEquivalent(D, Suggested);
+  return Ctx.IsEquivalent(D, Suggested);
 }
 
 /// Determine whether there is any declaration of \p D that was ever a
diff --git a/unittests/AST/StructuralEquivalenceTest.cpp b/unittests/AST/StructuralEquivalenceTest.cpp
index 19d2e334fc..d5b529c6b6 100644
--- a/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/unittests/AST/StructuralEquivalenceTest.cpp
@@ -82,7 +82,7 @@ struct StructuralEquivalenceTest : ::testing::Test {
     StructuralEquivalenceContext Ctx(
         D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls,
         StructuralEquivalenceKind::Default, false, false);
-    return Ctx.IsStructurallyEquivalent(D0, D1);
+    return Ctx.IsEquivalent(D0, D1);
   }
 
   bool testStructuralMatch(std::tuple t) {
-- 
GitLab


From e018aa40121dd0ecfef49924a3d5d3869a451550 Mon Sep 17 00:00:00 2001
From: Joerg Sonnenberger 
Date: Tue, 17 Jul 2018 13:13:34 +0000
Subject: [PATCH 0579/1023] Always use __mcount on NetBSD. Some platforms don't
 provide _mcount.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337277 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/Targets/OSTargets.h |  2 +-
 test/CodeGen/mcount.c         | 22 ++++++++++++----------
 test/Frontend/gnu-mcount.c    |  2 +-
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h
index 18239a2ec7..cb7f089c09 100644
--- a/lib/Basic/Targets/OSTargets.h
+++ b/lib/Basic/Targets/OSTargets.h
@@ -369,7 +369,7 @@ protected:
 public:
   NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
       : OSTargetInfo(Triple, Opts) {
-    this->MCountName = "_mcount";
+    this->MCountName = "__mcount";
   }
 };
 
diff --git a/test/CodeGen/mcount.c b/test/CodeGen/mcount.c
index 98a2a6b390..c67cf03c00 100644
--- a/test/CodeGen/mcount.c
+++ b/test/CodeGen/mcount.c
@@ -3,20 +3,20 @@
 // RUN: %clang_cc1 -pg -triple powerpc-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple powerpc64-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple powerpc64le-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple i386-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple x86_64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple arm-netbsd-eabi -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple aarch64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple mips-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple i386-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple x86_64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple arm-netbsd-eabi -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple aarch64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple mips-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple mips-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple mipsel-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple mips64-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -pg -triple mips64el-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple powerpc64le-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple sparc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
-// RUN: %clang_cc1 -pg -triple sparc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple powerpc64le-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple sparc-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
+// RUN: %clang_cc1 -pg -triple sparc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK-DOUBLE-PREFIXED,NO-MCOUNT1 %s
 // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -check-prefix=NO-MCOUNT
 
 int bar(void) {
@@ -39,5 +39,7 @@ int main(void) {
 // CHECK: attributes #1 = { {{.*}} }
 // CHECK-PREFIXED: attributes #0 = { {{.*}}"instrument-function-entry-inlined"="_mcount"{{.*}} }
 // CHECK-PREFIXED: attributes #1 = { {{.*}} }
+// CHECK-DOUBLE-PREFIXED: attributes #0 = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
+// CHECK-DOUBLE-PREFIXED: attributes #1 = { {{.*}} }
 // NO-MCOUNT-NOT: attributes #{{[0-9]}} = { {{.*}}"instrument-function-entry-inlined"={{.*}} }
 // NO-MCOUNT1-NOT: attributes #1 = { {{.*}}"instrument-function-entry-inlined"={{.*}} }
diff --git a/test/Frontend/gnu-mcount.c b/test/Frontend/gnu-mcount.c
index 3953d24153..baac555d13 100644
--- a/test/Frontend/gnu-mcount.c
+++ b/test/Frontend/gnu-mcount.c
@@ -59,7 +59,7 @@ int f() {
 // CHECK-ARM-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
 // CHECK-ARM64-EABI-FREEBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"=".mcount"{{.*}} }
 // CHECK-ARM64-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
-// CHECK-ARM-EABI-NETBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="_mcount"{{.*}} }
+// CHECK-ARM-EABI-NETBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
 // CHECK-ARM-EABI-NETBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
 // CHECK-ARM-EABI-OPENBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
 // CHECK-ARM-EABI-OPENBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
-- 
GitLab


From 30ed46c73401d62e0654092e227e5675fbc339d6 Mon Sep 17 00:00:00 2001
From: Benjamin Kramer 
Date: Tue, 17 Jul 2018 13:17:01 +0000
Subject: [PATCH 0580/1023] Revert "[Sema] Reword warning for constant captures
 that are not required"

This reverts commit r337152. This applies to non-constants too. The real
explanation is that the capture is not ODR-used, but putting that into
the warning message seems ... worse.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337278 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td  |  4 ++--
 test/SemaCXX/warn-unused-lambda-capture.cpp | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c32b5ea07a..1915f7e3be 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -341,8 +341,8 @@ def warn_unneeded_member_function : Warning<
   InGroup, DefaultIgnore;
 def warn_unused_private_field: Warning<"private field %0 is not used">,
   InGroup, DefaultIgnore;
-def warn_unused_lambda_capture: Warning<"lambda capture "
-  "%select{|of constant }1%0 is not %select{used|required for this use}1">,
+def warn_unused_lambda_capture: Warning<"lambda capture %0 is not "
+  "%select{used|required to be captured for this use}1">,
   InGroup, DefaultIgnore;
 
 def warn_parameter_size: Warning<
diff --git a/test/SemaCXX/warn-unused-lambda-capture.cpp b/test/SemaCXX/warn-unused-lambda-capture.cpp
index f1f0c9e2bc..52ec390b0b 100644
--- a/test/SemaCXX/warn-unused-lambda-capture.cpp
+++ b/test/SemaCXX/warn-unused-lambda-capture.cpp
@@ -41,9 +41,9 @@ void test() {
   auto explicit_by_value_used = [i] { return i + 1; };
   auto explicit_by_value_used_void = [i] { (void)i; };
   auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
-  auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture of constant 'i' is not required for this use}}
-  auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture of constant 'i' is not required for this use}}
-  auto explicit_by_value_unused_const = [k] { return k + 1; };         // expected-warning{{lambda capture of constant 'k' is not required for this use}}
+  auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+  auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+  auto explicit_by_value_unused_const = [k] { return k + 1; };         // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
 
   auto explicit_by_reference_used = [&i] { i++; };
   auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}
@@ -146,10 +146,10 @@ void test_templated() {
   auto explicit_by_value_used_void = [i] { (void)i; };
 
   auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
-  auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture of constant 'i' is not required for this use}}
+  auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
   auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}}
-  auto explicit_by_value_unused_const = [k] { return k + 1; };         // expected-warning{{lambda capture of constant 'k' is not required for this use}}
-  auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture of constant 'k' is not required for this use}}
+  auto explicit_by_value_unused_const = [k] { return k + 1; };         // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
+  auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
 
   auto explicit_by_reference_used = [&i] { i++; };
   auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}
-- 
GitLab


From 5e12144b17b760c132a1afad02c0949c77354b7a Mon Sep 17 00:00:00 2001
From: Simon Marchi 
Date: Tue, 17 Jul 2018 14:13:05 +0000
Subject: [PATCH 0581/1023] [Tooling] Add operator== to CompileCommand

Summary:
It does the obvious thing of comparing all fields.  This will be needed
for a clangd patch I have in the pipeline.

Subscribers: dblaikie, ilya-biryukov, ioeric, cfe-commits

Differential Revision: https://reviews.llvm.org/D49265

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337284 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Tooling/CompilationDatabase.h   |  9 ++++++
 unittests/Tooling/CompilationDatabaseTest.cpp | 28 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 185e496879..37e515fdc0 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -59,6 +59,15 @@ struct CompileCommand {
 
   /// The output file associated with the command.
   std::string Output;
+
+  friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) {
+    return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
+           LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output;
+  }
+
+  friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) {
+    return !(LHS == RHS);
+  }
 };
 
 /// Interface for compilation databases.
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index 42497f7069..ffc1d5b3a4 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -736,5 +736,33 @@ TEST_F(InterpolateTest, Case) {
   EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
 }
 
+TEST(CompileCommandTest, EqualityOperator) {
+  CompileCommand CCRef("/foo/bar", "hello.c", {"a", "b"}, "hello.o");
+  CompileCommand CCTest = CCRef;
+
+  EXPECT_TRUE(CCRef == CCTest);
+  EXPECT_FALSE(CCRef != CCTest);
+
+  CCTest = CCRef;
+  CCTest.Directory = "/foo/baz";
+  EXPECT_FALSE(CCRef == CCTest);
+  EXPECT_TRUE(CCRef != CCTest);
+
+  CCTest = CCRef;
+  CCTest.Filename = "bonjour.c";
+  EXPECT_FALSE(CCRef == CCTest);
+  EXPECT_TRUE(CCRef != CCTest);
+
+  CCTest = CCRef;
+  CCTest.CommandLine.push_back("c");
+  EXPECT_FALSE(CCRef == CCTest);
+  EXPECT_TRUE(CCRef != CCTest);
+
+  CCTest = CCRef;
+  CCTest.Output = "bonjour.o";
+  EXPECT_FALSE(CCRef == CCTest);
+  EXPECT_TRUE(CCRef != CCTest);
+}
+
 } // end namespace tooling
 } // end namespace clang
-- 
GitLab


From e4bc29d07fb7130830daf3528eb970b39be6f9f9 Mon Sep 17 00:00:00 2001
From: Nico Weber 
Date: Tue, 17 Jul 2018 14:20:02 +0000
Subject: [PATCH 0582/1023] Remove superfluous ; to fix -Wpedantic warning from
 gcc

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337285 91177308-0d34-0410-b5e6-96231b3b80d8
---
 unittests/AST/ASTImporterTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index 84bfdadae2..21b76173c1 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -276,7 +276,7 @@ public:
 template  RecordDecl *getRecordDecl(T *D) {
   auto *ET = cast(D->getType().getTypePtr());
   return cast(ET->getNamedType().getTypePtr())->getDecl();
-};
+}
 
 // This class provides generic methods to write tests which can check internal
 // attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
-- 
GitLab


From 2a5e6fd94b730b5c48ce534a96f58352667e3f45 Mon Sep 17 00:00:00 2001
From: Leonard Chan 
Date: Tue, 17 Jul 2018 14:58:49 +0000
Subject: [PATCH 0583/1023] [Fixed Point Arithmetic] Fix for bug where integer
 literals could be treated as fixed point literals

This addresses a bug brought up in https://bugs.llvm.org/show_bug.cgi?id=38161 where integer literals could be treated as fixed point types and throw errors related to fixed point types when the 'k' or 'r' suffix used. The fix also addresses the second issue brought up with the assertion by not treating integers as fixed point types in the first place.

Integers that have suffixes 'k' and 'r' now throw the error `invalid suffix 'k/r' on integer constant`.

A few more tests were also added to ensure that fixed point types, and any errors/warnings related to them, are limited to C for now.

Prior discussion also at https://reviews.llvm.org/D46915.

Differential Revision: https://reviews.llvm.org/D49327

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337289 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Lex/LiteralSupport.cpp              | 15 +++--
 test/Frontend/fixed_point_errors.c      | 84 +++++++++++++++++++++++++
 test/Frontend/fixed_point_errors.cpp    |  5 ++
 test/Frontend/fixed_point_not_enabled.c |  6 ++
 4 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index c1be3b2a97..e695b2ba37 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -572,10 +572,12 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
   checkSeparator(TokLoc, s, CSK_AfterDigits);
 
   // Initial scan to lookahead for fixed point suffix.
-  for (const char *c = s; c != ThisTokEnd; ++c) {
-    if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
-      saw_fixed_point_suffix = true;
-      break;
+  if (PP.getLangOpts().FixedPoint) {
+    for (const char *c = s; c != ThisTokEnd; ++c) {
+      if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
+        saw_fixed_point_suffix = true;
+        break;
+      }
     }
   }
 
@@ -589,12 +591,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
     switch (*s) {
     case 'R':
     case 'r':
+      if (!PP.getLangOpts().FixedPoint) break;
       if (isFract || isAccum) break;
+      if (!(saw_period || saw_exponent)) break;
       isFract = true;
       continue;
     case 'K':
     case 'k':
+      if (!PP.getLangOpts().FixedPoint) break;
       if (isFract || isAccum) break;
+      if (!(saw_period || saw_exponent)) break;
       isAccum = true;
       continue;
     case 'h':      // FP Suffix for "half".
@@ -734,7 +740,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
 
   if (!hadError && saw_fixed_point_suffix) {
     assert(isFract || isAccum);
-    //assert(radix == 16 || radix == 10);
   }
 }
 
diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c
index f55fc82f91..41427e3431 100644
--- a/test/Frontend/fixed_point_errors.c
+++ b/test/Frontend/fixed_point_errors.c
@@ -148,3 +148,87 @@ _Accum dec_with_hex_exp1 = 0.1p10k;    // expected-error{{invalid suffix 'p10k'
 _Accum dec_with_hex_exp2 = 0.1P10k;    // expected-error{{invalid suffix 'P10k' on integer constant}}
 _Accum hex_with_dex_exp1 = 0x0.1e10k;  // expected-error{{hexadecimal floating constant requires an exponent}}
 _Accum hex_with_dex_exp2 = 0x0.1E10k;  // expected-error{{hexadecimal floating constant requires an exponent}}
+
+void CheckSuffixOnIntegerLiterals() {
+  _Accum short_acc_int;
+  _Accum acc_int;
+  _Accum long_acc_int;
+
+  _Accum u_short_acc_int;
+  _Accum u_acc_int;
+  _Accum u_long_acc_int;
+
+  _Fract short_fract_int;
+  _Fract fract_int;
+  _Fract long_fract_int;
+
+  _Fract u_short_fract_int;
+  _Fract u_fract_int;
+  _Fract u_long_fract_int;
+
+  // Decimal integer literals (non-zero)
+  short_acc_int = 10hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+  acc_int = 10k;        // expected-error{{invalid suffix 'k' on integer constant}}
+  long_acc_int = 10lk;  // expected-error{{invalid suffix 'lk' on integer constant}}
+
+  u_short_acc_int = 10uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+  u_acc_int = 10uk;        // expected-error{{invalid suffix 'uk' on integer constant}}
+  u_long_acc_int = 10ulk;  // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+  short_fract_int = 10hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+  fract_int = 10r;        // expected-error{{invalid suffix 'r' on integer constant}}
+  long_fract_int = 10lr;  // expected-error{{invalid suffix 'lr' on integer constant}}
+
+  u_short_fract_int = 10uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+  u_fract_int = 10ur;        // expected-error{{invalid suffix 'ur' on integer constant}}
+  u_long_fract_int = 10ulr;  // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+  // Decimal integer literals (0)
+  short_acc_int = 0hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+  acc_int = 0k;        // expected-error{{invalid suffix 'k' on integer constant}}
+  long_acc_int = 0lk;  // expected-error{{invalid suffix 'lk' on integer constant}}
+
+  // Decimal integer literals (large number)
+  acc_int = 999999999999999999k;   // expected-error{{invalid suffix 'k' on integer constant}}
+  fract_int = 999999999999999999r; // expected-error{{invalid suffix 'r' on integer constant}}
+
+  // Octal integer literals
+  short_acc_int = 010hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+  acc_int = 010k;        // expected-error{{invalid suffix 'k' on integer constant}}
+  long_acc_int = 010lk;  // expected-error{{invalid suffix 'lk' on integer constant}}
+
+  u_short_acc_int = 010uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+  u_acc_int = 010uk;        // expected-error{{invalid suffix 'uk' on integer constant}}
+  u_long_acc_int = 010ulk;  // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+  short_fract_int = 010hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+  fract_int = 010r;        // expected-error{{invalid suffix 'r' on integer constant}}
+  long_fract_int = 010lr;  // expected-error{{invalid suffix 'lr' on integer constant}}
+
+  u_short_fract_int = 010uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+  u_fract_int = 010ur;        // expected-error{{invalid suffix 'ur' on integer constant}}
+  u_long_fract_int = 010ulr;  // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+  // Hexadecimal integer literals
+  short_acc_int = 0x10hk; // expected-error{{invalid suffix 'hk' on integer constant}}
+  acc_int = 0x10k;        // expected-error{{invalid suffix 'k' on integer constant}}
+  long_acc_int = 0x10lk;  // expected-error{{invalid suffix 'lk' on integer constant}}
+
+  u_short_acc_int = 0x10uhk; // expected-error{{invalid suffix 'uhk' on integer constant}}
+  u_acc_int = 0x10uk;        // expected-error{{invalid suffix 'uk' on integer constant}}
+  u_long_acc_int = 0x10ulk;  // expected-error{{invalid suffix 'ulk' on integer constant}}
+
+  short_fract_int = 0x10hr; // expected-error{{invalid suffix 'hr' on integer constant}}
+  fract_int = 0x10r;        // expected-error{{invalid suffix 'r' on integer constant}}
+  long_fract_int = 0x10lr;  // expected-error{{invalid suffix 'lr' on integer constant}}
+
+  u_short_fract_int = 0x10uhr; // expected-error{{invalid suffix 'uhr' on integer constant}}
+  u_fract_int = 0x10ur;        // expected-error{{invalid suffix 'ur' on integer constant}}
+  u_long_fract_int = 0x10ulr;  // expected-error{{invalid suffix 'ulr' on integer constant}}
+
+  // Using auto
+  auto auto_fract = 0r;  // expected-error{{invalid suffix 'r' on integer constant}}
+                         // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+  auto auto_accum = 0k;  // expected-error{{invalid suffix 'k' on integer constant}}
+                         // expected-warning@-1{{type specifier missing, defaults to 'int'}}
+}
diff --git a/test/Frontend/fixed_point_errors.cpp b/test/Frontend/fixed_point_errors.cpp
index 37027b4ef0..cdd90ceb75 100644
--- a/test/Frontend/fixed_point_errors.cpp
+++ b/test/Frontend/fixed_point_errors.cpp
@@ -7,3 +7,8 @@ _Accum accum;                           // expected-error{{unknown type name '_A
 _Fract fract;                           // expected-error{{unknown type name '_Fract'}}
 _Sat _Accum sat_accum;                  // expected-error{{unknown type name '_Sat'}}
                                         // expected-error@-1{{expected ';' after top level declarator}}
+
+int accum_int = 10k;     // expected-error{{invalid suffix 'k' on integer constant}}
+int fract_int = 10r;     // expected-error{{invalid suffix 'r' on integer constant}}
+float accum_flt = 10.0k; // expected-error{{invalid suffix 'k' on floating constant}}
+float fract_flt = 10.0r; // expected-error{{invalid suffix 'r' on floating constant}}
diff --git a/test/Frontend/fixed_point_not_enabled.c b/test/Frontend/fixed_point_not_enabled.c
index e5c82f54b6..e7522213f9 100644
--- a/test/Frontend/fixed_point_not_enabled.c
+++ b/test/Frontend/fixed_point_not_enabled.c
@@ -13,3 +13,9 @@ short _Accum short_accum;             // expected-error{{compile with '-ffixed-p
 _Accum accum;                         // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
                                       // expected-warning@-1{{type specifier missing, defaults to 'int'}}
 long _Accum long_accum;               // expected-error{{compile with '-ffixed-point' to enable fixed point types}}
+
+// Cannot use fixed point suffixes
+int accum_int = 10k;     // expected-error{{invalid suffix 'k' on integer constant}}
+int fract_int = 10r;     // expected-error{{invalid suffix 'r' on integer constant}}
+float accum_flt = 10.0k; // expected-error{{invalid suffix 'k' on floating constant}}
+float fract_flt = 10.0r; // expected-error{{invalid suffix 'r' on floating constant}}
-- 
GitLab


From 2ef99755830c3d74d9c54140ad06ff70eae3c34c Mon Sep 17 00:00:00 2001
From: Nico Weber 
Date: Tue, 17 Jul 2018 15:07:40 +0000
Subject: [PATCH 0584/1023] clang-cl: Postpone Wmsvc-not-found emission until
 link.exe gets used.

Wmsvc-not-found was added in r297851 to help diagnose why link.exe can't be
executed. However, it's emitted even when using -fuse-ld=lld, and in cross
builds there's no way to get rid of the warning other than disabling it.

Instead, emit it when we look up link.exe and it ends up not being executable.
That way, when passing -fuse-ld=lld it will never be printed.
It will also not be printed if we find link.exe on PATH.

(We might want to eventually default to lld one day, at least when running on a
non-Win host, but that's for another day.)

Fixes PR38016.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337290 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Driver/ToolChains/MSVC.cpp | 5 +++--
 lib/Driver/ToolChains/MSVC.h   | 2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp
index 3ce1bfa0aa..d062c6abc9 100644
--- a/lib/Driver/ToolChains/MSVC.cpp
+++ b/lib/Driver/ToolChains/MSVC.cpp
@@ -469,6 +469,9 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // their own link.exe which may come first.
     linkPath = FindVisualStudioExecutable(TC, "link.exe");
 
+    if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath))
+      C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
+
 #ifdef _WIN32
     // When cross-compiling with VS2017 or newer, link.exe expects to have
     // its containing bin directory at the top of PATH, followed by the
@@ -684,8 +687,6 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
 }
 
 Tool *MSVCToolChain::buildLinker() const {
-  if (VCToolChainPath.empty())
-    getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
   return new tools::visualstudio::Linker(*this);
 }
 
diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h
index d498cd5642..1db589ec97 100644
--- a/lib/Driver/ToolChains/MSVC.h
+++ b/lib/Driver/ToolChains/MSVC.h
@@ -123,6 +123,8 @@ public:
 
   void printVerboseInfo(raw_ostream &OS) const override;
 
+  bool FoundMSVCInstall() const { return !VCToolChainPath.empty(); }
+
 protected:
   void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
                                      llvm::opt::ArgStringList &CC1Args,
-- 
GitLab


From 387f78a0dc596db7be2f66f809abe32754fe7e55 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" 
Date: Tue, 17 Jul 2018 17:40:34 +0000
Subject: [PATCH 0585/1023] [analyzer] Fix Z3 backend after D48205

Summary:
An assertion was added in D48205 to catch places where a `nonloc::SymbolVal` was wrapping a `loc` object.

This patch fixes that in the Z3 backend by making the `SValBuilder` object accessible from inherited instances of `SimpleConstraintManager` and calling `SVB.makeSymbolVal(foo)` instead of `nonloc::SymbolVal(foo)`.

Reviewers: NoQ, george.karpenkov

Reviewed By: NoQ

Subscribers: xazax.hun, szepet, a.sidorin

Differential Revision: https://reviews.llvm.org/D49430

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337304 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../PathSensitive/SimpleConstraintManager.h   |  1 +
 .../Core/Z3ConstraintManager.cpp              | 59 +++++++++----------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
index db6b8c0900..d64b90e2d3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h
@@ -75,6 +75,7 @@ protected:
   // Internal implementation.
   //===------------------------------------------------------------------===//
 
+  SValBuilder &getSValBuilder() const { return SVB; }
   BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); }
   SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); }
 
diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
index 721e17759f..66a6cf5bad 100644
--- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1077,40 +1077,39 @@ bool Z3ConstraintManager::canReasonAbout(SVal X) const {
     return true;
 
   const SymExpr *Sym = SymVal->getSymbol();
-  do {
-    QualType Ty = Sym->getType();
+  QualType Ty = Sym->getType();
 
-    // Complex types are not modeled
-    if (Ty->isComplexType() || Ty->isComplexIntegerType())
-      return false;
+  // Complex types are not modeled
+  if (Ty->isComplexType() || Ty->isComplexIntegerType())
+    return false;
 
-    // Non-IEEE 754 floating-point types are not modeled
-    if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
-         (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
-          &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
-      return false;
+  // Non-IEEE 754 floating-point types are not modeled
+  if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+       (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
+        &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
+    return false;
 
-    if (isa(Sym)) {
-      break;
-    } else if (const SymbolCast *SC = dyn_cast(Sym)) {
-      Sym = SC->getOperand();
-    } else if (const BinarySymExpr *BSE = dyn_cast(Sym)) {
-      if (const SymIntExpr *SIE = dyn_cast(BSE)) {
-        Sym = SIE->getLHS();
-      } else if (const IntSymExpr *ISE = dyn_cast(BSE)) {
-        Sym = ISE->getRHS();
-      } else if (const SymSymExpr *SSM = dyn_cast(BSE)) {
-        return canReasonAbout(nonloc::SymbolVal(SSM->getLHS())) &&
-               canReasonAbout(nonloc::SymbolVal(SSM->getRHS()));
-      } else {
-        llvm_unreachable("Unsupported binary expression to reason about!");
-      }
-    } else {
-      llvm_unreachable("Unsupported expression to reason about!");
-    }
-  } while (Sym);
+  if (isa(Sym))
+    return true;
+
+  SValBuilder &SVB = getSValBuilder();
+
+  if (const SymbolCast *SC = dyn_cast(Sym))
+    return canReasonAbout(SVB.makeSymbolVal(SC->getOperand()));
+
+  if (const BinarySymExpr *BSE = dyn_cast(Sym)) {
+    if (const SymIntExpr *SIE = dyn_cast(BSE))
+      return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS()));
+
+    if (const IntSymExpr *ISE = dyn_cast(BSE))
+      return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS()));
+
+    if (const SymSymExpr *SSE = dyn_cast(BSE))
+      return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) &&
+             canReasonAbout(SVB.makeSymbolVal(SSE->getRHS()));
+  }
 
-  return true;
+  llvm_unreachable("Unsupported expression to reason about!");
 }
 
 ConditionTruthVal Z3ConstraintManager::checkNull(ProgramStateRef State,
-- 
GitLab


From 726843da082dc448eec5048f24bea1bfebbc969c Mon Sep 17 00:00:00 2001
From: Eric Christopher 
Date: Tue, 17 Jul 2018 20:22:17 +0000
Subject: [PATCH 0586/1023] Remove unnecessary trailing ; in macro intrinsic
 definition.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337321 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Headers/avx512dqintrin.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h
index 1ce1b212cb..8a00b3afa9 100644
--- a/lib/Headers/avx512dqintrin.h
+++ b/lib/Headers/avx512dqintrin.h
@@ -1105,7 +1105,7 @@ _mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A)
 #define _mm512_extractf32x8_ps(A, imm) \
   (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
                                            (__v8sf)_mm256_undefined_ps(), \
-                                           (__mmask8)-1);
+                                           (__mmask8)-1)
 
 #define _mm512_mask_extractf32x8_ps(W, U, A, imm) \
   (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
-- 
GitLab


From 4fbd5c5474db41197df34d8e9eaae28967a30aa4 Mon Sep 17 00:00:00 2001
From: Mandeep Singh Grang 
Date: Tue, 17 Jul 2018 22:03:24 +0000
Subject: [PATCH 0587/1023] [COFF] Add more missing MSVC ARM64 intrinsics

Summary:
Added the following intrinsics:
_BitScanForward, _BitScanReverse, _BitScanForward64, _BitScanReverse64
_InterlockedAnd64, _InterlockedDecrement64, _InterlockedExchange64,
_InterlockedExchangeAdd64, _InterlockedExchangeSub64,
_InterlockedIncrement64, _InterlockedOr64, _InterlockedXor64.

Reviewers: compnerd, mstorsjo, rnk, javed.absar

Reviewed By: mstorsjo

Subscribers: kristof.beyls, chrib, llvm-commits

Differential Revision: https://reviews.llvm.org/D49445

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337327 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/BuiltinsAArch64.def | 19 ++++++++++++++++++
 lib/CodeGen/CGBuiltin.cpp               | 26 +++++++++++++++++++++++--
 lib/Headers/intrin.h                    |  4 ++--
 test/CodeGen/ms-intrinsics.c            | 10 +++++++---
 4 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index af336ae1f5..b5d971d0bc 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -18,6 +18,10 @@
 #   define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
 #endif
 
+#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN)
+#  define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
 // In libgcc
 BUILTIN(__clear_cache, "vv*v*", "i")
 
@@ -85,5 +89,20 @@ LANGBUILTIN(__iso_volatile_store16, "vsD*s",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store32, "viD*i",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES)
 
+TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(_InterlockedAnd64,         "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedDecrement64,   "LLiLLiD*",    "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchange64,    "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedIncrement64,   "LLiLLiD*",    "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedOr64,          "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_InterlockedXor64,         "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
 #undef BUILTIN
 #undef LANGBUILTIN
+#undef TARGET_HEADER_BUILTIN
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index ad983372df..92091345f2 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -732,8 +732,8 @@ static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind,
   return RValue::get(CS.getInstruction());
 }
 
-// Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we
-// handle them here.
+// Many of MSVC builtins are on x64, ARM and AArch64; to avoid repeating code,
+// we handle them here.
 enum class CodeGenFunction::MSVCIntrin {
   _BitScanForward,
   _BitScanReverse,
@@ -8385,6 +8385,28 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
   case AArch64::BI__iso_volatile_store32:
   case AArch64::BI__iso_volatile_store64:
     return EmitISOVolatileStore(E);
+  case AArch64::BI_BitScanForward:
+  case AArch64::BI_BitScanForward64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E);
+  case AArch64::BI_BitScanReverse:
+  case AArch64::BI_BitScanReverse64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E);
+  case AArch64::BI_InterlockedAnd64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E);
+  case AArch64::BI_InterlockedExchange64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E);
+  case AArch64::BI_InterlockedExchangeAdd64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E);
+  case AArch64::BI_InterlockedExchangeSub64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E);
+  case AArch64::BI_InterlockedOr64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E);
+  case AArch64::BI_InterlockedXor64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E);
+  case AArch64::BI_InterlockedDecrement64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
+  case AArch64::BI_InterlockedIncrement64:
+    return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
   }
 }
 
diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h
index 7dd70acc37..edb947eef6 100644
--- a/lib/Headers/intrin.h
+++ b/lib/Headers/intrin.h
@@ -38,7 +38,7 @@
 #include 
 #endif
 
-#if defined(_M_ARM64)
+#if defined(__aarch64__)
 #include 
 #endif
 
@@ -299,7 +299,7 @@ unsigned __int64 _umul128(unsigned __int64,
 
 #endif /* __x86_64__ */
 
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
 
 static __inline__
 unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c
index 2e85be8926..a8c234123a 100644
--- a/test/CodeGen/ms-intrinsics.c
+++ b/test/CodeGen/ms-intrinsics.c
@@ -7,6 +7,9 @@
 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN:         -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \
 // RUN:         | FileCheck %s --check-prefixes CHECK,CHECK-X64,CHECK-ARM-X64,CHECK-INTEL
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN:         -triple aarch64-windows -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s --check-prefix CHECK-ARM-X64
 
 // intrin.h needs size_t, but -ffreestanding prevents us from getting it from
 // stddef.h.  Work around it with this typedef.
@@ -172,7 +175,7 @@ unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) {
 // CHECK:   store i32 [[INDEX]], i32* %Index, align 4
 // CHECK:   br label %[[END_LABEL]]
 
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
 unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask) {
   return _BitScanForward64(Index, Mask);
 }
@@ -469,7 +472,7 @@ long test_InterlockedDecrement(long volatile *Addend) {
 // CHECK: ret i32 [[RESULT]]
 // CHECK: }
 
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
 __int64 test_InterlockedExchange64(__int64 volatile *value, __int64 mask) {
   return _InterlockedExchange64(value, mask);
 }
@@ -587,6 +590,7 @@ __int64 test_InterlockedCompareExchange64_HLERelease(__int64 volatile *Destinati
 }
 #endif
 
+#if !defined(__aarch64__)
 void test__fastfail() {
   __fastfail(42);
 }
@@ -597,4 +601,4 @@ void test__fastfail() {
 // Attributes come last.
 
 // CHECK: attributes #[[NORETURN]] = { noreturn{{.*}} }
-
+#endif
-- 
GitLab


From 43554aef455595d09c8da17584ceeb7a65c4fc2a Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Tue, 17 Jul 2018 22:24:09 +0000
Subject: [PATCH 0588/1023] Restructure checking for, and warning on, lifetime
 extension.

This change implements C++ DR1696, which makes initialization of a
reference member of a class from a temporary object ill-formed. The
standard wording here is imprecise, but we interpret it as meaning that
any time a mem-initializer would result in lifetime extension, the
program is ill-formed.

This reinstates r337226, reverted in r337255, with a fix for the
InitializedEntity alignment problem that was breaking ARM buildbots.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337329 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticGroups.td       |   1 +
 include/clang/Basic/DiagnosticSemaKinds.td    |  40 +-
 include/clang/Sema/Initialization.h           |  36 +-
 include/clang/Sema/Sema.h                     |   5 +
 lib/Sema/SemaDeclCXX.cpp                      |   7 +-
 lib/Sema/SemaExprCXX.cpp                      |   7 -
 lib/Sema/SemaInit.cpp                         | 370 +++++++++++++-----
 test/Analysis/initializer.cpp                 |  23 --
 test/CXX/drs/dr16xx.cpp                       |  94 +++++
 test/CXX/drs/dr18xx.cpp                       |  11 +
 test/CXX/special/class.copy/p11.0x.copy.cpp   |  13 +-
 test/CXX/special/class.copy/p11.0x.move.cpp   |   2 +-
 test/CXX/special/class.ctor/p5-0x.cpp         |   6 +-
 test/CXX/temp/temp.param/p5.cpp               |  12 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |  30 --
 test/CodeGenCXX/temporaries.cpp               |  27 --
 test/SemaCXX/constant-expression-cxx11.cpp    |   9 +-
 test/SemaCXX/constexpr-default-arg.cpp        |   4 +-
 .../cxx0x-initializer-stdinitializerlist.cpp  |   9 +-
 test/SemaCXX/eval-crashes.cpp                 |   6 +-
 test/SemaCXX/member-init.cpp                  |   3 +-
 test/SemaCXX/warn-dangling-field.cpp          |   6 +-
 www/cxx_dr_status.html                        |   4 +-
 23 files changed, 484 insertions(+), 241 deletions(-)

diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index e021cf6975..e27dc0d764 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -272,6 +272,7 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
 def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
 def DanglingElse: DiagGroup<"dangling-else">;
 def DanglingField : DiagGroup<"dangling-field">;
+def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
 def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
 def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
 def FlagEnum : DiagGroup<"flag-enum">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 1915f7e3be..e441f7b8f5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2049,10 +2049,6 @@ def err_implied_std_initializer_list_not_found : Error<
   "not found; include ">;
 def err_malformed_std_initializer_list : Error<
   "std::initializer_list must be a class template with a single type parameter">;
-def warn_dangling_std_initializer_list : Warning<
-  "array backing the initializer list will be destroyed at the end of "
-  "%select{the full-expression|the constructor}0">,
-  InGroup>;
 def err_auto_init_list_from_c : Error<
   "cannot use __auto_type with initializer list in C">;
 def err_auto_bitfield : Error<
@@ -7844,13 +7840,39 @@ def warn_bind_ref_member_to_parameter : Warning<
 def warn_init_ptr_member_to_parameter_addr : Warning<
   "initializing pointer member %0 with the stack address of parameter %1">,
   InGroup;
-def warn_bind_ref_member_to_temporary : Warning<
-  "binding reference %select{|subobject of }1member %0 to a temporary value">,
-  InGroup;
 def note_ref_or_ptr_member_declared_here : Note<
   "%select{reference|pointer}0 member declared here">;
-def note_ref_subobject_of_member_declared_here : Note<
-  "member with reference subobject declared here">;
+
+def err_bind_ref_member_to_temporary : Error<
+  "%select{reference|backing array for 'std::initializer_list'}2 "
+  "%select{|subobject of }1member %0 "
+  "%select{binds to|is}2 a temporary object "
+  "whose lifetime would be shorter than the constructed object">;
+def note_lifetime_extending_member_declared_here : Note<
+  "%select{%select{reference|'std::initializer_list'}0 member|"
+  "member with %select{reference|'std::initializer_list'}0 subobject}1 "
+  "declared here">;
+def warn_new_dangling_reference : Warning<
+  "temporary bound to reference member of allocated object "
+  "will be destroyed at the end of the full-expression">,
+  InGroup;
+def warn_new_dangling_initializer_list : Warning<
+  "array backing "
+  "%select{initializer list subobject of the allocated object|"
+  "the allocated initializer list}0 "
+  "will be destroyed at the end of the full-expression">,
+  InGroup;
+def warn_default_member_init_temporary_not_extended : Warning<
+  "sorry, lifetime extension of temporary created by aggregate initialization "
+  "using default member initializer is not supported; lifetime of temporary "
+  "will end at the end of the full-expression">, InGroup;
+def warn_default_member_init_init_list_not_extended : Warning<
+  "sorry, lifetime extension of backing array of initializer list "
+  "created by aggregate initialization using default member initializer "
+  "is not supported; lifetime of backing array will end at the end of the "
+  "full-expression">, InGroup;
+def note_in_default_member_initalizer_here : Note<
+  "in default member initializer for field %0 used here">;
 
 // For non-floating point, expressions of the form x == x or x != x
 // should result in a warning, since these always evaluate to a constant.
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 1e6423c99d..b7ef8d0f47 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -46,7 +46,7 @@ class ObjCMethodDecl;
 class Sema;
 
 /// Describes an entity that is being initialized.
-class InitializedEntity {
+class alignas(8) InitializedEntity {
 public:
   /// Specifies the kind of entity being initialized.
   enum EntityKind {
@@ -63,7 +63,7 @@ public:
     /// is being thrown.
     EK_Exception,
 
-    /// The entity being initialized is a non-static data member 
+    /// The entity being initialized is a non-static data member
     /// subobject.
     EK_Member,
 
@@ -123,7 +123,7 @@ public:
     // enum as an index for its first %select.  When modifying this list,
     // that diagnostic text needs to be updated as well.
   };
-  
+
 private:
   /// The kind of entity being initialized.
   EntityKind Kind;
@@ -158,6 +158,10 @@ private:
     /// initialization in a copy or move constructor. These can perform array
     /// copies.
     bool IsImplicitFieldInit;
+
+    /// When Kind == EK_Member, whether this is the initial initialization
+    /// check for a default member initializer.
+    bool IsDefaultMemberInit;
   };
 
   struct C {
@@ -203,7 +207,7 @@ private:
 
   /// Create the initialization entity for a variable.
   InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
-      : Kind(EK), Type(Var->getType()), Variable{Var, false} {}
+      : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
   
   /// Create the initialization entity for the result of a
   /// function, throwing an object, performing an explicit cast, or
@@ -217,9 +221,9 @@ private:
   
   /// Create the initialization entity for a member subobject.
   InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
-                    bool Implicit) 
+                    bool Implicit, bool DefaultMemberInit)
       : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
-        Variable{Member, Implicit} {}
+        Variable{Member, Implicit, DefaultMemberInit} {}
   
   /// Create the initialization entity for an array element.
   InitializedEntity(ASTContext &Context, unsigned Index, 
@@ -339,21 +343,27 @@ public:
   static InitializedEntity InitializeDelegation(QualType Type) {
     return InitializedEntity(EK_Delegating, SourceLocation(), Type);
   }
-  
+
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(FieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member, Parent, Implicit);
+    return InitializedEntity(Member, Parent, Implicit, false);
   }
-  
+
   /// Create the initialization entity for a member subobject.
   static InitializedEntity
   InitializeMember(IndirectFieldDecl *Member,
                    const InitializedEntity *Parent = nullptr,
                    bool Implicit = false) {
-    return InitializedEntity(Member->getAnonField(), Parent, Implicit);
+    return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
+  }
+
+  /// Create the initialization entity for a default member initializer.
+  static InitializedEntity
+  InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
+    return InitializedEntity(Member, nullptr, false, true);
   }
 
   /// Create the initialization entity for an array element.
@@ -453,6 +463,12 @@ public:
     return getKind() == EK_Member && Variable.IsImplicitFieldInit;
   }
 
+  /// Is this the default member initializer of a member (specified inside
+  /// the class definition)?
+  bool isDefaultMemberInitializer() const {
+    return getKind() == EK_Member && Variable.IsDefaultMemberInit;
+  }
+
   /// Determine the location of the 'return' keyword when initializing
   /// the result of a function call.
   SourceLocation getReturnLoc() const {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 2425dff005..f13e423cef 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2582,6 +2582,11 @@ public:
                                                  NamedDecl *FoundDecl,
                                                  CXXMethodDecl *Method);
 
+  /// Check that the lifetime of the initializer (and its subobjects) is
+  /// sufficient for initializing the entity, and perform lifetime extension
+  /// (when permitted) if not.
+  void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
+
   ExprResult PerformContextuallyConvertToBool(Expr *From);
   ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 63d01c9d85..eda6e16195 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3621,7 +3621,8 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
 
   ExprResult Init = InitExpr;
   if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
-    InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
+    InitializedEntity Entity =
+        InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
     InitializationKind Kind =
         FD->getInClassInitStyle() == ICIS_ListInit
             ? InitializationKind::CreateDirectList(InitExpr->getLocStart(),
@@ -4646,6 +4647,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
         SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
     if (DIE.isInvalid())
       return true;
+
+    auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
+    SemaRef.checkInitializerLifetime(Entity, DIE.get());
+
     CXXCtorInitializer *Init;
     if (Indirect)
       Init = new (SemaRef.Context)
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fbf572e398..a7ad8e322d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1864,13 +1864,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
   if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
     return ExprError();
 
-  if (initStyle == CXXNewExpr::ListInit &&
-      isStdInitializerList(AllocType, nullptr)) {
-    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
-         diag::warn_dangling_std_initializer_list)
-        << /*at end of FE*/0 << Inits[0]->getSourceRange();
-  }
-
   // In ARC, infer 'retaining' for the allocated
   if (getLangOpts().ObjCAutoRefCount &&
       AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 320d93a99a..f94eabd671 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -572,6 +572,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
         hadError = true;
         return;
       }
+      SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
       if (Init < NumInits)
         ILE->setInit(Init, DIE.get());
       else {
@@ -6197,17 +6198,43 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
   llvm_unreachable("unknown entity kind");
 }
 
+namespace {
+enum LifetimeKind {
+  /// The lifetime of a temporary bound to this entity ends at the end of the
+  /// full-expression, and that's (probably) fine.
+  LK_FullExpression,
+
+  /// The lifetime of a temporary bound to this entity is extended to the
+  /// lifeitme of the entity itself.
+  LK_Extended,
+
+  /// The lifetime of a temporary bound to this entity probably ends too soon,
+  /// because the entity is allocated in a new-expression.
+  LK_New,
+
+  /// The lifetime of a temporary bound to this entity ends too soon, because
+  /// the entity is a return object.
+  LK_Return,
+
+  /// This is a mem-initializer: if it would extend a temporary (other than via
+  /// a default member initializer), the program is ill-formed.
+  LK_MemInitializer,
+};
+using LifetimeResult =
+    llvm::PointerIntPair;
+}
+
 /// Determine the declaration which an initialized entity ultimately refers to,
 /// for the purpose of lifetime-extending a temporary bound to a reference in
 /// the initialization of \p Entity.
-static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+static LifetimeResult getEntityForTemporaryLifetimeExtension(
     const InitializedEntity *Entity,
-    const InitializedEntity *FallbackDecl = nullptr) {
+    const InitializedEntity *InitField = nullptr) {
   // C++11 [class.temporary]p5:
   switch (Entity->getKind()) {
   case InitializedEntity::EK_Variable:
     //   The temporary [...] persists for the lifetime of the reference
-    return Entity;
+    return {Entity, LK_Extended};
 
   case InitializedEntity::EK_Member:
     // For subobjects, we look at the complete object.
@@ -6216,29 +6243,43 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
                                                     Entity);
 
     //   except:
-    //   -- A temporary bound to a reference member in a constructor's
-    //      ctor-initializer persists until the constructor exits.
-    return Entity;
+    // C++17 [class.base.init]p8:
+    //   A temporary expression bound to a reference member in a
+    //   mem-initializer is ill-formed.
+    // C++17 [class.base.init]p11:
+    //   A temporary expression bound to a reference member from a
+    //   default member initializer is ill-formed.
+    //
+    // The context of p11 and its example suggest that it's only the use of a
+    // default member initializer from a constructor that makes the program
+    // ill-formed, not its mere existence, and that it can even be used by
+    // aggregate initialization.
+    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
+                                                         : LK_MemInitializer};
 
   case InitializedEntity::EK_Binding:
     // Per [dcl.decomp]p3, the binding is treated as a variable of reference
     // type.
-    return Entity;
+    return {Entity, LK_Extended};
 
   case InitializedEntity::EK_Parameter:
   case InitializedEntity::EK_Parameter_CF_Audited:
     //   -- A temporary bound to a reference parameter in a function call
     //      persists until the completion of the full-expression containing
     //      the call.
+    return {nullptr, LK_FullExpression};
+
   case InitializedEntity::EK_Result:
     //   -- The lifetime of a temporary bound to the returned value in a
     //      function return statement is not extended; the temporary is
     //      destroyed at the end of the full-expression in the return statement.
+    return {nullptr, LK_Return};
+
   case InitializedEntity::EK_New:
     //   -- A temporary bound to a reference in a new-initializer persists
     //      until the completion of the full-expression containing the
     //      new-initializer.
-    return nullptr;
+    return {nullptr, LK_New};
 
   case InitializedEntity::EK_Temporary:
   case InitializedEntity::EK_CompoundLiteralInit:
@@ -6246,25 +6287,26 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
     // We don't yet know the storage duration of the surrounding temporary.
     // Assume it's got full-expression duration for now, it will patch up our
     // storage duration if that's not correct.
-    return nullptr;
+    return {nullptr, LK_FullExpression};
 
   case InitializedEntity::EK_ArrayElement:
     // For subobjects, we look at the complete object.
     return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                  FallbackDecl);
+                                                  InitField);
 
   case InitializedEntity::EK_Base:
     // For subobjects, we look at the complete object.
     if (Entity->getParent())
       return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
-                                                    Entity);
-    LLVM_FALLTHROUGH;
+                                                    InitField);
+    return {InitField, LK_MemInitializer};
+
   case InitializedEntity::EK_Delegating:
     // We can reach this case for aggregate initialization in a constructor:
     //   struct A { int &&r; };
     //   struct B : A { B() : A{0} {} };
-    // In this case, use the innermost field decl as the context.
-    return FallbackDecl;
+    // In this case, use the outermost field decl as the context.
+    return {InitField, LK_MemInitializer};
 
   case InitializedEntity::EK_BlockElement:
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -6272,30 +6314,54 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_ComplexElement:
-    return nullptr;
+    return {nullptr, LK_FullExpression};
   }
   llvm_unreachable("unknown entity kind");
 }
 
-static void performLifetimeExtension(Expr *Init,
-                                     const InitializedEntity *ExtendingEntity);
+namespace {
+enum ExtensionKind {
+  /// Lifetime would be extended by a reference binding to a temporary.
+  EK_ReferenceBinding,
+  /// Lifetime would be extended by a std::initializer_list object binding to
+  /// its backing array.
+  EK_StdInitializerList,
+};
+using IndirectTemporaryPathEntry =
+    llvm::PointerUnion;
+using IndirectTemporaryPath = llvm::SmallVectorImpl;
+
+struct RevertToOldSizeRAII {
+  IndirectTemporaryPath &Path;
+  unsigned OldSize = Path.size();
+  RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {}
+  ~RevertToOldSizeRAII() { Path.resize(OldSize); }
+};
+}
+
+template 
+static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
+                                                  Expr *Init,
+                                                  TemporaryVisitor Visit);
+
+/// Visit the temporaries whose lifetimes would be extended by binding a
+/// reference to the glvalue expression \c Init.
+template 
+static void
+visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,
+                                           Expr *Init, ExtensionKind EK,
+                                           TemporaryVisitor Visit) {
+  RevertToOldSizeRAII RAII(Path);
 
-/// Update a glvalue expression that is used as the initializer of a reference
-/// to note that its lifetime is extended.
-/// \return \c true if any temporary had its lifetime extended.
-static bool
-performReferenceExtension(Expr *Init,
-                          const InitializedEntity *ExtendingEntity) {
   // Walk past any constructs which we can lifetime-extend across.
   Expr *Old;
   do {
     Old = Init;
 
     if (InitListExpr *ILE = dyn_cast(Init)) {
-      if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
-        // This is just redundant braces around an initializer. Step over it.
+      // If this is just redundant braces around an initializer, step over it.
+      if (ILE->isTransparent())
         Init = ILE->getInit(0);
-      }
     }
 
     // Step over any subobject adjustments; we may have a materialized
@@ -6312,40 +6378,65 @@ performReferenceExtension(Expr *Init,
     // when performing lifetime extension.
     if (auto *ASE = dyn_cast(Init))
       Init = ASE->getBase();
+
+    // Step into CXXDefaultInitExprs so we can diagnose cases where a
+    // constructor inherits one as an implicit mem-initializer.
+    if (auto *DIE = dyn_cast(Init)) {
+      Path.push_back(DIE);
+      Init = DIE->getExpr();
+
+      if (auto *EWC = dyn_cast(Init))
+        Init = EWC->getSubExpr();
+    }
   } while (Init != Old);
 
-  if (MaterializeTemporaryExpr *ME = dyn_cast(Init)) {
-    // Update the storage duration of the materialized temporary.
-    // FIXME: Rebuild the expression instead of mutating it.
-    ME->setExtendingDecl(ExtendingEntity->getDecl(),
-                         ExtendingEntity->allocateManglingNumber());
-    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
-    return true;
+  if (auto *MTE = dyn_cast(Init)) {
+    if (Visit(Path, MTE, EK))
+      visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(),
+                                            Visit);
   }
-
-  return false;
 }
 
-/// Update a prvalue expression that is going to be materialized as a
-/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init,
-                                     const InitializedEntity *ExtendingEntity) {
+/// Visit the temporaries whose lifetimes would be extended by
+/// lifetime-extending the object initialized by the prvalue expression \c
+/// Init.
+template 
+static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path,
+                                                  Expr *Init,
+                                                  TemporaryVisitor Visit) {
+  RevertToOldSizeRAII RAII(Path);
+
+  // Step into CXXDefaultInitExprs so we can diagnose cases where a
+  // constructor inherits one as an implicit mem-initializer.
+  if (auto *DIE = dyn_cast(Init)) {
+    Path.push_back(DIE);
+    Init = DIE->getExpr();
+
+    if (auto *EWC = dyn_cast(Init))
+      Init = EWC->getSubExpr();
+  }
+
   // Dig out the expression which constructs the extended temporary.
   Init = const_cast(Init->skipRValueSubobjectAdjustments());
 
   if (CXXBindTemporaryExpr *BTE = dyn_cast(Init))
     Init = BTE->getSubExpr();
 
-  if (CXXStdInitializerListExpr *ILE =
-          dyn_cast(Init)) {
-    performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
-    return;
-  }
+  // C++17 [dcl.init.list]p6:
+  //   initializing an initializer_list object from the array extends the
+  //   lifetime of the array exactly like binding a reference to a temporary.
+  if (auto *ILE = dyn_cast(Init))
+    return visitTemporariesExtendedByReferenceBinding(
+        Path, ILE->getSubExpr(), EK_StdInitializerList, Visit);
 
   if (InitListExpr *ILE = dyn_cast(Init)) {
+    if (ILE->isTransparent())
+      return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),
+                                                   Visit);
+
     if (ILE->getType()->isArrayType()) {
       for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
-        performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
+        visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit);
       return;
     }
 
@@ -6357,7 +6448,8 @@ static void performLifetimeExtension(Expr *Init,
       // bound to temporaries, those temporaries are also lifetime-extended.
       if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
           ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
-        performReferenceExtension(ILE->getInit(0), ExtendingEntity);
+        visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0),
+                                                   EK_ReferenceBinding, Visit);
       else {
         unsigned Index = 0;
         for (const auto *I : RD->fields()) {
@@ -6367,13 +6459,13 @@ static void performLifetimeExtension(Expr *Init,
             continue;
           Expr *SubInit = ILE->getInit(Index);
           if (I->getType()->isReferenceType())
-            performReferenceExtension(SubInit, ExtendingEntity);
-          else if (isa(SubInit) ||
-                   isa(SubInit))
-            // This may be either aggregate-initialization of a member or
-            // initialization of a std::initializer_list object. Either way,
+            visitTemporariesExtendedByReferenceBinding(
+                Path, SubInit, EK_ReferenceBinding, Visit);
+          else
+            // This might be either aggregate-initialization of a member or
+            // initialization of a std::initializer_list object. Regardless,
             // we should recursively lifetime-extend that initializer.
-            performLifetimeExtension(SubInit, ExtendingEntity);
+            visitTemporariesExtendedByInitializer(Path, SubInit, Visit);
           ++Index;
         }
       }
@@ -6381,37 +6473,123 @@ static void performLifetimeExtension(Expr *Init,
   }
 }
 
-static void warnOnLifetimeExtension(Sema &S, const InitializedEntity &Entity,
-                                    const Expr *Init, bool IsInitializerList,
-                                    const ValueDecl *ExtendingDecl) {
-  // Warn if a field lifetime-extends a temporary.
-  if (isa(ExtendingDecl)) {
-    if (IsInitializerList) {
-      S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
-        << /*at end of constructor*/true;
-      return;
+/// Determine whether this is an indirect path to a temporary that we are
+/// supposed to lifetime-extend along (but don't).
+static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) {
+  for (auto Elem : Path) {
+    if (!Elem.is())
+      return false;
+  }
+  return true;
+}
+
+void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
+                                    Expr *Init) {
+  LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);
+  LifetimeKind LK = LR.getInt();
+  const InitializedEntity *ExtendingEntity = LR.getPointer();
+
+  // If this entity doesn't have an interesting lifetime, don't bother looking
+  // for temporaries within its initializer.
+  if (LK == LK_FullExpression)
+    return;
+
+  auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,
+                              MaterializeTemporaryExpr *MTE,
+                              ExtensionKind EK) -> bool {
+    switch (LK) {
+    case LK_FullExpression:
+      llvm_unreachable("already handled this");
+
+    case LK_Extended:
+      // Lifetime-extend the temporary.
+      if (Path.empty()) {
+        // Update the storage duration of the materialized temporary.
+        // FIXME: Rebuild the expression instead of mutating it.
+        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
+                              ExtendingEntity->allocateManglingNumber());
+        // Also visit the temporaries lifetime-extended by this initializer.
+        return true;
+      }
+
+      if (shouldLifetimeExtendThroughPath(Path)) {
+        // We're supposed to lifetime-extend the temporary along this path (per
+        // the resolution of DR1815), but we don't support that yet.
+        //
+        // FIXME: Properly handle this situation. Perhaps the easiest approach
+        // would be to clone the initializer expression on each use that would
+        // lifetime extend its temporaries.
+        Diag(MTE->getExprLoc(),
+             EK == EK_ReferenceBinding
+                 ? diag::warn_default_member_init_temporary_not_extended
+                 : diag::warn_default_member_init_init_list_not_extended);
+      } else {
+        llvm_unreachable("unexpected indirect temporary path");
+      }
+      break;
+
+    case LK_MemInitializer:
+      // Under C++ DR1696, if a mem-initializer (or a default member
+      // initializer used by the absence of one) would lifetime-extend a
+      // temporary, the program is ill-formed.
+      if (auto *ExtendingDecl = ExtendingEntity->getDecl()) {
+        bool IsSubobjectMember = ExtendingEntity != &Entity;
+        Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)
+            << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember
+            << EK;
+        // Don't bother adding a note pointing to the field if we're inside its
+        // default member initializer; our primary diagnostic points to the
+        // same place in that case.
+        if (Path.empty() || !Path.back().is()) {
+          Diag(ExtendingDecl->getLocation(),
+               diag::note_lifetime_extending_member_declared_here)
+              << EK << IsSubobjectMember;
+        }
+      } else {
+        // We have a mem-initializer but no particular field within it; this
+        // is either a base class or a delegating initializer directly
+        // initializing the base-class from something that doesn't live long
+        // enough. Either way, that can't happen.
+        // FIXME: Move CheckForDanglingReferenceOrPointer checks here.
+        llvm_unreachable(
+            "temporary initializer for base class / delegating ctor");
+      }
+      break;
+
+    case LK_New:
+      if (EK == EK_ReferenceBinding) {
+        Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);
+      } else {
+        Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)
+            << (ExtendingEntity != &Entity);
+      }
+      break;
+
+    case LK_Return:
+      // FIXME: Move -Wreturn-stack-address checks here.
+      return false;
     }
 
-    bool IsSubobjectMember = false;
-    for (const InitializedEntity *Ent = Entity.getParent(); Ent;
-         Ent = Ent->getParent()) {
-      if (Ent->getKind() != InitializedEntity::EK_Base) {
-        IsSubobjectMember = true;
-        break;
+    // FIXME: Model these as CodeSynthesisContexts to fix the note emission
+    // order.
+    for (auto Elem : llvm::reverse(Path)) {
+      if (auto *DIE = Elem.dyn_cast()) {
+        Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here)
+            << DIE->getField();
       }
     }
-    S.Diag(Init->getExprLoc(),
-           diag::warn_bind_ref_member_to_temporary)
-      << ExtendingDecl << Init->getSourceRange()
-      << IsSubobjectMember << IsInitializerList;
-    if (IsSubobjectMember)
-      S.Diag(ExtendingDecl->getLocation(),
-             diag::note_ref_subobject_of_member_declared_here);
-    else
-      S.Diag(ExtendingDecl->getLocation(),
-             diag::note_ref_or_ptr_member_declared_here)
-        << /*is pointer*/false;
-  }
+
+    // We didn't lifetime-extend, so don't go any further; we don't need more
+    // warnings or errors on inner temporaries within this one's initializer.
+    return false;
+  };
+
+  llvm::SmallVector Path;
+  if (Init->isGLValue())
+    visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding,
+                                               TemporaryVisitor);
+  else
+    visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);
 }
 
 static void DiagnoseNarrowingInInitList(Sema &S,
@@ -6838,14 +7016,9 @@ InitializationSequence::Perform(Sema &S,
       }
 
       // Even though we didn't materialize a temporary, the binding may still
-      // extend the lifetime of a temporary. This happens if we bind a reference
-      // to the result of a cast to reference type.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(CurInit.get(), ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/false,
-                                  ExtendingEntity->getDecl());
+      // extend the lifetime of a temporary. This happens if we bind a
+      // reference to the result of a cast to reference type.
+      S.checkInitializerLifetime(Entity, CurInit.get());
 
       CheckForNullPointerDereference(S, CurInit.get());
       break;
@@ -6861,23 +7034,17 @@ InitializationSequence::Perform(Sema &S,
       // Materialize the temporary into memory.
       MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
           Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType());
+      CurInit = MTE;
 
       // Maybe lifetime-extend the temporary's subobjects to match the
       // entity's lifetime.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(MTE, ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/false,
-                                  ExtendingEntity->getDecl());
+      S.checkInitializerLifetime(Entity, CurInit.get());
 
       // If we're extending this temporary to automatic storage duration -- we
       // need to register its cleanup during the full-expression's cleanups.
       if (MTE->getStorageDuration() == SD_Automatic &&
           MTE->getType().isDestructedType())
         S.Cleanup.setExprNeedsCleanups(true);
-
-      CurInit = MTE;
       break;
     }
 
@@ -7320,18 +7487,13 @@ InitializationSequence::Perform(Sema &S,
           CurInit.get()->getType(), CurInit.get(),
           /*BoundToLvalueReference=*/false);
 
-      // Maybe lifetime-extend the array temporary's subobjects to match the
-      // entity's lifetime.
-      if (const InitializedEntity *ExtendingEntity =
-              getEntityForTemporaryLifetimeExtension(&Entity))
-        if (performReferenceExtension(MTE, ExtendingEntity))
-          warnOnLifetimeExtension(S, Entity, CurInit.get(),
-                                  /*IsInitializerList=*/true,
-                                  ExtendingEntity->getDecl());
-
       // Wrap it in a construction of a std::initializer_list.
       CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
 
+      // Maybe lifetime-extend the array temporary's subobjects to match the
+      // entity's lifetime.
+      S.checkInitializerLifetime(Entity, CurInit.get());
+
       // Bind the result, in case the library has given initializer_list a
       // non-trivial destructor.
       if (shouldBindAsTemporary(Entity))
diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp
index b73a94f1db..0cb68c4a97 100644
--- a/test/Analysis/initializer.cpp
+++ b/test/Analysis/initializer.cpp
@@ -178,29 +178,6 @@ namespace ReferenceInitialization {
     const MyStruct &myStruct(OtherStruct(5));
     myStruct.method(); // no-warning
   }
-
-  struct HasMyStruct {
-    const MyStruct &ms; // expected-note {{reference member declared here}}
-    const MyStruct &msWithCleanups; // expected-note {{reference member declared here}}
-
-    // clang's Sema issues a warning when binding a reference member to a
-    // temporary value.
-    HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {
-        // expected-warning@-1 {{binding reference member 'ms' to a temporary value}}
-        // expected-warning@-2 {{binding reference member 'msWithCleanups' to a temporary value}}
-
-      // At this point the members are not garbage so we should not expect an
-      // analyzer warning here even though binding a reference member
-      // to a member is a terrible idea.
-      ms.method(); // no-warning
-      msWithCleanups.method(); // no-warning
-    }
-  };
-
-  void referenceInitializeField() {
-    HasMyStruct hms;
-  }
-
 };
 
 namespace PR31592 {
diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp
index e0af95ac39..54648cfe96 100644
--- a/test/CXX/drs/dr16xx.cpp
+++ b/test/CXX/drs/dr16xx.cpp
@@ -9,6 +9,20 @@
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
 #endif
 
+#if __cplusplus >= 201103L
+namespace std {
+  typedef decltype(sizeof(int)) size_t;
+
+  template class initializer_list {
+    const E *begin;
+    size_t size;
+
+  public:
+    initializer_list();
+  };
+} // std
+#endif
+
 namespace dr1611 { // dr1611: dup 1658
   struct A { A(int); };
   struct B : virtual A { virtual void f() = 0; };
@@ -269,3 +283,83 @@ namespace dr1687 { // dr1687: 7
   auto c = To() <=> To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}}
 #endif
 }
+
+namespace dr1696 { // dr1696: 7
+  namespace std_examples {
+#if __cplusplus >= 201402L
+    extern struct A a;
+    struct A {
+      const A &x = { A{a, a} };
+      const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}}
+    };
+    A a{a, a};
+#endif
+  }
+
+  struct A { A(); ~A(); };
+#if __cplusplus >= 201103L
+  struct B {
+    A &&a; // expected-note {{declared here}}
+    B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
+  } b;
+#endif
+
+  struct C {
+    C();
+    const A &a; // expected-note {{declared here}}
+  };
+  C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}}
+
+#if __cplusplus >= 201103L
+  // This is OK in C++14 onwards, per DR1815, though we don't support that yet:
+  //   D1 d1 = {};
+  // is equivalent to
+  //   D1 d1 = {A()};
+  // ... which lifetime-extends the A temporary.
+  struct D1 {
+    const A &a = A();
+#if __cplusplus < 201402L
+    // expected-error@-2 {{binds to a temporary}}
+    // expected-note@-4 {{here}}
+#else
+    // expected-warning-re@-5 {{sorry, lifetime extension {{.*}} not supported}}
+#endif
+  };
+  D1 d1 = {}; // expected-note {{here}}
+
+  struct D2 {
+    const A &a = A(); // expected-error {{binds to a temporary}}
+    D2() {} // expected-note {{used here}}
+  };
+
+  struct D3 { // expected-note {{used here}}
+    const A &a = A(); // expected-error {{binds to a temporary}}
+  };
+  D3 d3; // expected-note {{first required here}}
+
+  struct haslist1 {
+    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
+    haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+  };
+
+  struct haslist2 {
+    std::initializer_list il; // expected-note {{'std::initializer_list' member}}
+    haslist2();
+  };
+  haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+
+  struct haslist3 {
+    std::initializer_list il = {1, 2, 3};
+  };
+
+  struct haslist4 { // expected-note {{in default member initializer}}
+    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+  };
+  haslist4 hl4; // expected-note {{in implicit default constructor}}
+
+  struct haslist5 {
+    std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
+    haslist5() {} // expected-note {{in default member initializer}}
+  };
+#endif
+}
diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp
index a0f470ed4a..f6a4676bc7 100644
--- a/test/CXX/drs/dr18xx.cpp
+++ b/test/CXX/drs/dr18xx.cpp
@@ -30,6 +30,17 @@ namespace dr1813 { // dr1813: 7
   static_assert(!__is_standard_layout(U), "");
 }
 
+namespace dr1815 { // dr1815: no
+#if __cplusplus >= 201402L
+  // FIXME: needs codegen test
+  struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}}
+  A a = {}; // expected-note {{here}}
+
+  struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{here}}
+  B b; // expected-note {{here}}
+#endif
+}
+
 namespace dr1881 { // dr1881: 7
   struct A { int a : 4; };
   struct B : A { int b : 3; };
diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp
index 1ca0143d09..a4d0cdcdc7 100644
--- a/test/CXX/special/class.copy/p11.0x.copy.cpp
+++ b/test/CXX/special/class.copy/p11.0x.copy.cpp
@@ -121,13 +121,22 @@ extern HasNoAccessDtorBase HNADBa;
 HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
 
 // -- a non-static data member of rvalue reference type
+int some_int;
 struct RValue {
-  int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
-  // expected-warning@-1{{binding reference member 'ri' to a temporary}} expected-note@-1 {{here}}
+  int && ri = static_cast(some_int); // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
 };
 RValue RVa;
 RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}
 
+// FIXME: The note on the class-name is attached to the location of the
+// constructor. This is not especially clear.
+struct RValueTmp { // expected-note {{used here}}
+  int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
+  // expected-error@-1 {{reference member 'ri' binds to a temporary}}
+};
+RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}}
+RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}}
+
 namespace PR13381 {
   struct S {
     S(const S&);
diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp
index ab4259548e..5b016836e9 100644
--- a/test/CXX/special/class.copy/p11.0x.move.cpp
+++ b/test/CXX/special/class.copy/p11.0x.move.cpp
@@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy c
 // The restriction on rvalue reference members applies to only the copy
 // constructor.
 struct RValue {
-  int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
+  int &&ri = 1;
   RValue(RValue&&);
 };
 RValue::RValue(RValue&&) = default;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index 2360345a48..5558313ce7 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -43,8 +43,12 @@ class NotDeleted2a { int &a = n; };
 NotDeleted2a nd2a;
 class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}}
 NotDeleted2b nd2b;
-class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding reference member 'a' to a temporary}} expected-note {{here}}
+class NotDeleted2c { int &&a = static_cast(n); };
 NotDeleted2c nd2c;
+// Note: this one does not have a deleted default constructor even though the
+// implicit default constructor is ill-formed!
+class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{here}}
+NotDeleted2d nd2d; // expected-note {{first required here}}
 
 // - any non-variant non-static data member of const qualified type (or array
 // thereof) with no brace-or-equal-initializer does not have a user-provided
diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp
index aa0d7e92b9..de902a5e4d 100644
--- a/test/CXX/temp/temp.param/p5.cpp
+++ b/test/CXX/temp/temp.param/p5.cpp
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -verify %s -std=c++14
 
-template struct S {
+template struct S { // expected-note {{in default member initializer}}
   decltype(I) n;
-  int &&r = I; // expected-warning 2{{binding reference member 'r' to a temporary value}} expected-note 2{{declared here}}
+  int &&r = I; // expected-error {{reference member 'r' binds to a temporary object}}
 };
-S<5> s; // expected-note {{instantiation}}
+S<5> s; // expected-note {{implicit default constructor}}
 
-template struct U {
+template struct U { // expected-note {{in default member initializer}}
   decltype(v) n;
-  int &&r = v; // expected-warning {{binding reference member 'r' to a temporary value}} expected-note {{declared here}}
+  int &&r = v; // expected-error {{reference member 'r' binds to a temporary object}}
 };
-U u; // expected-note {{instantiation}}
+U u; // expected-note {{implicit default constructor}}
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 3299763997..0184a1d6e7 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -236,36 +236,6 @@ void fn9() {
   // CHECK: ret void
 }
 
-struct haslist1 {
-  std::initializer_list il;
-  haslist1(int i);
-};
-
-// CHECK-LABEL: define void @_ZN8haslist1C2Ei
-haslist1::haslist1(int i)
-// CHECK: alloca [3 x i32]
-// CHECK: store i32 %
-// CHECK: store i32 2
-// CHECK: store i32 3
-  : il{i, 2, 3}
-{
-  destroyme2 dm2;
-}
-
-struct haslist2 {
-  std::initializer_list il;
-  haslist2();
-};
-
-// CHECK-LABEL: define void @_ZN8haslist2C2Ev
-haslist2::haslist2()
-  : il{destroyme1(), destroyme1()}
-{
-  destroyme2 dm2;
-  // CHECK: call void @_ZN10destroyme2D1Ev
-  // CHECK: call void @_ZN10destroyme1D1Ev
-}
-
 void fn10(int i) {
   // CHECK-LABEL: define void @_Z4fn10i
   // CHECK: alloca [3 x i32]
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index bad51ba353..21372effbc 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -198,20 +198,6 @@ B::B()
   f();
 }
   
-struct C {
-  C();
-  
-  const B& b;
-};
-
-C::C() 
-  // CHECK: call void @_ZN6PR50771BC1Ev
-  : b(B()) {
-  // CHECK: call void @_ZN6PR50771fEv
-  f();
-  
-  // CHECK: call void @_ZN6PR50771BD1Ev
-}
 }
 
 A f8() {
@@ -816,16 +802,3 @@ namespace PR14130 {
   // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
   // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
 }
-
-namespace Ctor {
-  struct A { A(); ~A(); };
-  void f();
-  struct B {
-    A &&a;
-    B() : a{} { f(); }
-  } b;
-  // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
-  // CHECK: call void @_ZN4Ctor1AC1Ev(
-  // CHECK: call void @_ZN4Ctor1fEv(
-  // CHECK: call void @_ZN4Ctor1AD1Ev(
-}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 4b4bd43634..e921634b1b 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1892,14 +1892,15 @@ namespace Lifetime {
   }
 
   constexpr int &get(int &&n) { return n; }
+  constexpr int &&get_rv(int &&n) { return static_cast(n); }
   struct S {
-    int &&r; // expected-note 2{{declared here}}
+    int &&r;
     int &s;
     int t;
-    constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}}
-    constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}}
+    constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note {{read of object outside its lifetime}}
+    constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note {{read of object outside its lifetime}}
   };
-  constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor
+  constexpr int k1 = S().t; // expected-error {{constant expression}} expected-note {{in call}}
   constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
 }
 
diff --git a/test/SemaCXX/constexpr-default-arg.cpp b/test/SemaCXX/constexpr-default-arg.cpp
index 2fc873c3e5..165c31aab6 100644
--- a/test/SemaCXX/constexpr-default-arg.cpp
+++ b/test/SemaCXX/constexpr-default-arg.cpp
@@ -31,8 +31,8 @@ void test_default_arg2() {
 }
 
 // Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
-struct A { int &&r = 0; }; // expected-warning {{binding reference member}} // expected-note {{reference member declared here}}
+struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
 struct B { A x, y; };
-B b = {};
+B b = {}; // expected-note 2{{in default member initializer for field 'r' used here}}
 
 }
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index 860a4aa6c6..ece014d93a 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -153,13 +153,14 @@ void dangle() {
 }
 
 struct haslist1 {
-  std::initializer_list il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
-  std::initializer_list jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
+  std::initializer_list il // expected-note {{declared here}}
+    = {1, 2, 3}; // ok, unused
+  std::initializer_list jl{1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}
   haslist1();
 };
 
-haslist1::haslist1()
-: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
+haslist1::haslist1() // expected-note {{used here}}
+: il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
 {}
 
 namespace PR12119 {
diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp
index 23946845d8..33bde75de6 100644
--- a/test/SemaCXX/eval-crashes.cpp
+++ b/test/SemaCXX/eval-crashes.cpp
@@ -26,10 +26,10 @@ namespace pr33140_0b {
 
 namespace pr33140_2 {
   // FIXME: The declaration of 'b' below should lifetime-extend two int
-  // temporaries, invalidating this warning to some extent.
-  struct A { int &&r = 0; }; // expected-warning {{binding reference member 'r' to a temporary}} expected-note {{here}}
+  // temporaries.
+  struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
   struct B { A x, y; };
-  B b = {};
+  B b = {}; // expected-note 2{{used here}}
 }
 
 namespace pr33140_3 {
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index ad4a8f15b2..8a13eca2f1 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -86,9 +86,8 @@ namespace PR14838 {
   };
   struct thing {};
   struct another {
-    another() : r(thing()) {}
+    another() : r(thing()) {} // expected-error {{binds to a temporary object}}
     // expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}}
-    // expected-warning@-2 {{binding reference member 'r' to a temporary value}}
     const function &r; // expected-note {{reference member declared here}}
   } af;
 }
diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp
index eb65bd0669..97d4331c1f 100644
--- a/test/SemaCXX/warn-dangling-field.cpp
+++ b/test/SemaCXX/warn-dangling-field.cpp
@@ -20,7 +20,7 @@ struct S {
 
 struct S2 {
   const X &x; // expected-note {{reference member declared here}}
-  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}}
+  S2(int i) : x(i) {} // expected-error {{member 'x' binds to a temporary}}
 };
 
 struct S3 {
@@ -43,9 +43,9 @@ S5 s5 = { 0 }; // ok, lifetime-extended
 
 struct S6 {
   S5 s5; // expected-note {{here}}
-  S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}}
+  S6() : s5 { 0 } {} // expected-error {{reference subobject of member 's5' binds to a temporary}}
 };
 
 struct S7 : S5 {
-  S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}}
+  S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}}
 };
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index 93d4ee93fb..04dd0eae1c 100644
--- a/www/cxx_dr_status.html
+++ b/www/cxx_dr_status.html
@@ -9991,7 +9991,7 @@ and POD class
     1696
     CD4
     Temporary lifetime and non-static data member initializers
-    Unknown
+    SVN
   
   
     1697
@@ -10705,7 +10705,7 @@ and POD class
     1815
     CD4
     Lifetime extension in aggregate initialization
-    Unknown
+    No
   
   
     1816
-- 
GitLab


From ed683dcc4ef0546d1e6c04337222d90bac7b785c Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Tue, 17 Jul 2018 22:24:11 +0000
Subject: [PATCH 0589/1023] Replace LLVM_ALIGNAS with just alignas.

Various places in Clang and LLVM are already using alignas; it seems
our minimum host configuration now requires it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337330 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/Decl.h            | 4 ++--
 include/clang/AST/DeclBase.h        | 2 +-
 include/clang/AST/Type.h            | 4 ++--
 include/clang/Basic/SourceManager.h | 2 +-
 lib/CodeGen/CGCleanup.h             | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e419ded280..a0986085a1 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -83,7 +83,7 @@ class VarTemplateDecl;
 /// TypeLoc TL = TypeSourceInfo->getTypeLoc();
 /// TL.getStartLoc().print(OS, SrcMgr);
 /// @endcode
-class LLVM_ALIGNAS(8) TypeSourceInfo {
+class alignas(8) TypeSourceInfo {
   // Contains a memory block after the class, used for type source information,
   // allocated by ASTContext.
   friend class ASTContext;
@@ -2860,7 +2860,7 @@ public:
 
 /// Base class for declarations which introduce a typedef-name.
 class TypedefNameDecl : public TypeDecl, public Redeclarable {
-  struct LLVM_ALIGNAS(8) ModedTInfo {
+  struct alignas(8) ModedTInfo {
     TypeSourceInfo *first;
     QualType second;
   };
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 5ca5907832..f99bd62787 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -83,7 +83,7 @@ enum AvailabilityResult {
 /// (and its subclasses) in its Decl::operator new(). Proper alignment
 /// of all subclasses (not requiring more than the alignment of Decl) is
 /// asserted in DeclBase.cpp.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
+class alignas(8) Decl {
 public:
   /// Lists the kind of concrete classes of Decl.
   enum Kind {
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 9e024c12ff..cbdbc529f7 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -4644,7 +4644,7 @@ public:
 /// TemplateArguments, followed by a QualType representing the
 /// non-canonical aliased type when the template is a type alias
 /// template.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+class alignas(8) TemplateSpecializationType
     : public Type,
       public llvm::FoldingSetNode {
   friend class ASTContext; // ASTContext creates these
@@ -5062,7 +5062,7 @@ public:
 /// Represents a template specialization type whose template cannot be
 /// resolved, e.g.
 ///   A::template B
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+class alignas(8) DependentTemplateSpecializationType
     : public TypeWithKeyword,
       public llvm::FoldingSetNode {
   friend class ASTContext; // ASTContext creates these
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 33e63d9d40..99c36f4cdf 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -92,7 +92,7 @@ namespace SrcMgr {
   /// One instance of this struct is kept for every file loaded or used.
   ///
   /// This object owns the MemoryBuffer object.
-  class LLVM_ALIGNAS(8) ContentCache {
+  class alignas(8) ContentCache {
     enum CCFlags {
       /// Whether the buffer is invalid.
       InvalidFlag = 0x01,
diff --git a/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index 5530350b9b..93be3e6c15 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/lib/CodeGen/CGCleanup.h
@@ -230,7 +230,7 @@ public:
 };
 
 /// A cleanup scope which generates the cleanup blocks lazily.
-class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope {
+class alignas(8) EHCleanupScope : public EHScope {
   /// The nearest normal cleanup scope enclosing this one.
   EHScopeStack::stable_iterator EnclosingNormal;
 
-- 
GitLab


From af6ecdb85b3d3233cee3828183372144104f9aca Mon Sep 17 00:00:00 2001
From: Peter Collingbourne 
Date: Tue, 17 Jul 2018 23:17:16 +0000
Subject: [PATCH 0590/1023] Teach Clang to emit address-significance tables.

By default, we emit an address-significance table on all ELF
targets when the integrated assembler is enabled. The emission of an
address-significance table can be controlled with the -faddrsig and
-fno-addrsig flags.

Differential Revision: https://reviews.llvm.org/D48155

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337333 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst                     |  8 ++++++++
 docs/UsersManual.rst                      |  9 +++++++++
 include/clang/Driver/Options.td           |  4 ++++
 include/clang/Frontend/CodeGenOptions.def |  3 +++
 lib/CodeGen/BackendUtil.cpp               |  1 +
 lib/Driver/ToolChains/Clang.cpp           |  5 +++++
 lib/Frontend/CompilerInvocation.cpp       |  2 ++
 test/CodeGen/addrsig.c                    | 18 ++++++++++++++++++
 test/Driver/addrsig.c                     |  8 ++++++++
 9 files changed, 58 insertions(+)
 create mode 100644 test/CodeGen/addrsig.c
 create mode 100644 test/Driver/addrsig.c

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index c0ce10d6eb..99be2fdfe0 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -98,6 +98,14 @@ Non-comprehensive list of changes in this release
   finding out the warning hierarchy, and which of them are enabled by default
   or for a particular compiler invocation.
 
+- By default, Clang emits an address-significance table into
+  every ELF object file when using the integrated assembler.
+  Address-significance tables allow linkers to implement `safe ICF
+  `_ without the false
+  positives that can result from other implementation techniques such as
+  relocation scanning. The ``-faddrsig`` and ``-fno-addrsig`` flags can be
+  used to control whether to emit the address-significance table.
+
 - ...
 
 New Compiler Flags
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 4470dab947..418afb2d54 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1382,6 +1382,15 @@ are listed below.
         // value of -fmax-type-align.
       }
 
+.. option:: -faddrsig, -fno-addrsig
+
+   Controls whether Clang emits an address-significance table into the object
+   file. Address-significance tables allow linkers to implement `safe ICF
+   `_ without the false
+   positives that can result from other implementation techniques such as
+   relocation scanning. Address-significance tables are enabled by default
+   on ELF targets when using the integrated assembler. This flag currently
+   only has an effect on ELF targets.
 
 Profile Guided Optimization
 ---------------------------
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 9035a91ce2..b71d1e15ae 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -758,6 +758,10 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
 def fno_profile_use : Flag<["-"], "fno-profile-use">,
     Alias;
 
+def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Option]>,
+  HelpText<"Emit an address-significance table">;
+def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>,
+  HelpText<"Don't emit an address-significance table">;
 def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>,
   HelpText<"Enable the 'blocks' language feature">;
 def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group;
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index 99567e04ba..c199b5428e 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -335,6 +335,9 @@ CODEGENOPT(EmbedSource, 1, 0)
 /// Whether to emit all vtables
 CODEGENOPT(ForceEmitVTables, 1, 0)
 
+/// Whether to emit an address-significance table into the object file.
+CODEGENOPT(Addrsig, 1, 0)
+
 
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 226a27b216..415bd96262 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -454,6 +454,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
   Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
   Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
   Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
+  Options.EmitAddrsig = CodeGenOpts.Addrsig;
 
   if (CodeGenOpts.EnableSplitDwarf)
     Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index e7b15c7ad8..4db4dc19a8 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -4777,6 +4777,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
+                   getToolChain().getTriple().isOSBinFormatELF() &&
+                       getToolChain().useIntegratedAs()))
+    CmdArgs.push_back("-faddrsig");
+
   // Finally add the compile command to the compilation.
   if (Args.hasArg(options::OPT__SLASH_fallback) &&
       Output.getType() == types::TY_Object &&
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index d62429dc78..c26d5fb79b 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1119,6 +1119,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
 
   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
 
+  Opts.Addrsig = Args.hasArg(OPT_faddrsig);
+
   return Success;
 }
 
diff --git a/test/CodeGen/addrsig.c b/test/CodeGen/addrsig.c
new file mode 100644
index 0000000000..2cbdb2b554
--- /dev/null
+++ b/test/CodeGen/addrsig.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: .addrsig
+// ADDRSIG: .addrsig_sym g1
+// ADDRSIG-NOT: .addrsig_sym g2
+
+// NO-ADDRSIG-NOT: .addrsig
+
+extern const int g1[], g2[];
+
+const int *f1() {
+  return g1;
+}
+
+int f2() {
+  return g2[0];
+}
diff --git a/test/Driver/addrsig.c b/test/Driver/addrsig.c
new file mode 100644
index 0000000000..fd5598c472
--- /dev/null
+++ b/test/Driver/addrsig.c
@@ -0,0 +1,8 @@
+// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: -faddrsig
+// NO-ADDRSIG-NOT: -faddrsig
-- 
GitLab


From 6a156a84aeb7cb74aa8b95639ae73e57fb2aaa04 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne 
Date: Tue, 17 Jul 2018 23:56:30 +0000
Subject: [PATCH 0591/1023] Revert r337333, "Teach Clang to emit
 address-significance tables."

Causing multiple failures on sanitizer bots due to TLS symbol errors,
e.g.

/usr/bin/ld: __msan_origin_tls: TLS definition in /home/buildbots/ppc64be-clang-test/clang-ppc64be/stage1/lib/clang/7.0.0/lib/linux/libclang_rt.msan-powerpc64.a(msan.cc.o) section .tbss.__msan_origin_tls mismatches non-TLS reference in /tmp/lit_tmp_0a71tA/mallinfo-3ca75e.o

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337336 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst                     |  8 --------
 docs/UsersManual.rst                      |  9 ---------
 include/clang/Driver/Options.td           |  4 ----
 include/clang/Frontend/CodeGenOptions.def |  3 ---
 lib/CodeGen/BackendUtil.cpp               |  1 -
 lib/Driver/ToolChains/Clang.cpp           |  5 -----
 lib/Frontend/CompilerInvocation.cpp       |  2 --
 test/CodeGen/addrsig.c                    | 18 ------------------
 test/Driver/addrsig.c                     |  8 --------
 9 files changed, 58 deletions(-)
 delete mode 100644 test/CodeGen/addrsig.c
 delete mode 100644 test/Driver/addrsig.c

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 99be2fdfe0..c0ce10d6eb 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -98,14 +98,6 @@ Non-comprehensive list of changes in this release
   finding out the warning hierarchy, and which of them are enabled by default
   or for a particular compiler invocation.
 
-- By default, Clang emits an address-significance table into
-  every ELF object file when using the integrated assembler.
-  Address-significance tables allow linkers to implement `safe ICF
-  `_ without the false
-  positives that can result from other implementation techniques such as
-  relocation scanning. The ``-faddrsig`` and ``-fno-addrsig`` flags can be
-  used to control whether to emit the address-significance table.
-
 - ...
 
 New Compiler Flags
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 418afb2d54..4470dab947 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1382,15 +1382,6 @@ are listed below.
         // value of -fmax-type-align.
       }
 
-.. option:: -faddrsig, -fno-addrsig
-
-   Controls whether Clang emits an address-significance table into the object
-   file. Address-significance tables allow linkers to implement `safe ICF
-   `_ without the false
-   positives that can result from other implementation techniques such as
-   relocation scanning. Address-significance tables are enabled by default
-   on ELF targets when using the integrated assembler. This flag currently
-   only has an effect on ELF targets.
 
 Profile Guided Optimization
 ---------------------------
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index b71d1e15ae..9035a91ce2 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -758,10 +758,6 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
 def fno_profile_use : Flag<["-"], "fno-profile-use">,
     Alias;
 
-def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Option]>,
-  HelpText<"Emit an address-significance table">;
-def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>,
-  HelpText<"Don't emit an address-significance table">;
 def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>,
   HelpText<"Enable the 'blocks' language feature">;
 def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group;
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index c199b5428e..99567e04ba 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -335,9 +335,6 @@ CODEGENOPT(EmbedSource, 1, 0)
 /// Whether to emit all vtables
 CODEGENOPT(ForceEmitVTables, 1, 0)
 
-/// Whether to emit an address-significance table into the object file.
-CODEGENOPT(Addrsig, 1, 0)
-
 
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 415bd96262..226a27b216 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -454,7 +454,6 @@ static void initTargetOptions(llvm::TargetOptions &Options,
   Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
   Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
   Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
-  Options.EmitAddrsig = CodeGenOpts.Addrsig;
 
   if (CodeGenOpts.EnableSplitDwarf)
     Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 4db4dc19a8..e7b15c7ad8 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -4777,11 +4777,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
-                   getToolChain().getTriple().isOSBinFormatELF() &&
-                       getToolChain().useIntegratedAs()))
-    CmdArgs.push_back("-faddrsig");
-
   // Finally add the compile command to the compilation.
   if (Args.hasArg(options::OPT__SLASH_fallback) &&
       Output.getType() == types::TY_Object &&
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c26d5fb79b..d62429dc78 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1119,8 +1119,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
 
   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
 
-  Opts.Addrsig = Args.hasArg(OPT_faddrsig);
-
   return Success;
 }
 
diff --git a/test/CodeGen/addrsig.c b/test/CodeGen/addrsig.c
deleted file mode 100644
index 2cbdb2b554..0000000000
--- a/test/CodeGen/addrsig.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s
-// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s
-
-// ADDRSIG: .addrsig
-// ADDRSIG: .addrsig_sym g1
-// ADDRSIG-NOT: .addrsig_sym g2
-
-// NO-ADDRSIG-NOT: .addrsig
-
-extern const int g1[], g2[];
-
-const int *f1() {
-  return g1;
-}
-
-int f2() {
-  return g2[0];
-}
diff --git a/test/Driver/addrsig.c b/test/Driver/addrsig.c
deleted file mode 100644
index fd5598c472..0000000000
--- a/test/Driver/addrsig.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
-// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
-// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
-// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
-// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
-
-// ADDRSIG: -faddrsig
-// NO-ADDRSIG-NOT: -faddrsig
-- 
GitLab


From 641d6452c92bbb41eb207365a757b8026c7083ff Mon Sep 17 00:00:00 2001
From: Peter Collingbourne 
Date: Wed, 18 Jul 2018 00:27:07 +0000
Subject: [PATCH 0592/1023] Re-land r337333, "Teach Clang to emit
 address-significance tables.", which was reverted in r337336.

The problem that required a revert was fixed in r337338.

Also added a missing "REQUIRES: x86-registered-target" to one of
the tests.

Original commit message:
> Teach Clang to emit address-significance tables.
>
> By default, we emit an address-significance table on all ELF
> targets when the integrated assembler is enabled. The emission of an
> address-significance table can be controlled with the -faddrsig and
> -fno-addrsig flags.
>
> Differential Revision: https://reviews.llvm.org/D48155

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337339 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst                     |  8 ++++++++
 docs/UsersManual.rst                      |  9 +++++++++
 include/clang/Driver/Options.td           |  4 ++++
 include/clang/Frontend/CodeGenOptions.def |  3 +++
 lib/CodeGen/BackendUtil.cpp               |  1 +
 lib/Driver/ToolChains/Clang.cpp           |  5 +++++
 lib/Frontend/CompilerInvocation.cpp       |  2 ++
 test/CodeGen/addrsig.c                    | 20 ++++++++++++++++++++
 test/Driver/addrsig.c                     |  8 ++++++++
 9 files changed, 60 insertions(+)
 create mode 100644 test/CodeGen/addrsig.c
 create mode 100644 test/Driver/addrsig.c

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index c0ce10d6eb..99be2fdfe0 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -98,6 +98,14 @@ Non-comprehensive list of changes in this release
   finding out the warning hierarchy, and which of them are enabled by default
   or for a particular compiler invocation.
 
+- By default, Clang emits an address-significance table into
+  every ELF object file when using the integrated assembler.
+  Address-significance tables allow linkers to implement `safe ICF
+  `_ without the false
+  positives that can result from other implementation techniques such as
+  relocation scanning. The ``-faddrsig`` and ``-fno-addrsig`` flags can be
+  used to control whether to emit the address-significance table.
+
 - ...
 
 New Compiler Flags
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 4470dab947..418afb2d54 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1382,6 +1382,15 @@ are listed below.
         // value of -fmax-type-align.
       }
 
+.. option:: -faddrsig, -fno-addrsig
+
+   Controls whether Clang emits an address-significance table into the object
+   file. Address-significance tables allow linkers to implement `safe ICF
+   `_ without the false
+   positives that can result from other implementation techniques such as
+   relocation scanning. Address-significance tables are enabled by default
+   on ELF targets when using the integrated assembler. This flag currently
+   only has an effect on ELF targets.
 
 Profile Guided Optimization
 ---------------------------
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 9035a91ce2..b71d1e15ae 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -758,6 +758,10 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
 def fno_profile_use : Flag<["-"], "fno-profile-use">,
     Alias;
 
+def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Option]>,
+  HelpText<"Emit an address-significance table">;
+def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>,
+  HelpText<"Don't emit an address-significance table">;
 def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>,
   HelpText<"Enable the 'blocks' language feature">;
 def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group;
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index 99567e04ba..c199b5428e 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -335,6 +335,9 @@ CODEGENOPT(EmbedSource, 1, 0)
 /// Whether to emit all vtables
 CODEGENOPT(ForceEmitVTables, 1, 0)
 
+/// Whether to emit an address-significance table into the object file.
+CODEGENOPT(Addrsig, 1, 0)
+
 
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 226a27b216..415bd96262 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -454,6 +454,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
   Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
   Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
   Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
+  Options.EmitAddrsig = CodeGenOpts.Addrsig;
 
   if (CodeGenOpts.EnableSplitDwarf)
     Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index e7b15c7ad8..4db4dc19a8 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -4777,6 +4777,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
+                   getToolChain().getTriple().isOSBinFormatELF() &&
+                       getToolChain().useIntegratedAs()))
+    CmdArgs.push_back("-faddrsig");
+
   // Finally add the compile command to the compilation.
   if (Args.hasArg(options::OPT__SLASH_fallback) &&
       Output.getType() == types::TY_Object &&
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index d62429dc78..c26d5fb79b 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1119,6 +1119,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
 
   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
 
+  Opts.Addrsig = Args.hasArg(OPT_faddrsig);
+
   return Success;
 }
 
diff --git a/test/CodeGen/addrsig.c b/test/CodeGen/addrsig.c
new file mode 100644
index 0000000000..d7141092bb
--- /dev/null
+++ b/test/CodeGen/addrsig.c
@@ -0,0 +1,20 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -faddrsig -O -o - | FileCheck --check-prefix=ADDRSIG %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -S %s -O -o - | FileCheck --check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: .addrsig
+// ADDRSIG: .addrsig_sym g1
+// ADDRSIG-NOT: .addrsig_sym g2
+
+// NO-ADDRSIG-NOT: .addrsig
+
+extern const int g1[], g2[];
+
+const int *f1() {
+  return g1;
+}
+
+int f2() {
+  return g2[0];
+}
diff --git a/test/Driver/addrsig.c b/test/Driver/addrsig.c
new file mode 100644
index 0000000000..fd5598c472
--- /dev/null
+++ b/test/Driver/addrsig.c
@@ -0,0 +1,8 @@
+// RUN: %clang -### -target x86_64-unknown-linux -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-integrated-as -faddrsig -c %s 2>&1 | FileCheck -check-prefix=ADDRSIG %s
+// RUN: %clang -### -target x86_64-unknown-linux -fno-addrsig -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+// RUN: %clang -### -target x86_64-apple-darwin -c %s 2>&1 | FileCheck -check-prefix=NO-ADDRSIG %s
+
+// ADDRSIG: -faddrsig
+// NO-ADDRSIG-NOT: -faddrsig
-- 
GitLab


From 7847576370b75cbe43989eed51681e4e07fea273 Mon Sep 17 00:00:00 2001
From: Martin Storsjo 
Date: Wed, 18 Jul 2018 06:15:09 +0000
Subject: [PATCH 0593/1023] [AArch64] Define TARGET_HEADER_BUILTIN

Without it, the new intrinsics became available for all language
variants. This was missed in SVN r337327.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337352 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/Targets/AArch64.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index e55b606da9..1665a21435 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -29,6 +29,8 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
    {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
   {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
+  {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
 #include "clang/Basic/BuiltinsAArch64.def"
 };
 
-- 
GitLab


From d438ffd9aaa8c915f13d2cb87796ffd69ab12325 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Wed, 18 Jul 2018 06:49:33 +0000
Subject: [PATCH 0594/1023] [modules] Print input files when -module-file-info
 file switch is passed.

This patch improves traceability of duplicated header files which end
up in multiple pcms.

Differential Revision: https://reviews.llvm.org/D47118




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337353 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Frontend/FrontendActions.cpp | 39 ++++++++++++++++++++++++++++++++
 test/Modules/module_file_info.m  | 10 ++++++++
 2 files changed, 49 insertions(+)

diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 06db814f4b..9344e673c7 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -560,6 +560,45 @@ namespace {
 
       Out << "\n";
     }
+
+    /// Tells the \c ASTReaderListener that we want to receive the
+    /// input files of the AST file via \c visitInputFile.
+    bool needsInputFileVisitation() override { return true; }
+
+    /// Tells the \c ASTReaderListener that we want to receive the
+    /// input files of the AST file via \c visitInputFile.
+    bool needsSystemInputFileVisitation() override { return true; }
+
+    /// Indicates that the AST file contains particular input file.
+    ///
+    /// \returns true to continue receiving the next input file, false to stop.
+    bool visitInputFile(StringRef Filename, bool isSystem,
+                        bool isOverridden, bool isExplicitModule) override {
+
+      Out.indent(2) << "Input file: " << Filename;
+
+      if (isSystem || isOverridden || isExplicitModule) {
+        Out << " [";
+        if (isSystem) {
+          Out << "System";
+          if (isOverridden || isExplicitModule)
+            Out << ", ";
+        }
+        if (isOverridden) {
+          Out << "Overridden";
+          if (isExplicitModule)
+            Out << ", ";
+        }
+        if (isExplicitModule)
+          Out << "ExplicitModule";
+
+        Out << "]";
+      }
+
+      Out << "\n";
+
+      return true;
+    }
 #undef DUMP_BOOLEAN
   };
 }
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
index f2967be6f8..05d401b945 100644
--- a/test/Modules/module_file_info.m
+++ b/test/Modules/module_file_info.m
@@ -43,6 +43,16 @@
 // CHECK:   Predefined macros:
 // CHECK:     -DBLARG
 // CHECK:     -DWIBBLE=WOBBLE
+// CHECK: Input file: {{.*}}DependsOnModulePrivate.h
+// CHECK-NEXT: Input file: {{.*}}Other.h
+// CHECK-NEXT: Input file: {{.*}}SubFramework.h
+// CHECK-NEXT: Input file: {{.*}}not_coroutines.h
+// CHECK-NEXT: Input file: {{.*}}not_cxx.h
+// CHECK-NEXT: Input file: {{.*}}other.h
+// CHECK-NEXT: Input file: {{.*}}module.map
+// CHECK-NEXT: Input file: {{.*}}DependsOnModule.h
+// CHECK-NEXT: Input file: {{.*}}module_private.map
+// CHECK-NEXT: Input file: {{.*}}module.map
 
 // CHECK: Diagnostic options:
 // CHECK:   IgnoreWarnings: Yes
-- 
GitLab


From cdf04dc18cc75e98b6049179645fd676da3ec24d Mon Sep 17 00:00:00 2001
From: Nico Weber 
Date: Wed, 18 Jul 2018 11:55:03 +0000
Subject: [PATCH 0595/1023] Mention clang-cl improvements from r335466 and
 r336379 in ReleaseNotes.rst

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337381 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 99be2fdfe0..01c02f8d71 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -166,7 +166,19 @@ Attribute Changes in Clang
 Windows Support
 ---------------
 
-Clang's support for building native Windows programs ...
+- clang-cl's support for precompiled headers has been much improved:
+
+   - When using a pch file, clang-cl now no longer redundantly emits inline
+     methods that are already stored in the obj that was built together with
+     the pch file (matching cl.exe).  This speeds up builds using pch files
+     by around 30%.
+
+   - The /Ycfoo.h and /Yufoo.h flags an now be used without /FIfoo.h when
+     foo.h is instead included by an explicit `#include` directive. This means
+     Visual Studio's default stdafx.h setup now uses precompiled headers with
+     clang-cl.
+
+- ...
 
 
 C Language Changes in Clang
-- 
GitLab


From 8deba4344428131861f909fd6d59b0f2c4d643e2 Mon Sep 17 00:00:00 2001
From: Erich Keane 
Date: Wed, 18 Jul 2018 13:07:13 +0000
Subject: [PATCH 0596/1023] Clear properties inadvertantly added to tests in
 R336379

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


From 70cf0f619eaa16e62b228a20caee34af9be89ce8 Mon Sep 17 00:00:00 2001
From: Eric Liu 
Date: Wed, 18 Jul 2018 15:17:52 +0000
Subject: [PATCH 0597/1023] [CodeComplete] Allow getDeclaration on RK_Pattern
 result.

Summary:
RK_Pattern results can also have associated declarations e.g. field
decls in constructor initializers.

Reviewers: bkramer

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D49484

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337394 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Sema/CodeCompleteConsumer.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 606f3b3690..ede3ddf919 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -895,9 +895,11 @@ public:
     computeCursorKindAndAvailability();
   }
 
-  /// Retrieve the declaration stored in this result.
+  /// Retrieve the declaration stored in this result. This might be nullptr if
+  /// Kind is RK_Pattern.
   const NamedDecl *getDeclaration() const {
-    assert(Kind == RK_Declaration && "Not a declaration result");
+    assert(((Kind == RK_Declaration) || (Kind == RK_Pattern)) &&
+           "Not a declaration or pattern result");
     return Declaration;
   }
 
-- 
GitLab


From 43cba1e10e20f01a4a185649d6298b532ad46fa8 Mon Sep 17 00:00:00 2001
From: JF Bastien 
Date: Wed, 18 Jul 2018 18:01:41 +0000
Subject: [PATCH 0598/1023] Support implicit _Atomic struct load / store

Summary:
Using _Atomic to do implicit load / store is just a seq_cst atomic_load / atomic_store. Stores currently assert in Sema::ImpCastExprToType with 'can't implicitly cast lvalue to rvalue with this cast kind', but that's erroneous. The codegen is fine as the test shows.

While investigating I found that Richard had found the problem here: https://reviews.llvm.org/D46112#1113557



Reviewers: dexonsmith

Subscribers: cfe-commits, efriedma, rsmith, aaron.ballman

Differential Revision: https://reviews.llvm.org/D49458

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337410 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/Sema.cpp         |  1 +
 test/CodeGen/atomic-ops.c | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 55000e3e35..f81a34c40b 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -481,6 +481,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
     case CK_ArrayToPointerDecay:
     case CK_FunctionToPointerDecay:
     case CK_ToVoid:
+    case CK_NonAtomicToAtomic:
       break;
     }
   }
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c
index db97706c5d..500939f6fd 100644
--- a/test/CodeGen/atomic-ops.c
+++ b/test/CodeGen/atomic-ops.c
@@ -183,6 +183,18 @@ struct S {
   double x;
 };
 
+void implicit_store(_Atomic(struct S) *a, struct S s) {
+  // CHECK-LABEL: @implicit_store(
+  // CHECK: store atomic i64 %{{.*}}, i64* %{{.*}} seq_cst, align 8
+  *a = s;
+}
+
+struct S implicit_load(_Atomic(struct S) *a) {
+  // CHECK-LABEL: @implicit_load(
+  // CHECK: load atomic i64, i64* %{{.*}} seq_cst, align 8
+  return *a;
+}
+
 struct S fd1(struct S *a) {
   // CHECK-LABEL: @fd1
   // CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4
-- 
GitLab


From 0e4f59d7b40a4e5cb0189e4c69fce75279031a10 Mon Sep 17 00:00:00 2001
From: Artem Dergachev 
Date: Wed, 18 Jul 2018 18:44:40 +0000
Subject: [PATCH 0599/1023] [analyzer] Remove a debug print that was
 accidentally left around.

No functional change intended.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337417 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/StaticAnalyzer/Core/BugReporter.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 30d7edb9c6..096c8e7356 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2562,7 +2562,6 @@ generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode,
           assert(!LastPiece &&
                  "There can only be one final piece in a diagnostic.");
           LastPiece = std::move(Piece);
-          llvm::errs() << "Writing to last piece" << "\n";
           (*Notes)[ErrorNode].push_back(LastPiece);
         }
       }
-- 
GitLab


From 1a78aeb17c78bc38c5cc7580dccc49136079ac07 Mon Sep 17 00:00:00 2001
From: Erich Keane 
Date: Wed, 18 Jul 2018 20:04:48 +0000
Subject: [PATCH 0600/1023] Add support for __declspec(code_seg("segname"))

This patch uses CodeSegAttr to represent __declspec(code_seg) rather than
building on the existing support for #pragma code_seg.
The code_seg declspec is applied on functions and classes. This attribute
enables the placement of code into separate named segments, including compiler-
generated codes and template instantiations.

For more information, please see the following:
https://msdn.microsoft.com/en-us/library/dn636922.aspx

This patch fixes the regression for the support for attribute ((section).
https://github.com/llvm-mirror/clang/commit/746b78de7812bc785fbb5207b788348040b23fa7

Patch by Soumi Manna (Manna)
Differential Revision: https://reviews.llvm.org/D48841



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337420 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/Attr.td                |   7 ++
 include/clang/Basic/AttrDocs.td            |  12 ++
 include/clang/Basic/DiagnosticSemaKinds.td |  12 +-
 include/clang/Sema/Sema.h                  |   4 +
 lib/CodeGen/CodeGenModule.cpp              |  12 +-
 lib/Sema/SemaDecl.cpp                      |  79 ++++++++++++
 lib/Sema/SemaDeclAttr.cpp                  |  69 +++++++++-
 lib/Sema/SemaDeclCXX.cpp                   |  34 +++++
 lib/Sema/SemaLambda.cpp                    |   4 +
 test/CodeGenCXX/code-seg.cpp               | 139 +++++++++++++++++++++
 test/CodeGenCXX/code-seg1.cpp              |  87 +++++++++++++
 test/CodeGenCXX/code-seg2.cpp              | 111 ++++++++++++++++
 test/CodeGenCXX/code-seg3.cpp              |  65 ++++++++++
 test/SemaCXX/code-seg.cpp                  | 105 ++++++++++++++++
 test/SemaCXX/code-seg1.cpp                 |  97 ++++++++++++++
 15 files changed, 829 insertions(+), 8 deletions(-)
 create mode 100644 test/CodeGenCXX/code-seg.cpp
 create mode 100644 test/CodeGenCXX/code-seg1.cpp
 create mode 100644 test/CodeGenCXX/code-seg2.cpp
 create mode 100644 test/CodeGenCXX/code-seg3.cpp
 create mode 100644 test/SemaCXX/code-seg.cpp
 create mode 100644 test/SemaCXX/code-seg1.cpp

diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 0219c715d3..36c980029c 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1770,6 +1770,13 @@ def Section : InheritableAttr {
   let Documentation = [SectionDocs];
 }
 
+def CodeSeg : InheritableAttr {
+  let Spellings = [Declspec<"code_seg">];
+  let Args = [StringArgument<"Name">];
+  let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>;
+  let Documentation = [CodeSegDocs];
+}
+
 def PragmaClangBSSSection : InheritableAttr {
   // This attribute has no spellings as it is only ever created implicitly.
   let Spellings = [];
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 15aa77e357..ecaf95a933 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -306,6 +306,18 @@ An example of how to use ``alloc_size``
   }];
 }
 
+def CodeSegDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``__declspec(code_seg)`` attribute enables the placement of code into separate
+named segments that can be paged or locked in memory individually. This attribute
+is used to control the placement of instantiated templates and compiler-generated
+code. See the documentation for `__declspec(code_seg)`_ on MSDN.
+
+.. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx
+  }];
+}
+
 def AllocAlignDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e441f7b8f5..28eb36b056 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2668,11 +2668,19 @@ def err_only_annotate_after_access_spec : Error<
   "access specifier can only have annotation attributes">;
 
 def err_attribute_section_invalid_for_target : Error<
-  "argument to 'section' attribute is not valid for this target: %0">;
+  "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">;
 def warn_mismatched_section : Warning<
-  "section does not match previous declaration">, InGroup
; + "%select{codeseg|section}0 does not match previous declaration">, InGroup
; def warn_attribute_section_on_redeclaration : Warning< "section attribute is specified on redeclared variable">, InGroup
; +def err_mismatched_code_seg_base : Error< + "derived class must specify the same code segment as its base classes">; +def err_mismatched_code_seg_override : Error< + "overriding virtual function must specify the same code segment as its overridden function">; +def err_conflicting_codeseg_attribute : Error< + "conflicting code segment specifiers">; +def warn_duplicate_codeseg_attribute : Warning< + "duplicate code segment specifiers">, InGroup
; def err_anonymous_property: Error< "anonymous property is not supported">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f13e423cef..4ef982e24f 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1952,6 +1952,7 @@ public: bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); + Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, @@ -2446,6 +2447,8 @@ public: int FirstArg, unsigned AttrSpellingListIndex); SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, unsigned AttrSpellingListIndex); + CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name, + unsigned AttrSpellingListIndex); AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident, unsigned AttrSpellingListIndex); @@ -5852,6 +5855,7 @@ public: /// ensure that referenceDLLExportedClassMethods is called some point later /// when all outer classes of Class are complete. void checkClassLevelDLLAttribute(CXXRecordDecl *Class); + void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class); void referenceDLLExportedClassMethods(); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b412d3083f..6886870888 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1387,8 +1387,10 @@ void CodeGenModule::setNonAliasAttributes(GlobalDecl GD, F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs); } } - - if (const SectionAttr *SA = D->getAttr()) + + if (const auto *CSA = D->getAttr()) + GO->setSection(CSA->getName()); + else if (const auto *SA = D->getAttr()) GO->setSection(SA->getName()); } @@ -1485,8 +1487,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, setLinkageForGV(F, FD); setGVProperties(F, FD); - if (const SectionAttr *SA = FD->getAttr()) - F->setSection(SA->getName()); + if (const auto *CSA = FD->getAttr()) + F->setSection(CSA->getName()); + else if (const auto *SA = FD->getAttr()) + F->setSection(SA->getName()); if (FD->isReplaceableGlobalAllocationFunction()) { // A replaceable global allocation function does not act like a builtin by diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a754cc912d..b6381dc1e4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2452,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *SA = dyn_cast(Attr)) NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(), AttrSpellingListIndex); + else if (const auto *CSA = dyn_cast(Attr)) + NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(), + AttrSpellingListIndex); else if (const auto *IA = dyn_cast(Attr)) NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(), AttrSpellingListIndex, @@ -2670,6 +2673,15 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // Redeclaration adds code-seg attribute. + const auto *NewCSA = New->getAttr(); + if (NewCSA && !Old->hasAttr() && + !NewCSA->isImplicit() && isa(New)) { + Diag(New->getLocation(), diag::warn_mismatched_section) + << 0 /*codeseg*/; + Diag(Old->getLocation(), diag::note_previous_declaration); + } + if (!Old->hasAttrs()) return; @@ -8723,6 +8735,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->dropAttr(); } + // Apply an implicit CodeSegAttr from class declspec or + // apply an implicit SectionAttr from #pragma code_seg if active. + if (!NewFD->hasAttr()) { + if (Attr *SAttr = getImplicitCodeSegOrSectionAttrForFunction(NewFD, + D.isFunctionDefinition())) { + NewFD->addAttr(SAttr); + } + } + // Handle attributes. ProcessDeclAttributes(S, NewFD, D); @@ -9170,6 +9191,64 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, return NewFD; } +/// Return a CodeSegAttr from a containing class. The Microsoft docs say +/// when __declspec(code_seg) "is applied to a class, all member functions of +/// the class and nested classes -- this includes compiler-generated special +/// member functions -- are put in the specified segment." +/// The actual behavior is a little more complicated. The Microsoft compiler +/// won't check outer classes if there is an active value from #pragma code_seg. +/// The CodeSeg is always applied from the direct parent but only from outer +/// classes when the #pragma code_seg stack is empty. See: +/// https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer +/// available since MS has removed the page. +static Attr *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) { + const auto *Method = dyn_cast(FD); + if (!Method) + return nullptr; + const CXXRecordDecl *Parent = Method->getParent(); + if (const auto *SAttr = Parent->getAttr()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + + // The Microsoft compiler won't check outer classes for the CodeSeg + // when the #pragma code_seg stack is active. + if (S.CodeSegStack.CurrentValue) + return nullptr; + + while ((Parent = dyn_cast(Parent->getParent()))) { + if (const auto *SAttr = Parent->getAttr()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + } + return nullptr; +} + +/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a +/// containing class. Otherwise it will return implicit SectionAttr if the +/// function is a definition and there is an active value on CodeSegStack +/// (from the current #pragma code-seg value). +/// +/// \param FD Function being declared. +/// \param IsDefinition Whether it is a definition or just a declarartion. +/// \returns A CodeSegAttr or SectionAttr to apply to the function or +/// nullptr if no attribute should be added. +Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, + bool IsDefinition) { + if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD)) + return A; + if (!FD->hasAttr() && IsDefinition && + CodeSegStack.CurrentValue) { + return SectionAttr::CreateImplicit(getASTContext(), + SectionAttr::Declspec_allocate, + CodeSegStack.CurrentValue->getString(), + CodeSegStack.CurrentPragmaLocation); + } + return nullptr; +} /// Checks if the new declaration declared in dependent context must be /// put in the same redeclaration chain as the specified declaration. /// diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 47ef872e43..f549aa0468 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2825,10 +2825,18 @@ static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, unsigned AttrSpellingListIndex) { + // Explicit or partial specializations do not inherit + // the section attribute from the primary template. + if (const auto *FD = dyn_cast(D)) { + if (AttrSpellingListIndex == SectionAttr::Declspec_allocate && + FD->isFunctionTemplateSpecialization()) + return nullptr; + } if (SectionAttr *ExistingAttr = D->getAttr()) { if (ExistingAttr->getName() == Name) return nullptr; - Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section); + Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) + << 1 /*section*/; Diag(Range.getBegin(), diag::note_previous_attribute); return nullptr; } @@ -2839,7 +2847,8 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName); if (!Error.empty()) { - Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error; + Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error + << 1 /*'section'*/; return false; } return true; @@ -2870,6 +2879,59 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(NewAttr); } +static bool checkCodeSegName(Sema&S, SourceLocation LiteralLoc, StringRef CodeSegName) { + std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName); + if (!Error.empty()) { + S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error + << 0 /*'code-seg'*/; + return false; + } + return true; +} + +CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, SourceRange Range, + StringRef Name, + unsigned AttrSpellingListIndex) { + // Explicit or partial specializations do not inherit + // the code_seg attribute from the primary template. + if (const auto *FD = dyn_cast(D)) { + if (FD->isFunctionTemplateSpecialization()) + return nullptr; + } + if (const auto *ExistingAttr = D->getAttr()) { + if (ExistingAttr->getName() == Name) + return nullptr; + Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) + << 0 /*codeseg*/; + Diag(Range.getBegin(), diag::note_previous_attribute); + return nullptr; + } + return ::new (Context) CodeSegAttr(Range, Context, Name, + AttrSpellingListIndex); +} + +static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Str; + SourceLocation LiteralLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) + return; + if (!checkCodeSegName(S, LiteralLoc, Str)) + return; + if (const auto *ExistingAttr = D->getAttr()) { + if (!ExistingAttr->isImplicit()) { + S.Diag(AL.getLoc(), + ExistingAttr->getName() == Str + ? diag::warn_duplicate_codeseg_attribute + : diag::err_conflicting_codeseg_attribute); + return; + } + D->dropAttr(); + } + if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL.getRange(), Str, + AL.getAttributeSpellingListIndex())) + D->addAttr(CSA); +} + // Check for things we'd like to warn about. Multiversioning issues are // handled later in the process, once we know how many exist. bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { @@ -6120,6 +6182,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; + case ParsedAttr::AT_CodeSeg: + handleCodeSegAttr(S, D, AL); + break; case ParsedAttr::AT_Target: handleTargetAttr(S, D, AL); break; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index eda6e16195..d2a2bb2020 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2243,6 +2243,19 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, CXXRecordDecl *CXXBaseDecl = cast(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); + // Microsoft docs say: + // "If a base-class has a code_seg attribute, derived classes must have the + // same attribute." + const auto *BaseCSA = CXXBaseDecl->getAttr(); + const auto *DerivedCSA = Class->getAttr(); + if ((DerivedCSA || BaseCSA) && + (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { + Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); + Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) + << CXXBaseDecl; + return nullptr; + } + // A class which contains a flexible array member is not suitable for use as a // base class: // - If the layout determines that a base comes before another base, @@ -5614,6 +5627,16 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S, } } +void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { + // Mark any compiler-generated routines with the implicit code_seg attribute. + for (auto *Method : Class->methods()) { + if (Method->isUserProvided()) + continue; + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + Method->addAttr(A); + } +} + /// Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -6122,6 +6145,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } checkClassLevelDLLAttribute(Record); + checkClassLevelCodeSegAttribute(Record); bool ClangABICompat4 = Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4; @@ -14589,6 +14613,16 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, } } + // Virtual overrides must have the same code_seg. + const auto *OldCSA = Old->getAttr(); + const auto *NewCSA = New->getAttr(); + if ((NewCSA || OldCSA) && + (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) { + Diag(New->getLocation(), diag::err_mismatched_code_seg_override); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); // If the calling conventions match, everything is fine diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 0b768cc9fa..04d9e55bc6 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -913,6 +913,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // This represents the function body for the lambda function, check if we // have to apply optnone due to a pragma. AddRangeBasedOptnone(Method); + + // code_seg attribute on lambda apply to the method. + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + Method->addAttr(A); // Attributes on the lambda apply to the method. ProcessDeclAttributes(CurScope, Method, ParamInfo); diff --git a/test/CodeGenCXX/code-seg.cpp b/test/CodeGenCXX/code-seg.cpp new file mode 100644 index 0000000000..7dad927420 --- /dev/null +++ b/test/CodeGenCXX/code-seg.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics + +// Simple case + +int __declspec(code_seg("foo_one")) bar_one() { return 1; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_one" + +// Simple case - explicit attribute used over pragma +#pragma code_seg("foo_two") +int __declspec(code_seg("foo_three")) bar2() { return 2; } +//CHECK: define {{.*}}bar2{{.*}} section "foo_three" + +// Check that attribute on one function doesn't affect another +int another1() { return 1001; } +//CHECK: define {{.*}}another1{{.*}} section "foo_two" + +// Member functions + +struct __declspec(code_seg("foo_four")) Foo { + int bar3() {return 0;} + int bar4(); + int __declspec(code_seg("foo_six")) bar6() { return 6; } + int bar7() { return 7; } + struct Inner { + int bar5() { return 5; } + } z; + virtual int baz1() { return 1; } +}; + +struct __declspec(code_seg("foo_four")) FooTwo : Foo { + int baz1() { return 20; } +}; + +int caller1() { + Foo f; return f.bar3(); +} + +//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four" +int Foo::bar4() { return 4; } +//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_four" + +#pragma code_seg("someother") + +int caller2() { + Foo f; + Foo *fp = new FooTwo; + return f.z.bar5() + f.bar6() + f.bar7() + fp->baz1(); +} +// MS Compiler and Docs do not match for nested routines +// Doc says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_four" +// Compiler says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two" +// A bug has been reported: see https://reviews.llvm.org/D22931, the +// Microsoft feedback page is no longer available. +//CHECK: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two" +//CHECK: define {{.*}}bar6@Foo{{.*}} section "foo_six" +//CHECK: define {{.*}}bar7@Foo{{.*}} section "foo_four" +// Check that code_seg active at class declaration is not used on member +// declared outside class when it is not active. + +#pragma code_seg(push,"AnotherSeg") + +struct FooThree { + int bar8(); + int bar9() { return 9; } +}; + +#pragma code_seg(pop) + + +int FooThree::bar8() {return 0;} + +int caller3() +{ + FooThree f; + return f.bar8() + f.bar9(); +} + +//CHECK: define {{.*}}bar8@FooThree{{.*}} section "someother" +//CHECK: define {{.*}}bar9@FooThree{{.*}} section "AnotherSeg" + +struct NonTrivialCopy { + NonTrivialCopy(); + NonTrivialCopy(const NonTrivialCopy&); + ~NonTrivialCopy(); +}; + +// check the section for compiler-generated function with declspec. + +struct __declspec(code_seg("foo_seven")) FooFour { + FooFour() {} + int __declspec(code_seg("foo_eight")) bar10(int t) { return t; } + NonTrivialCopy f; +}; + +//CHECK: define {{.*}}0FooFour@@QAE@ABU0@@Z{{.*}} section "foo_seven" +// check the section for compiler-generated function with no declspec. + +struct FooFive { + FooFive() {} + int __declspec(code_seg("foo_nine")) bar11(int t) { return t; } + NonTrivialCopy f; +}; + +//CHECK: define {{.*}}0FooFive@@QAE@ABU0@@Z{{.*}} section "someother" + +#pragma code_seg("YetAnother") +int caller4() +{ + FooFour z1; + FooFour z2 = z1; + FooFive y1; + FooFive y2 = y1; + return z2.bar10(0) + y2.bar11(1); +} + +//CHECK: define {{.*}}bar10@FooFour{{.*}} section "foo_eight" +//CHECK: define {{.*}}bar11@FooFive{{.*}} section "foo_nine" + +struct FooSix { + #pragma code_seg("foo_ten") + int bar12() { return 12; } + #pragma code_seg("foo_eleven") + int bar13() { return 13; } +}; + +int bar14() { return 14; } +//CHECK: define {{.*}}bar14{{.*}} section "foo_eleven" + +int caller5() +{ + FooSix fsix; + return fsix.bar12() + fsix.bar13(); +} + +//CHECK: define {{.*}}bar12@FooSix{{.*}} section "foo_ten" +//CHECK: define {{.*}}bar13@FooSix{{.*}} section "foo_eleven" +//CHECK: define {{.*}}baz1@FooTwo{{.*}} section "foo_four" + diff --git a/test/CodeGenCXX/code-seg1.cpp b/test/CodeGenCXX/code-seg1.cpp new file mode 100644 index 0000000000..93be3e520a --- /dev/null +++ b/test/CodeGenCXX/code-seg1.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics +// The Microsoft document says: "When this attribute is applied to a class, +// all member functions of the class and nested classes - this includes +// compiler-generated special member functions - are put in the specified segment." +// But the MS compiler does not always follow that. A bug has been reported: +// see https://reviews.llvm.org/D22931, the Microsoft feedback page is no +// longer available. +// The MS compiler will apply a declspec from the parent class if there is no +// #pragma code_seg active at the class definition. If there is an active +// code_seg that is used instead. + +// No active code_seg + +struct __declspec(code_seg("foo_outer")) Foo1 { + struct Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo1::Inner::bar1() {} +void Foo1::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo1{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar2@Inner@Foo1{{.*}} section "foo_outer" + +struct __declspec(code_seg("foo_outer")) Foo2 { + struct __declspec(code_seg("foo_inner")) Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo2::Inner::bar1() {} +void Foo2::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo2{{.*}} section "foo_inner" +//CHECK: define {{.*}}bar2@Inner@Foo2{{.*}} section "foo_inner" + +#pragma code_seg(push, "otherseg") +struct __declspec(code_seg("foo_outer")) Foo3 { + struct Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo3::Inner::bar1() {} +void Foo3::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo3{{.*}} section "otherseg" +//CHECK: define {{.*}}bar2@Inner@Foo3{{.*}} section "otherseg" + +struct __declspec(code_seg("foo_outer")) Foo4 { + struct __declspec(code_seg("foo_inner")) Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo4::Inner::bar1() {} +void Foo4::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo4{{.*}} section "foo_inner" +//CHECK: define {{.*}}bar2@Inner@Foo4{{.*}} section "foo_inner" + +#pragma code_seg(pop) +// Back to no active pragma +struct __declspec(code_seg("foo_outer")) Foo5 { + struct Inner { + void bar1(); + static void bar2(); + struct __declspec(code_seg("inner1_seg")) Inner1 { + struct Inner2 { + void bar1(); + static void bar2(); + }; + }; + }; +}; +void Foo5::Inner::bar1() {} +void Foo5::Inner::bar2() {} +void Foo5::Inner::Inner1::Inner2::bar1() {} +void Foo5::Inner::Inner1::Inner2::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo5{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar2@Inner@Foo5{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar1@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg" +//CHECK: define {{.*}}bar2@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg" + diff --git a/test/CodeGenCXX/code-seg2.cpp b/test/CodeGenCXX/code-seg2.cpp new file mode 100644 index 0000000000..ab72bf44cb --- /dev/null +++ b/test/CodeGenCXX/code-seg2.cpp @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++11 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics + +// Class member templates + +#pragma code_seg(push, "something") + +template +struct __declspec(code_seg("foo_one")) ClassOne { + int bar1(T t) { return int(t); } + int bar2(T t); + int bar3(T t); +}; + +template +int ClassOne::bar2(T t) { + return int(t); +} + +int caller1() { + ClassOne coi; + return coi.bar1(6) + coi.bar2(3); +} + +//CHECK: define {{.*}}bar1@?$ClassOne{{.*}} section "foo_one" +//CHECK: define {{.*}}bar2@?$ClassOne{{.*}} section "foo_one" + + +template +struct ClassTwo { + int bar11(T t) { return int(t); } + int bar22(T t); + int bar33(T t); +}; + +#pragma code_seg("newone") + +template +int ClassTwo::bar22(T t) { + return int(t); +} + +#pragma code_seg("someother") + +template +int ClassTwo::bar33(T t) { + return int(t); +} + +#pragma code_seg("yetanother") + +int caller2() { + ClassTwo coi; + return coi.bar11(6) + coi.bar22(3) + coi.bar33(44); +} + +//CHECK: define {{.*}}bar11@?$ClassTwo{{.*}} section "something" +//CHECK: define {{.*}}bar22@?$ClassTwo{{.*}} section "newone" +//CHECK: define {{.*}}bar33@?$ClassTwo{{.*}} section "someother" + +template<> +struct ClassOne +{ + int bar44(double d) { return 1; } +}; +template<> +struct __declspec(code_seg("foo_three")) ClassOne +{ + int bar55(long d) { return 1; } +}; + +#pragma code_seg("onemore") +int caller3() { + ClassOne d; + ClassOne l; + return d.bar44(1.0)+l.bar55(1); +} + +//CHECK: define {{.*}}bar44{{.*}} section "yetanother" +//CHECK: define {{.*}}bar55{{.*}} section "foo_three" + + +// Function templates +template +int __declspec(code_seg("foo_four")) bar66(T t) { return int(t); } + +// specializations do not take the segment from primary +template<> +int bar66(int i) { return 0; } + +#pragma code_seg(pop) + +template<> +int bar66(char c) { return 0; } + +struct A1 {int i;}; +template<> +int __declspec(code_seg("foo_five")) bar66(A1 a) { return a.i; } + +int caller4() +{ +// but instantiations do use the section from the primary +return bar66(0) + bar66(1.0) + bar66('c'); +} +//CHECK: define {{.*}}bar66@H{{.*}} section "onemore" +//CHECK-NOT: define {{.*}}bar66@D{{.*}} section +//CHECK: define {{.*}}bar66@UA1{{.*}} section "foo_five" +//CHECK: define {{.*}}bar66@N{{.*}} section "foo_four" + + + diff --git a/test/CodeGenCXX/code-seg3.cpp b/test/CodeGenCXX/code-seg3.cpp new file mode 100644 index 0000000000..d6f267747e --- /dev/null +++ b/test/CodeGenCXX/code-seg3.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 +// expected-no-diagnostics + +// Non-Member Function Overloading is involved + +int __declspec(code_seg("foo_one")) bar_one(int) { return 1; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_one" +int __declspec(code_seg("foo_two")) bar_one(int,float) { return 11; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_two" +int __declspec(code_seg("foo_three")) bar_one(float) { return 12; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_three" + +// virtual function overloading is involved + +struct __declspec(code_seg("my_one")) Base3 { + virtual int barA(int) { return 1; } + virtual int barA(int,float) { return 2; } + virtual int barA(float) { return 3; } + + virtual void __declspec(code_seg("my_two")) barB(int) { } + virtual void __declspec(code_seg("my_three")) barB(float) { } + virtual void __declspec(code_seg("my_four")) barB(int, float) { } + +}; + +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_two" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_three" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_four" + +#pragma code_seg("another") +// Member functions +struct __declspec(code_seg("foo_four")) Foo { + int bar3() {return 0;} + __declspec(code_seg("foo_lala")) int bar4() {return 0;} }; int caller() {Foo f; return f.bar3() + f.bar4(); } + +//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four" +//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_lala" + +// Lambdas +#pragma code_seg("something") + +int __declspec(code_seg("foo")) bar1() +{ + int lala = 4; + auto l = [=](int i) { return i+4; }; + return l(-4); +} + +//CHECK: define {{.*}}bar1{{.*}} section "foo" +//CHECK: define {{.*}}lambda{{.*}}bar1{{.*}} section "something" + +double __declspec(code_seg("foo")) bar2() +{ + double lala = 4.0; + auto l = [=](double d) __declspec(code_seg("another")) { return d+4.0; }; + return l(4.0); +} + +//CHECK: define {{.*}}bar2{{.*}} section "foo" +//CHECK: define {{.*}}lambda{{.*}}bar2{{.*}} section "another" + + diff --git a/test/SemaCXX/code-seg.cpp b/test/SemaCXX/code-seg.cpp new file mode 100644 index 0000000000..c4ce6613ba --- /dev/null +++ b/test/SemaCXX/code-seg.cpp @@ -0,0 +1,105 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 + +struct __declspec(code_seg("my_one")) FooOne { + int barC(); +}; + +struct FooTwo { + int __declspec(code_seg("my_three")) barD(); + int barE(); +}; +int __declspec(code_seg("my_four")) FooOne::barC() { return 10; } +// expected-warning@-1 {{codeseg does not match previous declaration}} +// expected-note@3{{previous attribute is here}} +int __declspec(code_seg("my_five")) FooTwo::barD() { return 20; } +// expected-warning@-1 {{codeseg does not match previous declaration}} +// expected-note@8 {{previous attribute is here}} +int __declspec(code_seg("my_six")) FooTwo::barE() { return 30; } +// expected-warning@-1 {{codeseg does not match previous declaration}} +// expected-note@9 {{previous declaration is here}} + +// Microsoft docs say: +// If a base-class has a code_seg attribute, derived classes must have the +// same attribute. +struct __declspec(code_seg("my_base")) Base1 {}; +struct Base2 {}; + +struct D1 : Base1 {}; +//expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-note@24 {{base class 'Base1' specified here}} +struct __declspec(code_seg("my_derived")) D2 : Base1 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-note@24 {{base class 'Base1' specified here}} +struct __declspec(code_seg("my_derived")) D3 : Base2 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-note@25 {{base class 'Base2' specified here}} + +template struct __declspec(code_seg("my_base")) MB : T { }; +template struct __declspec(code_seg("my_derived")) MD : T { }; +MB mb1; // ok +MB mb2; +// expected-error@37 {{derived class must specify the same code segment as its base classes}} +// expected-note@-2 {{in instantiation of template class}} +// expected-note@25 {{base class 'Base2' specified here}} +MD md1; +// expected-error@38 {{derived class must specify the same code segment as its base classes}} +// expected-note@-2 {{in instantiation of template class}} +// expected-note@24 {{base class 'Base1' specified here}} +MD md2; +// expected-error@38 {{derived class must specify the same code segment as its base classes}} +// expected-note@-2 {{in instantiation of template class}} +// expected-note@25 {{base class 'Base2' specified here}} + +// Virtual overrides must have the same code_seg. +struct __declspec(code_seg("my_one")) Base3 { + virtual int barA() { return 1; } + virtual int __declspec(code_seg("my_two")) barB() { return 2; } +}; +struct __declspec(code_seg("my_one")) Derived3 : Base3 { + int barA() { return 4; } // ok + int barB() { return 6; } + // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}} + // expected-note@56 {{previous declaration is here}} +}; + +struct Base4 { + virtual int __declspec(code_seg("my_one")) barA() {return 1;} + virtual int barB() { return 2;} +}; +struct Derived4 : Base4 { + virtual int barA() {return 1;} + // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}} + // expected-note@66 {{previous declaration is here}} + virtual int __declspec(code_seg("my_two")) barB() {return 1;} + // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}} + // expected-note@67 {{previous declaration is here}} +}; + +// MS gives an error when different code segments are used but a warning when a duplicate is used + +// Function +int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; } +// expected-warning@-1 {{duplicate code segment specifiers}} +int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; } +// expected-error@-1 {{conflicting code segment specifiers}} + +// Class +struct __declspec(code_seg("foo")) __declspec(code_seg("foo")) Foo { + // expected-warning@-1 {{duplicate code segment specifiers}} + int bar3() {return 0;} +}; +struct __declspec(code_seg("foo")) __declspec(code_seg("bar")) FooSix { + // expected-error@-1 {{conflicting code segment specifiers}} + int bar3() {return 0;} +}; + +//Class Members +struct FooThree { + int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; } + // expected-warning@-1 {{duplicate code segment specifiers}} + int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; } + // expected-error@-1 {{conflicting code segment specifiers}} + int bar8(); + int bar9() { return 9; } +}; + diff --git a/test/SemaCXX/code-seg1.cpp b/test/SemaCXX/code-seg1.cpp new file mode 100644 index 0000000000..0537f9cab3 --- /dev/null +++ b/test/SemaCXX/code-seg1.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 + +// Multiple inheritance is involved (code segmments all disagree between the bases and derived class) +struct __declspec(code_seg("my_base")) Base1 {}; +struct Base2 {}; + +struct D1 : Base1, Base2 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-note@4 {{base class 'Base1' specified here}} + +struct __declspec(code_seg("my_derived")) D2 : Base2, Base1 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-error@-2 {{derived class must specify the same code segment as its base classes}} +// expected-note@5 {{base class 'Base2' specified here}} +// expected-note@4 {{base class 'Base1' specified here}} + +// Multiple inheritance (code segments partially agree between the bases and the derived class) +struct __declspec(code_seg("base_class")) BaseClass1 {}; +struct __declspec(code_seg("base_class")) BaseClass2 {}; + +struct Derived1 : BaseClass1, BaseClass2 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-error@-2 {{derived class must specify the same code segment as its base classes}} +// expected-note@18 {{base class 'BaseClass1' specified here}} +// expected-note@19 {{base class 'BaseClass2' specified here}} + +struct __declspec(code_seg("derived_class")) Derived2 : BaseClass2, BaseClass1 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-error@-2 {{derived class must specify the same code segment as its base classes}} +// expected-note@19 {{base class 'BaseClass2' specified here}} +// expected-note@18 {{base class 'BaseClass1' specified here}} + +struct __declspec(code_seg("base_class")) Derived3 : BaseClass2, BaseClass1 {}; //OK +struct __declspec(code_seg("base_class")) Derived4 : BaseClass1, BaseClass2 {}; //OK + +// Multiple inheritance is involved (code segmments all agree between the bases and derived class) +struct __declspec(code_seg("foo_base")) B1 {}; +struct __declspec(code_seg("foo_base")) B2 {}; +struct __declspec(code_seg("foo_base")) Derived : B1, B2 {}; + +// virtual Inheritance is involved (code segmments all disagree between the bases and derived class) +struct __declspec(code_seg("my_one")) Base { + virtual int barA() { return 1; } ; +}; + +struct __declspec(code_seg("my_two")) Derived5 : virtual Base { + virtual int barB() { return 2; }; +}; +// expected-error@-3 {{derived class must specify the same code segment as its base classes}} +// expected-note@42 {{base class 'Base' specified here}} + +struct __declspec(code_seg("my_three")) Derived6 : virtual Base { + virtual int barC() { return 3; }; +}; +// expected-error@-3 {{derived class must specify the same code segment as its base classes}} +// expected-note@42 {{base class 'Base' specified here}} + +struct __declspec(code_seg("my_four")) Derived7 : Derived5, Derived6 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-error@-2 {{derived class must specify the same code segment as its base classes}} +// expected-note@46 {{base class 'Derived5' specified here}} +// expected-note@52 {{base class 'Derived6' specified here}} + +// virtual Inheritance is involved (code segmments partially agree between the bases and derived class) +struct __declspec(code_seg("my_class")) BaseClass { + virtual int barA() { return 1; } ; +}; + +struct __declspec(code_seg("my_class")) DerivedClass1 : virtual BaseClass { //OK + virtual int barB() { return 2; }; +}; + +struct __declspec(code_seg("my_class")) DerivedClass2 : virtual BaseClass { //OK + virtual int barC() { return 3; }; +}; + +struct __declspec(code_seg("my_derived_one")) DerivedClass3 : DerivedClass1, DerivedClass2 {}; +// expected-error@-1 {{derived class must specify the same code segment as its base classes}} +// expected-error@-2 {{derived class must specify the same code segment as its base classes}} +// expected-note@69 {{base class 'DerivedClass1' specified here}} +// expected-note@73 {{base class 'DerivedClass2' specified here}} + +// virtual Inheritance is involved (code segmments all agree between the bases and derived class) +struct __declspec(code_seg("foo_one")) Class { + virtual int foo1() { return 10; } ; +}; + +struct __declspec(code_seg("foo_one")) Derived_One: virtual Class { //OK + virtual int foo2() { return 20; }; +}; + +struct __declspec(code_seg("foo_one")) Derived_Two : virtual Class { //OK + virtual int foo3() { return 30; }; +}; + +struct __declspec(code_seg("foo_one")) Derived_Three : Derived_One, Derived_Two {}; //OK + -- GitLab From 580f7daabc7696d50ad09d9643b2afeadbd387d8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 18 Jul 2018 20:13:36 +0000 Subject: [PATCH 0601/1023] DR330: when determining whether a cast casts away constness, consider qualifiers from all levels matching a multidimensional array. For example, this allows casting from pointer to array of array of const volatile int to pointer to const pointer to volatile pointer to int because the multidimensional array part of the source type corresponds to a part of the destination type that contains both 'const' and 'volatile'. Differential Revision: https://reviews.llvm.org/D49457 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337422 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 1 + lib/AST/ASTContext.cpp | 21 ++++---- lib/Sema/SemaCast.cpp | 95 +++++++++++++++++++++++----------- test/CXX/drs/dr3xx.cpp | 22 ++++++++ 4 files changed, 98 insertions(+), 41 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 8d3cf760a5..c6f8e2973e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -2289,6 +2289,7 @@ public: const ObjCMethodDecl *MethodImp); bool UnwrapSimilarTypes(QualType &T1, QualType &T2); + bool UnwrapSimilarArrayTypes(QualType &T1, QualType &T2); /// Determine if two types are similar, according to the C++ rules. That is, /// determine if they are the same other than qualifiers on the initial diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d6bc9c0c71..9cd0844184 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -5008,28 +5008,29 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, /// Attempt to unwrap two types that may both be array types with the same bound /// (or both be array types of unknown bound) for the purpose of comparing the /// cv-decomposition of two types per C++ [conv.qual]. -static void unwrapSimilarArrayTypes(ASTContext &Ctx, QualType &T1, - QualType &T2) { +bool ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) { + bool UnwrappedAny = false; while (true) { - auto *AT1 = Ctx.getAsArrayType(T1); - if (!AT1) return; + auto *AT1 = getAsArrayType(T1); + if (!AT1) return UnwrappedAny; - auto *AT2 = Ctx.getAsArrayType(T2); - if (!AT2) return; + auto *AT2 = getAsArrayType(T2); + if (!AT2) return UnwrappedAny; // If we don't have two array types with the same constant bound nor two // incomplete array types, we've unwrapped everything we can. if (auto *CAT1 = dyn_cast(AT1)) { auto *CAT2 = dyn_cast(AT2); if (!CAT2 || CAT1->getSize() != CAT2->getSize()) - return; + return UnwrappedAny; } else if (!isa(AT1) || !isa(AT2)) { - return; + return UnwrappedAny; } T1 = AT1->getElementType(); T2 = AT2->getElementType(); + UnwrappedAny = true; } } @@ -5046,7 +5047,7 @@ static void unwrapSimilarArrayTypes(ASTContext &Ctx, QualType &T1, /// \return \c true if a pointer type was unwrapped, \c false if we reached a /// pair of types that can't be unwrapped further. bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) { - unwrapSimilarArrayTypes(*this, T1, T2); + UnwrapSimilarArrayTypes(T1, T2); const auto *T1PtrType = T1->getAs(); const auto *T2PtrType = T2->getAs(); @@ -5055,7 +5056,7 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) { T2 = T2PtrType->getPointeeType(); return true; } - + const auto *T1MPType = T1->getAs(); const auto *T2MPType = T2->getAs(); if (T1MPType && T2MPType && diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index ec95032c4e..86633d6dd5 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -459,50 +459,83 @@ enum CastAwayConstnessKind { /// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from /// both types, provided that they're both pointer-like or array-like. Unlike /// the Sema function, doesn't care if the unwrapped pieces are related. +/// +/// This function may remove additional levels as necessary for correctness: +/// the resulting T1 is unwrapped sufficiently that it is never an array type, +/// so that its qualifiers can be directly compared to those of T2 (which will +/// have the combined set of qualifiers from all indermediate levels of T2), +/// as (effectively) required by [expr.const.cast]p7 replacing T1's qualifiers +/// with those from T2. static CastAwayConstnessKind unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { - // Note, even if this returns false, it may have unwrapped some number of - // matching "array of" pieces. That's OK, we don't need to check their - // cv-qualifiers (that check is covered by checking the qualifiers on the - // array types themselves). - if (Context.UnwrapSimilarTypes(T1, T2)) - return CastAwayConstnessKind::CACK_Similar; - - // Special case: if the destination type is a reference type, unwrap it as - // the first level. - if (T2->isReferenceType()) { - T2 = T2->getPointeeType(); - return CastAwayConstnessKind::CACK_Similar; - } - + enum { None, Ptr, MemPtr, BlockPtr, Array }; auto Classify = [](QualType T) { - if (T->isAnyPointerType()) return 1; - if (T->isMemberPointerType()) return 2; - if (T->isBlockPointerType()) return 3; + if (T->isAnyPointerType()) return Ptr; + if (T->isMemberPointerType()) return MemPtr; + if (T->isBlockPointerType()) return BlockPtr; // We somewhat-arbitrarily don't look through VLA types here. This is at // least consistent with the behavior of UnwrapSimilarTypes. - if (T->isConstantArrayType() || T->isIncompleteArrayType()) return 4; - return 0; + if (T->isConstantArrayType() || T->isIncompleteArrayType()) return Array; + return None; }; - int T1Class = Classify(T1); - if (!T1Class) - return CastAwayConstnessKind::CACK_None; - - int T2Class = Classify(T2); - if (!T2Class) - return CastAwayConstnessKind::CACK_None; - auto Unwrap = [&](QualType T) { if (auto *AT = Context.getAsArrayType(T)) return AT->getElementType(); return T->getPointeeType(); }; - T1 = Unwrap(T1); - T2 = Unwrap(T2); - return T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind - : CastAwayConstnessKind::CACK_Incoherent; + CastAwayConstnessKind Kind; + + if (T2->isReferenceType()) { + // Special case: if the destination type is a reference type, unwrap it as + // the first level. (The source will have been an lvalue expression in this + // case, so there is no corresponding "reference to" in T1 to remove.) This + // simulates removing a "pointer to" from both sides. + T2 = T2->getPointeeType(); + Kind = CastAwayConstnessKind::CACK_Similar; + } else if (Context.UnwrapSimilarTypes(T1, T2)) { + Kind = CastAwayConstnessKind::CACK_Similar; + } else { + // Try unwrapping mismatching levels. + int T1Class = Classify(T1); + if (T1Class == None) + return CastAwayConstnessKind::CACK_None; + + int T2Class = Classify(T2); + if (T2Class == None) + return CastAwayConstnessKind::CACK_None; + + T1 = Unwrap(T1); + T2 = Unwrap(T2); + Kind = T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind + : CastAwayConstnessKind::CACK_Incoherent; + } + + // We've unwrapped at least one level. If the resulting T1 is a (possibly + // multidimensional) array type, any qualifier on any matching layer of + // T2 is considered to correspond to T1. Decompose down to the element + // type of T1 so that we can compare properly. + while (true) { + Context.UnwrapSimilarArrayTypes(T1, T2); + + if (Classify(T1) != Array) + break; + + auto T2Class = Classify(T2); + if (T2Class == None) + break; + + if (T2Class != Array) + Kind = CastAwayConstnessKind::CACK_Incoherent; + else if (Kind != CastAwayConstnessKind::CACK_Incoherent) + Kind = CastAwayConstnessKind::CACK_SimilarKind; + + T1 = Unwrap(T1); + T2 = Unwrap(T2).withCVRQualifiers(T2.getCVRQualifiers()); + } + + return Kind; } /// Check if the pointer conversion from SrcType to DestType casts away diff --git a/test/CXX/drs/dr3xx.cpp b/test/CXX/drs/dr3xx.cpp index 04fd258a7c..d723c5b78c 100644 --- a/test/CXX/drs/dr3xx.cpp +++ b/test/CXX/drs/dr3xx.cpp @@ -403,6 +403,28 @@ namespace dr330 { // dr330: 7 (void) reinterpret_cast(q); // expected-error {{casts away qualifiers}} (void) reinterpret_cast(t); } + + namespace swift_17882 { + typedef const char P[72]; + typedef int *Q; + void f(P &pr, P *pp) { + (void) reinterpret_cast(pr); + (void) reinterpret_cast(pp); + } + + struct X {}; + typedef const volatile int A[1][2][3]; + typedef int *const X::*volatile *B1; + typedef int *const X::* *B2; + typedef int *X::* volatile *B3; + typedef volatile int *(*const B4)[4]; + void f(A *a) { + (void) reinterpret_cast(a); + (void) reinterpret_cast(a); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(a); // expected-error {{casts away qualifiers}} + (void) reinterpret_cast(a); + } + } } namespace dr331 { // dr331: yes -- GitLab From 3264f7f496b40d3348ee9dc1be5c0c577348ac8c Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 18 Jul 2018 23:21:19 +0000 Subject: [PATCH 0602/1023] Reapply r336660: [Modules] Autoload subdirectory modulemaps with specific LangOpts Summary: Reproducer and errors: https://bugs.llvm.org/show_bug.cgi?id=37878 lookupModule was falling back to loadSubdirectoryModuleMaps when it couldn't find ModuleName in (proper) search paths. This was causing iteration over all files in the search path subdirectories for example "/usr/include/foobar" in bugzilla case. Users don't expect Clang to load modulemaps in subdirectories implicitly, and also the disk access is not cheap. if (AllowExtraModuleMapSearch) true with ObjC with @import ModuleName. Reviewers: rsmith, aprantl, bruno Subscribers: cfe-commits, teemperor, v.g.vassilev Differential Revision: https://reviews.llvm.org/D48367 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337430 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/HeaderSearch.h | 12 ++++++++++-- lib/Frontend/CompilerInstance.cpp | 15 ++++++++++----- lib/Lex/HeaderSearch.cpp | 17 ++++++++++------- lib/Serialization/ASTReader.cpp | 4 +++- test/Modules/Inputs/autoload-subdirectory/a.h | 9 +++++++++ test/Modules/Inputs/autoload-subdirectory/b.h | 1 + test/Modules/Inputs/autoload-subdirectory/c.h | 7 +++++++ .../include/module.modulemap | 3 +++ .../autoload-subdirectory/module.modulemap | 3 +++ test/Modules/autoload-subdirectory.cpp | 10 ++++++++++ 10 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 test/Modules/Inputs/autoload-subdirectory/a.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/b.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/c.h create mode 100644 test/Modules/Inputs/autoload-subdirectory/include/module.modulemap create mode 100644 test/Modules/Inputs/autoload-subdirectory/module.modulemap create mode 100644 test/Modules/autoload-subdirectory.cpp diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index fd52000954..b7147c54fa 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -529,8 +529,12 @@ public: /// search directories to produce a module definition. If not, this lookup /// will only return an already-known module. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module with the given name. - Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true, + bool AllowExtraModuleMapSearch = false); /// Try to find a module map file in the given directory, returning /// \c nullptr if none is found. @@ -595,8 +599,12 @@ private: /// but for compatibility with some buggy frameworks, additional attempts /// may be made to find the module under a related-but-different search-name. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module named ModuleName. - Module *lookupModule(StringRef ModuleName, StringRef SearchName); + Module *lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch = false); /// Retrieve a module with the given name, which may be part of the /// given framework. diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 5727aae5f1..155ead4ac8 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1653,8 +1653,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Retrieve the cached top-level module. Module = Known->second; } else if (ModuleName == getLangOpts().CurrentModule) { - // This is the module we're building. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + // This is the module we're building. + Module = PP->getHeaderSearchInfo().lookupModule( + ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); /// FIXME: perhaps we should (a) look for a module using the module name // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? //if (Module == nullptr) { @@ -1666,7 +1668,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); HeaderSearchOptions &HSOpts = PP->getHeaderSearchInfo().getHeaderSearchOpts(); @@ -1743,7 +1746,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ImportLoc, ARRFlags)) { case ASTReader::Success: { if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { // Error out if Module does not refer to the file in the prebuilt @@ -1874,7 +1878,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); PrivPath.push_back(std::make_pair(&II, Path[0].second)); - if (PP->getHeaderSearchInfo().lookupModule(PrivateModule)) + if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true, + !IsInclusionDirective)) Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); if (Sub) { diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 312bd2d061..b1a2ef1212 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -198,14 +198,15 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, return Result.str().str(); } -Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, + bool AllowExtraModuleMapSearch) { // Look in the module map to determine if there is a module by this name. Module *Module = ModMap.findModule(ModuleName); if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) return Module; StringRef SearchName = ModuleName; - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); // The facility for "private modules" -- adjacent, optional module maps named // module.private.modulemap that are supposed to define private submodules -- @@ -216,13 +217,14 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { // could force building unwanted dependencies into the parent module and cause // dependency cycles. if (!Module && SearchName.consume_back("_Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); if (!Module && SearchName.consume_back("Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); return Module; } -Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch) { Module *Module = nullptr; // Look through the various header search paths to load any available module @@ -281,8 +283,9 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { continue; // Load all module maps in the immediate subdirectories of this search - // directory. - loadSubdirectoryModuleMaps(SearchDirs[Idx]); + // directory if ModuleName was from @import. + if (AllowExtraModuleMapSearch) + loadSubdirectoryModuleMaps(SearchDirs[Idx]); // Look again for the module. Module = ModMap.findModule(ModuleName); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 19b5af38df..4167e86880 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2626,7 +2626,9 @@ ASTReader::ReadControlBlock(ModuleFile &F, "MODULE_DIRECTORY found before MODULE_NAME"); // If we've already loaded a module map file covering this module, we may // have a better path for it (relative to the current build). - Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName); + Module *M = PP.getHeaderSearchInfo().lookupModule( + F.ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ true); if (M && M->Directory) { // If we're implicitly loading a module, the base directory can't // change between the build and use. diff --git a/test/Modules/Inputs/autoload-subdirectory/a.h b/test/Modules/Inputs/autoload-subdirectory/a.h new file mode 100644 index 0000000000..8be94312e3 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/a.h @@ -0,0 +1,9 @@ +#include "b.h" + +class foo { + int x, y; + +public: + foo(){}; + ~foo(){}; +}; diff --git a/test/Modules/Inputs/autoload-subdirectory/b.h b/test/Modules/Inputs/autoload-subdirectory/b.h new file mode 100644 index 0000000000..bfde5bf79f --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/b.h @@ -0,0 +1 @@ +class bar {}; diff --git a/test/Modules/Inputs/autoload-subdirectory/c.h b/test/Modules/Inputs/autoload-subdirectory/c.h new file mode 100644 index 0000000000..e5a45250f9 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/c.h @@ -0,0 +1,7 @@ +class nyan { + bool x, y; + +public: + nyan(){}; + ~nyan(){}; +}; diff --git a/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap new file mode 100644 index 0000000000..880ae38b97 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/include/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" } +module b { header "b.h" } +module c { header "c.h" } diff --git a/test/Modules/Inputs/autoload-subdirectory/module.modulemap b/test/Modules/Inputs/autoload-subdirectory/module.modulemap new file mode 100644 index 0000000000..880ae38b97 --- /dev/null +++ b/test/Modules/Inputs/autoload-subdirectory/module.modulemap @@ -0,0 +1,3 @@ +module a { header "a.h" } +module b { header "b.h" } +module c { header "c.h" } diff --git a/test/Modules/autoload-subdirectory.cpp b/test/Modules/autoload-subdirectory.cpp new file mode 100644 index 0000000000..e76f7056ab --- /dev/null +++ b/test/Modules/autoload-subdirectory.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fmodules -fmodule-name=Foo -I %S/Inputs/autoload-subdirectory/ %s -verify +// expected-no-diagnostics + +#include "a.h" +#import "c.h" + +int main() { + foo neko; + return 0; +} -- GitLab From fed5a86cd10a83b409c85bf84cb2176a61c0ab52 Mon Sep 17 00:00:00 2001 From: James Dennett Date: Wed, 18 Jul 2018 23:21:31 +0000 Subject: [PATCH 0603/1023] Documentation: fix a typo in the AST Matcher Reference docs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337431 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 938c99adfd..5c8ec31066 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -3015,7 +3015,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher, /// class A {}; /// using B = A; /// \endcode -/// The matcher type(hasUnqualifeidDesugaredType(recordType())) matches +/// The matcher type(hasUnqualifiedDesugaredType(recordType())) matches /// both B and A. AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher, InnerMatcher) { -- GitLab From cdd3c71916d2060e1047d2e7bb688a1f442204ac Mon Sep 17 00:00:00 2001 From: Manoj Gupta Date: Thu, 19 Jul 2018 00:44:52 +0000 Subject: [PATCH 0604/1023] [clang]: Add support for "-fno-delete-null-pointer-checks" Summary: Support for this option is needed for building Linux kernel. This is a very frequently requested feature by kernel developers. More details : https://lkml.org/lkml/2018/4/4/601 GCC option description for -fdelete-null-pointer-checks: This Assume that programs cannot safely dereference null pointers, and that no code or data element resides at address zero. -fno-delete-null-pointer-checks is the inverse of this implying that null pointer dereferencing is not undefined. This feature is implemented in as the function attribute "null-pointer-is-valid"="true". This CL only adds the attribute on the function. It also strips "nonnull" attributes from function arguments but keeps the related warnings unchanged. Corresponding LLVM change rL336613 already updated the optimizations to not treat null pointer dereferencing as undefined if the attribute is present. Reviewers: t.p.northover, efriedma, jyknight, chandlerc, rnk, srhines, void, george.burgess.iv Reviewed By: jyknight Subscribers: drinkcat, xbolva00, cfe-commits Differential Revision: https://reviews.llvm.org/D47894 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337433 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangCommandLineReference.rst | 8 ++++++ include/clang/Driver/Options.td | 9 +++++-- include/clang/Frontend/CodeGenOptions.def | 1 + lib/CodeGen/CGCall.cpp | 20 ++++++++++----- lib/Driver/ToolChains/Clang.cpp | 4 +++ lib/Frontend/CompilerInvocation.cpp | 2 ++ test/CodeGen/delete-null-pointer-checks.c | 20 +++++++++++++++ test/CodeGen/nonnull.c | 30 +++++++++++++++-------- test/CodeGen/vla.c | 6 +++-- test/CodeGenCXX/address-space-ref.cpp | 6 +++-- test/CodeGenCXX/constructors.cpp | 15 ++++++++---- test/CodeGenCXX/temporaries.cpp | 6 +++-- test/Driver/clang_f_opts.c | 9 +++++-- test/Sema/nonnull.c | 4 +++ 14 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 test/CodeGen/delete-null-pointer-checks.c diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 513128119e..87c7896ba7 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -1543,6 +1543,14 @@ Specifies the largest alignment guaranteed by '::operator new(size\_t)' Disable implicit builtin knowledge of a specific function +.. option:: -fdelete-null-pointer-checks, -fno-delete-null-pointer-checks + +When enabled, treat null pointer dereference, creation of a reference to null, +or passing a null pointer to a function parameter annotated with the "nonnull" +attribute as undefined behavior. (And, thus the optimizer may assume that any +pointer used in such a way must not have been null and optimize away the +branches accordingly.) On by default. + .. option:: -fno-elide-type Do not elide types when printing diagnostics diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index b71d1e15ae..6051608448 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1080,6 +1080,13 @@ def frewrite_imports : Flag<["-"], "frewrite-imports">, Group, Flags<[CC1Option]>; def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group; +def fdelete_null_pointer_checks : Flag<["-"], + "fdelete-null-pointer-checks">, Group, + HelpText<"Treat usage of null pointers as undefined behavior.">; +def fno_delete_null_pointer_checks : Flag<["-"], + "fno-delete-null-pointer-checks">, Group, Flags<[CC1Option]>, + HelpText<"Do not treat usage of null pointers as undefined behavior.">; + def frewrite_map_file : Separate<["-"], "frewrite-map-file">, Group, Flags<[ DriverOption, CC1Option ]>; @@ -2855,8 +2862,6 @@ defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group, Group; defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group; defm default_inline : BooleanFFlag<"default-inline">, Group; -defm delete_null_pointer_checks : BooleanFFlag<"delete-null-pointer-checks">, - Group; defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group; defm float_store : BooleanFFlag<"float-store">, Group; defm friend_injection : BooleanFFlag<"friend-injection">, Group; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index c199b5428e..2ed96d4327 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -130,6 +130,7 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero +CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined. CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated. CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 07fb6d56dd..fcc8a3e5f6 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1734,6 +1734,8 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, FuncAttrs.addAttribute("less-precise-fpmad", llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); + if (CodeGenOpts.NullPointerIsValid) + FuncAttrs.addAttribute("null-pointer-is-valid", "true"); if (!CodeGenOpts.FPDenormalMode.empty()) FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode); @@ -1867,7 +1869,8 @@ void CodeGenModule::ConstructAttributeList( } if (TargetDecl->hasAttr()) RetAttrs.addAttribute(llvm::Attribute::NoAlias); - if (TargetDecl->hasAttr()) + if (TargetDecl->hasAttr() && + !CodeGenOpts.NullPointerIsValid) RetAttrs.addAttribute(llvm::Attribute::NonNull); if (TargetDecl->hasAttr()) FuncAttrs.addAttribute("no_caller_saved_registers"); @@ -1974,7 +1977,8 @@ void CodeGenModule::ConstructAttributeList( if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) RetAttrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy) .getQuantity()); - else if (getContext().getTargetAddressSpace(PTy) == 0) + else if (getContext().getTargetAddressSpace(PTy) == 0 && + !CodeGenOpts.NullPointerIsValid) RetAttrs.addAttribute(llvm::Attribute::NonNull); } @@ -2083,7 +2087,8 @@ void CodeGenModule::ConstructAttributeList( if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) Attrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy) .getQuantity()); - else if (getContext().getTargetAddressSpace(PTy) == 0) + else if (getContext().getTargetAddressSpace(PTy) == 0 && + !CodeGenOpts.NullPointerIsValid) Attrs.addAttribute(llvm::Attribute::NonNull); } @@ -2343,7 +2348,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (const ParmVarDecl *PVD = dyn_cast(Arg)) { if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), - PVD->getFunctionScopeIndex())) + PVD->getFunctionScopeIndex()) && + !CGM.getCodeGenOpts().NullPointerIsValid) AI->addAttr(llvm::Attribute::NonNull); QualType OTy = PVD->getOriginalType(); @@ -2362,7 +2368,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Attrs.addDereferenceableAttr( getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize); AI->addAttrs(Attrs); - } else if (getContext().getTargetAddressSpace(ETy) == 0) { + } else if (getContext().getTargetAddressSpace(ETy) == 0 && + !CGM.getCodeGenOpts().NullPointerIsValid) { AI->addAttr(llvm::Attribute::NonNull); } } @@ -2372,7 +2379,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // we can't use the dereferenceable attribute, but in addrspace(0) // we know that it must be nonnull. if (ArrTy->getSizeModifier() == VariableArrayType::Static && - !getContext().getTargetAddressSpace(ArrTy->getElementType())) + !getContext().getTargetAddressSpace(ArrTy->getElementType()) && + !CGM.getCodeGenOpts().NullPointerIsValid) AI->addAttr(llvm::Attribute::NonNull); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 4db4dc19a8..e23ff16699 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3348,6 +3348,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_merge_all_constants, false)) CmdArgs.push_back("-fmerge-all-constants"); + if (Args.hasFlag(options::OPT_fno_delete_null_pointer_checks, + options::OPT_fdelete_null_pointer_checks, false)) + CmdArgs.push_back("-fno-delete-null-pointer-checks"); + // LLVM Code Generator Options. if (Args.hasArg(options::OPT_frewrite_map_file) || diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c26d5fb79b..9bb673d1e7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -746,6 +746,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); + Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks); + Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); diff --git a/test/CodeGen/delete-null-pointer-checks.c b/test/CodeGen/delete-null-pointer-checks.c new file mode 100644 index 0000000000..a3c1460f0a --- /dev/null +++ b/test/CodeGen/delete-null-pointer-checks.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s | FileCheck -check-prefix=NULL-POINTER-INVALID %s +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s -fno-delete-null-pointer-checks | FileCheck -check-prefix=NULL-POINTER-VALID %s + +// Test that clang does not remove the null pointer check with +// -fno-delete-null-pointer-checks. +int null_check(int *P) { +// NULL-POINTER-VALID: %[[TOBOOL:.*]] = icmp eq i32* %P, null +// NULL-POINTER-INVALID-NOT: icmp eq +// NULL-POINTER-VALID: %[[SEL:.*]] = select i1 %[[TOBOOL:.*]], i32* null, i32* +// NULL-POINTER-INVALID-NOT: select i1 +// NULL-POINTER-VALID: load i32, i32* %[[SEL:.*]] + int *Q = P; + if (P) { + Q = P + 2; + } + return *Q; +} + +// NULL-POINTER-INVALID-NOT: attributes #0 = {{.*}} "null-pointer-is-valid"="true" +// NULL-POINTER-VALID: attributes #0 = {{.*}} "null-pointer-is-valid"="true" diff --git a/test/CodeGen/nonnull.c b/test/CodeGen/nonnull.c index 7c33e6329f..30162441cf 100644 --- a/test/CodeGen/nonnull.c +++ b/test/CodeGen/nonnull.c @@ -1,32 +1,39 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefix=NULL-INVALID %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -fno-delete-null-pointer-checks < %s | FileCheck -check-prefix=NULL-VALID %s -// CHECK: define void @foo(i32* nonnull %x) +// NULL-INVALID: define void @foo(i32* nonnull %x) +// NULL-VALID: define void @foo(i32* %x) void foo(int * __attribute__((nonnull)) x) { *x = 0; } -// CHECK: define void @bar(i32* nonnull %x) +// NULL-INVALID: define void @bar(i32* nonnull %x) +// NULL-VALID: define void @bar(i32* %x) void bar(int * x) __attribute__((nonnull(1))) { *x = 0; } -// CHECK: define void @bar2(i32* %x, i32* nonnull %y) +// NULL-INVALID: define void @bar2(i32* %x, i32* nonnull %y) +// NULL-VALID: define void @bar2(i32* %x, i32* %y) void bar2(int * x, int * y) __attribute__((nonnull(2))) { *x = 0; } static int a; -// CHECK: define nonnull i32* @bar3() +// NULL-INVALID: define nonnull i32* @bar3() +// NULL-VALID: define i32* @bar3() int * bar3() __attribute__((returns_nonnull)) { return &a; } -// CHECK: define i32 @bar4(i32 %n, i32* nonnull %p) +// NULL-INVALID: define i32 @bar4(i32 %n, i32* nonnull %p) +// NULL-VALID: define i32 @bar4(i32 %n, i32* %p) int bar4(int n, int *p) __attribute__((nonnull)) { return n + *p; } -// CHECK: define i32 @bar5(i32 %n, i32* nonnull %p) +// NULL-INVALID: define i32 @bar5(i32 %n, i32* nonnull %p) +// NULL-VALID: define i32 @bar5(i32 %n, i32* %p) int bar5(int n, int *p) __attribute__((nonnull(1, 2))) { return n + *p; } @@ -37,15 +44,18 @@ typedef union { double d; } TransparentUnion __attribute__((transparent_union)); -// CHECK: define i32 @bar6(i64 % +// NULL-INVALID: define i32 @bar6(i64 % +// NULL-VALID: define i32 @bar6(i64 % int bar6(TransparentUnion tu) __attribute__((nonnull(1))) { return *tu.p; } -// CHECK: define void @bar7(i32* nonnull %a, i32* nonnull %b) +// NULL-INVALID: define void @bar7(i32* nonnull %a, i32* nonnull %b) +// NULL-VALID: define void @bar7(i32* %a, i32* %b) void bar7(int *a, int *b) __attribute__((nonnull(1))) __attribute__((nonnull(2))) {} -// CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b) +// NULL-INVALID: define void @bar8(i32* nonnull %a, i32* nonnull %b) +// NULL-VALID: define void @bar8(i32* %a, i32* %b) void bar8(int *a, int *b) __attribute__((nonnull)) __attribute__((nonnull(1))) {} diff --git a/test/CodeGen/vla.c b/test/CodeGen/vla.c index 0f2e2cdc66..37243cd172 100644 --- a/test/CodeGen/vla.c +++ b/test/CodeGen/vla.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID int b(char* x); @@ -202,5 +203,6 @@ void test8(int a[static 3]) { } // CHECK: define void @test8(i32* dereferenceable(12) %a) void test9(int n, int a[static n]) { } -// CHECK: define void @test9(i32 %n, i32* nonnull %a) +// NULL-INVALID: define void @test9(i32 %n, i32* nonnull %a) +// NULL-VALID: define void @test9(i32 %n, i32* %a) diff --git a/test/CodeGenCXX/address-space-ref.cpp b/test/CodeGenCXX/address-space-ref.cpp index de6bddca66..5f0a429503 100644 --- a/test/CodeGenCXX/address-space-ref.cpp +++ b/test/CodeGenCXX/address-space-ref.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fno-delete-null-pointer-checks -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID // For a reference to a complete type, output the dereferenceable attribute (in // any address space). @@ -29,6 +30,7 @@ bc & bar2(bc &x, bc & y) { return x; } -// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y) +// NULL-INVALID: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y) +// NULL-VALID: define %class.bc* @_Z4bar2R2bcS0_(%class.bc* %x, %class.bc* %y) diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index a898140383..9322c410f2 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-VALID struct Member { int x; Member(); Member(int); Member(const Member &); }; struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); }; @@ -21,10 +22,12 @@ struct A { A::A(struct Undeclared &ref) : mem(0) {} // Check that delegation works. -// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( -// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( A::A(ValueClass v) : mem(v.y - v.x) {} @@ -43,11 +46,13 @@ struct B : A { B::B(struct Undeclared &ref) : A(ref), mem(1) {} -// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( // CHECK: call void @_ZN6MemberC1Ei( -// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1BC2ER10Undeclared( diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 21372effbc..2eb27e71cb 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID namespace PR16263 { const unsigned int n = 1234; @@ -333,7 +334,8 @@ namespace PR6648 { struct D; D& zed(B); void foobar() { - // CHECK: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE + // NULL-INVALID: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE + // NULL-VALID: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE zed(foo); } } diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c index be9ca2c93d..9208d6b71b 100644 --- a/test/Driver/clang_f_opts.c +++ b/test/Driver/clang_f_opts.c @@ -348,7 +348,6 @@ // RUN: -fwhole-program \ // RUN: -fcaller-saves \ // RUN: -freorder-blocks \ -// RUN: -fdelete-null-pointer-checks \ // RUN: -ffat-lto-objects \ // RUN: -fmerge-constants \ // RUN: -finline-small-functions \ @@ -414,7 +413,6 @@ // CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported // CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-fdelete-null-pointer-checks' is not supported // CHECK-WARNING-DAG: optimization flag '-ffat-lto-objects' is not supported // CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported // CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported @@ -526,3 +524,10 @@ // RUN: %clang -### -S -fno-merge-all-constants -fmerge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-MERGE-ALL-CONSTANTS %s // CHECK-NO-MERGE-ALL-CONSTANTS-NOT: "-fmerge-all-constants" // CHECK-MERGE-ALL-CONSTANTS: "-fmerge-all-constants" + +// RUN: %clang -### -S -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s +// RUN: %clang -### -S -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s +// RUN: %clang -### -S -fdelete-null-pointer-checks -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s +// RUN: %clang -### -S -fno-delete-null-pointer-checks -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s +// CHECK-NO-NULL-POINTER-CHECKS: "-fno-delete-null-pointer-checks" +// CHECK-NULL-POINTER-CHECKS-NOT: "-fno-delete-null-pointer-checks" diff --git a/test/Sema/nonnull.c b/test/Sema/nonnull.c index b589bb3d1f..3410d36ddf 100644 --- a/test/Sema/nonnull.c +++ b/test/Sema/nonnull.c @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // rdar://9584012 +// +// Verify All warnings are still issued with the option -fno-delete-null-pointer-checks +// if nullptr is passed to function with nonnull attribute. +// RUN: %clang_cc1 -fsyntax-only -fno-delete-null-pointer-checks -verify %s typedef struct { char *str; -- GitLab From e89556485efbb31cc28b37605f5d59790efa8dd1 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 19 Jul 2018 12:32:06 +0000 Subject: [PATCH 0605/1023] [PCH+Modules] Load -fmodule-map-file content before including PCHs Consider: 1) Generate PCH with -fmodules and -fmodule-map-file 2) Use PCH with -fmodules and the same -fmodule-map-file If we don't load -fmodule-map-file content before including PCHs, the modules that are dependencies in PCHs cannot get loaded, since there's no matching module map file when reading back the AST. rdar://problem/40852867 Differential Revision: https://reviews.llvm.org/D48685 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337447 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Frontend/FrontendAction.cpp | 32 +++++++++---------- .../module-imported-by-pch-with-modulemap.m | 16 ++++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 test/Modules/module-imported-by-pch-with-modulemap.m diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 7711d8460c..a5929424e5 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -766,6 +766,22 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!BeginSourceFileAction(CI)) goto failure; + // If we were asked to load any module map files, do so now. + for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { + if (auto *File = CI.getFileManager().getFile(Filename)) + CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( + File, /*IsSystem*/false); + else + CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; + } + + // Add a module declaration scope so that modules from -fmodule-map-file + // arguments may shadow modules found implicitly in search paths. + CI.getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .finishModuleDeclarationScope(); + // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { @@ -855,22 +871,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, "doesn't support modules"); } - // If we were asked to load any module map files, do so now. - for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { - if (auto *File = CI.getFileManager().getFile(Filename)) - CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( - File, /*IsSystem*/false); - else - CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; - } - - // Add a module declaration scope so that modules from -fmodule-map-file - // arguments may shadow modules found implicitly in search paths. - CI.getPreprocessor() - .getHeaderSearchInfo() - .getModuleMap() - .finishModuleDeclarationScope(); - // If we were asked to load any module files, do so now. for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) if (!CI.loadModuleFile(ModuleFile)) diff --git a/test/Modules/module-imported-by-pch-with-modulemap.m b/test/Modules/module-imported-by-pch-with-modulemap.m new file mode 100644 index 0000000000..493034118a --- /dev/null +++ b/test/Modules/module-imported-by-pch-with-modulemap.m @@ -0,0 +1,16 @@ +// RUN: rm -rf %t.dst %t.cache +// RUN: mkdir -p %t.dst/folder-with-modulemap %t.dst/pch-folder +// RUN: echo '#import "folder-with-modulemap/included.h"' > %t.dst/header.h +// RUN: echo 'extern int MyModuleVersion;' > %t.dst/folder-with-modulemap/MyModule.h +// RUN: echo '@import MyModule;' > %t.dst/folder-with-modulemap/included.h +// RUN: echo 'module MyModule { header "MyModule.h" }' > %t.dst/folder-with-modulemap/MyModule.modulemap + +// RUN: %clang_cc1 -emit-pch -o %t.dst/pch-folder/header.pch -fmodule-map-file=%t.dst/folder-with-modulemap/MyModule.modulemap -x objective-c-header -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps %t.dst/header.h +// RUN: %clang_cc1 -fsyntax-only -fmodule-map-file=%t.dst/folder-with-modulemap/MyModule.modulemap -fmodules-cache-path=%t.cache -fmodules -fimplicit-module-maps %s -include-pch %t.dst/pch-folder/header.pch -verify + +// expected-no-diagnostics + +void test() { + (void)MyModuleVersion; // should be found by implicit import +} + -- GitLab From 9647e445b0468f6250492438c639c6cb61373a2b Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic Date: Thu, 19 Jul 2018 12:44:15 +0000 Subject: [PATCH 0606/1023] [PowerPC] Handle __builtin_xxpermdi the same way as GCC does The codegen for this builtin was initially implemented to match GCC. However, due to interest from users GCC changed behaviour to account for the big endian bias of the instruction and correct it. This patch brings the handling inline with GCC. Fixes https://bugs.llvm.org/show_bug.cgi?id=38192 Differential Revision: https://reviews.llvm.org/D49424 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337449 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 18 +++++------------- test/CodeGen/builtins-ppc-vsx.c | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 92091345f2..7deeea811b 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10831,19 +10831,11 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2)); Ops[1] = Builder.CreateBitCast(Ops[1], llvm::VectorType::get(Int64Ty, 2)); - // Element zero comes from the first input vector and element one comes from - // the second. The element indices within each vector are numbered in big - // endian order so the shuffle mask must be adjusted for this on little - // endian platforms (i.e. index is complemented and source vector reversed). - unsigned ElemIdx0; - unsigned ElemIdx1; - if (getTarget().isLittleEndian()) { - ElemIdx0 = (~Index & 1) + 2; - ElemIdx1 = (~Index & 2) >> 1; - } else { // BigEndian - ElemIdx0 = (Index & 2) >> 1; - ElemIdx1 = 2 + (Index & 1); - } + // Account for endianness by treating this as just a shuffle. So we use the + // same indices for both LE and BE in order to produce expected results in + // both cases. + unsigned ElemIdx0 = (Index & 2) >> 1;; + unsigned ElemIdx1 = 2 + (Index & 1);; Constant *ShuffleElts[2] = {ConstantInt::get(Int32Ty, ElemIdx0), ConstantInt::get(Int32Ty, ElemIdx1)}; diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c index 6dda19d5d9..848d24d4fb 100644 --- a/test/CodeGen/builtins-ppc-vsx.c +++ b/test/CodeGen/builtins-ppc-vsx.c @@ -1694,43 +1694,43 @@ vec_xst_be(vd, sll, ad); res_vd = vec_xxpermdi(vd, vd, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vf = vec_xxpermdi(vf, vf, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsll = vec_xxpermdi(vsll, vsll, 2); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vull = vec_xxpermdi(vull, vull, 3); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsi = vec_xxpermdi(vsi, vsi, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vui = vec_xxpermdi(vui, vui, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vss = vec_xxpermdi(vss, vss, 2); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vus = vec_xxpermdi(vus, vus, 3); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsc = vec_xxpermdi(vsc, vsc, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vuc = vec_xxpermdi(vuc, vuc, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> -// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vd = vec_xxsldwi(vd, vd, 0); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> @@ -1786,7 +1786,7 @@ vector int xxpermdi_should_not_assert(vector int a, vector int b) { // CHECK-LE: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> // CHECK-LE-NEXT: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> -// CHECK-LE-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> +// CHECK-LE-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE-NEXT: bitcast <2 x i64> %{{[0-9]+}} to <4 x i32> } -- GitLab From 55ada9863772a59b4355bcac0649767da13c802a Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic Date: Thu, 19 Jul 2018 12:49:27 +0000 Subject: [PATCH 0607/1023] NFC: Remove extraneous semicolons as pointed out in the differential review The commit for https://reviews.llvm.org/D49424 missed the comment about the extraneous semicolons. Remove them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337451 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 7deeea811b..07cb1c3adf 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -10834,8 +10834,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, // Account for endianness by treating this as just a shuffle. So we use the // same indices for both LE and BE in order to produce expected results in // both cases. - unsigned ElemIdx0 = (Index & 2) >> 1;; - unsigned ElemIdx1 = 2 + (Index & 1);; + unsigned ElemIdx0 = (Index & 2) >> 1; + unsigned ElemIdx1 = 2 + (Index & 1); Constant *ShuffleElts[2] = {ConstantInt::get(Int32Ty, ElemIdx0), ConstantInt::get(Int32Ty, ElemIdx1)}; -- GitLab From 16cd80eccb2a2babde9db7769ab3555cdfeef542 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 19 Jul 2018 13:32:00 +0000 Subject: [PATCH 0608/1023] [CodeComplete] Fix accessibilty of protected members from base class. Summary: Currently, protected members from base classes are marked as inaccessible when completing in derived class. This patch fixes the problem by setting the naming class correctly when looking up results in base class according to [11.2.p5]. Reviewers: aaron.ballman, sammccall, rsmith Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49421 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337453 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaAccess.cpp | 27 ++++++++++++++----------- lib/Sema/SemaCodeComplete.cpp | 29 +++++++++++++++++++++++++-- test/Index/complete-access-checks.cpp | 27 +++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 44d41ea4b0..9fbae2ca29 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Specifiers.h" #include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" @@ -1856,29 +1857,31 @@ void Sema::CheckLookupAccess(const LookupResult &R) { } } -/// Checks access to Decl from the given class. The check will take access +/// Checks access to Target from the given class. The check will take access /// specifiers into account, but no member access expressions and such. /// -/// \param Decl the declaration to check if it can be accessed +/// \param Target the declaration to check if it can be accessed /// \param Ctx the class/context from which to start the search -/// \return true if the Decl is accessible from the Class, false otherwise. -bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { +/// \return true if the Target is accessible from the Class, false otherwise. +bool Sema::IsSimplyAccessible(NamedDecl *Target, DeclContext *Ctx) { if (CXXRecordDecl *Class = dyn_cast(Ctx)) { - if (!Decl->isCXXClassMember()) + if (!Target->isCXXClassMember()) return true; + if (Target->getAccess() == AS_public) + return true; QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); + // The unprivileged access is AS_none as we don't know how the member was + // accessed, which is described by the access in DeclAccessPair. + // `IsAccessible` will examine the actual access of Target (i.e. + // Decl->getAccess()) when calculating the access. AccessTarget Entity(Context, AccessedEntity::Member, Class, - DeclAccessPair::make(Decl, Decl->getAccess()), - qType); - if (Entity.getAccess() == AS_public) - return true; - + DeclAccessPair::make(Target, AS_none), qType); EffectiveContext EC(CurContext); return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; } - - if (ObjCIvarDecl *Ivar = dyn_cast(Decl)) { + + if (ObjCIvarDecl *Ivar = dyn_cast(Target)) { // @public and @package ivars are always accessible. if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 700f5a2fee..ae5183408f 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1303,8 +1303,33 @@ namespace { void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass) override { bool Accessible = true; - if (Ctx) - Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); + if (Ctx) { + DeclContext *AccessingCtx = Ctx; + // If ND comes from a base class, set the naming class back to the + // derived class if the search starts from the derived class (i.e. + // InBaseClass is true). + // + // Example: + // class B { protected: int X; } + // class D : public B { void f(); } + // void D::f() { this->^; } + // The completion after "this->" will have `InBaseClass` set to true and + // `Ctx` set to "B", when looking up in `B`. We need to set the actual + // accessing context (i.e. naming class) to "D" so that access can be + // calculated correctly. + if (InBaseClass && isa(Ctx)) { + CXXRecordDecl *RC = nullptr; + // Get the enclosing record. + for (DeclContext *DC = CurContext; !DC->isFileContext(); + DC = DC->getParent()) { + if ((RC = dyn_cast(DC))) + break; + } + if (RC) + AccessingCtx = RC; + } + Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx); + } ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, false, Accessible, FixIts); diff --git a/test/Index/complete-access-checks.cpp b/test/Index/complete-access-checks.cpp index 7eec41ec56..54d9640f6f 100644 --- a/test/Index/complete-access-checks.cpp +++ b/test/Index/complete-access-checks.cpp @@ -36,10 +36,10 @@ void Y::doSomething() { // CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34) // CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func1}{LeftParen (}{RightParen )} (36) -// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36) (inaccessible) +// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36) // CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible) // CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member1} (37) -// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37) (inaccessible) +// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37) // CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member3} (37) (inaccessible) // CHECK-SUPER-ACCESS: CXXMethod:{ResultType Y &}{TypedText operator=}{LeftParen (}{Placeholder const Y &}{RightParen )} (79) // CHECK-SUPER-ACCESS: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (81) @@ -87,3 +87,26 @@ void f(P x, Q y) { // CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText Q}{Text ::} (75) // CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{Informative P::}{TypedText ~P}{LeftParen (}{RightParen )} (81) // CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~Q}{LeftParen (}{RightParen )} (79) + +class B { +protected: + int member; +}; + +class C : private B {}; + + +class D : public C { + public: + void f(::B *b); +}; + +void D::f(::B *that) { + // RUN: c-index-test -code-completion-at=%s:106:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THIS %s + this->; +// CHECK-PRIVATE-SUPER-THIS: FieldDecl:{ResultType int}{Informative B::}{TypedText member} (37) (inaccessible) + + // RUN: c-index-test -code-completion-at=%s:110:9 %s | FileCheck -check-prefix=CHECK-PRIVATE-SUPER-THAT %s + that->; +// CHECK-PRIVATE-SUPER-THAT: FieldDecl:{ResultType int}{TypedText member} (35) (inaccessible) +} -- GitLab From e47a2eb782da0040620eada009096214e640b1c4 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 19 Jul 2018 13:36:57 +0000 Subject: [PATCH 0609/1023] Enable C++2a Chrono Literals C++2a via http://wg21.link/p0355 permits the library literals of 'd' and 'y'. This patch enables them in the Lexer so that they can be properly parsed. Note that 'd' gets confused with the hex character, so modifications to how octal, binary, and decimal numbers are parsed were required. Since this is simply making previously invalid code legal, this should be fine. Hex still greedily parses the 'd' as a hexit, since it would a: violate [lex.ext]p1 b: break existing code. Differential Revision: https://reviews.llvm.org/D49504 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337454 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/LiteralSupport.cpp | 11 +++++--- test/SemaCXX/cxx2a-user-defined-literals.cpp | 27 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test/SemaCXX/cxx2a-user-defined-literals.cpp diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index e695b2ba37..966dafca27 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -751,7 +751,8 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ // If we have a hex digit other than 'e' (which denotes a FP exponent) then // the code is using an incorrect base. - if (isHexDigit(*s) && *s != 'e' && *s != 'E') { + if (isHexDigit(*s) && *s != 'e' && *s != 'E' && + !isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0); hadError = true; @@ -804,12 +805,14 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, if (!LangOpts.CPlusPlus14) return false; - // In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library. + // In C++14, "s", "h", "min", "ms", "us", and "ns" are used in the library. // Per tweaked N3660, "il", "i", and "if" are also used in the library. + // In C++2a "d" and "y" are used in the library. return llvm::StringSwitch(Suffix) .Cases("h", "min", "s", true) .Cases("ms", "us", "ns", true) .Cases("il", "i", "if", true) + .Cases("d", "y", LangOpts.CPlusPlus2a) .Default(false); } @@ -922,7 +925,9 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s = SkipBinaryDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isHexDigit(*s)) { + } else if (isHexDigit(*s) && + !isValidUDSuffix(PP.getLangOpts(), + StringRef(s, ThisTokEnd - s))) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_digit) << StringRef(s, 1) << 2; hadError = true; diff --git a/test/SemaCXX/cxx2a-user-defined-literals.cpp b/test/SemaCXX/cxx2a-user-defined-literals.cpp new file mode 100644 index 0000000000..d730eba741 --- /dev/null +++ b/test/SemaCXX/cxx2a-user-defined-literals.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++2a %s -include %s -verify + +#ifndef INCLUDED +#define INCLUDED + +#pragma clang system_header +namespace std { + namespace chrono { + struct day{}; + struct year{}; + } + constexpr chrono::day operator"" d(unsigned long long d) noexcept; + constexpr chrono::year operator"" y(unsigned long long y) noexcept; +} + +#else + +using namespace std; +chrono::day dec_d = 5d; +chrono::day oct_d = 05d; +chrono::day bin_d = 0b011d; +// expected-error@+3{{no viable conversion from 'int' to 'chrono::day'}} +// expected-note@9{{candidate constructor (the implicit copy constructor)}} +// expected-note@9{{candidate constructor (the implicit move constructor)}} +chrono::day hex_d = 0x44d; +chrono::year y = 10y; +#endif -- GitLab From 011d8f83ca5a93b4586fa401837a7f49ee8ad4dd Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 19 Jul 2018 14:05:22 +0000 Subject: [PATCH 0610/1023] [CodeGen] Disable aggressive structor optimizations at -O0, take 3 The previous version of this patch (r332839) was reverted because it was causing "definition with same mangled name as another definition" errors in some module builds. This was caused by an unrelated bug in module importing which it exposed. The importing problem was fixed in r336240, so this recommits the original patch (r332839). Differential Revision: https://reviews.llvm.org/D46685 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337456 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ItaniumCXXABI.cpp | 18 ++++++++--- test/CodeGenCXX/ctor-dtor-alias.cpp | 41 +++++++++++++++++++----- test/CodeGenCXX/float16-declarations.cpp | 2 +- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 8dd94e4955..d156ffab56 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -3737,12 +3737,22 @@ static StructorCodegen getCodegenToUse(CodeGenModule &CGM, } llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl); - if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) - return StructorCodegen::RAUW; + // All discardable structors can be RAUWed, but we don't want to do that in + // unoptimized code, as that makes complete structor symbol disappear + // completely, which degrades debugging experience. + // Symbols with private linkage can be safely aliased, so we special case them + // here. + if (llvm::GlobalValue::isLocalLinkage(Linkage)) + return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW + : StructorCodegen::Alias; + // Linkonce structors cannot be aliased nor placed in a comdat, so these need + // to be emitted separately. // FIXME: Should we allow available_externally aliases? - if (!llvm::GlobalAlias::isValidLinkage(Linkage)) - return StructorCodegen::RAUW; + if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) || + !llvm::GlobalAlias::isValidLinkage(Linkage)) + return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW + : StructorCodegen::Emit; if (llvm::GlobalValue::isWeakForLinker(Linkage)) { // Only ELF and wasm support COMDATs with arbitrary names (C5/D5). diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index 89244cc105..4715111a14 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s - +// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases > %t +// RUN: FileCheck --check-prefix=NOOPT1 --input-file=%t %s +// RUN: FileCheck --check-prefix=NOOPT2 --input-file=%t %s +// RUN: FileCheck --check-prefix=NOOPT3 --input-file=%t %s // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes > %t // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s @@ -21,6 +23,13 @@ namespace test1 { // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) // CHECK1-NOT: comdat +// This should happen regardless of the opt level. +// NOOPT1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev +// NOOPT1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// NOOPT1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) +// NOOPT1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) +// NOOPT1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) + // COFF doesn't support comdats with arbitrary names (C5/D5). // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC2Ev({{.*}} comdat align // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC1Ev({{.*}} comdat align @@ -37,12 +46,17 @@ template struct foobar; } namespace test2 { -// test that when the destrucor is linkonce_odr we just replace every use of +// test that when the destructor is linkonce_odr we just replace every use of // C1 with C2. // CHECK1: define internal void @__cxx_global_var_init() // CHECK1: call void @_ZN5test26foobarIvEC2Ev // CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev({{.*}} comdat align + +// At -O0, we should still emit the complete constructor. +// NOOPT1: define internal void @__cxx_global_var_init() +// NOOPT1: call void @_ZN5test26foobarIvEC1Ev +// NOOPT1: define linkonce_odr void @_ZN5test26foobarIvEC1Ev({{.*}} comdat align void g(); template struct foobar { foobar() { g(); } @@ -57,6 +71,11 @@ namespace test3 { // CHECK1: define internal void @__cxx_global_var_init.1() // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( + +// We can use an alias for internal symbols at -O0. +// NOOPT2: _ZN5test312_GLOBAL__N_11BD1Ev = internal unnamed_addr alias void {{.*}} @_ZN5test312_GLOBAL__N_11BD2Ev +// NOOPT2: define internal void @__cxx_global_var_init.1() +// NOOPT2: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11BD1Ev namespace { struct A { ~A() {} @@ -77,11 +96,12 @@ namespace test4 { // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align - // test that we don't do this optimization at -O0 so that the debugger can - // see both destructors. - // NOOPT: define internal void @__cxx_global_var_init.2() - // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev - // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align + // Test that we don't do this optimization at -O0 and call the complete + // destructor for B instead. This enables the debugger to see both + // destructors. + // NOOPT2: define internal void @__cxx_global_var_init.2() + // NOOPT2: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD1Ev + // NOOPT2: define linkonce_odr void @_ZN5test41BD1Ev({{.*}} comdat align struct A { virtual ~A() {} }; @@ -129,6 +149,11 @@ namespace test7 { // out if we should). // pr17875. // CHECK3: define void @_ZN5test71BD2Ev + + // At -O0, we should emit both destructors, the complete can be an alias to + // the base one. + // NOOPT3: @_ZN5test71BD1Ev = unnamed_addr alias void {{.*}} @_ZN5test71BD2Ev + // NOOPT3: define void @_ZN5test71BD2Ev template struct A { ~A() {} }; diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp index e82c05ec8c..1d6999fef0 100644 --- a/test/CodeGenCXX/float16-declarations.cpp +++ b/test/CodeGenCXX/float16-declarations.cpp @@ -103,7 +103,7 @@ int main(void) { C1 c1(f1l); // CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2 -// CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}}) +// CHECK-DAG: call void @_ZN2C1C1EDF16_(%class.C1* %{{.*}}, half %{{.*}}) S1<_Float16> s1 = { 132.f16 }; // CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2 -- GitLab From aa1e260245d675a611a2809099bc219c0962252f Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Thu, 19 Jul 2018 15:10:06 +0000 Subject: [PATCH 0611/1023] [analyzer] Add support for more basic_string API in DanglingInternalBufferChecker. A pointer referring to the elements of a basic_string may be invalidated by calling a non-const member function, except operator[], at, front, back, begin, rbegin, end, and rend. The checker now warns if the pointer is used after such operations. Differential Revision: https://reviews.llvm.org/D49360 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337463 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../DanglingInternalBufferChecker.cpp | 60 +++- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 22 +- test/Analysis/dangling-internal-buffer.cpp | 260 ++++++++++++++---- 3 files changed, 271 insertions(+), 71 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp index 2df86fdd3a..4515b4e453 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp @@ -32,8 +32,8 @@ REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet) // This is a trick to gain access to PtrSet's Factory. namespace clang { namespace ento { -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { +template <> +struct ProgramStateTrait : public ProgramStatePartialTrait { static void *GDMIndex() { static int Index = 0; return &Index; @@ -46,7 +46,10 @@ namespace { class DanglingInternalBufferChecker : public Checker { - CallDescription CStrFn, DataFn; + + CallDescription AppendFn, AssignFn, ClearFn, CStrFn, DataFn, EraseFn, + InsertFn, PopBackFn, PushBackFn, ReplaceFn, ReserveFn, ResizeFn, + ShrinkToFitFn, SwapFn; public: class DanglingBufferBRVisitor : public BugReporterVisitor { @@ -81,7 +84,17 @@ public: } }; - DanglingInternalBufferChecker() : CStrFn("c_str"), DataFn("data") {} + DanglingInternalBufferChecker() + : AppendFn("append"), AssignFn("assign"), ClearFn("clear"), + CStrFn("c_str"), DataFn("data"), EraseFn("erase"), InsertFn("insert"), + PopBackFn("pop_back"), PushBackFn("push_back"), ReplaceFn("replace"), + ReserveFn("reserve"), ResizeFn("resize"), + ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {} + + /// Check whether the function called on the container object is a + /// member function that potentially invalidates pointers referring + /// to the objects's internal buffer. + bool mayInvalidateBuffer(const CallEvent &Call) const; /// Record the connection between the symbol returned by c_str() and the /// corresponding string object region in the ProgramState. Mark the symbol @@ -94,6 +107,37 @@ public: } // end anonymous namespace +// [string.require] +// +// "References, pointers, and iterators referring to the elements of a +// basic_string sequence may be invalidated by the following uses of that +// basic_string object: +// +// -- TODO: As an argument to any standard library function taking a reference +// to non-const basic_string as an argument. For example, as an argument to +// non-member functions swap(), operator>>(), and getline(), or as an argument +// to basic_string::swap(). +// +// -- Calling non-const member functions, except operator[], at, front, back, +// begin, rbegin, end, and rend." +// +bool DanglingInternalBufferChecker::mayInvalidateBuffer( + const CallEvent &Call) const { + if (const auto *MemOpCall = dyn_cast(&Call)) { + OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator(); + if (Opc == OO_Equal || Opc == OO_PlusEqual) + return true; + return false; + } + return (isa(Call) || Call.isCalled(AppendFn) || + Call.isCalled(AssignFn) || Call.isCalled(ClearFn) || + Call.isCalled(EraseFn) || Call.isCalled(InsertFn) || + Call.isCalled(PopBackFn) || Call.isCalled(PushBackFn) || + Call.isCalled(ReplaceFn) || Call.isCalled(ReserveFn) || + Call.isCalled(ResizeFn) || Call.isCalled(ShrinkToFitFn) || + Call.isCalled(SwapFn)); +} + void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { const auto *ICall = dyn_cast(&Call); @@ -127,7 +171,7 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, return; } - if (isa(ICall)) { + if (mayInvalidateBuffer(Call)) { if (const PtrSet *PS = State->get(ObjRegion)) { // Mark all pointer symbols associated with the deleted object released. const Expr *Origin = Call.getOriginExpr(); @@ -161,8 +205,8 @@ void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, CleanedUpSet = F.remove(CleanedUpSet, Symbol); } State = CleanedUpSet.isEmpty() - ? State->remove(Entry.first) - : State->set(Entry.first, CleanedUpSet); + ? State->remove(Entry.first) + : State->set(Entry.first, CleanedUpSet); } } C.addTransition(State); @@ -183,7 +227,7 @@ DanglingInternalBufferChecker::DanglingBufferBRVisitor::VisitNode( SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); - OS << "Pointer to dangling buffer was obtained here"; + OS << "Dangling inner pointer obtained here"; PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getLocationContext()); return std::make_shared(Pos, OS.str(), true, diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index fd2699320d..9049fa324b 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2908,7 +2908,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( "Returned allocated memory"); } else if (isReleased(RS, RSPrev, S)) { const auto Family = RS->getAllocationFamily(); - switch(Family) { + switch (Family) { case AF_Alloca: case AF_Malloc: case AF_CXXNew: @@ -2916,9 +2916,25 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( case AF_IfNameIndex: Msg = "Memory is released"; break; - case AF_InternalBuffer: - Msg = "Internal buffer is released because the object was destroyed"; + case AF_InternalBuffer: { + SmallString<256> Buf; + llvm::raw_svector_ostream OS(Buf); + OS << "Inner pointer invalidated by call to "; + if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) { + OS << "destructor"; + } else { + OS << "'"; + const Stmt *S = RS->getStmt(); + if (const auto *MemCallE = dyn_cast(S)) { + OS << MemCallE->getMethodDecl()->getNameAsString(); + } else if (const auto *OpCallE = dyn_cast(S)) { + OS << OpCallE->getDirectCallee()->getNameAsString(); + } + OS << "'"; + } + Msg = OS.str().data(); break; + } case AF_None: llvm_unreachable("Unhandled allocation family!"); } diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/dangling-internal-buffer.cpp index f77229c630..fa8d5e154b 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/dangling-internal-buffer.cpp @@ -2,13 +2,35 @@ namespace std { -template< typename CharT > +typedef int size_type; + +template class basic_string { public: + basic_string(); + basic_string(const CharT *s); + ~basic_string(); + void clear(); + + basic_string &operator=(const basic_string &str); + basic_string &operator+=(const basic_string &str); + const CharT *c_str() const; const CharT *data() const; CharT *data(); + + basic_string &append(size_type count, CharT ch); + basic_string &assign(size_type count, CharT ch); + basic_string &erase(size_type index, size_type count); + basic_string &insert(size_type index, size_type count, CharT ch); + basic_string &replace(size_type pos, size_type count, const basic_string &str); + void pop_back(); + void push_back(CharT ch); + void reserve(size_type new_cap); + void resize(size_type count); + void shrink_to_fit(); + void swap(basic_string &other); }; typedef basic_string string; @@ -23,73 +45,70 @@ void consume(const wchar_t *) {} void consume(const char16_t *) {} void consume(const char32_t *) {} -void deref_after_scope_char_cstr() { - const char *c; +void deref_after_scope_char(bool cond) { + const char *c, *d; { std::string s; - c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + d = s.data(); // expected-note {{Dangling inner pointer obtained here}} + } // expected-note {{Inner pointer invalidated by call to destructor}} + // expected-note@-1 {{Inner pointer invalidated by call to destructor}} std::string s; const char *c2 = s.c_str(); - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} -} - -void deref_after_scope_char_data() { - const char *c; - { - std::string s; - c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::string s; - const char *c2 = s.data(); - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + if (cond) { + // expected-note@-1 {{Assuming 'cond' is not equal to 0}} + // expected-note@-2 {{Taking true branch}} + // expected-note@-3 {{Assuming 'cond' is 0}} + // expected-note@-4 {{Taking false branch}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} + } else { + consume(d); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} + } } void deref_after_scope_char_data_non_const() { char *c; { std::string s; - c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + } // expected-note {{Inner pointer invalidated by call to destructor}} std::string s; char *c2 = s.data(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } - -void deref_after_scope_wchar_t_cstr() { - const wchar_t *w; +void deref_after_scope_wchar_t(bool cond) { + const wchar_t *c, *d; { - std::wstring ws; - w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::wstring ws; - const wchar_t *w2 = ws.c_str(); - consume(w); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} -} - -void deref_after_scope_wchar_t_data() { - const wchar_t *w; - { - std::wstring ws; - w = ws.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::wstring ws; - const wchar_t *w2 = ws.data(); - consume(w); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + std::wstring s; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + d = s.data(); // expected-note {{Dangling inner pointer obtained here}} + } // expected-note {{Inner pointer invalidated by call to destructor}} + // expected-note@-1 {{Inner pointer invalidated by call to destructor}} + std::wstring s; + const wchar_t *c2 = s.c_str(); + if (cond) { + // expected-note@-1 {{Assuming 'cond' is not equal to 0}} + // expected-note@-2 {{Taking true branch}} + // expected-note@-3 {{Assuming 'cond' is 0}} + // expected-note@-4 {{Taking false branch}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} + } else { + consume(d); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} + } } void deref_after_scope_char16_t_cstr() { const char16_t *c16; { std::u16string s16; - c16 = s16.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} + c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}} + } // expected-note {{Inner pointer invalidated by call to destructor}} std::u16string s16; const char16_t *c16_2 = s16.c_str(); consume(c16); // expected-warning {{Use of memory after it is freed}} @@ -100,8 +119,8 @@ void deref_after_scope_char32_t_data() { const char32_t *c32; { std::u32string s32; - c32 = s32.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} + c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}} + } // expected-note {{Inner pointer invalidated by call to destructor}} std::u32string s32; const char32_t *c32_2 = s32.data(); consume(c32); // expected-warning {{Use of memory after it is freed}} @@ -112,12 +131,12 @@ void multiple_symbols(bool cond) { const char *c1, *d1; { std::string s1; - c1 = s1.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - d1 = s1.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}} + d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}} const char *local = s1.c_str(); consume(local); // no-warning - } // expected-note {{Internal buffer is released because the object was destroyed}} - // expected-note@-1 {{Internal buffer is released because the object was destroyed}} + } // expected-note {{Inner pointer invalidated by call to destructor}} + // expected-note@-1 {{Inner pointer invalidated by call to destructor}} std::string s2; const char *c2 = s2.c_str(); if (cond) { @@ -129,23 +148,144 @@ void multiple_symbols(bool cond) { // expected-note@-1 {{Use of memory after it is freed}} } else { consume(d1); // expected-warning {{Use of memory after it is freed}} - } // expected-note@-1 {{Use of memory after it is freed}} + } // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_equals() { + const char *c; + std::string s = "hello"; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_plus_equals() { + const char *c; + std::string s = "hello"; + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_cstr_ok() { +void deref_after_clear() { const char *c; std::string s; - { - c = s.c_str(); - } - consume(c); // no-warning + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_append() { + const char *c; + std::string s = "hello"; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_assign() { + const char *c; + std::string s; + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_erase() { + const char *c; + std::string s = "hello"; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} } -void deref_after_scope_data_ok() { +void deref_after_insert() { + const char *c; + std::string s = "ello"; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_replace() { + const char *c; + std::string s = "hello world"; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_pop_back() { const char *c; std::string s; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_push_back() { + const char *c; + std::string s; + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_reserve() { + const char *c; + std::string s; + c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} + s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_resize() { + const char *c; + std::string s; + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_shrink_to_fit() { + const char *c; + std::string s; + c = s.data(); // expected-note {{Dangling inner pointer obtained here}} + s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_swap() { + const char *c; + std::string s1, s2; + c = s1.data(); // expected-note {{Dangling inner pointer obtained here}} + s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}} + consume(c); // expected-warning {{Use of memory after it is freed}} + // expected-note@-1 {{Use of memory after it is freed}} +} + +void deref_after_scope_ok(bool cond) { + const char *c, *d; + std::string s; { - c = s.data(); + c = s.c_str(); + d = s.data(); } - consume(c); // no-warning + if (cond) + consume(c); // no-warning + else + consume(d); // no-warning } -- GitLab From 9934e6ea141eddb6a62383bd585555688539c394 Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Thu, 19 Jul 2018 15:44:46 +0000 Subject: [PATCH 0612/1023] [analyzer] Fix disappearing notes in DanglingInternalBufferChecker tests Correct a mistake of the exact same kind I am writing this checker for. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337466 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 9049fa324b..5dcd9b3863 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2901,6 +2901,9 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( // Find out if this is an interesting point and what is the kind. const char *Msg = nullptr; StackHintGeneratorForSymbol *StackHint = nullptr; + SmallString<256> Buf; + llvm::raw_svector_ostream OS(Buf); + if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { Msg = "Memory is allocated"; @@ -2917,8 +2920,6 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( Msg = "Memory is released"; break; case AF_InternalBuffer: { - SmallString<256> Buf; - llvm::raw_svector_ostream OS(Buf); OS << "Inner pointer invalidated by call to "; if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) { OS << "destructor"; -- GitLab From 4da33cdc63891fc48d632437e315279d271b71b4 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 19 Jul 2018 16:34:13 +0000 Subject: [PATCH 0613/1023] The patch adds support for the new map interface between clang and libomptarget. The changes in the interface are the following: device IDs are now 64-bit integers (as opposed to 32-bit) map flags are 64-bit long (used to be 32-bit) mappings for partially mapped structs are now calculated at compile time and members of partially mapped structs are flagged using the MEMBER_OF field Support for is_device_ptr on struct members was dropped - this functionality is not supported by the OpenMP standard and its implementation is technically infeasible (however, use_device_ptr on struct members works as a non-standard extension of the compiler) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337468 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 785 ++++++++++------ test/OpenMP/target_codegen.cpp | 108 ++- test/OpenMP/target_codegen_registration.cpp | 24 +- test/OpenMP/target_data_codegen.cpp | 26 +- .../target_data_use_device_ptr_codegen.cpp | 56 +- test/OpenMP/target_depend_codegen.cpp | 2 +- test/OpenMP/target_enter_data_codegen.cpp | 14 +- .../target_enter_data_depend_codegen.cpp | 5 +- test/OpenMP/target_exit_data_codegen.cpp | 14 +- .../target_exit_data_depend_codegen.cpp | 5 +- test/OpenMP/target_firstprivate_codegen.cpp | 70 +- test/OpenMP/target_is_device_ptr_codegen.cpp | 65 +- test/OpenMP/target_map_codegen.cpp | 861 +++++++++++------- test/OpenMP/target_parallel_codegen.cpp | 68 +- .../target_parallel_codegen_registration.cpp | 24 +- .../OpenMP/target_parallel_depend_codegen.cpp | 2 +- test/OpenMP/target_parallel_for_codegen.cpp | 68 +- ...rget_parallel_for_codegen_registration.cpp | 24 +- .../target_parallel_for_depend_codegen.cpp | 2 +- .../target_parallel_for_simd_codegen.cpp | 68 +- ...parallel_for_simd_codegen_registration.cpp | 24 +- ...arget_parallel_for_simd_depend_codegen.cpp | 2 +- test/OpenMP/target_parallel_if_codegen.cpp | 4 +- .../target_parallel_num_threads_codegen.cpp | 4 +- test/OpenMP/target_simd_codegen.cpp | 68 +- .../target_simd_codegen_registration.cpp | 24 +- test/OpenMP/target_simd_depend_codegen.cpp | 2 +- test/OpenMP/target_teams_codegen.cpp | 70 +- .../target_teams_codegen_registration.cpp | 24 +- test/OpenMP/target_teams_depend_codegen.cpp | 2 +- .../target_teams_distribute_codegen.cpp | 70 +- ..._teams_distribute_codegen_registration.cpp | 24 +- ...target_teams_distribute_depend_codegen.cpp | 2 +- ...distribute_parallel_for_depend_codegen.cpp | 2 +- ...parallel_for_simd_codegen_registration.cpp | 24 +- ...ibute_parallel_for_simd_depend_codegen.cpp | 2 +- .../target_teams_distribute_simd_codegen.cpp | 70 +- ...s_distribute_simd_codegen_registration.cpp | 24 +- ...t_teams_distribute_simd_depend_codegen.cpp | 2 +- .../OpenMP/target_teams_num_teams_codegen.cpp | 4 +- .../target_teams_thread_limit_codegen.cpp | 4 +- test/OpenMP/target_update_codegen.cpp | 13 +- test/OpenMP/target_update_depend_codegen.cpp | 5 +- test/OpenMP/teams_codegen.cpp | 4 +- ...s_distribute_parallel_for_simd_codegen.cpp | 2 +- 45 files changed, 1611 insertions(+), 1156 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 5594dd4438..8d4e83bf93 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6503,6 +6503,8 @@ emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime, } namespace { +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + // Utility to handle information from clauses associated with a given // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). // It provides a convenient interface to obtain the information and generate @@ -6511,7 +6513,9 @@ class MappableExprsHandler { public: /// Values for bit flags used to specify the mapping type for /// offloading. - enum OpenMPOffloadMappingFlags { + enum OpenMPOffloadMappingFlags : uint64_t { + /// No flags + OMP_MAP_NONE = 0x0, /// Allocate memory on the device and move data from host to device. OMP_MAP_TO = 0x01, /// Allocate memory on the device and move data from device to host. @@ -6539,6 +6543,10 @@ public: OMP_MAP_LITERAL = 0x100, /// Implicit map OMP_MAP_IMPLICIT = 0x200, + /// The 16 MSBs of the flags indicate whether the entry is member of some + /// struct/class. + OMP_MAP_MEMBER_OF = 0xffff000000000000, + LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), }; /// Class that associates information with a base pointer to be passed to the @@ -6558,11 +6566,52 @@ public: void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } }; - typedef SmallVector MapBaseValuesArrayTy; - typedef SmallVector MapValuesArrayTy; - typedef SmallVector MapFlagsArrayTy; + using MapBaseValuesArrayTy = SmallVector; + using MapValuesArrayTy = SmallVector; + using MapFlagsArrayTy = SmallVector; + + /// Map between a struct and the its lowest & highest elements which have been + /// mapped. + /// [ValueDecl *] --> {LE(FieldIndex, Pointer), + /// HE(FieldIndex, Pointer)} + struct StructRangeInfoTy { + std::pair LowestElem = { + 0, Address::invalid()}; + std::pair HighestElem = { + 0, Address::invalid()}; + Address Base = Address::invalid(); + }; private: + /// Kind that defines how a device pointer has to be returned. + struct MapInfo { + OMPClauseMappableExprCommon::MappableExprComponentListRef Components; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + bool ReturnDevicePointer = false; + bool IsImplicit = false; + + MapInfo() = default; + MapInfo( + OMPClauseMappableExprCommon::MappableExprComponentListRef Components, + OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, + bool ReturnDevicePointer, bool IsImplicit) + : Components(Components), MapType(MapType), + MapTypeModifier(MapTypeModifier), + ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} + }; + + /// If use_device_ptr is used on a pointer which is a struct member and there + /// is no map information about it, then emission of that entry is deferred + /// until the whole struct has been processed. + struct DeferredDevicePtrEntryTy { + const Expr *IE = nullptr; + const ValueDecl *VD = nullptr; + + DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) + : IE(IE), VD(VD) {} + }; + /// Directive from where the map clauses were extracted. const OMPExecutableDirective &CurDir; @@ -6571,8 +6620,6 @@ private: /// Set of all first private variables in the current directive. llvm::SmallPtrSet FirstPrivateDecls; - /// Set of all reduction variables in the current directive. - llvm::SmallPtrSet ReductionDecls; /// Map between device pointer declarations and their expression components. /// The key value for declarations in 'this' is null. @@ -6627,10 +6674,12 @@ private: /// a flag marking the map as a pointer if requested. Add a flag marking the /// map as the first one of a series of maps that relate to the same map /// expression. - uint64_t getMapTypeBits(OpenMPMapClauseKind MapType, - OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag, - bool AddIsTargetParamFlag) const { - uint64_t Bits = 0u; + OpenMPOffloadMappingFlags getMapTypeBits(OpenMPMapClauseKind MapType, + OpenMPMapClauseKind MapTypeModifier, + bool IsImplicit, bool AddPtrFlag, + bool AddIsTargetParamFlag) const { + OpenMPOffloadMappingFlags Bits = + IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; switch (MapType) { case OMPC_MAP_alloc: case OMPC_MAP_release: @@ -6640,20 +6689,20 @@ private: // type modifiers. break; case OMPC_MAP_to: - Bits = OMP_MAP_TO; + Bits |= OMP_MAP_TO; break; case OMPC_MAP_from: - Bits = OMP_MAP_FROM; + Bits |= OMP_MAP_FROM; break; case OMPC_MAP_tofrom: - Bits = OMP_MAP_TO | OMP_MAP_FROM; + Bits |= OMP_MAP_TO | OMP_MAP_FROM; break; case OMPC_MAP_delete: - Bits = OMP_MAP_DELETE; + Bits |= OMP_MAP_DELETE; break; - default: + case OMPC_MAP_always: + case OMPC_MAP_unknown: llvm_unreachable("Unexpected map type!"); - break; } if (AddPtrFlag) Bits |= OMP_MAP_PTR_AND_OBJ; @@ -6702,50 +6751,6 @@ private: return ConstLength.getSExtValue() != 1; } - /// Return the adjusted map modifiers if the declaration a capture - /// refers to appears in a first-private clause. This is expected to be used - /// only with directives that start with 'target'. - unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap, - unsigned CurrentModifiers) { - assert(Cap.capturesVariable() && "Expected capture by reference only!"); - - // A first private variable captured by reference will use only the - // 'private ptr' and 'map to' flag. Return the right flags if the captured - // declaration is known as first-private in this handler. - if (FirstPrivateDecls.count(Cap.getCapturedVar())) - return MappableExprsHandler::OMP_MAP_PRIVATE | - MappableExprsHandler::OMP_MAP_TO; - // Reduction variable will use only the 'private ptr' and 'map to_from' - // flag. - if (ReductionDecls.count(Cap.getCapturedVar())) { - return MappableExprsHandler::OMP_MAP_TO | - MappableExprsHandler::OMP_MAP_FROM; - } - - // We didn't modify anything. - return CurrentModifiers; - } - -public: - MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) - : CurDir(Dir), CGF(CGF) { - // Extract firstprivate clause information. - for (const auto *C : Dir.getClausesOfKind()) - for (const Expr *D : C->varlists()) - FirstPrivateDecls.insert( - cast(cast(D)->getDecl())->getCanonicalDecl()); - for (const auto *C : Dir.getClausesOfKind()) { - for (const Expr *D : C->varlists()) { - ReductionDecls.insert( - cast(cast(D)->getDecl())->getCanonicalDecl()); - } - } - // Extract device pointer clause information. - for (const auto *C : Dir.getClausesOfKind()) - for (const auto &L : C->component_lists()) - DevPointersMap[L.first].push_back(L.second); - } - /// Generate the base pointers, section pointers, sizes and map type /// bits for the provided map type, map modifier, and expression components. /// \a IsFirstComponent should be set to true if the provided set of @@ -6755,8 +6760,8 @@ public: OMPClauseMappableExprCommon::MappableExprComponentListRef Components, MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, - bool IsFirstComponentList, bool IsImplicit) const { - + StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, + bool IsImplicit) const { // The following summarizes what has to be generated for each map and the // types below. The generated information is expressed in this order: // base pointer, section pointer, size, flags @@ -6781,93 +6786,137 @@ public: // S2 *ps; // // map(d) - // &d, &d, sizeof(double), noflags + // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM // // map(i) - // &i, &i, 100*sizeof(int), noflags + // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM // // map(i[1:23]) - // &i(=&i[0]), &i[1], 23*sizeof(int), noflags + // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM // // map(p) - // &p, &p, sizeof(float*), noflags + // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM // // map(p[1:24]) - // p, &p[1], 24*sizeof(float), noflags + // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM // // map(s) - // &s, &s, sizeof(S2), noflags + // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM // // map(s.i) - // &s, &(s.i), sizeof(int), noflags + // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM // // map(s.s.f) - // &s, &(s.i.f), 50*sizeof(int), noflags + // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM // // map(s.p) - // &s, &(s.p), sizeof(double*), noflags + // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM // - // map(s.p[:22], s.a s.b) - // &s, &(s.p), sizeof(double*), noflags - // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + // map(to: s.p[:22]) + // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) + // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) + // &(s.p), &(s.p[0]), 22*sizeof(double), + // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) + // (*) alloc space for struct members, only this is a target parameter + // (**) map the pointer (nothing to be mapped in this example) (the compiler + // optimizes this entry out, same in the examples below) + // (***) map the pointee (map: to) // // map(s.ps) - // &s, &(s.ps), sizeof(S2*), noflags + // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM // - // map(s.ps->s.i) - // &s, &(s.ps), sizeof(S2*), noflags - // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + // map(from: s.ps->s.i) + // &s, &(s.ps), sizeof(S2*), TARGET_PARAM + // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) + // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM // - // map(s.ps->ps) - // &s, &(s.ps), sizeof(S2*), noflags - // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + // map(to: s.ps->ps) + // &s, &(s.ps), sizeof(S2*), TARGET_PARAM + // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) + // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO // // map(s.ps->ps->ps) - // &s, &(s.ps), sizeof(S2*), noflags - // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag - // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + // &s, &(s.ps), sizeof(S2*), TARGET_PARAM + // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) + // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ + // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM // - // map(s.ps->ps->s.f[:22]) - // &s, &(s.ps), sizeof(S2*), noflags - // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag - // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + // map(to: s.ps->ps->s.f[:22]) + // &s, &(s.ps), sizeof(S2*), TARGET_PARAM + // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) + // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ + // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO // // map(ps) - // &ps, &ps, sizeof(S2*), noflags + // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM // // map(ps->i) - // ps, &(ps->i), sizeof(int), noflags + // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM // // map(ps->s.f) - // ps, &(ps->s.f[0]), 50*sizeof(float), noflags + // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM // - // map(ps->p) - // ps, &(ps->p), sizeof(double*), noflags + // map(from: ps->p) + // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM // - // map(ps->p[:22]) - // ps, &(ps->p), sizeof(double*), noflags - // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + // map(to: ps->p[:22]) + // ps, &(ps->p), sizeof(double*), TARGET_PARAM + // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) + // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO // // map(ps->ps) - // ps, &(ps->ps), sizeof(S2*), noflags + // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM // - // map(ps->ps->s.i) - // ps, &(ps->ps), sizeof(S2*), noflags - // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + // map(from: ps->ps->s.i) + // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM + // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) + // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM // - // map(ps->ps->ps) - // ps, &(ps->ps), sizeof(S2*), noflags - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + // map(from: ps->ps->ps) + // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM + // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) + // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM // // map(ps->ps->ps->ps) - // ps, &(ps->ps), sizeof(S2*), noflags - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag - // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM + // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) + // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ + // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM + // + // map(to: ps->ps->ps->s.f[:22]) + // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM + // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) + // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ + // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO + // + // map(to: s.f[:22]) map(from: s.p[:33]) + // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + + // sizeof(double*) (**), TARGET_PARAM + // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO + // &s, &(s.p), sizeof(double*), MEMBER_OF(1) + // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM + // (*) allocate contiguous space needed to fit all mapped members even if + // we allocate space for members not mapped (in this example, + // s.f[22..49] and s.s are not mapped, yet we must allocate space for + // them as well because they fall between &s.f[0] and &s.p) + // + // map(from: s.f[:22]) map(to: ps->p[:33]) + // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM + // ps, &(ps->p), sizeof(S2*), TARGET_PARAM + // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) + // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO + // (*) the struct this entry pertains to is the 2nd element in the list of + // arguments, hence MEMBER_OF(2) // - // map(ps->ps->ps->s.f[:22]) - // ps, &(ps->ps), sizeof(S2*), noflags - // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag - // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + // map(from: s.f[:22], s.s) map(to: ps->p[:33]) + // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM + // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM + // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM + // ps, &(ps->p), sizeof(S2*), TARGET_PARAM + // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) + // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO + // (*) the struct this entry pertains to is the 4th element in the list + // of arguments, hence MEMBER_OF(4) // Track if the map information being generated is the first for a capture. bool IsCaptureFirstInfo = IsFirstComponentList; @@ -6881,25 +6930,23 @@ public: // Track if the map information being generated is the first for a list of // components. bool IsExpressionFirstInfo = true; - llvm::Value *BP = nullptr; + Address BP = Address::invalid(); if (const auto *ME = dyn_cast(I->getAssociatedExpression())) { // The base is the 'this' pointer. The content of the pointer is going // to be the base of the field being mapped. - BP = CGF.EmitScalarExpr(ME->getBase()); + BP = CGF.LoadCXXThisAddress(); } else { // The base is the reference to the variable. // BP = &Var. - BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer(); + BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); if (const auto *VD = dyn_cast_or_null(I->getAssociatedDeclaration())) { if (llvm::Optional Res = - isDeclareTargetDeclaration(VD)) + isDeclareTargetDeclaration(VD)) if (*Res == OMPDeclareTargetDeclAttr::MT_Link) { IsLink = true; - BP = CGF.CGM.getOpenMPRuntime() - .getAddrOfDeclareTargetLink(VD) - .getPointer(); + BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); } } @@ -6909,10 +6956,7 @@ public: QualType Ty = I->getAssociatedDeclaration()->getType().getNonReferenceType(); if (Ty->isAnyPointerType() && std::next(I) != CE) { - LValue PtrAddr = CGF.MakeNaturalAlignAddrLValue(BP, Ty); - BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(), - Ty->castAs()) - .getPointer(); + BP = CGF.EmitLoadOfPointer(BP, Ty->castAs()); // We do not need to generate individual map information for the // pointer, it can be associated with the combined storage. @@ -6920,8 +6964,41 @@ public: } } - uint64_t DefaultFlags = IsImplicit ? OMP_MAP_IMPLICIT : 0; + // Track whether a component of the list should be marked as MEMBER_OF some + // combined entry (for partial structs). Only the first PTR_AND_OBJ entry + // in a component list should be marked as MEMBER_OF, all subsequent entries + // do not belong to the base struct. E.g. + // struct S2 s; + // s.ps->ps->ps->f[:] + // (1) (2) (3) (4) + // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a + // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) + // is the pointee of ps(2) which is not member of struct s, so it should not + // be marked as such (it is still PTR_AND_OBJ). + // The variable is initialized to false so that PTR_AND_OBJ entries which + // are not struct members are not considered (e.g. array of pointers to + // data). + bool ShouldBeMemberOf = false; + + // Variable keeping track of whether or not we have encountered a component + // in the component list which is a member expression. Useful when we have a + // pointer or a final array section, in which case it is the previous + // component in the list which tells us whether we have a member expression. + // E.g. X.f[:] + // While processing the final array section "[:]" it is "f" which tells us + // whether we are dealing with a member of a declared struct. + const MemberExpr *EncounteredME = nullptr; + for (; I != CE; ++I) { + // If the current component is member of a struct (parent struct) mark it. + if (!EncounteredME) { + EncounteredME = dyn_cast(I->getAssociatedExpression()); + // If we encounter a PTR_AND_OBJ entry from now on it should be marked + // as MEMBER_OF the parent struct. + if (EncounteredME) + ShouldBeMemberOf = true; + } + auto Next = std::next(I); // We need to generate the addresses and sizes if this is the last @@ -6939,10 +7016,9 @@ public: const auto *OASE = dyn_cast(I->getAssociatedExpression()); bool IsPointer = - (OASE && - OMPArraySectionExpr::getBaseOriginalType(OASE) - .getCanonicalType() - ->isAnyPointerType()) || + (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) + .getCanonicalType() + ->isAnyPointerType()) || I->getAssociatedExpression()->getType()->isAnyPointerType(); if (Next == CE || IsPointer || IsFinalArraySection) { @@ -6954,45 +7030,68 @@ public: isa(Next->getAssociatedExpression())) && "Unexpected expression"); - llvm::Value *LB = - CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer(); + Address LB = + CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); - // If we have a member expression and the current component is a - // reference, we have to map the reference too. Whenever we have a - // reference, the section that reference refers to is going to be a - // load instruction from the storage assigned to the reference. - if (isa(I->getAssociatedExpression()) && - I->getAssociatedDeclaration()->getType()->isReferenceType()) { - auto *LI = cast(LB); - llvm::Value *RefAddr = LI->getPointerOperand(); - - BasePointers.push_back(BP); - Pointers.push_back(RefAddr); - Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); - Types.push_back(DefaultFlags | - getMapTypeBits( - /*MapType*/ OMPC_MAP_alloc, - /*MapTypeModifier=*/OMPC_MAP_unknown, - !IsExpressionFirstInfo, IsCaptureFirstInfo)); - IsExpressionFirstInfo = false; - IsCaptureFirstInfo = false; - // The reference will be the next base address. - BP = RefAddr; - } + // If this component is a pointer inside the base struct then we don't + // need to create any entry for it - it will be combined with the object + // it is pointing to into a single PTR_AND_OBJ entry. + bool IsMemberPointer = + IsPointer && EncounteredME && + (dyn_cast(I->getAssociatedExpression()) == + EncounteredME); + if (!IsMemberPointer) { + BasePointers.push_back(BP.getPointer()); + Pointers.push_back(LB.getPointer()); + Sizes.push_back(Size); + + // We need to add a pointer flag for each map that comes from the + // same expression except for the first one. We also need to signal + // this map is the first one that relates with the current capture + // (there is a set of entries for each capture). + OpenMPOffloadMappingFlags Flags = getMapTypeBits( + MapType, MapTypeModifier, IsImplicit, + !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink); + + if (!IsExpressionFirstInfo) { + // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, + // then we reset the TO/FROM/ALWAYS/DELETE flags. + if (IsPointer) + Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | + OMP_MAP_DELETE); + + if (ShouldBeMemberOf) { + // Set placeholder value MEMBER_OF=FFFF to indicate that the flag + // should be later updated with the correct value of MEMBER_OF. + Flags |= OMP_MAP_MEMBER_OF; + // From now on, all subsequent PTR_AND_OBJ entries should not be + // marked as MEMBER_OF. + ShouldBeMemberOf = false; + } + } - BasePointers.push_back(BP); - Pointers.push_back(LB); - Sizes.push_back(Size); + Types.push_back(Flags); + } - // We need to add a pointer flag for each map that comes from the - // same expression except for the first one. We also need to signal - // this map is the first one that relates with the current capture - // (there is a set of entries for each capture). - Types.push_back(DefaultFlags | - getMapTypeBits(MapType, MapTypeModifier, - !IsExpressionFirstInfo || IsLink, - IsCaptureFirstInfo && !IsLink)); + // If we have encountered a member expression so far, keep track of the + // mapped member. If the parent is "*this", then the value declaration + // is nullptr. + if (EncounteredME) { + const auto *FD = dyn_cast(EncounteredME->getMemberDecl()); + unsigned FieldIndex = FD->getFieldIndex(); + + // Update info about the lowest and highest elements for this struct + if (!PartialStruct.Base.isValid()) { + PartialStruct.LowestElem = {FieldIndex, LB}; + PartialStruct.HighestElem = {FieldIndex, LB}; + PartialStruct.Base = BP; + } else if (FieldIndex < PartialStruct.LowestElem.first) { + PartialStruct.LowestElem = {FieldIndex, LB}; + } else if (FieldIndex > PartialStruct.HighestElem.first) { + PartialStruct.HighestElem = {FieldIndex, LB}; + } + } // If we have a final array section, we are done with this expression. if (IsFinalArraySection) @@ -7008,6 +7107,93 @@ public: } } + /// Return the adjusted map modifiers if the declaration a capture refers to + /// appears in a first-private clause. This is expected to be used only with + /// directives that start with 'target'. + MappableExprsHandler::OpenMPOffloadMappingFlags + getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { + assert(Cap.capturesVariable() && "Expected capture by reference only!"); + + // A first private variable captured by reference will use only the + // 'private ptr' and 'map to' flag. Return the right flags if the captured + // declaration is known as first-private in this handler. + if (FirstPrivateDecls.count(Cap.getCapturedVar())) + return MappableExprsHandler::OMP_MAP_PRIVATE | + MappableExprsHandler::OMP_MAP_TO; + return MappableExprsHandler::OMP_MAP_TO | + MappableExprsHandler::OMP_MAP_FROM; + } + + static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { + // Member of is given by the 16 MSB of the flag, so rotate by 48 bits. + return static_cast(((uint64_t)Position + 1) + << 48); + } + + static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, + OpenMPOffloadMappingFlags MemberOfFlag) { + // If the entry is PTR_AND_OBJ but has not been marked with the special + // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be + // marked as MEMBER_OF. + if ((Flags & OMP_MAP_PTR_AND_OBJ) && + ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) + return; + + // Reset the placeholder value to prepare the flag for the assignment of the + // proper MEMBER_OF value. + Flags &= ~OMP_MAP_MEMBER_OF; + Flags |= MemberOfFlag; + } + +public: + MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) + : CurDir(Dir), CGF(CGF) { + // Extract firstprivate clause information. + for (const auto *C : Dir.getClausesOfKind()) + for (const auto *D : C->varlists()) + FirstPrivateDecls.insert( + cast(cast(D)->getDecl())->getCanonicalDecl()); + // Extract device pointer clause information. + for (const auto *C : Dir.getClausesOfKind()) + for (auto L : C->component_lists()) + DevPointersMap[L.first].push_back(L.second); + } + + /// Generate code for the combined entry if we have a partially mapped struct + /// and take care of the mapping flags of the arguments corresponding to + /// individual struct members. + void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, + MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, + MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, + const StructRangeInfoTy &PartialStruct) const { + // Base is the base of the struct + BasePointers.push_back(PartialStruct.Base.getPointer()); + // Pointer is the address of the lowest element + llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); + Pointers.push_back(LB); + // Size is (addr of {highest+1} element) - (addr of lowest element) + llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); + llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); + llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); + llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); + llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); + llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy, + /*isSinged=*/false); + Sizes.push_back(Size); + // Map type is always TARGET_PARAM + Types.push_back(OMP_MAP_TARGET_PARAM); + // Remove TARGET_PARAM flag from the first element + (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; + + // All other current entries will be MEMBER_OF the combined entry + // (except for PTR_AND_OBJ entries which do not have a placeholder value + // 0xFFFF in the MEMBER_OF field). + OpenMPOffloadMappingFlags MemberOfFlag = + getMemberOfFlag(BasePointers.size() - 1); + for (auto &M : CurTypes) + setCorrectMemberOfFlag(M, MemberOfFlag); + } + /// Generate all the base pointers, section pointers, sizes and map /// types for the extracted mappable expressions. Also, for each item that /// relates with a device pointer, a pair of the relevant declaration and @@ -7015,39 +7201,6 @@ public: void generateAllInfo(MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types) const { - BasePointers.clear(); - Pointers.clear(); - Sizes.clear(); - Types.clear(); - - struct MapInfo { - /// Kind that defines how a device pointer has to be returned. - enum ReturnPointerKind { - // Don't have to return any pointer. - RPK_None, - // Pointer is the base of the declaration. - RPK_Base, - // Pointer is a member of the base declaration - 'this' - RPK_Member, - // Pointer is a reference and a member of the base declaration - 'this' - RPK_MemberReference, - }; - OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType = OMPC_MAP_unknown; - OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; - ReturnPointerKind ReturnDevicePointer = RPK_None; - bool IsImplicit = false; - - MapInfo() = default; - MapInfo( - OMPClauseMappableExprCommon::MappableExprComponentListRef Components, - OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, - ReturnPointerKind ReturnDevicePointer, bool IsImplicit) - : Components(Components), MapType(MapType), - MapTypeModifier(MapTypeModifier), - ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} - }; - // We have to process the component lists that relate with the same // declaration in a single chunk so that we can generate the map flags // correctly. Therefore, we organize all lists in a map. @@ -7059,7 +7212,7 @@ public: const ValueDecl *D, OMPClauseMappableExprCommon::MappableExprComponentListRef L, OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier, - MapInfo::ReturnPointerKind ReturnDevicePointer, bool IsImplicit) { + bool ReturnDevicePointer, bool IsImplicit) { const ValueDecl *VD = D ? cast(D->getCanonicalDecl()) : nullptr; Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer, @@ -7070,25 +7223,31 @@ public: for (const auto *C : this->CurDir.getClausesOfKind()) for (const auto &L : C->component_lists()) { InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(), - MapInfo::RPK_None, C->isImplicit()); + /*ReturnDevicePointer=*/false, C->isImplicit()); } for (const auto *C : this->CurDir.getClausesOfKind()) for (const auto &L : C->component_lists()) { InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown, - MapInfo::RPK_None, C->isImplicit()); + /*ReturnDevicePointer=*/false, C->isImplicit()); } for (const auto *C : this->CurDir.getClausesOfKind()) for (const auto &L : C->component_lists()) { InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown, - MapInfo::RPK_None, C->isImplicit()); + /*ReturnDevicePointer=*/false, C->isImplicit()); } // Look at the use_device_ptr clause information and mark the existing map // entries as such. If there is no map information for an entry in the // use_device_ptr list, we create one with map type 'alloc' and zero size - // section. It is the user fault if that was not mapped before. + // section. It is the user fault if that was not mapped before. If there is + // no map information and the pointer is a struct member, then we defer the + // emission of that entry until the whole struct has been processed. + llvm::MapVector> + DeferredInfo; + // FIXME: MSVC 2013 seems to require this-> to find member CurDir. - for (const auto *C : this->CurDir.getClausesOfKind()) + for (const auto *C : + this->CurDir.getClausesOfKind()) { for (const auto &L : C->component_lists()) { assert(!L.second.empty() && "Not expecting empty list of components!"); const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); @@ -7109,54 +7268,65 @@ public: // If we found a map entry, signal that the pointer has to be returned // and move on to the next declaration. if (CI != It->second.end()) { - CI->ReturnDevicePointer = isa(IE) - ? (VD->getType()->isReferenceType() - ? MapInfo::RPK_MemberReference - : MapInfo::RPK_Member) - : MapInfo::RPK_Base; + CI->ReturnDevicePointer = true; continue; } } // We didn't find any match in our map information - generate a zero - // size array section. + // size array section - if the pointer is a struct member we defer this + // action until the whole struct has been processed. // FIXME: MSVC 2013 seems to require this-> to find member CGF. - llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(IE), - IE->getExprLoc()); - BasePointers.push_back({Ptr, VD}); - Pointers.push_back(Ptr); - Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); - Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); + if (isa(IE)) { + // Insert the pointer into Info to be processed by + // generateInfoForComponentList. Because it is a member pointer + // without a pointee, no entry will be generated for it, therefore + // we need to generate one after the whole struct has been processed. + // Nonetheless, generateInfoForComponentList must be called to take + // the pointer into account for the calculation of the range of the + // partial struct. + InfoGen(nullptr, L.second, OMPC_MAP_unknown, OMPC_MAP_unknown, + /*ReturnDevicePointer=*/false, C->isImplicit()); + DeferredInfo[nullptr].emplace_back(IE, VD); + } else { + llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( + this->CGF.EmitLValue(IE), IE->getExprLoc()); + BasePointers.emplace_back(Ptr, VD); + Pointers.push_back(Ptr); + Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); + Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); + } } + } for (const auto &M : Info) { // We need to know when we generate information for the first component // associated with a capture, because the mapping flags depend on it. bool IsFirstComponentList = true; + + // Temporary versions of arrays + MapBaseValuesArrayTy CurBasePointers; + MapValuesArrayTy CurPointers; + MapValuesArrayTy CurSizes; + MapFlagsArrayTy CurTypes; + StructRangeInfoTy PartialStruct; + for (const MapInfo &L : M.second) { assert(!L.Components.empty() && "Not expecting declaration with no component lists."); // Remember the current base pointer index. - unsigned CurrentBasePointersIdx = BasePointers.size(); + unsigned CurrentBasePointersIdx = CurBasePointers.size(); // FIXME: MSVC 2013 seems to require this-> to find the member method. this->generateInfoForComponentList( - L.MapType, L.MapTypeModifier, L.Components, BasePointers, Pointers, - Sizes, Types, IsFirstComponentList, L.IsImplicit); + L.MapType, L.MapTypeModifier, L.Components, CurBasePointers, + CurPointers, CurSizes, CurTypes, PartialStruct, + IsFirstComponentList, L.IsImplicit); // If this entry relates with a device pointer, set the relevant // declaration and add the 'return pointer' flag. - if (IsFirstComponentList && - L.ReturnDevicePointer != MapInfo::RPK_None) { - // If the pointer is not the base of the map, we need to skip the - // base. If it is a reference in a member field, we also need to skip - // the map of the reference. - if (L.ReturnDevicePointer != MapInfo::RPK_Base) { - ++CurrentBasePointersIdx; - if (L.ReturnDevicePointer == MapInfo::RPK_MemberReference) - ++CurrentBasePointersIdx; - } - assert(BasePointers.size() > CurrentBasePointersIdx && + if (L.ReturnDevicePointer) { + assert(CurBasePointers.size() > CurrentBasePointersIdx && "Unexpected number of mapped base pointers."); const ValueDecl *RelevantVD = @@ -7164,11 +7334,42 @@ public: assert(RelevantVD && "No relevant declaration related with device pointer??"); - BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); - Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; + CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); + CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; } IsFirstComponentList = false; } + + // Append any pending zero-length pointers which are struct members and + // used with use_device_ptr. + auto CI = DeferredInfo.find(M.first); + if (CI != DeferredInfo.end()) { + for (const DeferredDevicePtrEntryTy &L : CI->second) { + llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); + llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( + this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); + CurBasePointers.emplace_back(BasePtr, L.VD); + CurPointers.push_back(Ptr); + CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); + // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder + // value MEMBER_OF=FFFF so that the entry is later updated with the + // correct value of MEMBER_OF. + CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | + OMP_MAP_MEMBER_OF); + } + } + + // If there is an entry in PartialStruct it means we have a struct with + // individual members mapped. Emit an extra combined entry. + if (PartialStruct.Base.isValid()) + emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, + PartialStruct); + + // We need to append the results of this capture to what we already have. + BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); + Pointers.append(CurPointers.begin(), CurPointers.end()); + Sizes.append(CurSizes.begin(), CurSizes.end()); + Types.append(CurTypes.begin(), CurTypes.end()); } } @@ -7178,43 +7379,23 @@ public: llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, - MapValuesArrayTy &Sizes, - MapFlagsArrayTy &Types) const { + MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, + StructRangeInfoTy &PartialStruct) const { assert(!Cap->capturesVariableArrayType() && "Not expecting to generate map info for a variable array type!"); - BasePointers.clear(); - Pointers.clear(); - Sizes.clear(); - Types.clear(); - // We need to know when we generating information for the first component // associated with a capture, because the mapping flags depend on it. bool IsFirstComponentList = true; - const ValueDecl *VD = - Cap->capturesThis() - ? nullptr - : Cap->getCapturedVar()->getCanonicalDecl(); + const ValueDecl *VD = Cap->capturesThis() + ? nullptr + : Cap->getCapturedVar()->getCanonicalDecl(); // If this declaration appears in a is_device_ptr clause we just have to // pass the pointer by value. If it is a reference to a declaration, we just - // pass its value, otherwise, if it is a member expression, we need to map - // 'to' the field. - if (!VD) { - auto It = DevPointersMap.find(VD); - if (It != DevPointersMap.end()) { - for (ArrayRef L : - It->second) { - generateInfoForComponentList( - /*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L, - BasePointers, Pointers, Sizes, Types, IsFirstComponentList, - /*IsImplicit=*/false); - IsFirstComponentList = false; - } - return; - } - } else if (DevPointersMap.count(VD)) { + // pass its value. + if (DevPointersMap.count(VD)) { BasePointers.emplace_back(Arg, VD); Pointers.push_back(Arg); Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); @@ -7229,13 +7410,42 @@ public: "We got information for the wrong declaration??"); assert(!L.second.empty() && "Not expecting declaration with no component lists."); - generateInfoForComponentList( - C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers, - Pointers, Sizes, Types, IsFirstComponentList, C->isImplicit()); + generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(), + L.second, BasePointers, Pointers, Sizes, + Types, PartialStruct, IsFirstComponentList, + C->isImplicit()); IsFirstComponentList = false; } + } - return; + /// Generate the base pointers, section pointers, sizes and map types + /// associated with the declare target link variables. + void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, + MapValuesArrayTy &Pointers, + MapValuesArrayTy &Sizes, + MapFlagsArrayTy &Types) const { + // Map other list items in the map clause which are not captured variables + // but "declare target link" global variables., + for (const auto *C : this->CurDir.getClausesOfKind()) { + for (const auto &L : C->component_lists()) { + if (!L.first) + continue; + const auto *VD = dyn_cast(L.first); + if (!VD) + continue; + llvm::Optional Res = + isDeclareTargetDeclaration(VD); + if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) + continue; + StructRangeInfoTy PartialStruct; + generateInfoForComponentList( + C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers, + Pointers, Sizes, Types, PartialStruct, + /*IsFirstComponentList=*/true, C->isImplicit()); + assert(!PartialStruct.Base.isValid() && + "No partial structs for declare target link expected."); + } + } } /// Generate the default map information for a given capture \a CI, @@ -7245,8 +7455,7 @@ public: MapBaseValuesArrayTy &CurBasePointers, MapValuesArrayTy &CurPointers, MapValuesArrayTy &CurSizes, - MapFlagsArrayTy &CurMapTypes) { - + MapFlagsArrayTy &CurMapTypes) const { // Do the default mapping. if (CI.capturesThis()) { CurBasePointers.push_back(CV); @@ -7266,7 +7475,7 @@ public: } else { // Pointers are implicitly mapped with a zero size and no flags // (other than first map that is added for all implicit maps). - CurMapTypes.push_back(0u); + CurMapTypes.push_back(OMP_MAP_NONE); CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy)); } } else { @@ -7280,12 +7489,13 @@ public: // The default map type for a scalar/complex type is 'to' because by // default the value doesn't have to be retrieved. For an aggregate // type, the default is 'tofrom'. - CurMapTypes.emplace_back(adjustMapModifiersForPrivateClauses( - CI, ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM) - : OMP_MAP_TO)); + CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); } // Every default map produces a single argument which is a target parameter. CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; + + // Add flag stating this is an implicit map. + CurMapTypes.back() |= OMP_MAP_IMPLICIT; } }; @@ -7362,8 +7572,10 @@ emitOffloadingArrays(CodeGenFunction &CGF, // The map types are always constant so we don't need to generate code to // fill arrays. Instead, we create an array constant. + SmallVector Mapping(MapTypes.size(), 0); + llvm::copy(MapTypes, Mapping.begin()); llvm::Constant *MapTypesArrayInit = - llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes); + llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); std::string MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"}); auto *MapTypesArrayGbl = new llvm::GlobalVariable( @@ -7602,11 +7814,6 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, MappableExprsHandler::MapValuesArrayTy Sizes; MappableExprsHandler::MapFlagsArrayTy MapTypes; - MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; - MappableExprsHandler::MapValuesArrayTy CurPointers; - MappableExprsHandler::MapValuesArrayTy CurSizes; - MappableExprsHandler::MapFlagsArrayTy CurMapTypes; - // Get mappable expression information. MappableExprsHandler MEHandler(D, CGF); @@ -7615,10 +7822,11 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), CE = CS.capture_end(); CI != CE; ++CI, ++RI, ++CV) { - CurBasePointers.clear(); - CurPointers.clear(); - CurSizes.clear(); - CurMapTypes.clear(); + MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; + MappableExprsHandler::MapValuesArrayTy CurPointers; + MappableExprsHandler::MapValuesArrayTy CurSizes; + MappableExprsHandler::MapFlagsArrayTy CurMapTypes; + MappableExprsHandler::StructRangeInfoTy PartialStruct; // VLA sizes are passed to the outlined region by copy and do not have map // information associated. @@ -7633,7 +7841,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, // If we have any information in the map clause, we use it, otherwise we // just do a default mapping. MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, - CurSizes, CurMapTypes); + CurSizes, CurMapTypes, PartialStruct); if (CurBasePointers.empty()) MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, CurPointers, CurSizes, CurMapTypes); @@ -7646,6 +7854,12 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, CurBasePointers.size() == CurMapTypes.size() && "Inconsistent map information sizes!"); + // If there is an entry in PartialStruct it means we have a struct with + // individual members mapped. Emit an extra combined entry. + if (PartialStruct.Base.isValid()) + MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, + CurMapTypes, PartialStruct); + // We need to append the results of this capture to what we already have. BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); Pointers.append(CurPointers.begin(), CurPointers.end()); @@ -7654,23 +7868,8 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, } // Map other list items in the map clause which are not captured variables // but "declare target link" global variables. - for (const auto *C : D.getClausesOfKind()) { - for (const auto &L : C->component_lists()) { - if (!L.first) - continue; - const auto *VD = dyn_cast(L.first); - if (!VD) - continue; - llvm::Optional Res = - isDeclareTargetDeclaration(VD); - if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) - continue; - MEHandler.generateInfoForComponentList( - C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers, - Pointers, Sizes, MapTypes, /*IsFirstComponentList=*/true, - C->isImplicit()); - } - } + MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, + MapTypes); TargetDataInfo Info; // Fill up the arrays and create the arguments. diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp index 194ff9d9e5..15eb469fa2 100644 --- a/test/OpenMP/target_codegen.cpp +++ b/test/OpenMP/target_codegen.cpp @@ -49,21 +49,20 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // We have 8 target regions, but only 7 that actually will generate offloading -// code, only 6 will have mapped arguments, and only 4 have all-constant map -// sizes. +// code and have mapped arguments, and only 5 have all-constant map sizes. // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -79,8 +78,8 @@ // TCHECK: @{{.+}} = weak constant [[ENTTY]] // TCHECK: @{{.+}} = weak constant [[ENTTY]] // TCHECK: @{{.+}} = weak constant [[ENTTY]] -// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]] -// TCHECK: @{{.+}} = {{.*}}constant [[ENTTY]] +// TCHECK: @{{.+}} = weak constant [[ENTTY]] +// TCHECK: @{{.+}} = weak constant [[ENTTY]] // TCHECK-NOT: @{{.+}} = weak constant [[ENTTY]] // Check if offloading descriptor is created. @@ -523,57 +522,66 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0)) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX3]] -// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]] -// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 0, i32 [[IDX4]] -// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 0, i32 [[IDX4]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0)) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX0:0]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX1:1]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX2:2]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX3:3]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX4:4]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX4]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 0, i32 [[IDX5:5]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 0, i32 [[IDX5]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 0, i32 [[IDX5]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. +// CHECK-DAG: [[CBPADDR5:%.+]] = bitcast i8** [[BPADDR5]] to i16** +// CHECK-DAG: [[CPADDR5:%.+]] = bitcast i8** [[PADDR5]] to i16** +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5]] +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5]] +// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR5]] + +// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i[[SZ]]* +// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i[[SZ]]* +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR4]] +// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR4]] +// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR4]] + // CHECK-DAG: [[CBPADDR3:%.+]] = bitcast i8** [[BPADDR3]] to i[[SZ]]* // CHECK-DAG: [[CPADDR3:%.+]] = bitcast i8** [[PADDR3]] to i[[SZ]]* -// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CBPADDR3]] -// CHECK-DAG: store i[[SZ]] [[VLA0]], i[[SZ]]* [[CPADDR3]] +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR3]] +// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR3]] // CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR3]] // CHECK-DAG: [[CBPADDR2:%.+]] = bitcast i8** [[BPADDR2]] to i[[SZ]]* // CHECK-DAG: [[CPADDR2:%.+]] = bitcast i8** [[PADDR2]] to i[[SZ]]* -// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CBPADDR2]] -// CHECK-DAG: store i[[SZ]] 2, i[[SZ]]* [[CPADDR2]] -// CHECK-DAG: store i[[SZ]] {{4|8}}, i[[SZ]]* [[SADDR2]] - -// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to i[[SZ]]* -// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to i[[SZ]]* -// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR1]] -// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR1]] -// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR1]] +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CBPADDR2]] +// CHECK-DAG: store i[[SZ]] [[B_CVAL]], i[[SZ]]* [[CPADDR2]] +// CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* [[SADDR2]] // CHECK-DAG: [[CBPADDR0:%.+]] = bitcast i8** [[BPADDR0]] to [[S1]]** // CHECK-DAG: [[CPADDR0:%.+]] = bitcast i8** [[PADDR0]] to double** -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR0]] -// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR0]] -// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR0]] - -// CHECK-DAG: [[CBPADDR4:%.+]] = bitcast i8** [[BPADDR4]] to i16** -// CHECK-DAG: [[CPADDR4:%.+]] = bitcast i8** [[PADDR4]] to i16** -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4]] -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4]] -// CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* [[SADDR4]] +// CHECK-DAG: store [[S1]]* [[THIS:%.+]], [[S1]]** [[CBPADDR0]] +// CHECK-DAG: store double* [[A:%.+]], double** [[CPADDR0]] +// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* [[SADDR0]] + +// CHECK-DAG: [[CBPADDR1:%.+]] = bitcast i8** [[BPADDR1]] to [[S1]]** +// CHECK-DAG: [[CPADDR1:%.+]] = bitcast i8** [[PADDR1]] to double** +// CHECK-DAG: store [[S1]]* [[THIS]], [[S1]]** [[CBPADDR1]] +// CHECK-DAG: store double* [[A]], double** [[CPADDR1]] +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* [[SADDR1]] // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] diff --git a/test/OpenMP/target_codegen_registration.cpp b/test/OpenMP/target_codegen_registration.cpp index e0be51f2ec..b98b33c9a4 100644 --- a/test/OpenMP/target_codegen_registration.cpp +++ b/test/OpenMP/target_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_data_codegen.cpp b/test/OpenMP/target_data_codegen.cpp index f835bac8c0..80f7096a0b 100644 --- a/test/OpenMP/target_data_codegen.cpp +++ b/test/OpenMP/target_data_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 37] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673] // CK1-LABEL: _Z3fooi void foo(int arg) { @@ -65,7 +66,7 @@ void foo(int arg) { // CK1-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK1-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, // CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]] - // CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]] +// CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]] #pragma omp target data if(1+3-5) device(arg) map(from: gc) {++arg;} @@ -145,7 +146,6 @@ void foo(int arg) { // CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]] // CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]] - // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK1-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** @@ -195,8 +195,7 @@ struct ST { } }; -// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24] -// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 37, i64 21] +// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710677] // CK2-LABEL: _Z3bari int bar(int arg){ @@ -207,27 +206,31 @@ int bar(int arg){ // Region 00 // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]] // CK2: [[IFTHEN]] -// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) +// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, -// CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] -// CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK2-DAG: [[GEPBP]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%[^,]+]] +// CK2-DAG: [[GEPP]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[P:%[^,]+]] +// CK2-DAG: [[GEPS]] = getelementptr inbounds [2 x i[[sz]]], [2 x i[[sz]]]* [[S:%[^,]+]] // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] +// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 - // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK2-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** // CK2-DAG: store double** [[SEC0]], double*** [[CBP1]] // CK2-DAG: store double* [[SEC1:%.+]], double** [[CP1]] +// CK2-DAG: store i[[sz]] 24, i[[sz]]* [[S1]] // CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}double* [[SEC11:%[^,]+]], i{{.+}} 1 // CK2-DAG: [[SEC11]] = load double*, double** [[SEC111:%[^,]+]], // CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 @@ -241,11 +244,12 @@ int bar(int arg){ // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]] // CK2: [[IFTHEN]] -// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) +// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]] +// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S]] // CK2: br label %[[IFEND:[^,]+]] // CK2: [[IFELSE]] // CK2: br label %[[IFEND]] diff --git a/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/test/OpenMP/target_data_use_device_ptr_codegen.cpp index d6f18cca36..a3d8043b6b 100644 --- a/test/OpenMP/target_data_use_device_ptr_codegen.cpp +++ b/test/OpenMP/target_data_use_device_ptr_codegen.cpp @@ -346,10 +346,10 @@ void bar(float *&a, int *&b) { #ifdef CK2 // CK2: [[ST:%.+]] = type { double*, double** } -// CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 35, i64 83] -// CK2: [[MTYPE01:@.+]] = {{.*}}constant [3 x i64] [i64 32, i64 19, i64 83] -// CK2: [[MTYPE02:@.+]] = {{.*}}constant [2 x i64] [i64 96, i64 35] -// CK2: [[MTYPE03:@.+]] = {{.*}}constant [4 x i64] [i64 96, i64 32, i64 19, i64 83] +// CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 32, i64 281474976710739] +// CK2: [[MTYPE01:@.+]] = {{.*}}constant [2 x i64] [i64 32, i64 281474976710739] +// CK2: [[MTYPE02:@.+]] = {{.*}}constant [3 x i64] [i64 35, i64 32, i64 562949953421392] +// CK2: [[MTYPE03:@.+]] = {{.*}}constant [3 x i64] [i64 32, i64 281474976710739, i64 281474976710736] template struct ST { @@ -382,7 +382,7 @@ struct ST { // CK2: getelementptr inbounds double, double* [[TTT]], i32 1 a++; - // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2 + // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 1 // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double*** // CK2: store double** [[RVAL:%.+]], double*** [[CBP]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]] @@ -404,11 +404,12 @@ struct ST { // CK2: getelementptr inbounds double, double* [[TTTT]], i32 1 b++; - // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0 - // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** - // CK2: store double* [[RVAL:%.+]], double** [[CBP]], + // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2 + // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double*** + // CK2: store double** [[RVAL:%.+]], double*** [[CBP]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]] - // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], + // CK2: [[CVAL:%.+]] = bitcast double*** [[CBP]] to double** + // CK2: [[VAL:%.+]] = load double*, double** [[CVAL]], // CK2: store double* [[VAL]], double** [[PVT:%.+]], // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]], @@ -426,26 +427,27 @@ struct ST { a++; la++; - // CK2: [[BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 0 - // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double** - // CK2: store double* [[RVAL:%.+]], double** [[CBP]], - // CK2: [[_BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 3 - // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double*** - // CK2: store double** [[_RVAL:%.+]], double*** [[_CBP]], + // CK2: [[BP1:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 1 + // CK2: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** + // CK2: store double** [[RVAL1:%.+]], double*** [[CBP1]], + // CK2: [[BP2:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2 + // CK2: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double*** + // CK2: store double** [[RVAL2:%.+]], double*** [[CBP2]], // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]] - // CK2: [[VAL:%.+]] = load double*, double** [[CBP]], - // CK2: store double* [[VAL]], double** [[PVT:%.+]], - // CK2: store double** [[PVT]], double*** [[PVT2:%.+]], - // CK2: [[_CBP1:%.+]] = bitcast double*** [[_CBP]] to double** - // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP1]], - // CK2: store double* [[_VAL]], double** [[_PVT:%.+]], - // CK2: store double** [[_PVT]], double*** [[_PVT2:%.+]], - // CK2: [[TT1:%.+]] = load double**, double*** [[PVT2]], - // CK2: [[TT2:%.+]] = load double*, double** [[TT1]], - // CK2: getelementptr inbounds double, double* [[TT2]], i32 1 - // CK2: [[_TT1:%.+]] = load double**, double*** [[_PVT2]], - // CK2: [[_TT2:%.+]] = load double*, double** [[_TT1]], + // CK2: [[_CBP2:%.+]] = bitcast double*** [[CBP2]] to double** + // CK2: [[VAL2:%.+]] = load double*, double** [[_CBP2]], + // CK2: store double* [[VAL2]], double** [[PVT2:%.+]], + // CK2: store double** [[PVT2]], double*** [[_PVT2:%.+]], + // CK2: [[_CBP1:%.+]] = bitcast double*** [[CBP1]] to double** + // CK2: [[VAL1:%.+]] = load double*, double** [[_CBP1]], + // CK2: store double* [[VAL1]], double** [[PVT1:%.+]], + // CK2: store double** [[PVT1]], double*** [[_PVT1:%.+]], + // CK2: [[TT2:%.+]] = load double**, double*** [[_PVT2]], + // CK2: [[_TT2:%.+]] = load double*, double** [[TT2]], // CK2: getelementptr inbounds double, double* [[_TT2]], i32 1 + // CK2: [[TT1:%.+]] = load double**, double*** [[_PVT1]], + // CK2: [[_TT1:%.+]] = load double*, double** [[TT1]], + // CK2: getelementptr inbounds double, double* [[_TT1]], i32 1 #pragma omp target data map(b[:10]) use_device_ptr(a, b) { a++; diff --git a/test/OpenMP/target_depend_codegen.cpp b/test/OpenMP/target_depend_codegen.cpp index c60f830f08..bd709e1def 100644 --- a/test/OpenMP/target_depend_codegen.cpp +++ b/test/OpenMP/target_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_enter_data_codegen.cpp b/test/OpenMP/target_enter_data_codegen.cpp index 93ffb7abb1..b337fccb1c 100644 --- a/test/OpenMP/target_enter_data_codegen.cpp +++ b/test/OpenMP/target_enter_data_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 37] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673] // CK1-LABEL: _Z3fooi void foo(int arg) { @@ -177,8 +178,7 @@ struct ST { } }; -// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24] -// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 37, i64 21] +// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710677] // CK2-LABEL: _Z3bari int bar(int arg){ @@ -189,21 +189,23 @@ int bar(int arg){ // Region 00 // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]] // CK2: [[IFTHEN]] -// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) +// CK2-DAG: call void @__tgt_target_data_begin(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] +// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 - // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** diff --git a/test/OpenMP/target_enter_data_depend_codegen.cpp b/test/OpenMP/target_enter_data_depend_codegen.cpp index 8329f04667..e17150d576 100644 --- a/test/OpenMP/target_enter_data_depend_codegen.cpp +++ b/test/OpenMP/target_enter_data_depend_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 32] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673] // CK1-LABEL: _Z3fooi void foo(int arg) { diff --git a/test/OpenMP/target_exit_data_codegen.cpp b/test/OpenMP/target_exit_data_codegen.cpp index 45237761a5..ff84303bb0 100644 --- a/test/OpenMP/target_exit_data_codegen.cpp +++ b/test/OpenMP/target_exit_data_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 38] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 16] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710672] // CK1-LABEL: _Z3fooi void foo(int arg) { @@ -177,8 +178,7 @@ struct ST { } }; -// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24] -// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 36, i64 20] +// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710676] // CK2-LABEL: _Z3bari int bar(int arg){ @@ -190,21 +190,23 @@ int bar(int arg){ // CK2-NOT: __tgt_target_data_begin // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]] // CK2: [[IFTHEN]] -// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) +// CK2-DAG: call void @__tgt_target_data_end(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:.+]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** // CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]] // CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]] +// CK2-DAG: store i[[sz]] [[CSVAL0:%[^,]+]], i[[sz]]* [[S0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 - // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double*** diff --git a/test/OpenMP/target_exit_data_depend_codegen.cpp b/test/OpenMP/target_exit_data_depend_codegen.cpp index 1b1e573140..fec750dde2 100644 --- a/test/OpenMP/target_exit_data_depend_codegen.cpp +++ b/test/OpenMP/target_exit_data_depend_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 34, i64 18] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710674] // CK1-LABEL: _Z3fooi void foo(int arg) { diff --git a/test/OpenMP/target_firstprivate_codegen.cpp b/test/OpenMP/target_firstprivate_codegen.cpp index a74b98a518..4a2837b3c8 100644 --- a/test/OpenMP/target_firstprivate_codegen.cpp +++ b/test/OpenMP/target_firstprivate_codegen.cpp @@ -51,15 +51,15 @@ struct TT{ // TCHECK: [[S1:%.+]] = type { double } // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ:32|64]] 4] -// CHECK: [[MAPT:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 161, i64 288, i64 161, i64 161, i64 288, i64 288, i64 161, i64 161] +// CHECK: [[MAPT:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 673, i64 288, i64 673, i64 673, i64 288, i64 288, i64 673, i64 673] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] zeroinitializer -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [1 x i64] [i64 32] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 161] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [1 x i64] [i64 544] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 673] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i{{32|64}}] [i[[SZ]] 4, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 161] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 673] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [2 x i{{32|64}}] [i[[SZ]] 4, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 161] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 673] // CHECK: define {{.*}}[[FOO:@.+]]( @@ -413,59 +413,70 @@ struct S1 { // on the host side, we first generate r1, then the static function and the template above // CHECK: define{{.+}} i32 {{.+}}([[S1]]* {{.+}}, i{{[0-9]+}} {{.+}}) - // CHECK: [[BASE_PTRS4:%.+]] = alloca [5 x i8*], - // CHECK: [[PTRS4:%.+]] = alloca [5 x i8*], - // CHECK: [[SIZET4:%.+]] = alloca [5 x i{{[0-9]+}}], + // CHECK: [[BASE_PTRS4:%.+]] = alloca [6 x i8*], + // CHECK: [[PTRS4:%.+]] = alloca [6 x i8*], + // CHECK: [[SIZET4:%.+]] = alloca [6 x i{{[0-9]+}}], // map(this: this ptr is implicitly captured (not firstprivate matter) - // CHECK: {{.+}} = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store {{.+}}, {{.+}}, - // CHECK: {{.+}} = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store {{.+}}, {{.+}}, - // CHECK: {{.+}} getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // CHECK: store {{.+}}, {{.+}} + // CHECK: [[BP0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK: [[CBP0:%.+]] = bitcast i8** [[BP0]] to %struct.S1** + // CHECK: store %struct.S1* [[THIS:%.+]], %struct.S1** [[CBP0]], + // CHECK: [[P0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK: [[CP0:%.+]] = bitcast i8** [[P0]] to double** + // CHECK: store double* [[A:%.+]], double** [[CP0]], + // CHECK: [[SZ0:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK: store i{{[0-9]+}} %{{.+}}, i{{[0-9]+}}* [[SZ0]], + + // CHECK: [[BP1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: [[CBP1:%.+]] = bitcast i8** [[BP1]] to %struct.S1** + // CHECK: store %struct.S1* [[THIS]], %struct.S1** [[CBP1]], + // CHECK: [[P1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CHECK: store double* [[A]], double** [[CP1]], + // CHECK: [[SZ1:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SZ1]], // firstprivate(b): base_ptr = b, ptr = b, size = 4 (pass by-value) - // CHECK: [[BASE_PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: [[BASE_PTRS_GEP4_1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_1]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} [[B_CAST:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[PTRS_GEP4_1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: [[PTRS_GEP4_1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_1]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} [[B_CAST]], i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[SIZES_GEP4_1:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK: [[SIZES_GEP4_1:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_1]], // firstprivate(c), 3 entries: 2, n, c - // CHECK: [[BASE_PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 + // CHECK: [[BASE_PTRS_GEP4_2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_2]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[PTRS_GEP4_2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 + // CHECK: [[PTRS_GEP4_2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_2]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[SIZES_GEP4_2:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 + // CHECK: [[SIZES_GEP4_2:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 // CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_2]], // CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_2]], - // CHECK: [[BASE_PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 + // CHECK: [[BASE_PTRS_GEP4_3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_3]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} [[N:%.+]], i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[PTRS_GEP4_3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 + // CHECK: [[PTRS_GEP4_3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_3]] to i{{[0-9]+}}* // CHECK: store i{{[0-9]+}} [[N]], i{{[0-9]+}}* [[BCAST_TOPTR]], - // CHECK: [[SIZES_GEP4_3:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 + // CHECK: [[SIZES_GEP4_3:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 // CHECK-64: store i{{[0-9]+}} 8, i{{[0-9]+}}* [[SIZES_GEP4_3]], // CHECK-32: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIZES_GEP4_3]], - // CHECK: [[BASE_PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 + // CHECK: [[BASE_PTRS_GEP4_4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BASE_PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[BASE_PTRS_GEP4_4]] to i{{[0-9]+}}** // CHECK: store i{{[0-9]+}}* [[B:%.+]], i{{[0-9]+}}** [[BCAST_TOPTR]], - // CHECK: [[PTRS_GEP4_4:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 + // CHECK: [[PTRS_GEP4_4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[PTRS4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 // CHECK: [[BCAST_TOPTR:%.+]] = bitcast i8** [[PTRS_GEP4_4]] to i{{[0-9]+}}** // CHECK: store i{{[0-9]+}}* [[B]], i{{[0-9]+}}** [[BCAST_TOPTR]], - // CHECK: [[SIZES_GEP4_4:%.+]] = getelementptr inbounds [5 x i{{[0-9]+}}], [5 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 4 + // CHECK: [[SIZES_GEP4_4:%.+]] = getelementptr inbounds [6 x i{{[0-9]+}}], [6 x i{{[0-9]+}}]* [[SIZET4]], i{{[0-9]+}} 0, i{{[0-9]+}} 5 // CHECK: store i{{[0-9]+}} [[B_SIZE:%.+]], i{{[0-9]+}}* [[SIZES_GEP4_4]], // only check that we use the map types stored in the global variable - // CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 5, i8** {{.+}}, i8** {{.+}}, i{{[0-9]+}}* {{.+}}, i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT4]], i32 0, i32 0)) - + // CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 6, i8** {{.+}}, i8** {{.+}}, i{{[0-9]+}}* {{.+}}, i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT4]], i32 0, i32 0)) + // TCHECK: define weak void @__omp_offloading_{{.+}}([[S1]]* [[TH:%.+]], i{{[0-9]+}} [[B_IN:%.+]], i{{[0-9]+}} [[VLA:%.+]], i{{[0-9]+}} [[VLA1:%.+]], i{{[0-9]+}}{{.+}} [[C_IN:%.+]]) // TCHECK: [[TH_ADDR:%.+]] = alloca [[S1]]*, // TCHECK: [[B_ADDR:%.+]] = alloca i{{[0-9]+}}, @@ -577,7 +588,6 @@ int bar(int n, double *ptr){ // CHECK: call i32 @__tgt_target(i64 -1, {{.+}}, i32 2, i8** {{.+}}, i8** {{.+}}, i[[SZ]]* getelementptr inbounds ([2 x i[[SZ]]], [2 x i[[SZ]]]* [[SIZET6]], i32 0, i32 0), i64* getelementptr inbounds ([2 x i64], [2 x i64]* [[MAPT6]], i32 0, i32 0)) - // TCHECK: define weak void @__omp_offloading_{{.+}}(i{{[0-9]+}} [[A_IN:%.+]], [10 x i{{[0-9]+}}]*{{.+}} [[B_IN:%.+]]) // TCHECK: [[A_ADDR:%.+]] = alloca i{{[0-9]+}}, // TCHECK: [[B_ADDR:%.+]] = alloca [10 x i{{[0-9]+}}]*, diff --git a/test/OpenMP/target_is_device_ptr_codegen.cpp b/test/OpenMP/target_is_device_ptr_codegen.cpp index 68ef932d42..90514acadf 100644 --- a/test/OpenMP/target_is_device_ptr_codegen.cpp +++ b/test/OpenMP/target_is_device_ptr_codegen.cpp @@ -43,7 +43,7 @@ double *g; // CK1: [[SIZES06:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}] // CK1: [[TYPES06:@.+]] = {{.+}}constant [2 x i64] [i64 288, i64 288] -// CK1-LABEL: @_Z3foo +// CK1-LABEL: @_Z3foo{{.*}}( template void foo(float *&lr, T *&tr) { float *l; @@ -206,20 +206,20 @@ void bar(float *&a, int *&b) { // CK2: [[ST:%.+]] = type { double*, double** } -// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l245.region_id = weak constant i8 0 +// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l244.region_id = weak constant i8 0 // CK2: [[SIZE00:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}] -// CK2: [[MTYPE00:@.+]] = {{.+}}constant [1 x i64] [i64 33] +// CK2: [[MTYPE00:@.+]] = {{.+}}constant [1 x i64] [i64 288] -// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l269.region_id = weak constant i8 0 +// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l259.region_id = weak constant i8 0 -// CK2: [[SIZE01:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}] -// CK2: [[MTYPE01:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 17] +// CK2: [[SIZE01:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}] +// CK2: [[MTYPE01:@.+]] = {{.+}}constant [1 x i64] [i64 288] -// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l301.region_id = weak constant i8 0 +// CK2-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l274.region_id = weak constant i8 0 -// CK2: [[SIZE02:@.+]] = {{.+}}constant [3 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}, i[[sz]] {{8|4}}] -// CK2: [[MTYPE02:@.+]] = {{.+}}constant [3 x i64] [i64 33, i64 0, i64 17] +// CK2: [[SIZE02:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}] +// CK2: [[MTYPE02:@.+]] = {{.+}}constant [1 x i64] [i64 288] template struct ST { @@ -238,66 +238,39 @@ struct ST { // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** - // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] - // CK2-DAG: store double** [[SEC0:%.+]], double*** [[CP0]] - // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 + // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] #pragma omp target is_device_ptr(a) { a++; } - // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE01]]{{.+}}) + // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE01]]{{.+}}) // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** - // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double**** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] - // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]] - // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 - - // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double**** - // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** - // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]] - // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]] - // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]] + // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] #pragma omp target is_device_ptr(b) { b++; } - // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE02]]{{.+}}) + // CK2-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE02]]{{.+}}) // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] - // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** - // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double**** + // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[ST]]** // CK2-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] - // CK2-DAG: store double*** [[SEC0:%.+]], double**** [[CP0]] - // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 - - // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK2-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to double**** - // CK2-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** - // CK2-DAG: store double*** [[SEC0]], double**** [[CBP1]] - // CK2-DAG: store double** [[SEC1:%.+]], double*** [[CP1]] - // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]] - - // CK2-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK2-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK2-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** - // CK2-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** - // CK2-DAG: store [[ST]]* [[VAR2:%.+]], [[ST]]** [[CBP2]] - // CK2-DAG: store double** [[SEC2:%.+]], double*** [[CP2]] - // CK2-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 0 + // CK2-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CP0]] #pragma omp target is_device_ptr(a, b) { a++; diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp index 95ba61785c..ec99e8ed39 100644 --- a/test/OpenMP/target_map_codegen.cpp +++ b/test/OpenMP/target_map_codegen.cpp @@ -42,10 +42,10 @@ double B::VAR = 1.0; // CK1-LABEL: @.__omp_offloading_{{.*}}implicit_maps_integer{{.*}}_l68.region_id = weak constant i8 0 // CK1-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK1-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK1-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK1-LABEL: implicit_maps_integer +// CK1-LABEL: implicit_maps_integer{{.*}}( void implicit_maps_integer (int a){ // CK1: call void{{.*}}modify B::modify(a); @@ -79,6 +79,8 @@ void implicit_maps_integer (int a){ // CK1-32: {{.+}} = load i32, i32* [[ADDR]], #endif + + ///==========================================================================/// // RUN: %clang_cc1 -DCK2 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK2 --check-prefix CK2-64 // RUN: %clang_cc1 -DCK2 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s @@ -99,16 +101,14 @@ void implicit_maps_integer (int a){ // CK2-LABEL: @.__omp_offloading_{{.*}}implicit_maps_reference{{.*}}_l128.region_id = weak constant i8 0 // CK2: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK2: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] - +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK2: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] // CK2-LABEL: @.__omp_offloading_{{.*}}implicit_maps_reference{{.*}}_l147.region_id = weak constant i8 0 - // CK2: [[SIZES2:@.+]] = {{.+}}constant [1 x i[[sz]]] zeroinitializer -// Map types: OMP_MAP_IS_PTR = 32 -// CK2: [[TYPES2:@.+]] = {{.+}}constant [1 x i64] [i64 32] +// Map types: OMP_MAP_IS_PTR | OMP_MAP_IMPLICIT = 544 +// CK2: [[TYPES2:@.+]] = {{.+}}constant [1 x i64] [i64 544] -// CK2-LABEL: implicit_maps_reference +// CK2-LABEL: implicit_maps_reference{{.*}}( void implicit_maps_reference (int a, int *b){ int &i = a; // CK2-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}}) @@ -191,10 +191,10 @@ void implicit_maps_reference (int a, int *b){ // CK3-LABEL: @.__omp_offloading_{{.*}}implicit_maps_parameter{{.*}}_l214.region_id = weak constant i8 0 // CK3-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK3-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK3-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK3-LABEL: implicit_maps_parameter +// CK3-LABEL: implicit_maps_parameter{{.*}}( void implicit_maps_parameter (int a){ // CK3-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}}) @@ -245,10 +245,10 @@ void implicit_maps_parameter (int a){ // CK4-LABEL: @.__omp_offloading_{{.*}}implicit_maps_nested_integer{{.*}}_l276.region_id = weak constant i8 0 // CK4-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK4-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK4-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK4-LABEL: implicit_maps_nested_integer +// CK4-LABEL: implicit_maps_nested_integer{{.*}}( void implicit_maps_nested_integer (int a){ int i = a; @@ -311,10 +311,10 @@ void implicit_maps_nested_integer (int a){ // CK5-LABEL: @.__omp_offloading_{{.*}}implicit_maps_nested_integer_and_enum{{.*}}_l340.region_id = weak constant i8 0 // CK5-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK5-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK5-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK5-LABEL: implicit_maps_nested_integer_and_enum +// CK5-LABEL: implicit_maps_nested_integer_and_enum{{.*}}( void implicit_maps_nested_integer_and_enum (int a){ enum Bla { SomeEnum = 0x09 @@ -372,10 +372,10 @@ void implicit_maps_nested_integer_and_enum (int a){ // CK6-DAG: [[GBL:@Gi]] = global i32 0 // CK6-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK6-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK6-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK6-LABEL: implicit_maps_host_global +// CK6-LABEL: implicit_maps_host_global{{.*}}( int Gi; void implicit_maps_host_global (int a){ // CK6-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}}) @@ -431,12 +431,12 @@ void implicit_maps_host_global (int a){ // CK7-LABEL: @.__omp_offloading_{{.*}}implicit_maps_double{{.*}}_l464.region_id = weak constant i8 0 // CK7-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 8] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK7-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] -// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE_PTR | OMP_MAP_FIRST_REF = 161 -// CK7-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 161] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK7-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] +// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 673 +// CK7-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 673] -// CK7-LABEL: implicit_maps_double +// CK7-LABEL: implicit_maps_double{{.*}}( void implicit_maps_double (int a){ double d = (double)a; @@ -500,10 +500,10 @@ void implicit_maps_double (int a){ // CK8-LABEL: @.__omp_offloading_{{.*}}implicit_maps_float{{.*}}_l524.region_id = weak constant i8 0 // CK8-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] -// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_IS_FIRST = 288 -// CK8-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// Map types: OMP_MAP_PRIVATE_VAL | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK8-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] -// CK8-LABEL: implicit_maps_float +// CK8-LABEL: implicit_maps_float{{.*}}( void implicit_maps_float (int a){ float f = (float)a; @@ -554,10 +554,10 @@ void implicit_maps_float (int a){ // CK9-LABEL: @.__omp_offloading_{{.*}}implicit_maps_array{{.*}}_l575.region_id = weak constant i8 0 // CK9-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16] -// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547 +// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547 // CK9-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547] -// CK9-LABEL: implicit_maps_array +// CK9-LABEL: implicit_maps_array{{.*}}( void implicit_maps_array (int a){ double darr[2] = {(double)a, (double)a}; @@ -605,10 +605,10 @@ void implicit_maps_array (int a){ // CK10-LABEL: @.__omp_offloading_{{.*}}implicit_maps_pointer{{.*}}_l626.region_id = weak constant i8 0 // CK10-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] zeroinitializer -// Map types: OMP_MAP_IS_FIRST = 32 -// CK10-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 32] +// Map types: OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 544 +// CK10-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 544] -// CK10-LABEL: implicit_maps_pointer +// CK10-LABEL: implicit_maps_pointer{{.*}}( void implicit_maps_pointer (){ double *ddyn; @@ -657,10 +657,10 @@ void implicit_maps_pointer (){ // CK11-LABEL: @.__omp_offloading_{{.*}}implicit_maps_double_complex{{.*}}_l678.region_id = weak constant i8 0 // CK11-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 16] -// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547 +// Map types: OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547 // CK11-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547] -// CK11-LABEL: implicit_maps_double_complex +// CK11-LABEL: implicit_maps_double_complex{{.*}}( void implicit_maps_double_complex (int a){ double _Complex dc = (double)a; @@ -710,12 +710,12 @@ void implicit_maps_double_complex (int a){ // CK12-LABEL: @.__omp_offloading_{{.*}}implicit_maps_float_complex{{.*}}_l743.region_id = weak constant i8 0 // CK12-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 8] -// Map types: OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK12-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] -// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE_PTR | OMP_MAP_FIRST_REF = 161 -// CK12-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 161] +// Map types: OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK12-64-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] +// Map types: OMP_MAP_TO | OMP_MAP_PRIVATE | OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 673 +// CK12-32-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 673] -// CK12-LABEL: implicit_maps_float_complex +// CK12-LABEL: implicit_maps_float_complex{{.*}}( void implicit_maps_float_complex (int a){ float _Complex fc = (float)a; @@ -779,12 +779,12 @@ void implicit_maps_float_complex (int a){ // We don't have a constant map size for VLAs. // Map types: -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 (vla size) -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 (vla size) -// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_IMPICIT_MAP = 547 +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM = 288 (vla size) +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM = 288 (vla size) +// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547 // CK13-DAG: [[TYPES:@.+]] = {{.+}}constant [3 x i64] [i64 288, i64 288, i64 547] -// CK13-LABEL: implicit_maps_variable_length_array +// CK13-LABEL: implicit_maps_variable_length_array{{.*}}( void implicit_maps_variable_length_array (int a){ double vla[2][a]; @@ -861,12 +861,12 @@ void implicit_maps_variable_length_array (int a){ // CK14-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l877.region_id = weak constant i8 0 -// CK14-DAG: [[SIZES:@.+]] = {{.+}}constant [3 x i[[sz:64|32]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} 4] + // Map types: -// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_IMPLICIT_MAP = 547 -// - OMP_MAP_TO + OMP_MAP_FROM + OMP_IMPLICIT_MAP = 515 -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK14-DAG: [[TYPES:@.+]] = {{.+}}constant [3 x i64] [i64 547, i64 515, i64 288] +// - OMP_MAP_TARGET_PARAM = 32 +// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171 +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK14-DAG: [[TYPES:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800] class SSS { public: @@ -884,35 +884,51 @@ public: SSS(int a, double b) : a(a), b(b) {} }; -// CK14-LABEL: implicit_maps_class +// CK14-LABEL: implicit_maps_class{{.*}}( void implicit_maps_class (int a){ SSS sss(a, (double)a); // CK14: define {{.*}}void @{{.+}}foo{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}}) - // CK14-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 3, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}}) + // CK14-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz:64|32]]* [[SIZES:%[^,]+]], {{.+}}[[TYPES]]{{.+}}) // CK14-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0 // CK14-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 + // CK14-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0 // CK14-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK14-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 + // CK14-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0 // CK14-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK14-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK14-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] - // CK14-DAG: store i32* %{{.+}}, i32** [[CP0]] + // CK14-DAG: store i32* [[A:%.+]], i32** [[CP0]] + // CK14-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]] // CK14-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK14-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 + // CK14-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1 // CK14-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** - // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** // CK14-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]] - // CK14-DAG: store double* %{{.+}}, double** [[CP1]] - - // CK14-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2 - // CK14-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2 - // CK14-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[sz]]* - // CK14-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[sz]]* - // CK14-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP1]] - // CK14-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP1]] + // CK14-DAG: store i32* [[A]], i32** [[CP1]] + // CK14-DAG: store i[[sz]] 4, i[[sz]]* [[S1]] + + // CK14-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2 + // CK14-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2 + // CK14-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2 + // CK14-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** + // CK14-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK14-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]] + // CK14-DAG: store double* %{{.+}}, double** [[CP2]] + // CK14-DAG: store i[[sz]] 8, i[[sz]]* [[S2]] + + // CK14-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3 + // CK14-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3 + // CK14-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3 + // CK14-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]* + // CK14-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]* + // CK14-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]] + // CK14-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]] + // CK14-DAG: store i[[sz]] 4, i[[sz]]* [[S3]] // CK14-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK14-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK14-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -950,32 +966,30 @@ void implicit_maps_class (int a){ // SIMD-ONLY14-NOT: {{__kmpc|__tgt}} #ifdef CK15 -// CK15: [[ST:%.+]] = type { i32, double, i32* } -// CK15: [[SIZES:@.+]] = {{.+}}constant [5 x i[[sz:64|32]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} {{8|4}}, i{{64|32}} 4, i{{64|32}} 4] +// CK15: [[ST:%.+]] = type { i32, double } // Map types: -// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547 -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK15: [[TYPES:@.+]] = {{.+}}constant [5 x i64] [i64 547, i64 515, i64 512, i64 531, i64 288] +// - OMP_MAP_TARGET_PARAM = 32 +// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171 +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK15: [[TYPES:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800] -// CK15: [[SIZES2:@.+]] = {{.+}}constant [5 x i[[sz]]] [i{{64|32}} 4, i{{64|32}} 8, i{{64|32}} {{8|4}}, i{{64|32}} 4, i{{64|32}} 4] // Map types: -// - OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST = 35 -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK15: [[TYPES2:@.+]] = {{.+}}constant [5 x i64] [i64 547, i64 515, i64 512, i64 531, i64 288] +// - OMP_MAP_TARGET_PARAM = 32 +// - OMP_MAP_TO + OMP_MAP_FROM | OMP_MAP_IMPLICIT | OMP_MAP_MEMBER_OF = 281474976711171 +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK15: [[TYPES2:@.+]] = {{.+}}constant [4 x i64] [i64 32, i64 281474976711171, i64 281474976711171, i64 800] template class SSST { public: int a; double b; - int &r; void foo(int c) { #pragma omp target { a += c + x; b += (double)(c + x); - r += x; } } template @@ -984,56 +998,57 @@ public: { a += c + x + y; b += (double)(c + x + y); - r += x + y; } } - SSST(int a, double b, int &r) : a(a), b(b), r(r) {} + SSST(int a, double b) : a(a), b(b) {} }; -// CK15-LABEL: implicit_maps_templated_class +// CK15-LABEL: implicit_maps_templated_class{{.*}}( void implicit_maps_templated_class (int a){ - SSST<123> ssst(a, (double)a, a); + SSST<123> ssst(a, (double)a); // CK15: define {{.*}}void @{{.+}}foo{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}}) - // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 5, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}}) + // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz:64|32]]* [[SIZES:%[^,]+]], {{.+}}[[TYPES]]{{.+}}) // CK15-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0 // CK15-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 + // CK15-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0 // CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 + // CK15-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0 // CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] - // CK15-DAG: store i32* %{{.+}}, i32** [[CP0]] + // CK15-DAG: store i32* [[A:%.+]], i32** [[CP0]] + // CK15-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]] // CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 + // CK15-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1 // CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** - // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]] - // CK15-DAG: store double* %{{.+}}, double** [[CP1]] + // CK15-DAG: store i32* [[A]], i32** [[CP1]] + // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S1]] // CK15-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2 // CK15-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2 + // CK15-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2 // CK15-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** - // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32*** + // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]] - // CK15-DAG: store i32** %{{.+}}, i32*** [[CP2]] + // CK15-DAG: store double* %{{.+}}, double** [[CP2]] + // CK15-DAG: store i[[sz]] 8, i[[sz]]* [[S2]] // CK15-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3 // CK15-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3 - // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i32*** - // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32** - // CK15-DAG: store i32** %{{.+}}, i32*** [[CBP3]] - // CK15-DAG: store i32* %{{.+}}, i32** [[CP3]] - - // CK15-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 4 - // CK15-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 4 - // CK15-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to i[[sz]]* - // CK15-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to i[[sz]]* - // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP4]] - // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP4]] + // CK15-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3 + // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]* + // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]* + // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]] + // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]] + // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S3]] // CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -1042,44 +1057,46 @@ void implicit_maps_templated_class (int a){ ssst.foo(456); // CK15: define {{.*}}void @{{.+}}bar{{.+}}([[ST]]* {{[^,]+}}, i32 {{[^,]+}}) - // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 5, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES2]]{{.+}}, {{.+}}[[TYPES2]]{{.+}}) + // CK15-DAG: call i32 @__tgt_target(i64 {{.+}}, i8* {{.+}}, i32 4, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], i[[sz]]* [[SIZES:[^,]+]], {{.+}}[[TYPES2]]{{.+}}) // CK15-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0 // CK15-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0 + // CK15-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]], i32 0, i32 0 // CK15-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0 // CK15-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0 + // CK15-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 0 // CK15-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK15-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** - // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP0]] - // CK15-DAG: store i32* %{{.+}}, i32** [[CP0]] + // CK15-DAG: store [[ST]]* [[DECL:%.+]], [[ST]]** [[CBP0]] + // CK15-DAG: store i32* [[A:%.+]], i32** [[CP0]] + // CK15-DAG: store i[[sz]] %{{.+}}, i[[sz]]* [[S0]] // CK15-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1 // CK15-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1 + // CK15-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 1 // CK15-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** - // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double** + // CK15-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP1]] - // CK15-DAG: store double* %{{.+}}, double** [[CP1]] + // CK15-DAG: store i32* [[A]], i32** [[CP1]] + // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S1]] // CK15-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 2 // CK15-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 2 + // CK15-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 2 // CK15-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** - // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32*** + // CK15-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** // CK15-DAG: store [[ST]]* [[DECL]], [[ST]]** [[CBP2]] - // CK15-DAG: store i32** %{{.+}}, i32*** [[CP2]] + // CK15-DAG: store double* %{{.+}}, double** [[CP2]] + // CK15-DAG: store i[[sz]] 8, i[[sz]]* [[S2]] // CK15-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 3 // CK15-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 3 - // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i32*** - // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32** - // CK15-DAG: store i32** %{{.+}}, i32*** [[CBP3]] - // CK15-DAG: store i32* %{{.+}}, i32** [[CP3]] - - // CK15-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 4 - // CK15-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 4 - // CK15-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to i[[sz]]* - // CK15-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to i[[sz]]* - // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP4]] - // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP4]] + // CK15-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i32 0, i32 3 + // CK15-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to i[[sz]]* + // CK15-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i[[sz]]* + // CK15-DAG: store i[[sz]] [[VAL:%.+]], i[[sz]]* [[CBP3]] + // CK15-DAG: store i[[sz]] [[VAL]], i[[sz]]* [[CP3]] + // CK15-DAG: store i[[sz]] 4, i[[sz]]* [[S3]] // CK15-DAG: [[VAL]] = load i[[sz]], i[[sz]]* [[ADDR:%.+]], // CK15-64-DAG: [[CADDR:%.+]] = bitcast i[[sz]]* [[ADDR]] to i32* // CK15-64-DAG: store i32 {{.+}}, i32* [[CADDR]], @@ -1130,8 +1147,8 @@ void implicit_maps_templated_class (int a){ // CK16-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] // Map types: -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK16-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK16-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] template int foo(int d) { @@ -1142,7 +1159,7 @@ int foo(int d) { } return res; } -// CK16-LABEL: implicit_maps_templated_function +// CK16-LABEL: implicit_maps_templated_function{{.*}}( void implicit_maps_templated_function (int a){ int i = a; @@ -1190,9 +1207,9 @@ void implicit_maps_templated_function (int a){ #ifdef CK17 // CK17-DAG: [[ST:%.+]] = type { i32, double } -// CK17-LABEL: @.__omp_offloading_{{.*}}implicit_maps_struct{{.*}}_l1219.region_id = weak constant i8 0 +// CK17-LABEL: @.__omp_offloading_{{.*}}implicit_maps_struct{{.*}}_l1236.region_id = weak constant i8 0 // CK17-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{16|12}}] -// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_IS_FIRST + OMP_MAP_IMPLICIT = 547 +// Map types: OMP_MAP_TO + OMP_MAP_FROM + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 547 // CK17-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 547] class SSS { @@ -1201,7 +1218,7 @@ public: double b; }; -// CK17-LABEL: implicit_maps_struct +// CK17-LABEL: implicit_maps_struct{{.*}}( void implicit_maps_struct (int a){ SSS s = {a, (double)a}; @@ -1248,8 +1265,8 @@ void implicit_maps_struct (int a){ // CK18-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4] // Map types: -// - OMP_MAP_PRIVATE_VAL + OMP_MAP_IS_FIRST = 288 -// CK18-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 288] +// - OMP_MAP_PRIVATE_VAL + OMP_MAP_TARGET_PARAM | OMP_MAP_IMPLICIT = 800 +// CK18-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i64] [i64 800] template int foo(T d) { @@ -1259,7 +1276,7 @@ int foo(T d) { } return d; } -// CK18-LABEL: implicit_maps_template_type_capture +// CK18-LABEL: implicit_maps_template_type_capture{{.*}}( void implicit_maps_template_type_capture (int a){ int i = a; @@ -1306,173 +1323,173 @@ void implicit_maps_template_type_capture (int a){ // SIMD-ONLY18-NOT: {{__kmpc|__tgt}} #ifdef CK19 -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1493.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1510.region_id = weak constant i8 0 // CK19: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] // CK19: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1514.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1531.region_id = weak constant i8 0 // CK19: [[SIZE00n:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE00n:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1536.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1553.region_id = weak constant i8 0 // CK19: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400] // CK19: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1555.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1572.region_id = weak constant i8 0 // CK19: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240] // CK19: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 34] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1574.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1591.region_id = weak constant i8 0 // CK19: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240] // CK19: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1593.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1610.region_id = weak constant i8 0 // CK19: [[SIZE04:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400] // CK19: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1612.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1629.region_id = weak constant i8 0 // CK19: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1635.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1652.region_id = weak constant i8 0 // CK19: [[MTYPE06:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1658.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1675.region_id = weak constant i8 0 // CK19: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1677.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1694.region_id = weak constant i8 0 // CK19: [[SIZE08:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE08:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1698.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1715.region_id = weak constant i8 0 // CK19: [[SIZE09:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}] // CK19: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 34] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1719.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1736.region_id = weak constant i8 0 // CK19: [[SIZE10:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240] // CK19: [[MTYPE10:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1740.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1757.region_id = weak constant i8 0 // CK19: [[SIZE11:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 240] // CK19: [[MTYPE11:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1761.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1778.region_id = weak constant i8 0 // CK19: [[SIZE12:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE12:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1786.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1803.region_id = weak constant i8 0 // CK19: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1811.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1828.region_id = weak constant i8 0 // CK19: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1832.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1849.region_id = weak constant i8 0 // CK19: [[SIZE15:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 34] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1866.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1883.region_id = weak constant i8 0 // CK19: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1892.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1909.region_id = weak constant i8 0 // CK19: [[SIZE17:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 240] // CK19: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 34] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1918.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1935.region_id = weak constant i8 0 // CK19: [[SIZE18:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 240] // CK19: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1950.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1967.region_id = weak constant i8 0 // CK19: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 32] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1976.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l1993.region_id = weak constant i8 0 // CK19: [[SIZE20:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4] // CK19: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 33] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2008.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2025.region_id = weak constant i8 0 // CK19: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2034.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2051.region_id = weak constant i8 0 // CK19: [[SIZE22:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4] // CK19: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2053.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2070.region_id = weak constant i8 0 // CK19: [[SIZE23:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE23:@.+]] = private {{.*}}constant [1 x i64] [i64 39] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2075.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2092.region_id = weak constant i8 0 // CK19: [[SIZE24:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 480] // CK19: [[MTYPE24:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2096.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2113.region_id = weak constant i8 0 // CK19: [[SIZE25:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16] // CK19: [[MTYPE25:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2117.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2134.region_id = weak constant i8 0 // CK19: [[SIZE26:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 24] // CK19: [[MTYPE26:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2138.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2155.region_id = weak constant i8 0 // CK19: [[SIZE27:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK19: [[MTYPE27:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2183.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2200.region_id = weak constant i8 0 // CK19: [[SIZE28:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 16] -// CK19: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19] +// CK19: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2228.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2245.region_id = weak constant i8 0 // CK19: [[SIZE29:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 4] -// CK19: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19] +// CK19: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2284.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2301.region_id = weak constant i8 0 // CK19: [[MTYPE30:@.+]] = private {{.*}}constant [4 x i64] [i64 288, i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2328.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2345.region_id = weak constant i8 0 // CK19: [[SIZE31:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 40] // CK19: [[MTYPE31:@.+]] = private {{.*}}constant [4 x i64] [i64 288, i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2351.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2368.region_id = weak constant i8 0 // CK19: [[SIZE32:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728] // CK19: [[MTYPE32:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2370.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2387.region_id = weak constant i8 0 // CK19: [[SIZE33:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728] // CK19: [[MTYPE33:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2389.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2406.region_id = weak constant i8 0 // CK19: [[SIZE34:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 13728] // CK19: [[MTYPE34:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2414.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2431.region_id = weak constant i8 0 // CK19: [[MTYPE35:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2435.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2452.region_id = weak constant i8 0 // CK19: [[SIZE36:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 208] // CK19: [[MTYPE36:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2475.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2492.region_id = weak constant i8 0 // CK19: [[MTYPE37:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2517.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2534.region_id = weak constant i8 0 // CK19: [[MTYPE38:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2559.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2576.region_id = weak constant i8 0 // CK19: [[MTYPE39:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2601.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2618.region_id = weak constant i8 0 // CK19: [[MTYPE40:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2636.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2653.region_id = weak constant i8 0 // CK19: [[SIZE41:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 208] // CK19: [[MTYPE41:@.+]] = private {{.*}}constant [3 x i64] [i64 288, i64 288, i64 35] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2681.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2698.region_id = weak constant i8 0 // CK19: [[SIZE42:@.+]] = private {{.*}}constant [3 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 104] -// CK19: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 19, i64 19] +// CK19: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19] -// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2706.region_id = weak constant i8 0 +// CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l2723.region_id = weak constant i8 0 // CK19: [[MTYPE43:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK19-LABEL: explicit_maps_single +// CK19-LABEL: explicit_maps_single{{.*}}( void explicit_maps_single (int ii){ // Map of a scalar. int a = ii; @@ -2711,7 +2728,6 @@ void explicit_maps_single (int ii){ } // CK19: define {{.+}}[[CALL00]] -// CK19: define {{.+}}[[CALL00n]] // CK19: define {{.+}}[[CALL01]] // CK19: define {{.+}}[[CALL02]] // CK19: define {{.+}}[[CALL03]] @@ -2774,23 +2790,23 @@ void explicit_maps_single (int ii){ // SIMD-ONLY19-NOT: {{__kmpc|__tgt}} #ifdef CK20 -// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2816.region_id = weak constant i8 0 +// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2832.region_id = weak constant i8 0 // CK20: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] // CK20: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2837.region_id = weak constant i8 0 +// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2853.region_id = weak constant i8 0 // CK20: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20] // CK20: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2855.region_id = weak constant i8 0 +// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2871.region_id = weak constant i8 0 // CK20: [[SIZE02:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] // CK20: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 34] -// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2876.region_id = weak constant i8 0 +// CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l2892.region_id = weak constant i8 0 // CK20: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 12] // CK20: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 34] -// CK20-LABEL: explicit_maps_references_and_function_args +// CK20-LABEL: explicit_maps_references_and_function_args{{.*}}( void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], float *d){ int &aa = a; @@ -2904,16 +2920,14 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK21: [[ST:%.+]] = type { i32, i32, float* } // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK21: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] -// CK21: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK21: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK21: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 492] +// CK21: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 492] // CK21: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 500] -// CK21: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 34, i64 18] +// CK21: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710674] // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK21: [[SIZE03:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 492] @@ -2924,10 +2938,9 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // CK21: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 34] // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK21: [[SIZE05:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] 4, i[[Z]] 4] -// CK21: [[MTYPE05:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 3] +// CK21: [[MTYPE05:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710659] -// CK21-LABEL: explicit_maps_template_args_and_members +// CK21-LABEL: explicit_maps_template_args_and_members{{.*}}( template struct CC { @@ -2940,18 +2953,31 @@ struct CC { T *lb; // Region 00 - // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}}) + // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0 + // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** + // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK21-DAG: store [[ST]]* [[VAR1:%.+]], [[ST]]** [[CBP1]] + // CK21-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]] + // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 0 + // CK21: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) #pragma omp target map(A) { @@ -2980,24 +3006,29 @@ struct CC { } // Region 02 - // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE02]]{{.+}}) + // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE02]]{{.+}}) // CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to float*** // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK21-DAG: store float** [[SEC0:%.+]], float*** [[CP0]] + // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to float*** // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to float** // CK21-DAG: store float** [[SEC0]], float*** [[CBP1]] // CK21-DAG: store float* [[SEC1:%.+]], float** [[CP1]] + // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]] // CK21-DAG: [[SEC1]] = getelementptr {{.*}}float* [[RVAR1:%[^,]+]], i{{.+}} 123 // CK21-DAG: [[RVAR1]] = load float*, float** [[SEC1_:%[^,]+]] // CK21-DAG: [[SEC1_]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 @@ -3046,25 +3077,39 @@ struct CC { // Make sure the extra flag is passed to the second map. // Region 05 - // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE05]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE05]]{{.+}}) + // CK21-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE05]]{{.+}}) // CK21-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK21-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK21-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK21-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK21-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK21-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK21-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]] // CK21-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK21-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** // CK21-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK21-DAG: store [[ST]]* [[VAR1:%.+]], [[ST]]** [[CBP1]] - // CK21-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 + // CK21-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CBP1]] + // CK21-DAG: store i32* [[SEC0]], i32** [[CP1]] + // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]] + + // CK21-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK21-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK21-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK21-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[ST]]** + // CK21-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** + // CK21-DAG: store [[ST]]* [[VAR2:%.+]], [[ST]]** [[CBP2]] + // CK21-DAG: store i32* [[SEC2:%.+]], i32** [[CP2]] + // CK21-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S2]] + // CK21-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 1 // CK21: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}}) #pragma omp target map(A, A2) @@ -3189,7 +3234,7 @@ STT sta ; STT stc[100]; STT *std; -// CK22-LABEL: explicit_maps_globals +// CK22-LABEL: explicit_maps_globals{{.*}}( int explicit_maps_globals(void){ // Region 00 // CK22-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}}) @@ -3499,7 +3544,7 @@ int explicit_maps_globals(void){ // CK23: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 16] // CK23: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK23-LABEL: explicit_maps_inside_captured +// CK23-LABEL: explicit_maps_inside_captured{{.*}}( int explicit_maps_inside_captured(int a){ float b; float c[100]; @@ -3680,56 +3725,43 @@ struct SC{ }; // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] -// CK24: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE13:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] -// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE14:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{56|48}}] -// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE15:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] -// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE16:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 20] -// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE17:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{3560|2880}}] -// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19] +// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE18:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] -// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE19:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4] -// CK24: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19] +// CK24: [[MTYPE19:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE20:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4] -// CK24: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19] +// CK24: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE21:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] 4] -// CK24: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19] +// CK24: [[MTYPE21:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE22:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] {{8|4}}] -// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [1 x i64] [i64 35] +// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE23:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}] -// CK24: [[MTYPE23:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 19] +// CK24: [[MTYPE23:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675] // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK24: [[SIZE24:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 4] -// CK24: [[MTYPE24:@.+]] = private {{.*}}constant [4 x i64] [i64 35, i64 19, i64 19, i64 19] +// CK24: [[MTYPE24:@.+]] = private {{.*}}constant [4 x i64] [i64 32, i64 281474976710672, i64 16, i64 19] // CK24-LABEL: explicit_maps_struct_fields int explicit_maps_struct_fields(int a){ @@ -3737,81 +3769,129 @@ int explicit_maps_struct_fields(int a){ SC *p; // Region 01 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE01]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE01]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24: call void [[CALL01:@.+]]([[SC]]* {{[^,]+}}) #pragma omp target map(s.a) { s.a++; } - + // // Same thing but starting from a pointer. // // Region 13 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE13]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE13]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE13]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24: call void [[CALL13:@.+]]([[SC]]* {{[^,]+}}) #pragma omp target map(p->a) { p->a++; } - + // Region 14 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE14]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE14]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE14]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SA]]* [[SEC0:%.+]], [[SA]]** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store [[SA]]* [[SEC0]], [[SA]]** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24: call void [[CALL14:@.+]]([[SC]]* {{[^,]+}}) #pragma omp target map(p->s.s) { p->a++; } - + // Region 15 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE15]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE15]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE15]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} @@ -3820,19 +3900,31 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 16 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE16]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE16]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE16]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 3 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} @@ -3841,24 +3933,29 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 17 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE17]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE17]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE17]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** // CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SB]]** // CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] // CK24-DAG: store [[SB]]* [[SEC1:%.+]], [[SB]]** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2 @@ -3872,21 +3969,33 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 18 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE18]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE18]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE18]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SA]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[10 x [[SA]]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC0000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} @@ -3895,26 +4004,38 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 19 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE19]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE19]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE19]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SB]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** -// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** -// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] -// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + +// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** +// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[10 x [[SA]]*]* [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3 @@ -3930,16 +4051,19 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 20 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE20]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE20]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE20]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 @@ -3961,25 +4085,39 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 21 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE21]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE21]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE21]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** -// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** -// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] -// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + +// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** +// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SA]]* [[SEC11:%[^,]+]], i{{.+}} 0 // CK24-DAG: [[SEC11]] = load [[SA]]*, [[SA]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SB]]* [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -3994,21 +4132,33 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 22 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE22]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE22]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE22]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[10 x i32]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SA]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}[[SB]]* [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC0000]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store i32* [[SEC0]], i32** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + // CK24-DAG: [[VAR0]] = load [[SC]]*, [[SC]]** %{{.+}} // CK24-DAG: [[VAR00]] = load [[SC]]*, [[SC]]** %{{.+}} @@ -4017,25 +4167,39 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 23 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE23]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE23]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE23]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SA]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SA]]** [[SEC0:%.+]], [[SA]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SB]]* [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 -// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SA]]*** -// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** -// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP1]] -// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SC]]** +// CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** +// CK24-DAG: store [[SC]]* [[VAR0]], [[SC]]** [[CBP1]] +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] + +// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** +// CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i32** +// CK24-DAG: store [[SA]]** [[SEC0]], [[SA]]*** [[CBP2]] +// CK24-DAG: store i32* [[SEC1:%.+]], i32** [[CP2]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[10 x i32]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC11]] = getelementptr {{.*}}[[SA]]* [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[SEC111]] = load [[SA]]*, [[SA]]** [[SEC1111:%[^,]+]], @@ -4051,34 +4215,41 @@ int explicit_maps_struct_fields(int a){ { p->a++; } // Region 24 -// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE24]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE24]]{{.+}}) +// CK24-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE24]]{{.+}}) // CK24-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK24-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK24-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SC]]** // CK24-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SB]]*** // CK24-DAG: store [[SC]]* [[VAR0:%.+]], [[SC]]** [[CBP0]] // CK24-DAG: store [[SB]]** [[SEC0:%.+]], [[SB]]*** [[CP0]] +// CK24-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK24-DAG: [[SEC0]] = getelementptr {{.*}}[[SC]]* [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SB]]*** // CK24-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SA]]*** // CK24-DAG: store [[SB]]** [[SEC0]], [[SB]]*** [[CBP1]] // CK24-DAG: store [[SA]]** [[SEC1:%.+]], [[SA]]*** [[CP1]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S1]] // CK24-DAG: [[SEC1]] = getelementptr {{.*}}[[SB]]* [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 4 // CK24-DAG: [[SEC11]] = load [[SB]]*, [[SB]]** [[SEC111:%[^,]+]], // CK24-DAG: [[SEC111]] = getelementptr {{.*}}[[SC]]* [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 +// CK24-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 // CK24-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SA]]*** // CK24-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [[SA]]*** // CK24-DAG: store [[SA]]** [[SEC1]], [[SA]]*** [[CBP2]] // CK24-DAG: store [[SA]]** [[SEC2:%.+]], [[SA]]*** [[CP2]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S2]] // CK24-DAG: [[SEC2]] = getelementptr {{.*}}[[SA]]* [[SEC22:%[^,]+]], i{{.+}} 0, i{{.+}} 1 // CK24-DAG: [[SEC22]] = load [[SA]]*, [[SA]]** [[SEC222:%[^,]+]], // CK24-DAG: [[SEC222]] = getelementptr {{.*}}[[SB]]* [[SEC2222:%[^,]+]], i{{.+}} 0, i{{.+}} 4 @@ -4087,10 +4258,12 @@ int explicit_maps_struct_fields(int a){ // CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 +// CK24-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 3 // CK24-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to [[SA]]*** // CK24-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to i32** // CK24-DAG: store [[SA]]** [[SEC2]], [[SA]]*** [[CBP3]] // CK24-DAG: store i32* [[SEC3:%.+]], i32** [[CP3]] +// CK24-DAG: store i[[sz]] {{.+}}, i[[sz]]* [[S3]] // CK24-DAG: [[SEC3]] = getelementptr {{.*}}[[SA]]* [[SEC33:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK24-DAG: [[SEC33]] = load [[SA]]*, [[SA]]** [[SEC333:%[^,]+]], // CK24-DAG: [[SEC333]] = getelementptr {{.*}}[[SA]]* [[SEC3333:%[^,]+]], i{{.+}} 0, i{{.+}} 1 @@ -4147,14 +4320,13 @@ int explicit_maps_struct_fields(int a){ // CK25: [[CA01:%.+]] = type { i32* } // CK25-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK25: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] -// CK25: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 33] +// CK25: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710657] // CK25-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK25: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] +// CK25: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] 4] // CK25: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 33] -// CK25-LABEL: explicit_maps_with_inner_lambda +// CK25-LABEL: explicit_maps_with_inner_lambda{{.*}}( template struct CC { @@ -4163,18 +4335,30 @@ struct CC { int foo(T arg) { // Region 00 - // CK25-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}}) + // CK25-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK25-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK25-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK25-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK25-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK25-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK25-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK25-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK25-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** // CK25-DAG: store [[ST]]* [[VAR0:%.+]], [[ST]]** [[CBP0]] // CK25-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK25-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[S0]] // CK25-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0:%.+]], i{{.+}} 0, i{{.+}} 0 + // CK25-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK25-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK25-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK25-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[ST]]** + // CK25-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK25-DAG: store [[ST]]* [[VAR0]], [[ST]]** [[CBP1]] + // CK25-DAG: store i32* [[SEC0]], i32** [[CP1]] + // CK25-DAG: store i[[Z]] {{.+}}, i[[Z]]* [[S1]] + // CK25: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) #pragma omp target map(to:A) { @@ -4250,21 +4434,21 @@ int explicit_maps_with_inner_lambda(int a){ // CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK26: [[SIZE00:@.+]] = private {{.*}}constant [2 x i[[Z:64|32]]] [i[[Z:64|32]] {{32|16}}, i[[Z:64|32]] 4] -// CK26: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] +// CK26: [[MTYPE00:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35] // CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK26: [[SIZE01:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4] -// CK26: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] +// CK26: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35] // CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK26: [[SIZE02:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4] -// CK26: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] +// CK26: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35] // CK26-LABEL: @.__omp_offloading_{{.*}}CC{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK26: [[SIZE03:@.+]] = private {{.*}}constant [2 x i[[Z]]] [i[[Z]] {{32|16}}, i[[Z]] 4] -// CK26: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] +// CK26: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 547, i64 35] -// CK26-LABEL: explicit_maps_with_private_class_members +// CK26-LABEL: explicit_maps_with_private_class_members{{.*}}( struct CC { int fA; @@ -4445,7 +4629,7 @@ int explicit_maps_with_private_class_members(){ // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] zeroinitializer -// CK27: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 32] +// CK27: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 544] // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer @@ -4462,19 +4646,19 @@ int explicit_maps_with_private_class_members(){ // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27: [[SIZE05:@.+]] = private {{.*}}constant [1 x i[[Z]]] zeroinitializer -// CK27: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 32] +// CK27: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 544] // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27: [[SIZE07:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 4] -// CK27: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 288] +// CK27: [[MTYPE07:@.+]] = private {{.*}}constant [1 x i64] [i64 800] // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK27: [[SIZE09:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 40] -// CK27: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 161] +// CK27: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 673] -// CK27-LABEL: zero_size_section_and_private_maps +// CK27-LABEL: zero_size_section_and_private_maps{{.*}}( void zero_size_section_and_private_maps (int ii){ // Map of a pointer. @@ -4680,7 +4864,7 @@ void zero_size_section_and_private_maps (int ii){ // CK28: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400] // CK28: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35] -// CK28-LABEL: explicit_maps_pointer_references +// CK28-LABEL: explicit_maps_pointer_references{{.*}}( void explicit_maps_pointer_references (int *p){ int *&a = p; @@ -4749,16 +4933,13 @@ void explicit_maps_pointer_references (int *p){ // CK29: [[SSB:%.+]] = type { [[SSA]]*, [[SSA]]** } // CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK29: [[SIZE00:@.+]] = private {{.*}}constant [4 x i[[Z:64|32]]] [i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] {{8|4}}, i[[Z:64|32]] 80] -// CK29: [[MTYPE00:@.+]] = private {{.*}}constant [4 x i64] [i64 35, i64 16, i64 19, i64 19] +// CK29: [[MTYPE00:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19] // CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK29: [[SIZE01:@.+]] = private {{.*}}constant [4 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 80] -// CK29: [[MTYPE01:@.+]] = private {{.*}}constant [4 x i64] [i64 32, i64 19, i64 19, i64 19] +// CK29: [[MTYPE01:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19] // CK29-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK29: [[SIZE02:@.+]] = private {{.*}}constant [5 x i[[Z]]] [i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] {{8|4}}, i[[Z]] 80] -// CK29: [[MTYPE02:@.+]] = private {{.*}}constant [5 x i64] [i64 32, i64 19, i64 16, i64 19, i64 19] +// CK29: [[MTYPE02:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710672, i64 19] struct SSA{ double *p; @@ -4775,45 +4956,44 @@ struct SSB{ void foo() { // Region 00 - // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE00]]{{.+}}) + // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]** // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]] + // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]] // CK29-DAG: [[VAR0]] = load [[SSB]]*, [[SSB]]** % // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 0 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]*** - // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double**** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]] - // CK29-DAG: store double*** [[VAR1:%.+]], double**** [[CP1]] - // CK29-DAG: [[VAR1]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 + // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]] + // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] + // CK29-DAG: [[VAR1]] = load double**, double*** [[VAR1_REF:%.+]], + // CK29-DAG: [[VAR1_REF]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double**** - // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** - // CK29-DAG: store double*** [[VAR1]], double**** [[CBP2]] - // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]] - // CK29-DAG: [[VAR2]] = load double**, double*** [[VAR22:%.+]], - // CK29-DAG: [[VAR22]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 - - // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double*** - // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** - // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]] - // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]] - // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0 - // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}}, + // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double*** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]] + // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]] + // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]] + // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0 + // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}}, // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}}) #pragma omp target map(p->pr[:10]) @@ -4822,43 +5002,43 @@ struct SSB{ } // Region 01 - // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE01]]{{.+}}) + // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE01]]{{.+}}) // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** - // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**** - // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] - // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]] - // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 + // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]** + // CK29-DAG: store [[SSB]]* [[VAR0]], [[SSB]]** [[CBP0]] + // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]] + // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]] + // CK29-DAG: [[VAR00]] = load [[SSA]]**, [[SSA]]*** [[VAR000:%.+]], + // CK29-DAG: [[VAR000]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]**** - // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]*** - // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]] - // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]] - // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]], + // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]*** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** + // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]] + // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]] + // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] + // CK29-DAG: [[VAR1]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 0 // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]*** - // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double*** - // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]] - // CK29-DAG: store double** [[VAR2:%.+]], double*** [[CP2]] - // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 0 - - // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double*** - // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** - // CK29-DAG: store double** [[VAR2]], double*** [[CBP3]] - // CK29-DAG: store double* [[VAR3:%.+]], double** [[CP3]] - // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0 - // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}}, + // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double*** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]] + // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]] + // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]] + // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0 + // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}}, // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}}) #pragma omp target map(pr->p[:10]) @@ -4867,51 +5047,44 @@ struct SSB{ } // Region 02 - // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 5, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[MTYPE02]]{{.+}}) + // CK29-DAG: call i32 @__tgt_target(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[Z]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE02]]{{.+}}) // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] + // CK29-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK29-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK29-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[SSB]]** - // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]**** - // CK29-DAG: store [[SSB]]* [[VAR0:%.+]], [[SSB]]** [[CBP0]] - // CK29-DAG: store [[SSA]]*** [[VAR00:%.+]], [[SSA]]**** [[CP0]] - // CK29-DAG: [[VAR00]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 + // CK29-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [[SSA]]** + // CK29-DAG: store [[SSB]]* [[VAR0]], [[SSB]]** [[CBP0]] + // CK29-DAG: store [[SSA]]** [[VAR00:%.+]], [[SSA]]*** [[CP0]] + // CK29-DAG: store i[[Z]] %{{.+}}, i[[Z]]* [[S0]] + // CK29-DAG: [[VAR00]] = load [[SSA]]**, [[SSA]]*** [[VAR000:%.+]], + // CK29-DAG: [[VAR000]] = getelementptr inbounds [[SSB]], [[SSB]]* [[VAR0]], i32 0, i32 1 // CK29-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 // CK29-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]**** - // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to [[SSA]]*** - // CK29-DAG: store [[SSA]]*** [[VAR00]], [[SSA]]**** [[CBP1]] - // CK29-DAG: store [[SSA]]** [[VAR1:%.+]], [[SSA]]*** [[CP1]] - // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]], + // CK29-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK29-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to [[SSA]]*** + // CK29-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to double*** + // CK29-DAG: store [[SSA]]** [[VAR00]], [[SSA]]*** [[CBP1]] + // CK29-DAG: store double** [[VAR1:%.+]], double*** [[CP1]] + // CK29-DAG: store i[[Z]] {{8|4}}, i[[Z]]* [[S1]] + // CK29-DAG: [[VAR1]] = load double**, double*** [[VAR1_REF:%.+]], + // CK29-DAG: [[VAR1_REF]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [[SSA]]*** - // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double**** - // CK29-DAG: store [[SSA]]** [[VAR1]], [[SSA]]*** [[CBP2]] - // CK29-DAG: store double*** [[VAR2:%.+]], double**** [[CP2]] - // CK29-DAG: [[VAR2]] = getelementptr inbounds [[SSA]], [[SSA]]* %{{.+}}, i32 0, i32 1 - - // CK29-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK29-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double**** - // CK29-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double*** - // CK29-DAG: store double*** [[VAR2]], double**** [[CBP3]] - // CK29-DAG: store double** [[VAR3:%.+]], double*** [[CP3]] - // CK29-DAG: [[VAR3]] = load double**, double*** [[VAR2]], - - // CK29-DAG: [[BP4:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 4 - // CK29-DAG: [[P4:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 4 - // CK29-DAG: [[CBP4:%.+]] = bitcast i8** [[BP4]] to double*** - // CK29-DAG: [[CP4:%.+]] = bitcast i8** [[P4]] to double** - // CK29-DAG: store double** [[VAR3]], double*** [[CBP4]] - // CK29-DAG: store double* [[VAR4:%.+]], double** [[CP4]] - // CK29-DAG: [[VAR4]] = getelementptr inbounds double, double* [[VAR44:%.+]], i{{.+}} 0 - // CK29-DAG: [[VAR44]] = load double*, double** + // CK29-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK29-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to double*** + // CK29-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to double** + // CK29-DAG: store double** [[VAR1]], double*** [[CBP2]] + // CK29-DAG: store double* [[VAR2:%.+]], double** [[CP2]] + // CK29-DAG: store i[[Z]] 80, i[[Z]]* [[S2]] + // CK29-DAG: [[VAR2]] = getelementptr inbounds double, double* [[VAR22:%.+]], i{{.+}} 0 + // CK29-DAG: [[VAR22]] = load double*, double** %{{.+}}, // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}}) #pragma omp target map(pr->pr[:10]) diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp index d1920ecf25..f1a511a6bb 100644 --- a/test/OpenMP/target_parallel_codegen.cpp +++ b/test/OpenMP/target_parallel_codegen.cpp @@ -52,20 +52,19 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat -// We have 8 target regions, but only 7 that actually will generate offloading -// code, only 6 will have mapped arguments, and only 4 have all-constant map -// sizes. +// We have 8 target regions, but only 6 that actually will generate offloading +// code and have mapped arguments, and only 4 have all-constant map sizes. -// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ:32|64]] 2] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -539,22 +538,25 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -580,12 +582,18 @@ int bar(int n){ // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** // CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: store i[[SZ]] %{{.+}}, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_parallel_codegen_registration.cpp b/test/OpenMP/target_parallel_codegen_registration.cpp index 1862e96277..c9892eae36 100644 --- a/test/OpenMP/target_parallel_codegen_registration.cpp +++ b/test/OpenMP/target_parallel_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_parallel_depend_codegen.cpp b/test/OpenMP/target_parallel_depend_codegen.cpp index 0499a5f81a..52d13a34d8 100644 --- a/test/OpenMP/target_parallel_depend_codegen.cpp +++ b/test/OpenMP/target_parallel_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp index 7b022edbf7..d541d14670 100644 --- a/test/OpenMP/target_parallel_for_codegen.cpp +++ b/test/OpenMP/target_parallel_for_codegen.cpp @@ -57,15 +57,15 @@ // sizes. // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 288] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -566,22 +566,28 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -604,15 +610,21 @@ int bar(int n){ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** -// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_parallel_for_codegen_registration.cpp b/test/OpenMP/target_parallel_for_codegen_registration.cpp index 89ff8d629a..9a69ea994e 100644 --- a/test/OpenMP/target_parallel_for_codegen_registration.cpp +++ b/test/OpenMP/target_parallel_for_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_parallel_for_depend_codegen.cpp b/test/OpenMP/target_parallel_for_depend_codegen.cpp index b4eda46234..c6e71375f1 100644 --- a/test/OpenMP/target_parallel_for_depend_codegen.cpp +++ b/test/OpenMP/target_parallel_for_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp index a49ce0d564..012b2f86be 100644 --- a/test/OpenMP/target_parallel_for_simd_codegen.cpp +++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp @@ -56,15 +56,15 @@ // sizes. // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 288] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -566,22 +566,28 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 1, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -604,15 +610,21 @@ int bar(int n){ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** -// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp index b31a5fc636..5973c8d182 100644 --- a/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp +++ b/test/OpenMP/target_parallel_for_simd_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp index 3d834bcbed..6fc71a7875 100644 --- a/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp +++ b/test/OpenMP/target_parallel_for_simd_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_parallel_if_codegen.cpp b/test/OpenMP/target_parallel_if_codegen.cpp index 9d5896ce9a..aab1a14a5e 100644 --- a/test/OpenMP/target_parallel_if_codegen.cpp +++ b/test/OpenMP/target_parallel_if_codegen.cpp @@ -163,7 +163,7 @@ int bar(int n){ // CHECK: store i8 [[FB]], i8* [[CONV]], align // CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 0) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 1, i32 0) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // @@ -189,7 +189,7 @@ int bar(int n){ // CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]] // // CHECK: [[IF_THEN]] -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.*}}, i32 1, i32 0) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 0) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK-NEXT: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // CHECK: [[FAIL]] diff --git a/test/OpenMP/target_parallel_num_threads_codegen.cpp b/test/OpenMP/target_parallel_num_threads_codegen.cpp index 81df91bb5e..e6b93113c5 100644 --- a/test/OpenMP/target_parallel_num_threads_codegen.cpp +++ b/test/OpenMP/target_parallel_num_threads_codegen.cpp @@ -165,7 +165,7 @@ int bar(int n){ // CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align // CHECK: [[THREADS:%.+]] = load i32, i32* [[CAPE_ADDR]], align // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 1, i32 [[THREADS]]) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 1, i32 [[THREADS]]) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // @@ -176,7 +176,7 @@ int bar(int n){ // // // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 1, i32 1024) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 1, i32 1024) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp index 3d3fa795e3..a2ec51c4e2 100644 --- a/test/OpenMP/target_simd_codegen.cpp +++ b/test/OpenMP/target_simd_codegen.cpp @@ -53,15 +53,15 @@ // sizes. // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -489,22 +489,28 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0)) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0)) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX5:[0-9]+]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX5]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX5]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -527,15 +533,21 @@ int bar(int n){ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** -// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_simd_codegen_registration.cpp b/test/OpenMP/target_simd_codegen_registration.cpp index 0a883dcf54..39e930a5d5 100644 --- a/test/OpenMP/target_simd_codegen_registration.cpp +++ b/test/OpenMP/target_simd_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_simd_depend_codegen.cpp b/test/OpenMP/target_simd_depend_codegen.cpp index e41009ad1b..ed34dd12df 100644 --- a/test/OpenMP/target_simd_depend_codegen.cpp +++ b/test/OpenMP/target_simd_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp index 0850389c0e..5c18a0cba3 100644 --- a/test/OpenMP/target_teams_codegen.cpp +++ b/test/OpenMP/target_teams_codegen.cpp @@ -52,22 +52,21 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat -// We have 8 target regions, but only 7 that actually will generate offloading -// code, only 6 will have mapped arguments, and only 4 have all-constant map -// sizes. +// We have 8 target regions, but only 6 that actually will generate offloading +// code and have mapped arguments, and only 4 have all-constant map sizes. // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] -// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] +// CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i{{32|64}}] [i[[SZ]] 2] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] // CHECK-DAG: [[SIZET5:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [4 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 288, i64 288, i64 288, i64 547] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [4 x i64] [i64 800, i64 800, i64 800, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -564,22 +563,25 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT7]], i32 0, i32 0), i32 0, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT7]], i32 0, i32 0), i32 0, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX4:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX4]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX4]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -607,10 +609,16 @@ int bar(int n){ // CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_teams_codegen_registration.cpp b/test/OpenMP/target_teams_codegen_registration.cpp index bc69ff0dde..e62be68134 100644 --- a/test/OpenMP/target_teams_codegen_registration.cpp +++ b/test/OpenMP/target_teams_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_teams_depend_codegen.cpp b/test/OpenMP/target_teams_depend_codegen.cpp index 23f9b71f8e..a5fbc5afc1 100644 --- a/test/OpenMP/target_teams_depend_codegen.cpp +++ b/test/OpenMP/target_teams_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp index b659c121fc..f9500a73ef 100644 --- a/test/OpenMP/target_teams_distribute_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_codegen.cpp @@ -57,17 +57,17 @@ // sizes. // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 288] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [10 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547, i64 800] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [5 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 288, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 800, i64 800, i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET7:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -575,22 +575,28 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -613,15 +619,21 @@ int bar(int n){ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** -// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_teams_distribute_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_codegen_registration.cpp index b9e5fdd6a8..e45e040b1f 100644 --- a/test/OpenMP/target_teams_distribute_codegen_registration.cpp +++ b/test/OpenMP/target_teams_distribute_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_teams_distribute_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_depend_codegen.cpp index 2bb15c64a4..f066574e87 100644 --- a/test/OpenMP/target_teams_distribute_depend_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp index 47a366f001..5cfa2cca51 100644 --- a/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_parallel_for_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp index 61b60f4da4..76a7b4d0bd 100644 --- a/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp +++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp index b216763408..2a10ae8723 100644 --- a/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp index 7646f4ab3a..c400e08671 100644 --- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp @@ -57,17 +57,17 @@ // sizes. // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 2, i[[SZ]] 4, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 800] // CHECK-DAG: [[SIZET2:@.+]] = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 2] -// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: [[MAPT2:@.+]] = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: [[SIZET3:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2] -// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 288, i64 288] -// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 288, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] -// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [5 x i64] [i64 547, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT3:@.+]] = private unnamed_addr constant [2 x i64] [i64 800, i64 800] +// CHECK-DAG: [[MAPT4:@.+]] = private unnamed_addr constant [9 x i64] [i64 800, i64 547, i64 288, i64 547, i64 547, i64 288, i64 288, i64 547, i64 547] +// CHECK-DAG: [[MAPT5:@.+]] = private unnamed_addr constant [6 x i64] [i64 32, i64 281474976711171, i64 800, i64 288, i64 288, i64 547] // CHECK-DAG: [[SIZET6:@.+]] = private unnamed_addr constant [5 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 1, i[[SZ]] 40] -// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 288, i64 288, i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT6:@.+]] = private unnamed_addr constant [5 x i64] [i64 800, i64 800, i64 800, i64 800, i64 547] // CHECK-DAG: [[SIZET7:@.+]] = private unnamed_addr constant [3 x i[[SZ]]] [i[[SZ]] 4, i[[SZ]] 2, i[[SZ]] 40] -// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 288, i64 288, i64 547] +// CHECK-DAG: [[MAPT7:@.+]] = private unnamed_addr constant [3 x i64] [i64 800, i64 800, i64 547] // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 // CHECK-DAG: @{{.*}} = weak constant i8 0 @@ -564,22 +564,28 @@ int bar(int n){ // CHECK: [[CELEMSIZE2:%.+]] = mul nuw i[[SZ]] 2, [[VLA0:%.+]] // CHECK: [[CSIZE:%.+]] = mul nuw i[[SZ]] [[CELEMSIZE2]], 2 -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 5, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([5 x i64], [5 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0) -// CHECK-DAG: [[BPR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP:%.+]], i32 0, i32 0 -// CHECK-DAG: [[PR]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SR]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 -// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] -// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX0]] -// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX0]] -// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] -// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX1]] -// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX1]] -// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] -// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX2]] -// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX2]] -// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [5 x i[[SZ]]], [5 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] -// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[BP]], i32 [[IDX3]] -// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [5 x i8*], [5 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 6, i8** [[BPR:%[^,]+]], i8** [[PR:%[^,]+]], i[[SZ]]* [[SR:%[^,]+]], i64* getelementptr inbounds ([6 x i64], [6 x i64]* [[MAPT5]], i32 0, i32 0), i32 0, i32 0) +// CHECK-DAG: [[BPR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP:%.+]], i32 0, i32 0 +// CHECK-DAG: [[PR]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SR]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S:%.+]], i32 0, i32 0 +// CHECK-DAG: [[SADDR0:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX0:[0-9]+]] +// CHECK-DAG: [[BPADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX0]] +// CHECK-DAG: [[PADDR0:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX0]] +// CHECK-DAG: [[SADDR1:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX1:[0-9]+]] +// CHECK-DAG: [[BPADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX1]] +// CHECK-DAG: [[PADDR1:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX1]] +// CHECK-DAG: [[SADDR2:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX2:[0-9]+]] +// CHECK-DAG: [[BPADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX2]] +// CHECK-DAG: [[PADDR2:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX2]] +// CHECK-DAG: [[SADDR3:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR3:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR4:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR4:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] +// CHECK-DAG: [[SADDR5:%.+]] = getelementptr inbounds [6 x i[[SZ]]], [6 x i[[SZ]]]* [[S]], i32 [[IDX3:[0-9]+]] +// CHECK-DAG: [[BPADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[BP]], i32 [[IDX3]] +// CHECK-DAG: [[PADDR5:%.+]] = getelementptr inbounds [6 x i8*], [6 x i8*]* [[P]], i32 [[IDX3]] // The names below are not necessarily consistent with the names used for the // addresses above as some are repeated. @@ -602,15 +608,21 @@ int bar(int n){ // CHECK-DAG: store i[[SZ]] 4, i[[SZ]]* {{%[^,]+}} // CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR3:%.+]], -// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CPADDR3:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR3:%.+]], // CHECK-DAG: [[CBPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** -// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR3]] = bitcast i8** {{%[^,]+}} to double** +// CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} + +// CHECK-DAG: store [[S1]]* %{{.+}}, [[S1]]** [[CBPADDR4:%.+]], +// CHECK-DAG: store double* %{{.+}}, double** [[CPADDR4:%.+]], +// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to [[S1]]** +// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to double** // CHECK-DAG: store i[[SZ]] 8, i[[SZ]]* {{%[^,]+}} -// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR4:%.+]], -// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR4:%.+]], -// CHECK-DAG: [[CBPADDR4]] = bitcast i8** {{%[^,]+}} to i16** -// CHECK-DAG: [[CPADDR4]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: store i16* %{{.+}}, i16** [[CBPADDR5:%.+]], +// CHECK-DAG: store i16* %{{.+}}, i16** [[CPADDR5:%.+]], +// CHECK-DAG: [[CBPADDR5]] = bitcast i8** {{%[^,]+}} to i16** +// CHECK-DAG: [[CPADDR5]] = bitcast i8** {{%[^,]+}} to i16** // CHECK-DAG: store i[[SZ]] [[CSIZE]], i[[SZ]]* {{%[^,]+}} // CHECK-NEXT: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 diff --git a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp index 36507f497c..5020bcc87a 100644 --- a/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp +++ b/test/OpenMP/target_teams_distribute_simd_codegen_registration.cpp @@ -84,40 +84,40 @@ // CHECK-DAG: {{@.+}} = weak constant i8 0 // TCHECK-NOT: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-DAG: {{@.+}} = weak constant i8 0 // CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i[[SZ]]] [i[[SZ]] 4] -// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 288] +// CHECK-DAG: {{@.+}} = private unnamed_addr constant [1 x i64] [i64 800] // CHECK-NTARGET-NOT: weak constant i8 0 // CHECK-NTARGET-NOT: private unnamed_addr constant [1 x i diff --git a/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp index 41e97a9ee7..0c1c13e1e9 100644 --- a/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_depend_codegen.cpp @@ -48,7 +48,7 @@ // CHECK-DAG: $[[REGFN:\.omp_offloading\..+]] = comdat // CHECK-DAG: [[SIZET:@.+]] = private unnamed_addr constant [2 x i[[SZ]]] [i[[SZ]] 0, i[[SZ]] 4] -// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 32, i64 288] +// CHECK-DAG: [[MAPT:@.+]] = private unnamed_addr constant [2 x i64] [i64 544, i64 800] // CHECK-DAG: @{{.*}} = weak constant i8 0 // TCHECK: @{{.+}} = weak constant [[ENTTY]] diff --git a/test/OpenMP/target_teams_num_teams_codegen.cpp b/test/OpenMP/target_teams_num_teams_codegen.cpp index 2c812ac875..0961c03e30 100644 --- a/test/OpenMP/target_teams_num_teams_codegen.cpp +++ b/test/OpenMP/target_teams_num_teams_codegen.cpp @@ -165,7 +165,7 @@ int bar(int n){ // CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align // CHECK: [[TEAMS:%.+]] = load i32, i32* [[CAPE_ADDR]], align // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 [[TEAMS]], i32 0) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 [[TEAMS]], i32 0) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // @@ -176,7 +176,7 @@ int bar(int n){ // // // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 1024, i32 0) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 1024, i32 0) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // diff --git a/test/OpenMP/target_teams_thread_limit_codegen.cpp b/test/OpenMP/target_teams_thread_limit_codegen.cpp index 6418147a29..21c9c5a68e 100644 --- a/test/OpenMP/target_teams_thread_limit_codegen.cpp +++ b/test/OpenMP/target_teams_thread_limit_codegen.cpp @@ -165,7 +165,7 @@ int bar(int n){ // CHECK: [[ARG:%.+]] = load i[[SZ]], i[[SZ]]* [[CAPEC_ADDR]], align // CHECK: [[TL:%.+]] = load i32, i32* [[CAPE_ADDR]], align // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, {{.*}}, i32 0, i32 [[TL]]) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 4, {{.*}}, i32 0, i32 [[TL]]) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // @@ -176,7 +176,7 @@ int bar(int n){ // // // -// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 1, {{.+}}, i32 0, i32 1024) +// CHECK-DAG: [[RET:%.+]] = call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, {{.+}}, i32 0, i32 1024) // CHECK: [[ERROR:%.+]] = icmp ne i32 [[RET]], 0 // CHECK: br i1 [[ERROR]], label %[[FAIL:.+]], label %[[END:[^,]+]] // diff --git a/test/OpenMP/target_update_codegen.cpp b/test/OpenMP/target_update_codegen.cpp index ee76525d4e..5beb853a2f 100644 --- a/test/OpenMP/target_update_codegen.cpp +++ b/test/OpenMP/target_update_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673] // CK1-LABEL: _Z3fooi void foo(int arg) { @@ -175,8 +176,7 @@ struct ST { } }; -// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}, i{{64|32}} 24] -// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 34, i64 18] +// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710674] // CK2-LABEL: _Z3bari int bar(int arg){ @@ -187,18 +187,21 @@ int bar(int arg){ // Region 00 // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]] // CK2: [[IFTHEN]] -// CK2-DAG: call void @__tgt_target_data_update(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) +// CK2-DAG: call void @__tgt_target_data_update(i64 [[DEV:%[^,]+]], i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i[[sz:64|32]]* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE00]]{{.+}}) // CK2-DAG: [[DEV]] = sext i32 [[DEVi32:%[^,]+]] to i64 // CK2-DAG: [[DEVi32]] = load i32, i32* %{{[^,]+}}, // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CK2-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 // CK2-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [[ST]]** // CK2-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double*** // CK2-DAG: store [[ST]]* [[VAR0:%[^,]+]], [[ST]]** [[CBP0]] // CK2-DAG: store double** [[SEC0:%[^,]+]], double*** [[CP0]] +// CK2-DAG: store i[[sz]] {{%.+}}, i[[sz]]* [[S0]] // CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}[[ST]]* [[VAR0]], i32 0, i32 1 diff --git a/test/OpenMP/target_update_depend_codegen.cpp b/test/OpenMP/target_update_depend_codegen.cpp index b8f486175c..ee1b0bfcee 100644 --- a/test/OpenMP/target_update_depend_codegen.cpp +++ b/test/OpenMP/target_update_depend_codegen.cpp @@ -37,8 +37,9 @@ double gc[100]; // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 34] -// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] 24] -// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 17] +// CK1-64: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64 24] +// CK1-32: [[SIZE04:@.+]] = {{.+}}constant [2 x i32] [i32 trunc (i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)) to i32), i32 24] +// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 32, i64 281474976710673] // CK1-LABEL: _Z3fooi void foo(int arg) { diff --git a/test/OpenMP/teams_codegen.cpp b/test/OpenMP/teams_codegen.cpp index e616f3db9c..057c557883 100644 --- a/test/OpenMP/teams_codegen.cpp +++ b/test/OpenMP/teams_codegen.cpp @@ -205,7 +205,7 @@ struct SS{ int foo(void) { int comp = 1; - // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 [[NT:%[^,]+]], i32 123) + // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 [[NT:%[^,]+]], i32 123) // CK3-DAG: [[NT]] = load i32, i32* [[NTA:%[^,]+]], // CK3-DAG: [[NTA]] = getelementptr inbounds [[SSI]], [[SSI]]* [[NTB:%[^,]+]], i32 0, i32 0 @@ -218,7 +218,7 @@ struct SS{ ++comp; } - // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 456, i32 [[TL:%[^,]+]]) + // CK3-DAG: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i32 456, i32 [[TL:%[^,]+]]) // CK3-DAG: [[TL]] = add nsw i32 [[TLA:%[^,]+]], 123 // CK3-DAG: [[TLA]] = fptosi float [[TLB:%[^,]+]] to i32 diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp index 9c363d7a63..784deeef7c 100644 --- a/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp +++ b/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp @@ -168,7 +168,7 @@ struct SS{ // CK3: define {{.*}}i32 @{{.+}}foo{{.+}}( int foo(void) { int i; - // CK3: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 2, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0) + // CK3: call i32 @__tgt_target_teams(i64 -1, i8* @{{[^,]+}}, i32 3, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* %{{[^,]+}}, i64* {{.+}}@{{[^,]+}}, i32 0, i32 0) // CK3: call void @[[OFFL1:.+]]([[SSI]]* %{{.+}}) #pragma omp target #pragma omp teams distribute parallel for simd safelen(4) aligned(a) linear(i) -- GitLab From bc7f4ca3e4f17a52e031b96b66604b5a26298012 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Thu, 19 Jul 2018 16:46:15 +0000 Subject: [PATCH 0614/1023] [Sema] Add a new warning, -Wmemset-transposed-args This diagnoses calls to memset that have the second and third arguments transposed, for example: memset(buf, sizeof(buf), 0); This is done by checking if the third argument is a literal 0, or if the second is a sizeof expression (and the third isn't). The first check is also done for calls to bzero. Differential revision: https://reviews.llvm.org/D49112 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337470 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 7 ++ include/clang/Basic/DiagnosticSemaKinds.td | 18 +++- lib/Sema/SemaChecking.cpp | 103 +++++++++++++++++++-- test/Sema/transpose-memset.c | 60 ++++++++++++ 4 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 test/Sema/transpose-memset.c diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index e27dc0d764..40dfbe5f7a 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -443,6 +443,13 @@ def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">; +def MemsetTransposedArgs : DiagGroup<"memset-transposed-args">; +def DynamicClassMemaccess : DiagGroup<"dynamic-class-memaccess">; +def NonTrivialMemaccess : DiagGroup<"nontrivial-memaccess">; +def SuspiciousBzero : DiagGroup<"suspicious-bzero">; +def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess", + [SizeofPointerMemaccess, DynamicClassMemaccess, + NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>; def StaticInInline : DiagGroup<"static-in-inline">; def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 28eb36b056..3bda262963 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -619,14 +619,14 @@ def warn_cstruct_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to record %2 that is not trivial to " "%select{primitive-default-initialize|primitive-copy}3">, - InGroup>; + InGroup; def note_nontrivial_field : Note< "field is non-trivial to %select{copy|default-initialize}0">; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to %select{|class containing a }2dynamic class %3; " "vtable pointer will be %select{overwritten|copied|moved|compared}4">, - InGroup>; + InGroup; def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; def warn_sizeof_pointer_expr_memaccess : Warning< @@ -655,7 +655,19 @@ def note_memsize_comparison_paren : Note< "did you mean to compare the result of %0 instead?">; def note_memsize_comparison_cast_silence : Note< "explicitly cast the argument to size_t to silence this warning">; - +def warn_suspicious_sizeof_memset : Warning< + "%select{'size' argument to memset is '0'|" + "setting buffer to a 'sizeof' expression}0" + "; did you mean to transpose the last two arguments?">, + InGroup; +def note_suspicious_sizeof_memset_silence : Note< + "%select{parenthesize the third argument|" + "cast the second argument to 'int'}0 to silence">; +def warn_suspicious_bzero_size : Warning<"'size' argument to bzero is '0'">, + InGroup; +def note_suspicious_bzero_size_silence : Note< + "parenthesize the second argument to silence">; + def warn_strncat_large_size : Warning< "the value of the size argument in 'strncat' is too large, might lead to a " "buffer overflow">, InGroup; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 5b800ec5ae..df1c60969f 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -8629,24 +8629,26 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, return nullptr; } +static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) { + if (const auto *Unary = dyn_cast(E)) + if (Unary->getKind() == UETT_SizeOf) + return Unary; + return nullptr; +} + /// If E is a sizeof expression, returns its argument expression, /// otherwise returns NULL. static const Expr *getSizeOfExprArg(const Expr *E) { - if (const UnaryExprOrTypeTraitExpr *SizeOf = - dyn_cast(E)) - if (SizeOf->getKind() == UETT_SizeOf && !SizeOf->isArgumentType()) + if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) + if (!SizeOf->isArgumentType()) return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); - return nullptr; } /// If E is a sizeof expression, returns its argument type. static QualType getSizeOfArgType(const Expr *E) { - if (const UnaryExprOrTypeTraitExpr *SizeOf = - dyn_cast(E)) - if (SizeOf->getKind() == UETT_SizeOf) - return SizeOf->getTypeOfArgument(); - + if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) + return SizeOf->getTypeOfArgument(); return QualType(); } @@ -8742,6 +8744,86 @@ struct SearchNonTrivialToCopyField } +/// Detect if \c SizeofExpr is likely to calculate the sizeof an object. +static bool doesExprLikelyComputeSize(const Expr *SizeofExpr) { + SizeofExpr = SizeofExpr->IgnoreParenImpCasts(); + + if (const auto *BO = dyn_cast(SizeofExpr)) { + if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add) + return false; + + return doesExprLikelyComputeSize(BO->getLHS()) || + doesExprLikelyComputeSize(BO->getRHS()); + } + + return getAsSizeOfExpr(SizeofExpr) != nullptr; +} + +/// Check if the ArgLoc originated from a macro passed to the call at CallLoc. +/// +/// \code +/// #define MACRO 0 +/// foo(MACRO); +/// foo(0); +/// \endcode +/// +/// This should return true for the first call to foo, but not for the second +/// (regardless of whether foo is a macro or function). +static bool isArgumentExpandedFromMacro(SourceManager &SM, + SourceLocation CallLoc, + SourceLocation ArgLoc) { + if (!CallLoc.isMacroID()) + return SM.getFileID(CallLoc) != SM.getFileID(ArgLoc); + + return SM.getFileID(SM.getImmediateMacroCallerLoc(CallLoc)) != + SM.getFileID(SM.getImmediateMacroCallerLoc(ArgLoc)); +} + +/// Diagnose cases like 'memset(buf, sizeof(buf), 0)', which should have the +/// last two arguments transposed. +static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) { + if (BId != Builtin::BImemset && BId != Builtin::BIbzero) + return; + + const Expr *SizeArg = + Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts(); + + // If we're memsetting or bzeroing 0 bytes, then this is likely an error. + SourceLocation CallLoc = Call->getRParenLoc(); + SourceManager &SM = S.getSourceManager(); + if (isa(SizeArg) && + cast(SizeArg)->getValue() == 0 && + !isArgumentExpandedFromMacro(SM, CallLoc, SizeArg->getExprLoc())) { + + SourceLocation DiagLoc = SizeArg->getExprLoc(); + + // Some platforms #define bzero to __builtin_memset. See if this is the + // case, and if so, emit a better diagnostic. + if (BId == Builtin::BIbzero || + (CallLoc.isMacroID() && Lexer::getImmediateMacroName( + CallLoc, SM, S.getLangOpts()) == "bzero")) { + S.Diag(DiagLoc, diag::warn_suspicious_bzero_size); + S.Diag(DiagLoc, diag::note_suspicious_bzero_size_silence); + } else { + S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0; + S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0; + } + return; + } + + // If the second argument to a memset is a sizeof expression and the third + // isn't, this is also likely an error. This should catch + // 'memset(buf, sizeof(buf), 0xff)'. + if (BId == Builtin::BImemset && + doesExprLikelyComputeSize(Call->getArg(1)) && + !doesExprLikelyComputeSize(Call->getArg(2))) { + SourceLocation DiagLoc = Call->getArg(1)->getExprLoc(); + S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1; + S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1; + return; + } +} + /// Check for dangerous or invalid arguments to memset(). /// /// This issues warnings on known problematic, dangerous or unspecified @@ -8771,6 +8853,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, Call->getLocStart(), Call->getRParenLoc())) return; + // Catch cases like 'memset(buf, sizeof(buf), 0)'. + CheckMemaccessSize(*this, BId, Call); + // We have special checking when the length is a sizeof expression. QualType SizeOfArgTy = getSizeOfArgType(LenExpr); const Expr *SizeOfArg = getSizeOfExprArg(LenExpr); diff --git a/test/Sema/transpose-memset.c b/test/Sema/transpose-memset.c new file mode 100644 index 0000000000..0180d5051e --- /dev/null +++ b/test/Sema/transpose-memset.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -Wmemset-transposed-args -verify %s +// RUN: %clang_cc1 -xc++ -Wmemset-transposed-args -verify %s + +#define memset(...) __builtin_memset(__VA_ARGS__) +#define bzero(x,y) __builtin_memset(x, 0, y) +#define real_bzero(x,y) __builtin_bzero(x,y) + +int array[10]; +int *ptr; + +int main() { + memset(array, sizeof(array), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}} + memset(array, sizeof(array), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} + memset(ptr, sizeof(ptr), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}} + memset(ptr, sizeof(*ptr) * 10, 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} + memset(ptr, 10 * sizeof(int *), 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} + memset(ptr, 10 * sizeof(int *) + 10, 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} + memset(ptr, sizeof(char) * sizeof(int *), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} + memset(array, sizeof(array), sizeof(array)); // Uh... fine I guess. + memset(array, 0, sizeof(array)); + memset(ptr, 0, sizeof(int *) * 10); + memset(array, (int)sizeof(array), (0)); // no warning + memset(array, (int)sizeof(array), 32); // no warning + memset(array, 32, (0)); // no warning + + bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}} + real_bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}} +} + +void macros() { +#define ZERO 0 + int array[10]; + memset(array, 0xff, ZERO); // no warning + // Still emit a diagnostic for memsetting a sizeof expression: + memset(array, sizeof(array), ZERO); // expected-warning{{'sizeof'}} expected-note{{cast}} + bzero(array, ZERO); // no warning + real_bzero(array, ZERO); // no warning +#define NESTED_DONT_DIAG \ + memset(array, 0xff, ZERO); \ + real_bzero(array, ZERO); + + NESTED_DONT_DIAG; + +#define NESTED_DO_DIAG \ + memset(array, 0xff, 0); \ + real_bzero(array, 0) + + NESTED_DO_DIAG; // expected-warning{{'size' argument to memset}} expected-warning{{'size' argument to bzero}} expected-note2{{parenthesize}} + +#define FN_MACRO(p) \ + memset(array, 0xff, p) + + FN_MACRO(ZERO); + FN_MACRO(0); // FIXME: should we diagnose this? + + __builtin_memset(array, 0, ZERO); // no warning + __builtin_bzero(array, ZERO); + __builtin_memset(array, 0, 0); // expected-warning{{'size' argument to memset}} // expected-note{{parenthesize}} + __builtin_bzero(array, 0); // expected-warning{{'size' argument to bzero}} // expected-note{{parenthesize}} +} -- GitLab From 6efe16570639bb09816c2dba8b39df8cff31bfcc Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 19 Jul 2018 17:03:12 +0000 Subject: [PATCH 0615/1023] [analyzer] Memoize complexity of SymExpr Summary: This patch introduces a new member to SymExpr, which stores the symbol complexity, avoiding recalculating it every time computeComplexity() is called. Also, increase the complexity of conjured Symbols by one, so it's clear that it has a greater complexity than its underlying symbols. Reviewers: NoQ, george.karpenkov Reviewed By: NoQ, george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49232 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337472 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SymExpr.h | 8 ++++++- .../Core/PathSensitive/SymbolManager.h | 24 +++++++++++++++++++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 2 +- lib/StaticAnalyzer/Core/SymbolManager.cpp | 7 ------ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 5fcc42b909..69b9858d3f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -49,6 +49,8 @@ protected: return !T.isNull() && !T->isVoidType(); } + mutable unsigned Complexity = 0; + public: virtual ~SymExpr() = default; @@ -85,7 +87,7 @@ public: symbol_iterator symbol_begin() const { return symbol_iterator(this); } static symbol_iterator symbol_end() { return symbol_iterator(); } - unsigned computeComplexity() const; + virtual unsigned computeComplexity() const = 0; /// Find the region from which this symbol originates. /// @@ -127,6 +129,10 @@ public: SymbolID getSymbolID() const { return Sym; } + unsigned computeComplexity() const override { + return 1; + }; + // Implement isa support. static inline bool classof(const SymExpr *SE) { Kind k = SE->getKind(); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 1a8b0dc013..cc3ce72f9e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -270,6 +270,12 @@ public: // Otherwise, 'To' should also be a valid type. } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + Operand->computeComplexity(); + return Complexity; + } + QualType getType() const override { return ToTy; } const SymExpr *getOperand() const { return Operand; } @@ -337,6 +343,12 @@ public: const SymExpr *getLHS() const { return LHS; } const llvm::APSInt &getRHS() const { return RHS; } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + LHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t) { @@ -374,6 +386,12 @@ public: const SymExpr *getRHS() const { return RHS; } const llvm::APSInt &getLHS() const { return LHS; } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + RHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { @@ -412,6 +430,12 @@ public: void dumpToStream(raw_ostream &os) const override; + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = RHS->computeComplexity() + LHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { ID.AddInteger((unsigned) SymSymExprKind); diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index a4abb82e2a..eac07e659d 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -390,7 +390,7 @@ unsigned AnalyzerOptions::getGraphTrimInterval() { unsigned AnalyzerOptions::getMaxSymbolComplexity() { if (!MaxSymbolComplexity.hasValue()) - MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 25); + MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35); return MaxSymbolComplexity.getValue(); } diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index 3efbd8331b..ed197010eb 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -159,13 +159,6 @@ void SymExpr::symbol_iterator::expand() { llvm_unreachable("unhandled expansion case"); } -unsigned SymExpr::computeComplexity() const { - unsigned R = 0; - for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I) - R++; - return R; -} - const SymbolRegionValue* SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { llvm::FoldingSetNodeID profile; -- GitLab From 262361d19d59e1d1840d9360cf4adfc6bd24d860 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 19 Jul 2018 17:19:16 +0000 Subject: [PATCH 0616/1023] Fix unused variable warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337473 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 8d4e83bf93..478fda7d91 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6932,7 +6932,7 @@ private: bool IsExpressionFirstInfo = true; Address BP = Address::invalid(); - if (const auto *ME = dyn_cast(I->getAssociatedExpression())) { + if (isa(I->getAssociatedExpression())) { // The base is the 'this' pointer. The content of the pointer is going // to be the base of the field being mapped. BP = CGF.LoadCXXThisAddress(); -- GitLab From 77c4e2380a572bfab344ca1bfc7b59beb9cf8fff Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Thu, 19 Jul 2018 17:43:09 +0000 Subject: [PATCH 0617/1023] [analyzer] Fix memory sanitizer error in MallocChecker. StringRef's data() returns a string that may be non-null-terminated. Switch to using StringRefs from const char pointers in visitor notes to avoid problems. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337474 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 5dcd9b3863..be3289a395 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -2899,7 +2899,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( // (__attribute__((cleanup))). // Find out if this is an interesting point and what is the kind. - const char *Msg = nullptr; + StringRef Msg; StackHintGeneratorForSymbol *StackHint = nullptr; SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); @@ -2933,7 +2933,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( } OS << "'"; } - Msg = OS.str().data(); + Msg = OS.str(); break; } case AF_None: @@ -3004,7 +3004,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( } } - if (!Msg) + if (Msg.empty()) return nullptr; assert(StackHint); -- GitLab From b6dc4f6ec37a4fca5d3d7289a4130b35e8f42bf8 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 19 Jul 2018 18:59:38 +0000 Subject: [PATCH 0618/1023] fix typo in comment git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337480 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MicrosoftCXXABI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index a58982bd0c..e5e9cf67fd 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -3336,7 +3336,7 @@ CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { // a reference to the TypeInfo for the type and a reference to the // CompleteHierarchyDescriptor for the type. // -// ClassHieararchyDescriptor: Contains information about a class hierarchy. +// ClassHierarchyDescriptor: Contains information about a class hierarchy. // Used during dynamic_cast to walk a class hierarchy. References a base // class array and the size of said array. // -- GitLab From 0f6b139a0ce2f74a708f120da6336c05c14ea1cb Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 19 Jul 2018 19:00:37 +0000 Subject: [PATCH 0619/1023] Fix template argument deduction when a parameter pack has a value provided by an outer template. We made the incorrect assumption in various places that the only way we can have any arguments already provided for a pack during template argument deduction was from a partially-specified pack. That's not true; we can also have arguments from an enclosing already-instantiated template, and that can even result in the function template's own pack parameters having a fixed length and not being packs for the purposes of template argument deduction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337481 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 6 + include/clang/Sema/Sema.h | 3 + include/clang/Sema/TemplateDeduction.h | 22 ++ lib/Sema/SemaOverload.cpp | 19 ++ lib/Sema/SemaTemplate.cpp | 45 ++-- lib/Sema/SemaTemplateDeduction.cpp | 290 +++++++++++++-------- lib/Sema/SemaTemplateVariadic.cpp | 33 ++- test/SemaTemplate/pack-deduction.cpp | 101 +++++++ 8 files changed, 385 insertions(+), 134 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 3bda262963..ee51db2d0a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3589,6 +3589,9 @@ def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " "couldn't infer template argument %0">; +def note_ovl_candidate_incomplete_deduction_pack : Note<"candidate template ignored: " + "deduced too few arguments for expanded pack %0; no argument for %ordinal1 " + "expanded parameter in deduced argument pack %2">; def note_ovl_candidate_inconsistent_deduction : Note< "candidate template ignored: deduced conflicting %select{types|values|" "templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">; @@ -4462,6 +4465,9 @@ def err_pack_expansion_length_conflict : Error< def err_pack_expansion_length_conflict_multilevel : Error< "pack expansion contains parameter pack %0 that has a different " "length (%1 vs. %2) from outer parameter packs">; +def err_pack_expansion_length_conflict_partial : Error< + "pack expansion contains parameter pack %0 that has a different " + "length (at least %1 vs. %2) from outer parameter packs">; def err_pack_expansion_member_init : Error< "pack expansion for initialization of member %0">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4ef982e24f..0aa1fc42c6 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6911,6 +6911,9 @@ public: /// Template argument deduction did not deduce a value /// for every template parameter. TDK_Incomplete, + /// Template argument deduction did not deduce a value for every + /// expansion of an expanded template parameter pack. + TDK_IncompletePack, /// Template argument deduction produced inconsistent /// deduced values for the given template parameter. TDK_Inconsistent, diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index bf379db2ae..93395b4945 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -51,6 +51,10 @@ class TemplateDeductionInfo { /// The template parameter depth for which we're performing deduction. unsigned DeducedDepth; + /// The number of parameters with explicitly-specified template arguments, + /// up to and including the partially-specified pack (if any). + unsigned ExplicitArgs = 0; + /// Warnings (and follow-on notes) that were suppressed due to /// SFINAE while performing template argument deduction. SmallVector SuppressedDiagnostics; @@ -73,6 +77,11 @@ public: return DeducedDepth; } + /// Get the number of explicitly-specified arguments. + unsigned getNumExplicitArgs() const { + return ExplicitArgs; + } + /// Take ownership of the deduced template argument list. TemplateArgumentList *take() { TemplateArgumentList *Result = Deduced; @@ -100,6 +109,13 @@ public: return SuppressedDiagnostics.front(); } + /// Provide an initial template argument list that contains the + /// explicitly-specified arguments. + void setExplicitArgs(TemplateArgumentList *NewDeduced) { + Deduced = NewDeduced; + ExplicitArgs = Deduced->size(); + } + /// Provide a new template argument list that contains the /// results of template argument deduction. void reset(TemplateArgumentList *NewDeduced) { @@ -149,6 +165,9 @@ public: /// TDK_Incomplete: this is the first template parameter whose /// corresponding template argument was not deduced. /// + /// TDK_IncompletePack: this is the expanded parameter pack for + /// which we deduced too few arguments. + /// /// TDK_Inconsistent: this is the template parameter for which /// two different template argument values were deduced. TemplateParameter Param; @@ -159,6 +178,9 @@ public: /// Depending on the result of the template argument deduction, /// this template argument may have different meanings: /// + /// TDK_IncompletePack: this is the number of arguments we deduced + /// for the pack. + /// /// TDK_Inconsistent: this argument is the first value deduced /// for the corresponding template parameter. /// diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 35c3612c71..822c3c0c6b 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -629,6 +629,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } + case Sema::TDK_IncompletePack: + // FIXME: It's slightly wasteful to allocate two TemplateArguments for this. case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. @@ -671,6 +673,7 @@ void DeductionFailureInfo::Destroy() { case Sema::TDK_NonDependentConversionFailure: break; + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: case Sema::TDK_DeducedMismatch: @@ -720,6 +723,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_InvalidExplicitArguments: return TemplateParameter::getFromOpaqueValue(Data); + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: return static_cast(Data)->Param; @@ -740,6 +744,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: @@ -777,6 +782,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { case Sema::TDK_NonDependentConversionFailure: return nullptr; + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: case Sema::TDK_DeducedMismatch: @@ -798,6 +804,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: @@ -9893,6 +9900,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } + case Sema::TDK_IncompletePack: { + assert(ParamD && "no parameter found for incomplete deduction result"); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_incomplete_deduction_pack) + << ParamD->getDeclName() + << (DeductionFailure.getFirstArg()->pack_size() + 1) + << *DeductionFailure.getFirstArg(); + MaybeEmitInheritedConstructorNote(S, Found); + return; + } + case Sema::TDK_Underqualified: { assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast(ParamD); @@ -10372,6 +10390,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { case Sema::TDK_Invalid: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: return 1; case Sema::TDK_Underqualified: diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c1d8c24796..935264cb8c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4914,27 +4914,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return false; } -/// Diagnose an arity mismatch in the -static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs) { - TemplateParameterList *Params = Template->getTemplateParameters(); - unsigned NumParams = Params->size(); - unsigned NumArgs = TemplateArgs.size(); - - SourceRange Range; - if (NumArgs > NumParams) - Range = SourceRange(TemplateArgs[NumParams].getLocation(), - TemplateArgs.getRAngleLoc()); - S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << (NumArgs > NumParams) - << (int)S.getTemplateNameKindForDiagnostics(TemplateName(Template)) - << Template << Range; - S.Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); - return true; -} - /// Check whether the template parameter is a pack expansion, and if so, /// determine the number of parameters produced by that expansion. For instance: /// @@ -4988,7 +4967,15 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, // FIXME: If there's a more recent default argument that *is* visible, // diagnose that it was declared too late. - return diagnoseArityMismatch(S, TD, Loc, Args); + TemplateParameterList *Params = TD->getTemplateParameters(); + + S.Diag(Loc, diag::err_template_arg_list_different_arity) + << /*not enough args*/0 + << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD)) + << TD; + S.Diag(TD->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; } /// Check that the given template argument list is well-formed @@ -5040,7 +5027,7 @@ bool Sema::CheckTemplateArgumentList( } else if (ArgIdx == NumArgs && !PartialTemplateArgs) { // Not enough arguments for this parameter pack. Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << false + << /*not enough args*/0 << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template; Diag(Template->getLocation(), diag::note_template_decl_here) @@ -5235,8 +5222,16 @@ bool Sema::CheckTemplateArgumentList( // If we have any leftover arguments, then there were too many arguments. // Complain and fail. - if (ArgIdx < NumArgs) - return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs); + if (ArgIdx < NumArgs) { + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << /*too many args*/1 + << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) + << Template + << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc()); + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; + } // No problems found with the new argument list, propagate changes back // to caller. diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 51d2bae08c..0b41a515d9 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -662,6 +662,19 @@ static TemplateParameter makeTemplateParameter(Decl *D) { return TemplateParameter(cast(D)); } +/// If \p Param is an expanded parameter pack, get the number of expansions. +static Optional getExpandedPackSize(NamedDecl *Param) { + if (auto *NTTP = dyn_cast(Param)) + if (NTTP->isExpandedParameterPack()) + return NTTP->getNumExpansionTypes(); + + if (auto *TTP = dyn_cast(Param)) + if (TTP->isExpandedParameterPack()) + return TTP->getNumExpansionTemplateParameters(); + + return None; +} + /// A pack that we're currently deducing. struct clang::DeducedPack { // The index of the pack. @@ -688,10 +701,83 @@ namespace { /// A scope in which we're performing pack deduction. class PackDeductionScope { public: + /// Prepare to deduce the packs named within Pattern. PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams, SmallVectorImpl &Deduced, TemplateDeductionInfo &Info, TemplateArgument Pattern) : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) { + unsigned NumNamedPacks = addPacks(Pattern); + finishConstruction(NumNamedPacks); + } + + /// Prepare to directly deduce arguments of the parameter with index \p Index. + PackDeductionScope(Sema &S, TemplateParameterList *TemplateParams, + SmallVectorImpl &Deduced, + TemplateDeductionInfo &Info, unsigned Index) + : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info) { + addPack(Index); + finishConstruction(1); + } + +private: + void addPack(unsigned Index) { + // Save the deduced template argument for the parameter pack expanded + // by this pack expansion, then clear out the deduction. + DeducedPack Pack(Index); + Pack.Saved = Deduced[Index]; + Deduced[Index] = TemplateArgument(); + + // FIXME: What if we encounter multiple packs with different numbers of + // pre-expanded expansions? (This should already have been diagnosed + // during substitution.) + if (Optional ExpandedPackExpansions = + getExpandedPackSize(TemplateParams->getParam(Index))) + FixedNumExpansions = ExpandedPackExpansions; + + Packs.push_back(Pack); + } + + unsigned addPacks(TemplateArgument Pattern) { + // Compute the set of template parameter indices that correspond to + // parameter packs expanded by the pack expansion. + llvm::SmallBitVector SawIndices(TemplateParams->size()); + + auto AddPack = [&](unsigned Index) { + if (SawIndices[Index]) + return; + SawIndices[Index] = true; + addPack(Index); + }; + + // First look for unexpanded packs in the pattern. + SmallVector Unexpanded; + S.collectUnexpandedParameterPacks(Pattern, Unexpanded); + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + unsigned Depth, Index; + std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); + if (Depth == Info.getDeducedDepth()) + AddPack(Index); + } + assert(!Packs.empty() && "Pack expansion without unexpanded packs?"); + + unsigned NumNamedPacks = Packs.size(); + + // We can also have deduced template parameters that do not actually + // appear in the pattern, but can be deduced by it (the type of a non-type + // template parameter pack, in particular). These won't have prevented us + // from partially expanding the pack. + llvm::SmallBitVector Used(TemplateParams->size()); + MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true, + Info.getDeducedDepth(), Used); + for (int Index = Used.find_first(); Index != -1; + Index = Used.find_next(Index)) + if (TemplateParams->getParam(Index)->isParameterPack()) + AddPack(Index); + + return NumNamedPacks; + } + + void finishConstruction(unsigned NumNamedPacks) { // Dig out the partially-substituted pack, if there is one. const TemplateArgument *PartialPackArgs = nullptr; unsigned NumPartialPackArgs = 0; @@ -701,60 +787,29 @@ public: &PartialPackArgs, &NumPartialPackArgs)) PartialPackDepthIndex = getDepthAndIndex(Partial); - // Compute the set of template parameter indices that correspond to - // parameter packs expanded by the pack expansion. - { - llvm::SmallBitVector SawIndices(TemplateParams->size()); - - auto AddPack = [&](unsigned Index) { - if (SawIndices[Index]) - return; - SawIndices[Index] = true; - - // Save the deduced template argument for the parameter pack expanded - // by this pack expansion, then clear out the deduction. - DeducedPack Pack(Index); - Pack.Saved = Deduced[Index]; - Deduced[Index] = TemplateArgument(); - - Packs.push_back(Pack); - }; - - // First look for unexpanded packs in the pattern. - SmallVector Unexpanded; - S.collectUnexpandedParameterPacks(Pattern, Unexpanded); - for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { - unsigned Depth, Index; - std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); - if (Depth == Info.getDeducedDepth()) - AddPack(Index); + // This pack expansion will have been partially or fully expanded if + // it only names explicitly-specified parameter packs (including the + // partially-substituted one, if any). + bool IsExpanded = true; + for (unsigned I = 0; I != NumNamedPacks; ++I) { + if (Packs[I].Index >= Info.getNumExplicitArgs()) { + IsExpanded = false; + IsPartiallyExpanded = false; + break; + } + if (PartialPackDepthIndex == + std::make_pair(Info.getDeducedDepth(), Packs[I].Index)) { + IsPartiallyExpanded = true; } - assert(!Packs.empty() && "Pack expansion without unexpanded packs?"); - - // This pack expansion will have been partially expanded iff the only - // unexpanded parameter pack within it is the partially-substituted pack. - IsPartiallyExpanded = - Packs.size() == 1 && - PartialPackDepthIndex == - std::make_pair(Info.getDeducedDepth(), Packs.front().Index); - - // Skip over the pack elements that were expanded into separate arguments. - if (IsPartiallyExpanded) - PackElements += NumPartialPackArgs; - - // We can also have deduced template parameters that do not actually - // appear in the pattern, but can be deduced by it (the type of a non-type - // template parameter pack, in particular). These won't have prevented us - // from partially expanding the pack. - llvm::SmallBitVector Used(TemplateParams->size()); - MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true, - Info.getDeducedDepth(), Used); - for (int Index = Used.find_first(); Index != -1; - Index = Used.find_next(Index)) - if (TemplateParams->getParam(Index)->isParameterPack()) - AddPack(Index); } + // Skip over the pack elements that were expanded into separate arguments. + // If we partially expanded, this is the number of partial arguments. + if (IsPartiallyExpanded) + PackElements += NumPartialPackArgs; + else if (IsExpanded) + PackElements += *FixedNumExpansions; + for (auto &Pack : Packs) { if (Info.PendingDeducedPacks.size() > Pack.Index) Pack.Outer = Info.PendingDeducedPacks[Pack.Index]; @@ -773,12 +828,13 @@ public: // FIXME: If we could represent a "depth i, index j, pack elem k" // parameter, we could substitute the partially-substituted pack // everywhere and avoid this. - if (Pack.New.size() > PackElements) + if (!IsPartiallyExpanded) Deduced[Pack.Index] = Pack.New[PackElements]; } } } +public: ~PackDeductionScope() { for (auto &Pack : Packs) Info.PendingDeducedPacks[Pack.Index] = Pack.Outer; @@ -788,6 +844,18 @@ public: /// sequence of (prior) function parameters / template arguments. bool isPartiallyExpanded() { return IsPartiallyExpanded; } + /// Determine whether this pack expansion scope has a known, fixed arity. + /// This happens if it involves a pack from an outer template that has + /// (notionally) already been expanded. + bool hasFixedArity() { return FixedNumExpansions.hasValue(); } + + /// Determine whether the next element of the argument is still part of this + /// pack. This is the case unless the pack is already expanded to a fixed + /// length. + bool hasNextElement() { + return !FixedNumExpansions || *FixedNumExpansions > PackElements; + } + /// Move to deducing the next element in each pack that is being deduced. void nextPackElement() { // Capture the deduced template arguments for each parameter pack expanded @@ -813,13 +881,21 @@ public: /// Finish template argument deduction for a set of argument packs, /// producing the argument packs and checking for consistency with prior /// deductions. - Sema::TemplateDeductionResult finish() { + Sema::TemplateDeductionResult + finish(bool TreatNoDeductionsAsNonDeduced = true) { // Build argument packs for each of the parameter packs expanded by this // pack expansion. for (auto &Pack : Packs) { // Put back the old value for this pack. Deduced[Pack.Index] = Pack.Saved; + // If we are deducing the size of this pack even if we didn't deduce any + // values for it, then make sure we build a pack of the right size. + // FIXME: Should we always deduce the size, even if the pack appears in + // a non-deduced context? + if (!TreatNoDeductionsAsNonDeduced) + Pack.New.resize(PackElements); + // Build or find a new value for this pack. DeducedTemplateArgument NewPack; if (PackElements && Pack.New.empty()) { @@ -875,14 +951,24 @@ public: Result = checkDeducedTemplateArguments(S.Context, OldPack, NewPack); } + NamedDecl *Param = TemplateParams->getParam(Pack.Index); if (Result.isNull()) { - Info.Param = - makeTemplateParameter(TemplateParams->getParam(Pack.Index)); + Info.Param = makeTemplateParameter(Param); Info.FirstArg = OldPack; Info.SecondArg = NewPack; return Sema::TDK_Inconsistent; } + // If we have a pre-expanded pack and we didn't deduce enough elements + // for it, fail deduction. + if (Optional Expansions = getExpandedPackSize(Param)) { + if (*Expansions != PackElements) { + Info.Param = makeTemplateParameter(Param); + Info.FirstArg = Result; + return Sema::TDK_IncompletePack; + } + } + *Loc = Result; } @@ -896,6 +982,8 @@ private: TemplateDeductionInfo &Info; unsigned PackElements = 0; bool IsPartiallyExpanded = false; + /// The number of expansions, if we have a fully-expanded pack in this scope. + Optional FixedNumExpansions; SmallVector Packs; }; @@ -987,8 +1075,10 @@ DeduceTemplateArguments(Sema &S, QualType Pattern = Expansion->getPattern(); PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern); - if (ParamIdx + 1 == NumParams) { - for (; ArgIdx < NumArgs; ++ArgIdx) { + // A pack scope with fixed arity is not really a pack any more, so is not + // a non-deduced context. + if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity()) { + for (; ArgIdx < NumArgs && PackScope.hasNextElement(); ++ArgIdx) { // Deduce template arguments from the pattern. if (Sema::TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, @@ -2193,6 +2283,8 @@ static bool hasPackExpansionBeforeEnd(ArrayRef Args) { if (A.getKind() == TemplateArgument::Pack) return hasPackExpansionBeforeEnd(A.pack_elements()); + // FIXME: If this is a fixed-arity pack expansion from an outer level of + // templates, it should not be treated as a pack expansion. if (A.isPackExpansion()) FoundPackExpansion = true; } @@ -2262,7 +2354,9 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // Keep track of the deduced template arguments for each parameter pack // expanded by this pack expansion (the outer index) and for each // template argument (the inner SmallVectors). - for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) { + for (; hasTemplateArgumentForDeduction(Args, ArgIdx) && + PackScope.hasNextElement(); + ++ArgIdx) { // Deduce template arguments from the pattern. if (Sema::TemplateDeductionResult Result = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx], @@ -2534,6 +2628,16 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { NamedDecl *Param = TemplateParams->getParam(I); + // C++0x [temp.arg.explicit]p3: + // A trailing template parameter pack (14.5.3) not otherwise deduced will + // be deduced to an empty sequence of template arguments. + // FIXME: Where did the word "trailing" come from? + if (Deduced[I].isNull() && Param->isTemplateParameterPack()) { + if (auto Result = PackDeductionScope(S, TemplateParams, Deduced, Info, I) + .finish(/*TreatNoDeductionsAsNonDeduced*/false)) + return Result; + } + if (!Deduced[I].isNull()) { if (I < NumAlreadyConverted) { // We may have had explicitly-specified template arguments for a @@ -2568,40 +2672,6 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( continue; } - // C++0x [temp.arg.explicit]p3: - // A trailing template parameter pack (14.5.3) not otherwise deduced will - // be deduced to an empty sequence of template arguments. - // FIXME: Where did the word "trailing" come from? - if (Param->isTemplateParameterPack()) { - // We may have had explicitly-specified template arguments for this - // template parameter pack. If so, our empty deduction extends the - // explicitly-specified set (C++0x [temp.arg.explicit]p9). - const TemplateArgument *ExplicitArgs; - unsigned NumExplicitArgs; - if (CurrentInstantiationScope && - CurrentInstantiationScope->getPartiallySubstitutedPack( - &ExplicitArgs, &NumExplicitArgs) == Param) { - Builder.push_back(TemplateArgument( - llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs))); - - // Forget the partially-substituted pack; its substitution is now - // complete. - CurrentInstantiationScope->ResetPartiallySubstitutedPack(); - } else { - // Go through the motions of checking the empty argument pack against - // the parameter pack. - DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack()); - if (ConvertDeducedTemplateArgument(S, Param, DeducedPack, Template, - Info, IsDeduced, Builder)) { - Info.Param = makeTemplateParameter(Param); - // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder)); - return Sema::TDK_SubstitutionFailure; - } - } - continue; - } - // Substitute into the default template argument, if available. bool HasDefaultArg = false; TemplateDecl *TD = dyn_cast(Template); @@ -2962,7 +3032,7 @@ Sema::SubstituteExplicitTemplateArguments( Trap.hasErrorOccurred()) { unsigned Index = Builder.size(); if (Index >= TemplateParams->size()) - Index = TemplateParams->size() - 1; + return TDK_SubstitutionFailure; Info.Param = makeTemplateParameter(TemplateParams->getParam(Index)); return TDK_InvalidExplicitArguments; } @@ -2971,7 +3041,7 @@ Sema::SubstituteExplicitTemplateArguments( // template arguments. TemplateArgumentList *ExplicitArgumentList = TemplateArgumentList::CreateCopy(Context, Builder); - Info.reset(ExplicitArgumentList); + Info.setExplicitArgs(ExplicitArgumentList); // Template argument deduction and the final substitution should be // done in the context of the templated declaration. Explicit @@ -2983,14 +3053,19 @@ Sema::SubstituteExplicitTemplateArguments( // note that the template argument pack is partially substituted and record // the explicit template arguments. They'll be used as part of deduction // for this template parameter pack. - for (unsigned I = 0, N = Builder.size(); I != N; ++I) { - const TemplateArgument &Arg = Builder[I]; + unsigned PartiallySubstitutedPackIndex = -1u; + if (!Builder.empty()) { + const TemplateArgument &Arg = Builder.back(); if (Arg.getKind() == TemplateArgument::Pack) { - CurrentInstantiationScope->SetPartiallySubstitutedPack( - TemplateParams->getParam(I), - Arg.pack_begin(), - Arg.pack_size()); - break; + auto *Param = TemplateParams->getParam(Builder.size() - 1); + // If this is a fully-saturated fixed-size pack, it should be + // fully-substituted, not partially-substituted. + Optional Expansions = getExpandedPackSize(Param); + if (!Expansions || Arg.pack_size() < *Expansions) { + PartiallySubstitutedPackIndex = Builder.size() - 1; + CurrentInstantiationScope->SetPartiallySubstitutedPack( + Param, Arg.pack_begin(), Arg.pack_size()); + } } } @@ -3080,13 +3155,13 @@ Sema::SubstituteExplicitTemplateArguments( // case, the empty template argument list <> itself may also be omitted. // // Take all of the explicitly-specified arguments and put them into - // the set of deduced template arguments. Explicitly-specified - // parameter packs, however, will be set to NULL since the deduction - // mechanisms handle explicitly-specified argument packs directly. + // the set of deduced template arguments. The partially-substituted + // parameter pack, however, will be set to NULL since the deduction + // mechanism handles the partially-substituted argument pack directly. Deduced.reserve(TemplateParams->size()); for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) { const TemplateArgument &Arg = ExplicitArgumentList->get(I); - if (Arg.getKind() == TemplateArgument::Pack) + if (I == PartiallySubstitutedPackIndex) Deduced.push_back(DeducedTemplateArgument()); else Deduced.push_back(Arg); @@ -3852,8 +3927,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // the length of the explicitly-specified pack if it's expanded by the // parameter pack and 0 otherwise, and we treat each deduction as a // non-deduced context. - if (ParamIdx + 1 == NumParamTypes) { - for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) { + if (ParamIdx + 1 == NumParamTypes || PackScope.hasFixedArity()) { + for (; ArgIdx < Args.size() && PackScope.hasNextElement(); + PackScope.nextPackElement(), ++ArgIdx) { ParamTypesForArgChecking.push_back(ParamPattern); if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) return Result; diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 71c583367b..9dfdd0555f 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -646,7 +646,9 @@ bool Sema::CheckParameterPacksForExpansion( RetainExpansion = false; std::pair FirstPack; bool HaveFirstPack = false; - + Optional NumPartialExpansions; + SourceLocation PartiallySubstitutedPackLoc; + for (ArrayRef::iterator i = Unexpanded.begin(), end = Unexpanded.end(); i != end; ++i) { @@ -711,8 +713,13 @@ bool Sema::CheckParameterPacksForExpansion( = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); - if (PartialDepth == Depth && PartialIndex == Index) + if (PartialDepth == Depth && PartialIndex == Index) { RetainExpansion = true; + // We don't actually know the new pack size yet. + NumPartialExpansions = NewPackSize; + PartiallySubstitutedPackLoc = i->second; + continue; + } } } @@ -742,6 +749,28 @@ bool Sema::CheckParameterPacksForExpansion( } } + // If we're performing a partial expansion but we also have a full expansion, + // expand to the number of common arguments. For example, given: + // + // template struct A { + // template void f(pair...); + // }; + // + // ... a call to 'A().f' should expand the pack once and + // retain an expansion. + if (NumPartialExpansions) { + if (NumExpansions && *NumExpansions < *NumPartialExpansions) { + NamedDecl *PartialPack = + CurrentInstantiationScope->getPartiallySubstitutedPack(); + Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial) + << PartialPack << *NumPartialExpansions << *NumExpansions + << SourceRange(PartiallySubstitutedPackLoc); + return true; + } + + NumExpansions = NumPartialExpansions; + } + return false; } diff --git a/test/SemaTemplate/pack-deduction.cpp b/test/SemaTemplate/pack-deduction.cpp index 84eefa63d2..db0bb58526 100644 --- a/test/SemaTemplate/pack-deduction.cpp +++ b/test/SemaTemplate/pack-deduction.cpp @@ -65,3 +65,104 @@ namespace PR14615 { void f() { check(1, 2); } // expected-error {{no matching function}} } } + +namespace fully_expanded_packs { + template struct A { + template static constexpr int f() { + // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}} + // expected-note@-2 1+{{too many template arguments}} + return (X + ... + 0); // expected-warning {{extension}} + } + + template static constexpr int g() { + // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}} + // expected-note@-2 1+{{couldn't infer template argument 'Y'}} + // expected-note@-3 1+{{too many template arguments}} + return (X + ... + (1000 * Y)); // expected-warning {{extension}} + } + + template static constexpr int h() { + // expected-note@-1 1+{{deduced too few arguments for expanded pack 'X'}} + // expected-note@-2 1+{{couldn't infer template argument 'Y'}} + // expected-note@-3 1+{{deduced too few arguments for expanded pack 'Z'}} + // expected-note@-4 1+{{too many template arguments}} + return (X + ... + (1000 * Y)) + 1000000 * (Z + ... + 0); // expected-warning 2{{extension}} + } + + template static constexpr int i() { + return (X + ... + 0) + 1000 * (Z + ... + 0); // expected-warning 2{{extension}} + } + + template static constexpr int j() { + return (X + ... + (1000 * Y)) + 1000000 * (Z + ... + 0); // expected-warning 2{{extension}} + } + }; + + void check_invalid_calls() { + A::f(); // expected-error {{no matching function}} + A::f<>(); // expected-error {{no matching function}} + A::f<0>(); // expected-error {{no matching function}} + A::g(); // expected-error {{no matching function}} + A::g<>(); // expected-error {{no matching function}} + A::g<0>(); // expected-error {{no matching function}} + A::g<0, 0>(); // expected-error {{no matching function}} + A<>::f<0>(); // expected-error {{no matching function}} + A<>::g(); // expected-error {{no matching function}} + A<>::g<>(); // expected-error {{no matching function}} + A<>::g<0, 0>(); // expected-error {{no matching function}} + A<>::h<>(); // expected-error {{no matching function}} + A::h<>(); // expected-error {{no matching function}} + A::h<0, 0>(); // expected-error {{no matching function}} + A<>::h<0, 0>(); // expected-error {{no matching function}} + } + + static_assert(A<>::f() == 0, ""); + static_assert(A::f<1>() == 1, ""); + static_assert(A<>::g<1>() == 1000, ""); + static_assert(A::g<1, 2>() == 2001, ""); + static_assert(A<>::h<1>() == 1000, ""); + static_assert(A::h<1, 2, 3>() == 3002001, ""); + static_assert(A::h<1, 20, 3, 4, 50>() == 54003021, ""); + static_assert(A<>::i<1>() == 1000, ""); + static_assert(A::i<1>() == 1, ""); + static_assert(A<>::j<1, 2, 30>() == 32001000, ""); + static_assert(A::j<1, 2, 3, 40>() == 43002001, ""); +} + +namespace partial_full_mix { + template struct pair {}; + template struct tuple {}; + template struct A { + template static pair, tuple> f(pair ...p); + // expected-note@-1 {{[with U = ]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}} + // expected-note@-2 {{[with U = ]: pack expansion contains parameter pack 'U' that has a different length (at least 3 vs. 2) from outer parameter packs}} + + template static pair, tuple> g(pair ...p, ...); + // expected-note@-1 {{[with U = ]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 3) from outer parameter packs}} + + template static tuple h(tuple..., pair>); + // expected-note@-1 {{[with U = ]: pack expansion contains parameter pack 'U' that has a different length (2 vs. 1) from outer parameter packs}} + }; + + pair, tuple> k1 = A().f(pair(), pair()); + pair, tuple> k2 = A().f(pair(), pair(), pair()); // expected-error {{no match}} + pair, tuple> k3 = A().f(pair(), pair()); // expected-error {{no match}} + + // FIXME: We should accept this by treating the pack 'p' as having a fixed length of 2 here. + pair, tuple> k4 = A().g(pair(), pair(), pair()); // expected-error {{no match}} + + // FIXME: We should accept this by treating the pack of pairs as having a fixed length of 2 here. + tuple k5 = A::h(tuple, pair, pair>()); // expected-error {{no match}} +} + +namespace substitution_vs_function_deduction { + template struct A { + template void f(void(*...)(T, U)); // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}} + template void g(void...(T, U)); // expected-note {{could not match 'void (T, U)' against 'void (*)(int, int)'}} + }; + void f(int, int) { + A().f(f); + // FIXME: We fail to decay the parameter to a pointer type. + A().g(f); // expected-error {{no match}} + } +} -- GitLab From add6b02377f0bec53d6a89be6dce07717d63c30e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 19 Jul 2018 19:05:13 +0000 Subject: [PATCH 0620/1023] Fix failing testcase to actually be valid. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337483 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaTemplate/pack-deduction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SemaTemplate/pack-deduction.cpp b/test/SemaTemplate/pack-deduction.cpp index db0bb58526..f9309d5211 100644 --- a/test/SemaTemplate/pack-deduction.cpp +++ b/test/SemaTemplate/pack-deduction.cpp @@ -152,7 +152,7 @@ namespace partial_full_mix { pair, tuple> k4 = A().g(pair(), pair(), pair()); // expected-error {{no match}} // FIXME: We should accept this by treating the pack of pairs as having a fixed length of 2 here. - tuple k5 = A::h(tuple, pair, pair>()); // expected-error {{no match}} + tuple k5 = A::h(tuple, pair, pair>()); // expected-error {{no match}} } namespace substitution_vs_function_deduction { -- GitLab From 48b5ee7a0b384726615ebdbace53d37a87d889e5 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Thu, 19 Jul 2018 20:40:20 +0000 Subject: [PATCH 0621/1023] [Sema] Diagnose an invalid dependent function template specialization Previously, clang marked the specialization as invalid without emitting a diagnostic. This lead to an assert in CodeGen. rdar://41806724 Differential revision: https://reviews.llvm.org/D49085 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337497 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 7 ++++++ lib/Sema/SemaTemplate.cpp | 27 ++++++++++++++++---- test/CXX/temp/temp.decls/temp.friend/p1.cpp | 28 +++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ee51db2d0a..f623bd3773 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4106,6 +4106,13 @@ def ext_explicit_specialization_storage_class : ExtWarn< def err_explicit_specialization_inconsistent_storage_class : Error< "explicit specialization has extraneous, inconsistent storage class " "'%select{none|extern|static|__private_extern__|auto|register}0'">; +def err_dependent_function_template_spec_no_match : Error< + "no candidate function template was found for dependent" + " friend function template specialization">; +def note_dependent_function_template_spec_discard_reason : Note< + "candidate ignored: %select{not a function template" + "|not a member of the enclosing namespace;" + " did you mean to explicitly qualify the specialization?}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 935264cb8c..dd11632671 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -8003,17 +8003,34 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, // the correct context. DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); LookupResult::Filter F = Previous.makeFilter(); + enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing }; + SmallVector, 8> DiscardedCandidates; while (F.hasNext()) { NamedDecl *D = F.next()->getUnderlyingDecl(); - if (!isa(D) || - !FDLookupContext->InEnclosingNamespaceSetOf( - D->getDeclContext()->getRedeclContext())) + if (!isa(D)) { F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D)); + continue; + } + + if (!FDLookupContext->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) { + F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D)); + continue; + } } F.done(); - // Should this be diagnosed here? - if (Previous.empty()) return true; + if (Previous.empty()) { + Diag(FD->getLocation(), + diag::err_dependent_function_template_spec_no_match); + for (auto &P : DiscardedCandidates) + Diag(P.second->getLocation(), + diag::note_dependent_function_template_spec_discard_reason) + << P.first; + return true; + } FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(), ExplicitTemplateArgs); diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp index f1f3f70162..849728a448 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -359,3 +359,31 @@ namespace PR10913 { template void f2(X *); template void f2(X *); // expected-note{{in instantiation of function template specialization 'PR10913::f2' requested here}} } + +namespace test16 { +template struct foo {}; // expected-note{{candidate ignored: not a function template}} +template class A { + friend void foo(); // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test17 { +namespace ns { +template void foo() {} // expected-note{{candidate ignored: not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}} +} +using ns::foo; +template struct A { + friend void foo() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} + +namespace test18 { +namespace ns1 { template struct foo {}; } // expected-note{{candidate ignored: not a function template}} +namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}} +using ns1::foo; +using ns2::foo; + +template class A { + friend void foo() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} +}; +} -- GitLab From f9af50d37f8d3ae675069543ba14b2a6ace05428 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 19 Jul 2018 21:38:56 +0000 Subject: [PATCH 0622/1023] When we choose to use zeroinitializer for a trailing portion of an array constant, don't convert the rest into a packed struct. If an array constant has a large non-zero portion and a large zero portion, we want to emit the first part as an array and the rest as a zeroinitializer if possible. This fixes a memory usage regression from r333141 when compiling PHP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337498 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprConstant.cpp | 14 +++++++++++++- test/CodeGen/init.c | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b26ff3d20e..afe2bfe8e9 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -659,7 +659,19 @@ EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType, if (TrailingZeroes >= 8) { assert(Elements.size() >= NonzeroLength && "missing initializer for non-zero element"); - Elements.resize(NonzeroLength + 1); + + // If all the elements had the same type up to the trailing zeroes, emit a + // struct of two arrays (the nonzero data and the zeroinitializer). + if (CommonElementType && NonzeroLength >= 8) { + llvm::Constant *Initial = llvm::ConstantArray::get( + llvm::ArrayType::get(CommonElementType, ArrayBound), + makeArrayRef(Elements).take_front(NonzeroLength)); + Elements.resize(2); + Elements[0] = Initial; + } else { + Elements.resize(NonzeroLength + 1); + } + auto *FillerType = CommonElementType ? CommonElementType diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index b539681010..770995f93f 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -81,6 +81,10 @@ struct Huge { int arr[1000 * 1000 * 1000]; } huge_struct = {1, {2, 0, 0, 0}}; +// CHECK-DAG: @large_array_with_zeroes = constant <{ [21 x i8], [979 x i8] }> <{ [21 x i8] c"abc\01\02\03xyzzy\00\00\00\00\00\00\00\00\00q", [979 x i8] zeroinitializer }> +const char large_array_with_zeroes[1000] = { + 'a', 'b', 'c', 1, 2, 3, 'x', 'y', 'z', 'z', 'y', [20] = 'q' +}; // PR279 comment #3 char test8(int X) { -- GitLab From 73ce27a67980d4bb3d56c34a86d362de70d6fe45 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 19 Jul 2018 21:50:03 +0000 Subject: [PATCH 0623/1023] [CStringSyntaxChecker] Check strlcpy sizeof syntax The last argument is expected to be the destination buffer size (or less). Detects if it points to destination buffer size directly or via a variable. Detects if it is an integral, try to detect if the destination buffer can receive the source length. Updating bsd-string.c unit tests as it make it fails now. Reviewers: george.karpenpov, NoQ Reviewed By: george.karpenkov Differential Revision: https://reviews.llvm.org/D48884 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337499 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CStringSyntaxChecker.cpp | 62 +++++++++++++++++++ test/Analysis/bsd-string.c | 2 +- test/Analysis/cstring-syntax.c | 15 +++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp index 4b5e97b692..633e9724b6 100644 --- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp @@ -80,6 +80,17 @@ class WalkAST: public StmtVisitor { /// of bytes to copy. bool containsBadStrncatPattern(const CallExpr *CE); + /// Identify erroneous patterns in the last argument to strlcpy - the number + /// of bytes to copy. + /// The bad pattern checked is when the size is known + /// to be larger than the destination can handle. + /// char dst[2]; + /// size_t cpy = 4; + /// strlcpy(dst, "abcd", sizeof("abcd") - 1); + /// strlcpy(dst, "abcd", 4); + /// strlcpy(dst, "abcd", cpy); + bool containsBadStrlcpyPattern(const CallExpr *CE); + public: WalkAST(const CheckerBase *Checker, BugReporter &BR, AnalysisDeclContext *AC) : Checker(Checker), BR(BR), AC(AC) {} @@ -130,6 +141,38 @@ bool WalkAST::containsBadStrncatPattern(const CallExpr *CE) { return false; } +bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { + if (CE->getNumArgs() != 3) + return false; + const Expr *DstArg = CE->getArg(0); + const Expr *LenArg = CE->getArg(2); + + const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenCasts()); + const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts()); + // - size_t dstlen = sizeof(dst) + if (LenArgDecl) { + const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl()); + if (LenArgVal->getInit()) + LenArg = LenArgVal->getInit(); + } + + // - integral value + // We try to figure out if the last argument is possibly longer + // than the destination can possibly handle if its size can be defined + if (const auto *IL = dyn_cast(LenArg->IgnoreParenCasts())) { + uint64_t ILRawVal = IL->getValue().getZExtValue(); + if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) { + ASTContext &C = BR.getContext(); + uint64_t Usize = C.getTypeSizeInChars(DstArg->getType()).getQuantity(); + uint64_t BufferLen = BR.getContext().getTypeSize(Buffer) / Usize; + if (BufferLen < ILRawVal) + return true; + } + } + + return false; +} + void WalkAST::VisitCallExpr(CallExpr *CE) { const FunctionDecl *FD = CE->getDirectCallee(); if (!FD) @@ -155,6 +198,25 @@ void WalkAST::VisitCallExpr(CallExpr *CE) { os << "U"; os << "se a safer 'strlcat' API"; + BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument", + "C String API", os.str(), Loc, + LenArg->getSourceRange()); + } + } else if (CheckerContext::isCLibraryFunction(FD, "strlcpy")) { + if (containsBadStrlcpyPattern(CE)) { + const Expr *DstArg = CE->getArg(0); + const Expr *LenArg = CE->getArg(2); + PathDiagnosticLocation Loc = + PathDiagnosticLocation::createBegin(LenArg, BR.getSourceManager(), AC); + + StringRef DstName = getPrintableName(DstArg); + + SmallString<256> S; + llvm::raw_svector_ostream os(S); + os << "The third argument is larger than the size of the input buffer. "; + if (!DstName.empty()) + os << "Replace with the value 'sizeof(" << DstName << ")` or lower"; + BR.EmitBasicReport(FD, Checker, "Anti-pattern in the argument", "C String API", os.str(), Loc, LenArg->getSourceRange()); diff --git a/test/Analysis/bsd-string.c b/test/Analysis/bsd-string.c index 14e1b00fc0..bca42ca896 100644 --- a/test/Analysis/bsd-string.c +++ b/test/Analysis/bsd-string.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring.NullArg,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s #define NULL ((void *)0) diff --git a/test/Analysis/cstring-syntax.c b/test/Analysis/cstring-syntax.c index 313ac54495..d7df3f082c 100644 --- a/test/Analysis/cstring-syntax.c +++ b/test/Analysis/cstring-syntax.c @@ -3,6 +3,7 @@ typedef __SIZE_TYPE__ size_t; char *strncat(char *, const char *, size_t); size_t strlen (const char *s); +size_t strlcpy(char *, const char *, size_t); void testStrncat(const char *src) { char dest[10]; @@ -13,3 +14,17 @@ void testStrncat(const char *src) { // Should not crash when sizeof has a type argument. strncat(dest, "AAAAAAAAAAAAAAAAAAAAAAAAAAA", sizeof(char)); } + +void testStrlcpy(const char *src) { + char dest[10]; + size_t destlen = sizeof(dest); + size_t srclen = sizeof(src); + size_t badlen = 20; + size_t ulen; + strlcpy(dest, src, sizeof(dest)); + strlcpy(dest, src, destlen); + strlcpy(dest, src, 10); + strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}} + strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}} + strlcpy(dest, src, ulen); +} -- GitLab From b89b5e148bb4bdccf2a10d6a77afc9d5a2fa376c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 19 Jul 2018 22:45:41 +0000 Subject: [PATCH 0624/1023] [docs] Correct -fvisibility-inlines-hidden description git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337505 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangCommandLineReference.rst | 2 +- include/clang/Driver/Options.td | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index 87c7896ba7..5c15482cb2 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -1928,7 +1928,7 @@ Enable the loop vectorization passes .. option:: -fvisibility-inlines-hidden -Give inline C++ member functions default visibility by default +Give inline C++ member functions hidden visibility by default .. option:: -fvisibility-ms-compat diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 6051608448..d0a31f9495 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1694,7 +1694,7 @@ def fverbose_asm : Flag<["-"], "fverbose-asm">, Group; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group, HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, - HelpText<"Give inline C++ member functions default visibility by default">, + HelpText<"Give inline C++ member functions hidden visibility by default">, Flags<[CC1Option]>; def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group, HelpText<"Give global types 'default' visibility and global functions and " -- GitLab From 02e5d2661dfbdc64039d7cd01900efad5137b85f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 19 Jul 2018 23:24:41 +0000 Subject: [PATCH 0625/1023] Fix typo causing assert in self-host. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337508 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprConstant.cpp | 2 +- test/CodeGen/init.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index afe2bfe8e9..cfd0b85923 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -664,7 +664,7 @@ EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType, // struct of two arrays (the nonzero data and the zeroinitializer). if (CommonElementType && NonzeroLength >= 8) { llvm::Constant *Initial = llvm::ConstantArray::get( - llvm::ArrayType::get(CommonElementType, ArrayBound), + llvm::ArrayType::get(CommonElementType, NonzeroLength), makeArrayRef(Elements).take_front(NonzeroLength)); Elements.resize(2); Elements[0] = Initial; diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index 770995f93f..0353ba8be1 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -86,6 +86,17 @@ const char large_array_with_zeroes[1000] = { 'a', 'b', 'c', 1, 2, 3, 'x', 'y', 'z', 'z', 'y', [20] = 'q' }; +char global; + +// CHECK-DAG: @large_array_with_zeroes_2 = global <{ [10 x i8*], [90 x i8*] }> <{ [10 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* @global], [90 x i8*] zeroinitializer }> +const void *large_array_with_zeroes_2[100] = { + [9] = &global +}; +// CHECK-DAG: @large_array_with_zeroes_3 = global <{ [10 x i8*], [990 x i8*] }> <{ [10 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* @global], [990 x i8*] zeroinitializer }> +const void *large_array_with_zeroes_3[1000] = { + [9] = &global +}; + // PR279 comment #3 char test8(int X) { char str[100000] = "abc"; // tail should be memset. -- GitLab From 39698523d89c79606c71c98d6e714defb6a04c4d Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 20 Jul 2018 05:40:09 +0000 Subject: [PATCH 0626/1023] Fix and improve the ARC spec's wording about unmanaged objects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337524 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/AutomaticReferenceCounting.rst | 76 +++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst index fbd1ba4c4d..bf4d094567 100644 --- a/docs/AutomaticReferenceCounting.rst +++ b/docs/AutomaticReferenceCounting.rst @@ -974,28 +974,66 @@ It is undefined behavior to access an ownership-qualified object through an lvalue of a differently-qualified type, except that any non-``__weak`` object may be read through an ``__unsafe_unretained`` lvalue. -It is undefined behavior if a managed operation is performed on a ``__strong`` -or ``__weak`` object without a guarantee that it contains a primitive zero -bit-pattern, or if the storage for such an object is freed or reused without the -object being first assigned a null pointer. +It is undefined behavior if the storage of a ``__strong`` or ``__weak`` +object is not properly initialized before the first managed operation +is performed on the object, or if the storage of such an object is freed +or reused before the object has been properly deinitialized. Storage for +a ``__strong`` or ``__weak`` object may be properly initialized by filling +it with the representation of a null pointer, e.g. by acquiring the memory +with ``calloc`` or using ``bzero`` to zero it out. A ``__strong`` or +``__weak`` object may be properly deinitialized by assigning a null pointer +into it. A ``__strong`` object may also be properly initialized +by copying into it (e.g. with ``memcpy``) the representation of a +different ``__strong`` object whose storage has been properly initialized; +doing this properly deinitializes the source object and causes its storage +to no longer be properly initialized. A ``__weak`` object may not be +representation-copied in this way. + +These requirements are followed automatically for objects whose +initialization and deinitialization are under the control of ARC: + +* objects of static, automatic, and temporary storage duration +* instance variables of Objective-C objects +* elements of arrays where the array object's initialization and + deinitialization are under the control of ARC +* fields of Objective-C struct types where the struct object's + initialization and deinitialization are under the control of ARC +* non-static data members of Objective-C++ non-union class types +* Objective-C++ objects and arrays of dynamic storage duration created + with the ``new`` or ``new[]`` operators and destroyed with the + corresponding ``delete`` or ``delete[]`` operator + +They are not followed automatically for these objects: + +* objects of dynamic storage duration created in other memory, such as + that returned by ``malloc`` +* union members .. admonition:: Rationale - ARC cannot differentiate between an assignment operator which is intended to - "initialize" dynamic memory and one which is intended to potentially replace - a value. Therefore the object's pointer must be valid before letting ARC at - it. Similarly, C and Objective-C do not provide any language hooks for - destroying objects held in dynamic memory, so it is the programmer's - responsibility to avoid leaks (``__strong`` objects) and consistency errors - (``__weak`` objects). - -These requirements are followed automatically in Objective-C++ when creating -objects of retainable object owner type with ``new`` or ``new[]`` and destroying -them with ``delete``, ``delete[]``, or a pseudo-destructor expression. Note -that arrays of nontrivially-ownership-qualified type are not ABI compatible with -non-ARC code because the element type is non-POD: such arrays that are -``new[]``'d in ARC translation units cannot be ``delete[]``'d in non-ARC -translation units and vice-versa. + ARC must perform special operations when initializing an object and + when destroying it. In many common situations, ARC knows when an + object is created and when it is destroyed and can ensure that these + operations are performed correctly. Otherwise, however, ARC requires + programmer cooperation to establish its initialization invariants + because it is infeasible for ARC to dynamically infer whether they + are intact. For example, there is no syntactic difference in C between + an assignment that is intended by the programmer to initialize a variable + and one that is intended to replace the existing value stored there, + but ARC must perform one operation or the other. ARC chooses to always + assume that objects are initialized (except when it is in charge of + initializing them) because the only workable alternative would be to + ban all code patterns that could potentially be used to access + uninitialized memory, and that would be too limiting. In practice, + this is rarely a problem because programmers do not generally need to + work with objects for which the requirements are not handled + automatically. + +Note that dynamically-allocated Objective-C++ arrays of +nontrivially-ownership-qualified type are not ABI-compatible with non-ARC +code because the non-ARC code will consider the element type to be POD. +Such arrays that are ``new[]``'d in ARC translation units cannot be +``delete[]``'d in non-ARC translation units and vice-versa. .. _arc.ownership.restrictions.pass_by_writeback: -- GitLab From 141ca05e332ab0be507a7325313fe230a9506a7a Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 20 Jul 2018 05:40:12 +0000 Subject: [PATCH 0627/1023] Document -fobjc-weak as an extension. Fixes rdar://24091053. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337525 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LanguageExtensions.rst | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 1d6c7ec5eb..1aef265a85 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -1200,6 +1200,51 @@ Objective-C objects. ``__has_feature(objc_arc_fields)`` indicates that C structs are allowed to have fields that are pointers to Objective-C objects managed by automatic reference counting. +.. _objc-weak: + +Weak references +--------------- + +Clang supports ARC-style weak and unsafe references in Objective-C even +outside of ARC mode. Weak references must be explicitly enabled with +the ``-fobjc-weak`` option; use ``__has_feature((objc_arc_weak))`` +to test whether they are enabled. Unsafe references are enabled +unconditionally. ARC-style weak and unsafe references cannot be used +when Objective-C garbage collection is enabled. + +Except as noted below, the language rules for the ``__weak`` and +``__unsafe_unretained`` qualifiers (and the ``weak`` and +``unsafe_unretained`` property attributes) are just as laid out +in the :doc:`ARC specification `. +In particular, note that some classes do not support forming weak +references to their instances, and note that special care must be +taken when storing weak references in memory where initialization +and deinitialization are outside the responsibility of the compiler +(such as in ``malloc``-ed memory). + +Loading from a ``__weak`` variable always implicitly retains the +loaded value. In non-ARC modes, this retain is normally balanced +by an implicit autorelease. This autorelease can be suppressed +by performing the load in the receiver position of a ``-retain`` +message send (e.g. ``[weakReference retain]``); note that this performs +only a single retain (the retain done when primitively loading from +the weak reference). + +For the most part, ``__unsafe_unretained`` in non-ARC modes is just the +default behavior of variables and therefore is not needed. However, +it does have an effect on the semantics of block captures: normally, +copying a block which captures an Objective-C object or block pointer +causes the captured pointer to be retained or copied, respectively, +but that behavior is suppressed when the captured variable is qualified +with ``__unsafe_unretained``. + +Note that the ``__weak`` qualifier formerly meant the GC qualifier in +all non-ARC modes and was silently ignored outside of GC modes. It now +means the ARC-style qualifier in all non-GC modes and is no longer +allowed if not enabled by either ``-fobjc-arc`` or ``-fobjc-weak``. +It is expected that ``-fobjc-weak`` will eventually be enabled by default +in all non-GC Objective-C modes. + .. _objc-fixed-enum: Enumerations with a fixed underlying type -- GitLab From 3f7d4073a85d7d8be791ca7f018bd109adda0e0f Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Fri, 20 Jul 2018 08:08:56 +0000 Subject: [PATCH 0628/1023] [Index] Set OrigD before D is changed. Reviewers: akyrtzi, arphaman Reviewed By: akyrtzi Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49476 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337529 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Index/IndexingContext.cpp | 6 +++--- test/Index/index-template-specialization.cpp | 19 +++++++++++++++++++ tools/c-index-test/c-index-test.c | 2 ++ tools/libclang/Indexing.cpp | 2 ++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 test/Index/index-template-specialization.cpp diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index 6c09ac7c09..80d851b43d 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -350,6 +350,9 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, } } + if (!OrigD) + OrigD = D; + if (isTemplateImplicitInstantiation(D)) { if (!IsRef) return true; @@ -359,9 +362,6 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, assert(!isTemplateImplicitInstantiation(D)); } - if (!OrigD) - OrigD = D; - if (IsRef) Roles |= (unsigned)SymbolRole::Reference; else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) diff --git a/test/Index/index-template-specialization.cpp b/test/Index/index-template-specialization.cpp new file mode 100644 index 0000000000..d11754113c --- /dev/null +++ b/test/Index/index-template-specialization.cpp @@ -0,0 +1,19 @@ +template +class Foo { +public: + void f(T t) {} +}; + +void g() { + Foo foo; + foo.f(0); +} + +// FIXME: if c-index-test uses OrigD for symbol info, refererences below should +// refer to template specialization decls. +// RUN: env CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS=1 c-index-test -index-file %s | FileCheck %s +// CHECK: [indexDeclaration]: kind: c++-class-template | name: Foo +// CHECK-NEXT: [indexDeclaration]: kind: c++-instance-method | name: f +// CHECK-NEXT: [indexDeclaration]: kind: function | name: g +// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: Foo | USR: c:@ST>1#T@Foo +// CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: f | USR: c:@ST>1#T@Foo@F@f#t0.0# diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index dd1652e32c..70ab11866e 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -3652,6 +3652,8 @@ static unsigned getIndexOptions(void) { index_opts |= CXIndexOpt_IndexFunctionLocalSymbols; if (!getenv("CINDEXTEST_DISABLE_SKIPPARSEDBODIES")) index_opts |= CXIndexOpt_SkipParsedBodiesInSession; + if (getenv("CINDEXTEST_INDEXIMPLICITTEMPLATEINSTANTIATIONS")) + index_opts |= CXIndexOpt_IndexImplicitTemplateInstantiations; return index_opts; } diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 545edfbef4..4da046b282 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -402,6 +402,8 @@ static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) { IndexingOptions IdxOpts; if (index_options & CXIndexOpt_IndexFunctionLocalSymbols) IdxOpts.IndexFunctionLocals = true; + if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations) + IdxOpts.IndexImplicitInstantiation = true; return IdxOpts; } -- GitLab From 1a8f8375fb2268e94c72dbc26c55992702d8ca6c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 20 Jul 2018 08:19:20 +0000 Subject: [PATCH 0629/1023] Change \t to spaces git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337530 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/BuildSystem.h | 2 +- include/clang/Basic/Attr.td | 2 +- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- include/clang/Basic/arm_neon.td | 6 +++--- include/clang/Driver/CC1Options.td | 2 +- include/clang/Frontend/CodeGenOptions.def | 2 +- lib/AST/TypeLoc.cpp | 2 +- lib/CodeGen/CGBuiltin.cpp | 8 ++++---- lib/CodeGen/CodeGenAction.cpp | 2 +- lib/Driver/Distro.cpp | 2 +- lib/Driver/ToolChains/Arch/ARM.cpp | 2 +- lib/Driver/ToolChains/Arch/PPC.h | 2 +- lib/Frontend/CompilerInvocation.cpp | 2 +- lib/Sema/AnalysisBasedWarnings.cpp | 7 ++++--- lib/Sema/SemaChecking.cpp | 2 +- lib/Sema/SemaDeclAttr.cpp | 2 +- lib/Sema/SemaExprCXX.cpp | 8 ++++---- lib/Sema/SemaLambda.cpp | 2 +- lib/Sema/SemaLookup.cpp | 2 +- lib/Sema/SemaTemplateVariadic.cpp | 10 +++++----- lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp | 2 +- .../Checkers/CheckSecuritySyntaxOnly.cpp | 2 +- 22 files changed, 38 insertions(+), 37 deletions(-) diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h index c999dab36d..3cfec38830 100644 --- a/include/clang-c/BuildSystem.h +++ b/include/clang-c/BuildSystem.h @@ -66,7 +66,7 @@ clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay, */ CINDEX_LINKAGE enum CXErrorCode clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay, - int caseSensitive); + int caseSensitive); /** * Write out the \c CXVirtualFileOverlay object to a char buffer. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 36c980029c..b36cb9c312 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1932,7 +1932,7 @@ def Target : InheritableAttr { // overall feature validity for the function with the rest of the // attributes on the function. if (Feature.startswith("fpmath=") || Feature.startswith("tune=")) - continue; + continue; // While we're here iterating check for a different target cpu. if (Feature.startswith("arch=")) { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f623bd3773..f2c82568ec 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -9102,9 +9102,9 @@ def note_equivalent_internal_linkage_decl : Note< "declared here%select{ in module '%1'|}0">; def note_redefinition_modules_same_file : Note< - "'%0' included multiple times, additional include site in header from module '%1'">; + "'%0' included multiple times, additional include site in header from module '%1'">; def note_redefinition_include_same_file : Note< - "'%0' included multiple times, additional include site here">; + "'%0' included multiple times, additional include site here">; } let CategoryName = "Coroutines Issue" in { diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index ed0bad5bee..f7c8ea5281 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -1438,12 +1438,12 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { // Comparison let InstName = "vacge" in { - def VCAGEH : SInst<"vcage", "udd", "hQh">; - def VCALEH : SInst<"vcale", "udd", "hQh">; + def VCAGEH : SInst<"vcage", "udd", "hQh">; + def VCALEH : SInst<"vcale", "udd", "hQh">; } let InstName = "vacgt" in { def VCAGTH : SInst<"vcagt", "udd", "hQh">; - def VCALTH : SInst<"vcalt", "udd", "hQh">; + def VCALTH : SInst<"vcalt", "udd", "hQh">; } def VCEQH : SOpInst<"vceq", "udd", "hQh", OP_EQ>; def VCGEH : SOpInst<"vcge", "udd", "hQh", OP_GE>; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 9f5a64b8a9..7cb9724a57 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -37,7 +37,7 @@ def mfpmath : Separate<["-"], "mfpmath">, HelpText<"Which unit to use for fp math">; def fpadding_on_unsigned_fixed_point : Flag<["-"], "fpadding-on-unsigned-fixed-point">, - HelpText<"Force each unsigned fixed point type to have an extra bit of padding to align their scales with those of signed fixed point types">; + HelpText<"Force each unsigned fixed point type to have an extra bit of padding to align their scales with those of signed fixed point types">; def fno_padding_on_unsigned_fixed_point : Flag<["-"], "fno-padding-on-unsigned-fixed-point">; //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 2ed96d4327..a7e71f7ac0 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -252,7 +252,7 @@ CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the ///< skeleton CU to allow for symbolication - ///< of inline stack frames without .dwo files. + ///< of inline stack frames without .dwo files. CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete ///< template parameter descriptions in ///< forward declarations (versus just diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 2bf560305a..6fa76e14a5 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -254,7 +254,7 @@ SourceLocation TypeLoc::getEndLoc() const { case RValueReference: case PackExpansion: if (!Last) - Last = Cur; + Last = Cur; break; case Qualified: case Elaborated: diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 07cb1c3adf..a256eb1bf0 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -7567,14 +7567,14 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vcvt_u32_v: case NEON::BI__builtin_neon_vcvt_s64_v: case NEON::BI__builtin_neon_vcvt_u64_v: - case NEON::BI__builtin_neon_vcvt_s16_v: - case NEON::BI__builtin_neon_vcvt_u16_v: + case NEON::BI__builtin_neon_vcvt_s16_v: + case NEON::BI__builtin_neon_vcvt_u16_v: case NEON::BI__builtin_neon_vcvtq_s32_v: case NEON::BI__builtin_neon_vcvtq_u32_v: case NEON::BI__builtin_neon_vcvtq_s64_v: case NEON::BI__builtin_neon_vcvtq_u64_v: - case NEON::BI__builtin_neon_vcvtq_s16_v: - case NEON::BI__builtin_neon_vcvtq_u16_v: { + case NEON::BI__builtin_neon_vcvtq_s16_v: + case NEON::BI__builtin_neon_vcvtq_u16_v: { Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type)); if (usgn) return Builder.CreateFPToUI(Ops[0], Ty); diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index 9b9f562f85..7ca55070d4 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -241,7 +241,7 @@ namespace clang { LLVMIRGeneration.stopTimer(); } - IRGenFinished = true; + IRGenFinished = true; } // Silently ignore if we weren't initialized for some reason. diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp index 3fbf1637dd..2c4d44faf8 100644 --- a/lib/Driver/Distro.cpp +++ b/lib/Driver/Distro.cpp @@ -24,7 +24,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) { StringRef Data = File.get()->getBuffer(); SmallVector Lines; Data.split(Lines, "\n"); - Distro::DistroType Version = Distro::UnknownDistro; + Distro::DistroType Version = Distro::UnknownDistro; for (StringRef Line : Lines) if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME=")) Version = llvm::StringSwitch(Line.substr(17)) diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index 44f35a95dc..bb1685de76 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -448,7 +448,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC, if (B->getOption().matches(options::OPT_mlong_calls)) D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); } - Features.push_back("+execute-only"); + Features.push_back("+execute-only"); } } } diff --git a/lib/Driver/ToolChains/Arch/PPC.h b/lib/Driver/ToolChains/Arch/PPC.h index 7eb675cdd1..3acee91a2a 100644 --- a/lib/Driver/ToolChains/Arch/PPC.h +++ b/lib/Driver/ToolChains/Arch/PPC.h @@ -39,7 +39,7 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getPPCTargetCPU(const llvm::opt::ArgList &Args); const char *getPPCAsmModeForCPU(StringRef Name); ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, - const llvm::opt::ArgList &Args); + const llvm::opt::ArgList &Args); void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9bb673d1e7..a494b27a39 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -808,7 +808,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } } - // Handle -fembed-bitcode option. + // Handle -fembed-bitcode option. if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) { StringRef Name = A->getValue(); unsigned Model = llvm::StringSwitch(Name) diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 5ea2979900..8938c34157 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -417,9 +417,10 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { CFGBlock::FilterOptions FO; FO.IgnoreDefaultsWithCoveredEnums = 1; - for (CFGBlock::filtered_pred_iterator - I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { - const CFGBlock& B = **I; + for (CFGBlock::filtered_pred_iterator I = + cfg->getExit().filtered_pred_start_end(FO); + I.hasMore(); ++I) { + const CFGBlock &B = **I; if (!live[B.getBlockID()]) continue; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index df1c60969f..1e72083f3c 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -237,7 +237,7 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { } static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, - CallExpr *TheCall, unsigned SizeIdx, + CallExpr *TheCall, unsigned SizeIdx, unsigned DstSizeIdx) { if (TheCall->getNumArgs() <= SizeIdx || TheCall->getNumArgs() <= DstSizeIdx) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index f549aa0468..55fb21af0d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6654,7 +6654,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, VD->getType(), VD->getTypeSourceInfo(), VD->getStorageClass()); if (VD->getQualifier()) - cast(NewD)->setQualifierInfo(VD->getQualifierLoc()); + cast(NewD)->setQualifierInfo(VD->getQualifierLoc()); } return NewD; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a7ad8e322d..30876c09a9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1660,9 +1660,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { if (getLangOpts().CPlusPlus14) { - // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator - // shall be a converted constant expression (5.19) of type std::size_t - // and shall evaluate to a strictly positive value. + // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator + // shall be a converted constant expression (5.19) of type std::size_t + // and shall evaluate to a strictly positive value. unsigned IntWidth = Context.getTargetInfo().getIntWidth(); assert(IntWidth && "Builtin type of size 0?"); llvm::APSInt Value(IntWidth); @@ -1893,7 +1893,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?"); ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(), - AA_Converting); + AA_Converting); if (!ConvertedSize.isInvalid() && ArraySize->getType()->getAs()) diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 04d9e55bc6..a42b2e827e 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1565,7 +1565,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); if (!NonODRUsedInitCapture) { bool IsLast = (I + 1) == LSI->NumExplicitCaptures; - SourceRange FixItRange; + SourceRange FixItRange; if (CaptureRange.isValid()) { if (!CurHasPreviousCapture && !IsLast) { // If there are no captures preceding this capture, remove the diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 4545bf9d85..2732112c00 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2318,7 +2318,7 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { CXXRecordDecl *RD = cast( BaseSpec.getType()->castAs()->getDecl()); LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind()); - Result.setBaseObjectType(Context.getRecordType(Class)); + Result.setBaseObjectType(Context.getRecordType(Class)); LookupQualifiedName(Result, RD); // Copy the lookup results into the target, merging the base's access into diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 9dfdd0555f..8f7a75a165 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -919,8 +919,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { if (Chunk.Fun.hasTrailingReturnType()) { QualType T = Chunk.Fun.getTrailingReturnType().get(); - if (!T.isNull() && T->containsUnexpandedParameterPack()) - return true; + if (!T.isNull() && T->containsUnexpandedParameterPack()) + return true; } break; @@ -931,7 +931,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { break; } } - + return false; } @@ -993,12 +993,12 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: break; - + case LookupResult::Ambiguous: DiagnoseAmbiguousLookup(R); return ExprError(); } - + if (!ParameterPack || !ParameterPack->isParameterPack()) { Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) << &Name; diff --git a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp index 633e9724b6..6654e822e1 100644 --- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp @@ -153,7 +153,7 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { if (LenArgDecl) { const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl()); if (LenArgVal->getInit()) - LenArg = LenArgVal->getInit(); + LenArg = LenArgVal->getInit(); } // - integral value diff --git a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp index 15a13d8ac9..202233acff 100644 --- a/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp +++ b/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp @@ -388,7 +388,7 @@ void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) { "Use of deprecated function in call to 'bcopy()'", "Security", "The bcopy() function is obsoleted by memcpy() " - "or memmove().", + "or memmove().", CELoc, CE->getCallee()->getSourceRange()); } -- GitLab From 0bb7730cf5a4fff5ff9caad7d38bc7ca193aa9c4 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Fri, 20 Jul 2018 11:32:51 +0000 Subject: [PATCH 0630/1023] Sema: Fix explicit address space cast in C++ Currently clang does not allow implicit cast of a pointer to a pointer type in different address space but allows C-style cast of a pointer to a pointer type in different address space. However, there is a bug in Sema causing incorrect Cast Expr in AST for the latter case, which in turn results in invalid LLVM IR in codegen. This is because Sema::IsQualificationConversion returns true for a cast of pointer to a pointer type in different address space, which in turn allows a standard conversion and results in a cast expression with no op in AST. This patch fixes that by let Sema::IsQualificationConversion returns false for a cast of pointer to a pointer type in different address space, which in turn disallows standard conversion, implicit cast, and static cast. Finally it results in an reinterpret cast and correct conversion kind is set. Differential Revision: https://reviews.llvm.org/D49294 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337540 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCast.cpp | 8 ++++++++ lib/Sema/SemaOverload.cpp | 9 +++++++++ test/CodeGenCXX/address-space-cast.cpp | 15 +++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 test/CodeGenCXX/address-space-cast.cpp diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 86633d6dd5..b3f6be4aec 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1955,6 +1955,12 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType, return Result.isUsable(); } +static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) { + return SrcType->isPointerType() && DestType->isPointerType() && + SrcType->getAs()->getPointeeType().getAddressSpace() != + DestType->getAs()->getPointeeType().getAddressSpace(); +} + static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, SourceRange OpRange, @@ -2198,6 +2204,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, } else { Kind = CK_BitCast; } + } else if (IsAddressSpaceConversion(SrcType, DestType)) { + Kind = CK_AddressSpaceConversion; } else { Kind = CK_BitCast; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 822c3c0c6b..390782b35e 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3150,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, = PreviousToQualsIncludeConst && ToQuals.hasConst(); } + // Allows address space promotion by language rules implemented in + // Type::Qualifiers::isAddressSpaceSupersetOf. + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) && + !FromQuals.isAddressSpaceSupersetOf(ToQuals)) { + return false; + } + // We are left with FromType and ToType being the pointee types // after unwrapping the original FromType and ToType the same number // of types. If we unwrapped any pointers, and if FromType and diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp new file mode 100644 index 0000000000..334a1a63e6 --- /dev/null +++ b/test/CodeGenCXX/address-space-cast.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s + +#define __private__ __attribute__((address_space(5))) + +void func_pchar(__private__ char *x); + +void test_cast(char *gen_ptr) { + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + __private__ char *priv_ptr = (__private__ char *)gen_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]]) + func_pchar((__private__ char *)gen_ptr); +} -- GitLab From 9eb2866868720b509babc97c7ab8b1000ed85426 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 20 Jul 2018 14:13:28 +0000 Subject: [PATCH 0631/1023] Implement cpu_dispatch/cpu_specific Multiversioning As documented here: https://software.intel.com/en-us/node/682969 and https://software.intel.com/en-us/node/523346. cpu_dispatch multiversioning is an ICC feature that provides for function multiversioning. This feature is implemented with two attributes: First, cpu_specific, which specifies the individual function versions. Second, cpu_dispatch, which specifies the location of the resolver function and the list of resolvable functions. This is valuable since it provides a mechanism where the resolver's TU can be specified in one location, and the individual implementions each in their own translation units. The goal of this patch is to be source-compatible with ICC, so this implementation diverges from the ICC implementation in a few ways: 1- Linux x86/64 only: This implementation uses ifuncs in order to properly dispatch functions. This is is a valuable performance benefit over the ICC implementation. A future patch will be provided to enable this feature on Windows, but it will obviously more closely fit ICC's implementation. 2- CPU Identification functions: ICC uses a set of custom functions to identify the feature list of the host processor. This patch uses the cpu_supports functionality in order to better align with 'target' multiversioning. 1- cpu_dispatch function def/decl: ICC's cpu_dispatch requires that the function marked cpu_dispatch be an empty definition. This patch supports that as well, however declarations are also permitted, since the linker will solve the issue of multiple emissions. Differential Revision: https://reviews.llvm.org/D47474 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337552 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 7 + include/clang/Basic/Attr.td | 22 + include/clang/Basic/AttrDocs.td | 59 +++ include/clang/Basic/DiagnosticGroups.td | 4 + include/clang/Basic/DiagnosticSemaKinds.td | 35 +- include/clang/Basic/TargetInfo.h | 21 + include/clang/Basic/X86Target.def | 47 ++ lib/AST/Decl.cpp | 8 + lib/Basic/Targets/X86.cpp | 32 ++ lib/Basic/Targets/X86.h | 8 + lib/CodeGen/CGBuiltin.cpp | 12 +- lib/CodeGen/CodeGenFunction.cpp | 52 +- lib/CodeGen/CodeGenFunction.h | 35 +- lib/CodeGen/CodeGenModule.cpp | 170 +++++-- lib/CodeGen/CodeGenModule.h | 9 +- lib/Parse/ParseDecl.cpp | 42 +- lib/Sema/AnalysisBasedWarnings.cpp | 5 + lib/Sema/Sema.cpp | 46 +- lib/Sema/SemaDecl.cpp | 451 +++++++++++++----- lib/Sema/SemaDeclAttr.cpp | 48 ++ lib/Sema/SemaExpr.cpp | 15 +- lib/Sema/SemaOverload.cpp | 61 ++- test/CodeGen/attr-cpuspecific.c | 101 ++++ ...a-attribute-supported-attributes-list.test | 4 +- test/Sema/attr-cpuspecific.c | 96 ++++ test/SemaCXX/attr-cpuspecific.cpp | 111 +++++ utils/TableGen/ClangAttrEmitter.cpp | 38 ++ 27 files changed, 1317 insertions(+), 222 deletions(-) create mode 100644 test/CodeGen/attr-cpuspecific.c create mode 100644 test/Sema/attr-cpuspecific.c create mode 100644 test/SemaCXX/attr-cpuspecific.cpp diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a0986085a1..4e19434b16 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2209,6 +2209,13 @@ public: getCanonicalDecl()->IsMultiVersion = V; } + /// True if this function is a multiversioned dispatch function as a part of + /// the cpu_specific/cpu_dispatch functionality. + bool isCPUDispatchMultiVersion() const; + /// True if this function is a multiversioned processor specific function as a + /// part of the cpu_specific/cpu_dispatch functionality. + bool isCPUSpecificMultiVersion() const; + void setPreviousDeclaration(FunctionDecl * PrevDecl); FunctionDecl *getCanonicalDecl() override; diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index b36cb9c312..47da0896ce 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -168,6 +168,7 @@ class UnsignedArgument : Argument; class VariadicUnsignedArgument : Argument; class VariadicExprArgument : Argument; class VariadicStringArgument : Argument; +class VariadicIdentifierArgument : Argument; // Like VariadicUnsignedArgument except values are ParamIdx. class VariadicParamIdxArgument : Argument; @@ -845,6 +846,27 @@ def Constructor : InheritableAttr { let Documentation = [Undocumented]; } +def CPUSpecific : InheritableAttr { + let Spellings = [Clang<"cpu_specific">]; + let Args = [VariadicIdentifierArgument<"Cpus">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [CPUSpecificCPUDispatchDocs]; + let AdditionalMembers = [{ + unsigned ActiveArgIndex = 0; + + IdentifierInfo *getCurCPUName() const { + return *(cpus_begin() + ActiveArgIndex); + } + }]; +} + +def CPUDispatch : InheritableAttr { + let Spellings = [Clang<"cpu_dispatch">]; + let Args = [VariadicIdentifierArgument<"Cpus">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [CPUSpecificCPUDispatchDocs]; +} + // CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__), // and they do not receive a [[]] spelling. def CUDAConstant : InheritableAttr { diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index ecaf95a933..61e7682059 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -191,6 +191,65 @@ in generation of more efficient code. }]; } +def CPUSpecificCPUDispatchDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + }]; +} + def C11NoReturnDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 40dfbe5f7a..ab0a556713 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -1022,3 +1022,7 @@ def SpirCompat : DiagGroup<"spir-compat">; // Warning for the experimental-isel options. def ExperimentalISel : DiagGroup<"experimental-isel">; + +// A warning group specifically for warnings related to function +// multiversioning. +def FunctionMultiVersioning : DiagGroup<"function-multiversion">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f2c82568ec..5ae749fa93 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -608,6 +608,8 @@ def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">; def err_arm_invalid_specialreg : Error<"invalid special register for builtin">; def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">; def err_invalid_cpu_is : Error<"invalid cpu name for builtin">; +def err_invalid_cpu_specific_dispatch_value : Error< +"invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">; def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error<"always_inline function %1 requires target feature '%2', but would " @@ -3788,8 +3790,8 @@ def err_ovl_no_viable_subscript : def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; def err_ovl_unresolvable : Error< - "reference to overloaded function could not be resolved; " - "did you mean to call it%select{| with no arguments}0?">; + "reference to %select{overloaded|multiversioned}1 function could not be " + "resolved; did you mean to call it%select{| with no arguments}0?">; def err_bound_member_function : Error< "reference to non-static member function must be called" "%select{|; did you mean to call it with no arguments?}0">; @@ -9355,9 +9357,9 @@ def warn_shadow_field : InGroup, DefaultIgnore; def note_shadow_field : Note<"declared here">; -def err_target_required_in_redecl : Error< - "function declaration is missing 'target' attribute in a multiversioned " - "function">; +def err_multiversion_required_in_redecl : Error< + "function declaration is missing %select{'target'|'cpu_specific' or " + "'cpu_dispatch'}0 attribute in a multiversioned function">; def note_multiversioning_caused_here : Note< "function multiversioning caused by this declaration">; def err_multiversion_after_used : Error< @@ -9371,20 +9373,33 @@ def err_multiversion_duplicate : Error< def err_multiversion_noproto : Error< "multiversioned function must have a prototype">; def err_multiversion_no_other_attrs : Error< - "attribute 'target' multiversioning cannot be combined with other " - "attributes">; + "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" + " with other attributes">; def err_multiversion_diff : Error< "multiversioned function declaration has a different %select{calling convention" "|return type|constexpr specification|inline specification|storage class|" "linkage}0">; def err_multiversion_doesnt_support : Error< - "multiversioned functions do not yet support %select{function templates|" - "virtual functions|deduced return types|constructors|destructors|" - "deleted functions|defaulted functions}0">; + "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not " + "yet support %select{function templates|virtual functions|" + "deduced return types|constructors|destructors|deleted functions|" + "defaulted functions|constexpr functions}1">; def err_multiversion_not_allowed_on_main : Error< "'main' cannot be a multiversioned function">; def err_multiversion_not_supported : Error< "function multiversioning is not supported on the current target">; +def err_multiversion_types_mixed : Error< + "multiversioning attributes cannot be combined">; +def err_cpu_dispatch_mismatch : Error< + "'cpu_dispatch' function redeclared with different CPUs">; +def err_cpu_specific_multiple_defs : Error< + "multiple 'cpu_specific' functions cannot specify the same CPU: %0">; +def warn_multiversion_duplicate_entries : Warning< + "CPU list contains duplicate entries; attribute ignored">, + InGroup; +def warn_dispatch_body_ignored : Warning< + "body of cpu_dispatch function will be ignored">, + InGroup; // three-way comparison operator diagnostics def err_implied_comparison_category_type_not_found : Error< diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index fd9e2e03fa..ee97f2b8f6 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -1092,6 +1092,27 @@ public: // argument. virtual bool validateCpuIs(StringRef Name) const { return false; } + // Validate a cpu_dispatch/cpu_specific CPU option, which is a different list + // from cpu_is, since it checks via features rather than CPUs directly. + virtual bool validateCPUSpecificCPUDispatch(StringRef Name) const { + return false; + } + + // Get the character to be added for mangling purposes for cpu_specific. + virtual char CPUSpecificManglingCharacter(StringRef Name) const { + llvm_unreachable( + "cpu_specific Multiversioning not implemented on this target"); + } + + // Get a list of the features that make up the CPU option for + // cpu_specific/cpu_dispatch so that it can be passed to llvm as optimization + // options. + virtual void getCPUSpecificCPUDispatchFeatures( + StringRef Name, llvm::SmallVectorImpl &Features) const { + llvm_unreachable( + "cpu_specific Multiversioning not implemented on this target"); + } + // Returns maximal number of args passed in registers. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); diff --git a/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def index 862d3009c8..d2d2540e50 100644 --- a/include/clang/Basic/X86Target.def +++ b/include/clang/Basic/X86Target.def @@ -29,6 +29,14 @@ #define FEATURE(ENUM) #endif +#ifndef CPU_SPECIFIC +#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) +#endif + +#ifndef CPU_SPECIFIC_ALIAS +#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) +#endif + #define PROC_64_BIT true #define PROC_32_BIT false @@ -276,6 +284,45 @@ FEATURE(FEATURE_AVX5124VNNIW) FEATURE(FEATURE_AVX5124FMAPS) FEATURE(FEATURE_AVX512VPOPCNTDQ) + +// FIXME: When commented out features are supported in LLVM, enable them here. +CPU_SPECIFIC("generic", 'A', "") +CPU_SPECIFIC("pentium", 'B', "") +CPU_SPECIFIC("pentium_pro", 'C', "+cmov") +CPU_SPECIFIC("pentium_mmx", 'D', "+mmx") +CPU_SPECIFIC("pentium_ii", 'E', "+cmov,+mmx") +CPU_SPECIFIC("pentium_iii", 'H', "+cmov,+mmx,+sse") +CPU_SPECIFIC("pentium_iii_no_xmm_regs", 'H',"+cmov,+sse") +CPU_SPECIFIC("pentium_4", 'J', "+cmov,+mmx,+sse,+sse2") +CPU_SPECIFIC("pentium_m", 'K', "+cmov,+mmx,+sse,+sse2") +CPU_SPECIFIC("pentium_4_sse3", 'L', "+cmov,+mmx,+sse,+sse2,+sse3") +CPU_SPECIFIC("core_2_duo_ssse3", 'M', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3") +CPU_SPECIFIC("core_2_duo_sse4_1", 'N', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1") +CPU_SPECIFIC("atom", 'O', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+movbe") +CPU_SPECIFIC("atom_sse4_2", 'c', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("core_i7_sse4_2", 'P', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("core_aes_pclmulqdq", 'Q', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("atom_sse4_2_movbe", 'd', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt") +CPU_SPECIFIC("goldmont", 'i', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt") +CPU_SPECIFIC("sandybridge", 'R', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+avx") +CPU_SPECIFIC_ALIAS("core_2nd_gen_avx", "sandybridge") +CPU_SPECIFIC("ivybridge", 'S', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+f16c,+avx") +CPU_SPECIFIC_ALIAS("core_3rd_gen_avx", "ivybridge") +CPU_SPECIFIC("haswell", 'V', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2") +CPU_SPECIFIC_ALIAS("core_4th_gen_avx", "haswell") +CPU_SPECIFIC("core_4th_gen_avx_tsx", 'W', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2") +CPU_SPECIFIC("broadwell", 'X', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx") +CPU_SPECIFIC_ALIAS("core_5th_gen_avx", "broadwell") +CPU_SPECIFIC("core_5th_gen_avx_tsx", 'Y', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx") +CPU_SPECIFIC("knl", 'Z', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd") +CPU_SPECIFIC_ALIAS("mic_avx512", "knl") +CPU_SPECIFIC("skylake", 'b', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx,+mpx") +CPU_SPECIFIC( "skylake_avx512", 'a', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512cd,+avx512bw,+avx512vl,+clwb") +CPU_SPECIFIC("cannonlake", 'e', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512ifma,+avx512cd,+avx512bw,+avx512vl,+avx512vbmi") +CPU_SPECIFIC("knm", 'j', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd,+avx5124fmaps,+avx5124vnniw,+avx512vpopcntdq") + +#undef CPU_SPECIFIC_ALIAS +#undef CPU_SPECIFIC #undef PROC_64_BIT #undef PROC_32_BIT #undef FEATURE diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7db105eded..a23499f3fe 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2873,6 +2873,14 @@ bool FunctionDecl::isNoReturn() const { return false; } +bool FunctionDecl::isCPUDispatchMultiVersion() const { + return isMultiVersion() && hasAttr(); +} + +bool FunctionDecl::isCPUSpecificMultiVersion() const { + return isMultiVersion() && hasAttr(); +} + void FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { redeclarable_base::setPreviousDecl(PrevDecl); diff --git a/lib/Basic/Targets/X86.cpp b/lib/Basic/Targets/X86.cpp index 43fbdc0329..7ae0696ce7 100644 --- a/lib/Basic/Targets/X86.cpp +++ b/lib/Basic/Targets/X86.cpp @@ -1484,6 +1484,38 @@ unsigned X86TargetInfo::multiVersionSortPriority(StringRef Name) const { return getFeaturePriority(getFeature(Name)) << 1; } +bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const { + return llvm::StringSwitch(Name) +#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, true) +#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, true) +#include "clang/Basic/X86Target.def" + .Default(false); +} + +static StringRef CPUSpecificCPUDispatchNameDealias(StringRef Name) { + return llvm::StringSwitch(Name) +#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) .Case(NEW_NAME, NAME) +#include "clang/Basic/X86Target.def" + .Default(Name); +} + +char X86TargetInfo::CPUSpecificManglingCharacter(StringRef Name) const { + return llvm::StringSwitch(CPUSpecificCPUDispatchNameDealias(Name)) +#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, MANGLING) +#include "clang/Basic/X86Target.def" + .Default(0); +} + +void X86TargetInfo::getCPUSpecificCPUDispatchFeatures( + StringRef Name, llvm::SmallVectorImpl &Features) const { + StringRef WholeList = + llvm::StringSwitch(CPUSpecificCPUDispatchNameDealias(Name)) +#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) .Case(NAME, FEATURES) +#include "clang/Basic/X86Target.def" + .Default(""); + WholeList.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false); +} + std::string X86TargetInfo::getCPUKindCanonicalName(CPUKind Kind) const { switch (Kind) { case CK_Generic: diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h index 5b862face9..dd04dee087 100644 --- a/lib/Basic/Targets/X86.h +++ b/lib/Basic/Targets/X86.h @@ -150,6 +150,14 @@ public: bool validateCpuIs(StringRef Name) const override; + bool validateCPUSpecificCPUDispatch(StringRef Name) const override; + + char CPUSpecificManglingCharacter(StringRef Name) const override; + + void getCPUSpecificCPUDispatchFeatures( + StringRef Name, + llvm::SmallVectorImpl &Features) const override; + bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &info) const override; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a256eb1bf0..b6d30a956d 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -8904,11 +8904,10 @@ Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) { return EmitX86CpuSupports(FeatureStr); } -Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef FeatureStrs) { +uint32_t +CodeGenFunction::GetX86CpuSupportsMask(ArrayRef FeatureStrs) { // Processor features and mapping to processor feature value. - uint32_t FeaturesMask = 0; - for (const StringRef &FeatureStr : FeatureStrs) { unsigned Feature = StringSwitch(FeatureStr) @@ -8917,7 +8916,14 @@ Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef FeatureStrs) { ; FeaturesMask |= (1U << Feature); } + return FeaturesMask; +} + +Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef FeatureStrs) { + return EmitX86CpuSupports(GetX86CpuSupportsMask(FeatureStrs)); +} +llvm::Value *CodeGenFunction::EmitX86CpuSupports(uint32_t FeaturesMask) { // Matching the struct layout from the compiler-rt/libgcc structure that is // filled in: // unsigned int __cpu_vendor; diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 99af1a18e8..3c582688e9 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -2323,7 +2323,8 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E, << TargetDecl->getDeclName() << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); - } else if (TargetDecl->hasAttr()) { + } else if (TargetDecl->hasAttr() || + TargetDecl->hasAttr()) { // Get the required features for the callee. const TargetAttr *TD = TargetDecl->getAttr(); @@ -2358,8 +2359,8 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) { CGM.getSanStats().create(IRB, SSK); } -llvm::Value * -CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) { +llvm::Value *CodeGenFunction::FormResolverCondition( + const TargetMultiVersionResolverOption &RO) { llvm::Value *TrueCondition = nullptr; if (!RO.ParsedAttribute.Architecture.empty()) TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture); @@ -2377,8 +2378,9 @@ CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) { return TrueCondition; } -void CodeGenFunction::EmitMultiVersionResolver( - llvm::Function *Resolver, ArrayRef Options) { +void CodeGenFunction::EmitTargetMultiVersionResolver( + llvm::Function *Resolver, + ArrayRef Options) { assert((getContext().getTargetInfo().getTriple().getArch() == llvm::Triple::x86 || getContext().getTargetInfo().getTriple().getArch() == @@ -2391,7 +2393,7 @@ void CodeGenFunction::EmitMultiVersionResolver( EmitX86CpuInit(); llvm::Function *DefaultFunc = nullptr; - for (const MultiVersionResolverOption &RO : Options) { + for (const TargetMultiVersionResolverOption &RO : Options) { Builder.SetInsertPoint(CurBlock); llvm::Value *TrueCondition = FormResolverCondition(RO); @@ -2412,6 +2414,44 @@ void CodeGenFunction::EmitMultiVersionResolver( Builder.CreateRet(DefaultFunc); } +void CodeGenFunction::EmitCPUDispatchMultiVersionResolver( + llvm::Function *Resolver, + ArrayRef Options) { + assert((getContext().getTargetInfo().getTriple().getArch() == + llvm::Triple::x86 || + getContext().getTargetInfo().getTriple().getArch() == + llvm::Triple::x86_64) && + "Only implemented for x86 targets"); + + // Main function's basic block. + llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver); + Builder.SetInsertPoint(CurBlock); + EmitX86CpuInit(); + + for (const CPUDispatchMultiVersionResolverOption &RO : Options) { + Builder.SetInsertPoint(CurBlock); + + // "generic" case should catch-all. + if (RO.FeatureMask == 0) { + Builder.CreateRet(RO.Function); + return; + } + llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver); + llvm::IRBuilder<> RetBuilder(RetBlock); + RetBuilder.CreateRet(RO.Function); + CurBlock = createBasicBlock("resolver_else", Resolver); + llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask); + Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock); + } + + Builder.SetInsertPoint(CurBlock); + llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); + TrapCall->setDoesNotReturn(); + TrapCall->setDoesNotThrow(); + Builder.CreateUnreachable(); + Builder.ClearInsertionPoint(); +} + llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) { if (CGDebugInfo *DI = getDebugInfo()) return DI->SourceLocToDebugLoc(Location); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d6deb65582..1fc445c66d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -4113,12 +4113,13 @@ public: void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK); - struct MultiVersionResolverOption { + struct TargetMultiVersionResolverOption { llvm::Function *Function; TargetAttr::ParsedTargetAttr ParsedAttribute; unsigned Priority; - MultiVersionResolverOption(const TargetInfo &TargInfo, llvm::Function *F, - const clang::TargetAttr::ParsedTargetAttr &PT) + TargetMultiVersionResolverOption( + const TargetInfo &TargInfo, llvm::Function *F, + const clang::TargetAttr::ParsedTargetAttr &PT) : Function(F), ParsedAttribute(PT), Priority(0u) { for (StringRef Feat : PT.Features) Priority = std::max(Priority, @@ -4129,12 +4130,30 @@ public: TargInfo.multiVersionSortPriority(PT.Architecture)); } - bool operator>(const MultiVersionResolverOption &Other) const { + bool operator>(const TargetMultiVersionResolverOption &Other) const { return Priority > Other.Priority; } }; - void EmitMultiVersionResolver(llvm::Function *Resolver, - ArrayRef Options); + void EmitTargetMultiVersionResolver( + llvm::Function *Resolver, + ArrayRef Options); + + struct CPUDispatchMultiVersionResolverOption { + llvm::Function *Function; + // Note: EmitX86CPUSupports only has 32 bits available, so we store the mask + // as 32 bits here. When 64-bit support is added to __builtin_cpu_supports, + // this can be extended to 64 bits. + uint32_t FeatureMask; + CPUDispatchMultiVersionResolverOption(llvm::Function *F, uint64_t Mask) + : Function(F), FeatureMask(static_cast(Mask)) {} + bool operator>(const CPUDispatchMultiVersionResolverOption &Other) const { + return FeatureMask > Other.FeatureMask; + } + }; + void EmitCPUDispatchMultiVersionResolver( + llvm::Function *Resolver, + ArrayRef Options); + static uint32_t GetX86CpuSupportsMask(ArrayRef FeatureStrs); private: QualType getVarArgType(const Expr *Arg); @@ -4151,8 +4170,10 @@ private: llvm::Value *EmitX86CpuIs(StringRef CPUStr); llvm::Value *EmitX86CpuSupports(const CallExpr *E); llvm::Value *EmitX86CpuSupports(ArrayRef FeatureStrs); + llvm::Value *EmitX86CpuSupports(uint32_t Mask); llvm::Value *EmitX86CpuInit(); - llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO); + llvm::Value * + FormResolverCondition(const TargetMultiVersionResolverOption &RO); }; /// Helper class with most of the code for saving a value for a diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6886870888..627a33d8b5 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -861,22 +861,38 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const { GV->setThreadLocalMode(TLM); } +static std::string getCPUSpecificMangling(const CodeGenModule &CGM, + StringRef Name) { + const TargetInfo &Target = CGM.getTarget(); + return (Twine('.') + Twine(Target.CPUSpecificManglingCharacter(Name))).str(); +} + +static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, + const CPUSpecificAttr *Attr, + raw_ostream &Out) { + // cpu_specific gets the current name, dispatch gets the resolver. + if (Attr) + Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName()); + else + Out << ".resolver"; +} + static void AppendTargetMangling(const CodeGenModule &CGM, const TargetAttr *Attr, raw_ostream &Out) { if (Attr->isDefaultVersion()) return; Out << '.'; - const auto &Target = CGM.getTarget(); + const TargetInfo &Target = CGM.getTarget(); TargetAttr::ParsedTargetAttr Info = Attr->parse([&Target](StringRef LHS, StringRef RHS) { - // Multiversioning doesn't allow "no-${feature}", so we can - // only have "+" prefixes here. - assert(LHS.startswith("+") && RHS.startswith("+") && - "Features should always have a prefix."); - return Target.multiVersionSortPriority(LHS.substr(1)) > - Target.multiVersionSortPriority(RHS.substr(1)); - }); + // Multiversioning doesn't allow "no-${feature}", so we can + // only have "+" prefixes here. + assert(LHS.startswith("+") && RHS.startswith("+") && + "Features should always have a prefix."); + return Target.multiVersionSortPriority(LHS.substr(1)) > + Target.multiVersionSortPriority(RHS.substr(1)); + }); bool IsFirst = true; @@ -895,7 +911,7 @@ static void AppendTargetMangling(const CodeGenModule &CGM, static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, - bool OmitTargetMangling = false) { + bool OmitMultiVersionMangling = false) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); MangleContext &MC = CGM.getCXXABI().getMangleContext(); @@ -922,8 +938,14 @@ static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, } if (const auto *FD = dyn_cast(ND)) - if (FD->isMultiVersion() && !OmitTargetMangling) - AppendTargetMangling(CGM, FD->getAttr(), Out); + if (FD->isMultiVersion() && !OmitMultiVersionMangling) { + if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()) + AppendCPUSpecificCPUDispatchMangling( + CGM, FD->getAttr(), Out); + else + AppendTargetMangling(CGM, FD->getAttr(), Out); + } + return Out.str(); } @@ -936,7 +958,7 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD, // allows us to lookup the version that was emitted when this wasn't a // multiversion function. std::string NonTargetName = - getMangledNameImpl(*this, GD, FD, /*OmitTargetMangling=*/true); + getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); GlobalDecl OtherGD; if (lookupRepresentativeDecl(NonTargetName, OtherGD)) { assert(OtherGD.getCanonicalDecl() @@ -979,11 +1001,30 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { } } + const auto *FD = dyn_cast(GD.getDecl()); + // Since CPUSpecific can require multiple emits per decl, store the manglings + // separately. + if (FD && + (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) { + const auto *SD = FD->getAttr(); + + std::pair SpecCanonicalGD{ + CanonicalGD, + SD ? SD->ActiveArgIndex : std::numeric_limits::max()}; + + auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD); + if (FoundName != CPUSpecificMangledDeclNames.end()) + return FoundName->second; + + auto Result = CPUSpecificManglings.insert( + std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD)); + return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first(); + } + auto FoundName = MangledDeclNames.find(CanonicalGD); if (FoundName != MangledDeclNames.end()) return FoundName->second; - // Keep the first result in the case of a mangling collision. const auto *ND = cast(GD.getDecl()); auto Result = @@ -1321,8 +1362,9 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, const auto *FD = dyn_cast_or_null(D); FD = FD ? FD->getMostRecentDecl() : FD; const auto *TD = FD ? FD->getAttr() : nullptr; + const auto *SD = FD ? FD->getAttr() : nullptr; bool AddedAttr = false; - if (TD) { + if (TD || SD) { llvm::StringMap FeatureMap; getFunctionFeatureMap(FeatureMap, FD); @@ -1334,10 +1376,12 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, // While we populated the feature map above, we still need to // get and parse the target attribute so we can get the cpu for // the function. - TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - if (ParsedAttr.Architecture != "" && - getTarget().isValidCPUName(ParsedAttr.Architecture)) - TargetCPU = ParsedAttr.Architecture; + if (TD) { + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + if (ParsedAttr.Architecture != "" && + getTarget().isValidCPUName(ParsedAttr.Architecture)) + TargetCPU = ParsedAttr.Architecture; + } } else { // Otherwise just add the existing target cpu and target features to the // function. @@ -2037,6 +2081,10 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { if (Global->hasAttr()) return emitIFuncDefinition(GD); + // If this is a cpu_dispatch multiversion function, emit the resolver. + if (Global->hasAttr()) + return emitCPUDispatchDefinition(GD); + // If this is CUDA, be selective about which declarations we emit. if (LangOpts.CUDA) { if (LangOpts.CUDAIsDevice) { @@ -2355,7 +2403,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::emitMultiVersionFunctions() { for (GlobalDecl GD : MultiVersionFuncs) { - SmallVector Options; + SmallVector Options; const FunctionDecl *FD = cast(GD.getDecl()); getContext().forEachMultiversionedFunctionVersion( FD, [this, &GD, &Options](const FunctionDecl *CurFD) { @@ -2387,28 +2435,75 @@ void CodeGenModule::emitMultiVersionFunctions() { getModule().getOrInsertComdat(ResolverFunc->getName())); std::stable_sort( Options.begin(), Options.end(), - std::greater()); + std::greater()); CodeGenFunction CGF(*this); - CGF.EmitMultiVersionResolver(ResolverFunc, Options); + CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options); } } +void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { + const auto *FD = cast(GD.getDecl()); + assert(FD && "Not a FunctionDecl?"); + const auto *DD = FD->getAttr(); + assert(DD && "Not a cpu_dispatch Function?"); + llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType()); + + StringRef ResolverName = getMangledName(GD); + llvm::Type *ResolverType = llvm::FunctionType::get( + llvm::PointerType::get(DeclTy, + Context.getTargetAddressSpace(FD->getType())), + false); + auto *ResolverFunc = cast( + GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, + /*ForVTable=*/false)); + + SmallVector + Options; + const TargetInfo &Target = getTarget(); + for (const IdentifierInfo *II : DD->cpus()) { + // Get the name of the target function so we can look it up/create it. + std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + + getCPUSpecificMangling(*this, II->getName()); + llvm::Constant *Func = GetOrCreateLLVMFunction( + MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false, + /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); + llvm::SmallVector Features; + Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); + llvm::transform(Features, Features.begin(), + [](StringRef Str) { return Str.substr(1); }); + Features.erase(std::remove_if( + Features.begin(), Features.end(), [&Target](StringRef Feat) { + return !Target.validateCpuSupports(Feat); + }), Features.end()); + Options.emplace_back(cast(Func), + CodeGenFunction::GetX86CpuSupportsMask(Features)); + } + + llvm::sort( + Options.begin(), Options.end(), + std::greater()); + CodeGenFunction CGF(*this); + CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options); +} + /// If an ifunc for the specified mangled name is not in the module, create and /// return an llvm IFunc Function with the specified type. llvm::Constant * CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy, - StringRef MangledName, const FunctionDecl *FD) { - std::string IFuncName = (MangledName + ".ifunc").str(); + std::string MangledName = + getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); + std::string IFuncName = MangledName + ".ifunc"; if (llvm::GlobalValue *IFuncGV = GetGlobalValue(IFuncName)) return IFuncGV; // Since this is the first time we've created this IFunc, make sure // that we put this multiversioned function into the list to be - // replaced later. - MultiVersionFuncs.push_back(GD); + // replaced later if necessary (target multiversioning only). + if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion()) + MultiVersionFuncs.push_back(GD); - std::string ResolverName = (MangledName + ".resolver").str(); + std::string ResolverName = MangledName + ".resolver"; llvm::Type *ResolverType = llvm::FunctionType::get( llvm::PointerType::get(DeclTy, Context.getTargetAddressSpace(FD->getType())), @@ -2455,10 +2550,12 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( addDeferredDeclToEmit(GDDef); } - if (FD->isMultiVersion() && FD->getAttr()->isDefaultVersion()) { - UpdateMultiVersionNames(GD, FD); + if (FD->isMultiVersion()) { + const auto *TA = FD->getAttr(); + if (TA && TA->isDefaultVersion()) + UpdateMultiVersionNames(GD, FD); if (!IsForDefinition) - return GetOrCreateMultiVersionIFunc(GD, Ty, MangledName, FD); + return GetOrCreateMultiVersionIFunc(GD, Ty, FD); } } @@ -3727,6 +3824,15 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, AddGlobalDtor(Fn, DA->getPriority()); if (D->hasAttr()) AddGlobalAnnotations(D, Fn); + + if (D->isCPUSpecificMultiVersion()) { + auto *Spec = D->getAttr(); + // If there is another specific version we need to emit, do so here. + if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) { + ++Spec->ActiveArgIndex; + EmitGlobalFunctionDefinition(GD, nullptr); + } + } } void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { @@ -5107,6 +5213,12 @@ void CodeGenModule::getFunctionFeatureMap(llvm::StringMap &FeatureMap, // the attribute. Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, ParsedAttr.Features); + } else if (const auto *SD = FD->getAttr()) { + llvm::SmallVector FeaturesTmp; + Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(), + FeaturesTmp); + std::vector Features(FeaturesTmp.begin(), FeaturesTmp.end()); + Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features); } else { Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Target.getTargetOpts().Features); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index d2c7b327f9..ee64ed4f2a 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -366,6 +366,13 @@ private: llvm::MapVector MangledDeclNames; llvm::StringMap Manglings; + // An ordered map of canonical GlobalDecls paired with the cpu-index for + // cpu-specific name manglings. + llvm::MapVector, StringRef> + CPUSpecificMangledDeclNames; + llvm::StringMap, llvm::BumpPtrAllocator> + CPUSpecificManglings; + /// Global annotations. std::vector Annotations; @@ -1283,7 +1290,6 @@ private: llvm::Constant *GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy, - StringRef MangledName, const FunctionDecl *FD); void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD); @@ -1307,6 +1313,7 @@ private: void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false); void EmitAliasDefinition(GlobalDecl GD); void emitIFuncDefinition(GlobalDecl GD); + void emitCPUDispatchDefinition(GlobalDecl GD); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); void EmitObjCIvarInitializations(ObjCImplementationDecl *D); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9b552e1040..4f6bb08bdc 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -215,6 +215,15 @@ static bool attributeHasIdentifierArg(const IdentifierInfo &II) { #undef CLANG_ATTR_IDENTIFIER_ARG_LIST } +/// Determine whether the given attribute has a variadic identifier argument. +static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) { +#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST + return llvm::StringSwitch(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST +} + /// Determine whether the given attribute parses a type argument. static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { #define CLANG_ATTR_TYPE_ARG_LIST @@ -282,7 +291,8 @@ unsigned Parser::ParseAttributeArgsCommon( ArgsVector ArgExprs; if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. - bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName); + bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) || + attributeHasVariadicIdentifierArg(*AttrName); ParsedAttr::Kind AttrKind = ParsedAttr::getKind(AttrName, ScopeName, Syntax); @@ -305,19 +315,25 @@ unsigned Parser::ParseAttributeArgsCommon( // Parse the non-empty comma-separated list of expressions. do { - bool Uneval = attributeParsedArgsUnevaluated(*AttrName); - EnterExpressionEvaluationContext Unevaluated( - Actions, - Uneval ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult ArgExpr( - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); - if (ArgExpr.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return 0; + ExprResult ArgExpr; + if (Tok.is(tok::identifier) && + attributeHasVariadicIdentifierArg(*AttrName)) { + ArgExprs.push_back(ParseIdentifierLoc()); + } else { + bool Uneval = attributeParsedArgsUnevaluated(*AttrName); + EnterExpressionEvaluationContext Unevaluated( + Actions, + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); + if (ArgExpr.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + ArgExprs.push_back(ArgExpr.get()); } - ArgExprs.push_back(ArgExpr.get()); // Eat the comma, move to the next argument } while (TryConsumeToken(tok::comma)); } diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 8938c34157..82d9df25d9 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -658,6 +658,11 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, else S.Diag(Loc, DiagID); }; + + // cpu_dispatch functions permit empty function bodies for ICC compatibility. + if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion()) + return; + // Either in a function body compound statement, or a function-try-block. switch (CheckFallThrough(AC)) { case UnknownFallThrough: diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index f81a34c40b..d57473c561 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1585,6 +1585,7 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, } bool Ambiguous = false; + bool IsMV = false; if (Overloads) { for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), @@ -1598,11 +1599,16 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, if (const FunctionDecl *OverloadDecl = dyn_cast((*it)->getUnderlyingDecl())) { if (OverloadDecl->getMinRequiredArguments() == 0) { - if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) { + if (!ZeroArgCallReturnTy.isNull() && !Ambiguous && + (!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() || + OverloadDecl->isCPUSpecificMultiVersion()))) { ZeroArgCallReturnTy = QualType(); Ambiguous = true; - } else + } else { ZeroArgCallReturnTy = OverloadDecl->getReturnType(); + IsMV = OverloadDecl->isCPUDispatchMultiVersion() || + OverloadDecl->isCPUSpecificMultiVersion(); + } } } } @@ -1683,7 +1689,7 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, NamedDecl *Fn = (*It)->getUnderlyingDecl(); // Don't print overloads for non-default multiversioned functions. if (const auto *FD = Fn->getAsFunction()) { - if (FD->isMultiVersion() && + if (FD->isMultiVersion() && FD->hasAttr() && !FD->getAttr()->isDefaultVersion()) continue; } @@ -1725,6 +1731,21 @@ static bool IsCallableWithAppend(Expr *E) { !isa(E)); } +static bool IsCPUDispatchCPUSpecificMultiVersion(const Expr *E) { + if (const auto *UO = dyn_cast(E)) + E = UO->getSubExpr(); + + if (const auto *ULE = dyn_cast(E)) { + if (ULE->getNumDecls() == 0) + return false; + + const NamedDecl *ND = *ULE->decls_begin(); + if (const auto *FD = dyn_cast(ND)) + return FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion(); + } + return false; +} + bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, bool ForceComplain, bool (*IsPlausibleResult)(QualType)) { @@ -1741,12 +1762,13 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // so we can emit a fixit and carry on pretending that E was // actually a CallExpr. SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd()); - Diag(Loc, PD) - << /*zero-arg*/ 1 << Range - << (IsCallableWithAppend(E.get()) - ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") - : FixItHint()); - notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get()); + Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range + << (IsCallableWithAppend(E.get()) + ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") + : FixItHint()); + if (!IsMV) + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); // FIXME: Try this before emitting the fixit, and suppress diagnostics // while doing so. @@ -1757,8 +1779,10 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, if (!ForceComplain) return false; - Diag(Loc, PD) << /*not zero-arg*/ 0 << Range; - notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get()); + Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range; + if (!IsMV) + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); E = ExprError(); return true; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b6381dc1e4..e91e9d3ac1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9275,6 +9275,20 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { D->getFriendObjectKind() != Decl::FOK_None); } +namespace MultiVersioning { +enum Type { None, Target, CPUSpecific, CPUDispatch}; +} // MultiVersionType + +static MultiVersioning::Type +getMultiVersionType(const FunctionDecl *FD) { + if (FD->hasAttr()) + return MultiVersioning::Target; + if (FD->hasAttr()) + return MultiVersioning::CPUDispatch; + if (FD->hasAttr()) + return MultiVersioning::CPUSpecific; + return MultiVersioning::None; +} /// Check the target attribute of the function for MultiVersion /// validity. /// @@ -9313,7 +9327,8 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, const FunctionDecl *NewFD, - bool CausesMV) { + bool CausesMV, + MultiVersioning::Type MVType) { enum DoesntSupport { FuncTemplates = 0, VirtFuncs = 1, @@ -9321,7 +9336,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, Constructors = 3, Destructors = 4, DeletedFuncs = 5, - DefaultedFuncs = 6 + DefaultedFuncs = 6, + ConstexprFuncs = 7, }; enum Different { CallingConv = 0, @@ -9332,46 +9348,73 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, Linkage = 5 }; + bool IsCPUSpecificCPUDispatchMVType = + MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific; + + if (OldFD && !OldFD->getType()->getAs()) { + S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto); + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + return true; + } + + if (!NewFD->getType()->getAs()) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto); + + if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); + if (OldFD) + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + return true; + } + // For now, disallow all other attributes. These should be opt-in, but // an analysis of all of them is a future FIXME. if (CausesMV && OldFD && std::distance(OldFD->attr_begin(), OldFD->attr_end()) != 1) { - S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs); + S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs) + << IsCPUSpecificCPUDispatchMVType; S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); return true; } if (std::distance(NewFD->attr_begin(), NewFD->attr_end()) != 1) - return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs); + return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs) + << IsCPUSpecificCPUDispatchMVType; if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) - << FuncTemplates; + << IsCPUSpecificCPUDispatchMVType << FuncTemplates; if (const auto *NewCXXFD = dyn_cast(NewFD)) { if (NewCXXFD->isVirtual()) return S.Diag(NewCXXFD->getLocation(), diag::err_multiversion_doesnt_support) - << VirtFuncs; + << IsCPUSpecificCPUDispatchMVType << VirtFuncs; if (const auto *NewCXXCtor = dyn_cast(NewFD)) return S.Diag(NewCXXCtor->getLocation(), diag::err_multiversion_doesnt_support) - << Constructors; + << IsCPUSpecificCPUDispatchMVType << Constructors; if (const auto *NewCXXDtor = dyn_cast(NewFD)) return S.Diag(NewCXXDtor->getLocation(), diag::err_multiversion_doesnt_support) - << Destructors; + << IsCPUSpecificCPUDispatchMVType << Destructors; } if (NewFD->isDeleted()) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) - << DeletedFuncs; + << IsCPUSpecificCPUDispatchMVType << DeletedFuncs; if (NewFD->isDefaulted()) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) - << DefaultedFuncs; + << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs; + + if (NewFD->isConstexpr() && (MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific)) + return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) + << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs; QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType()); const auto *NewType = cast(NewQType); @@ -9379,7 +9422,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, if (NewReturnType->isUndeducedType()) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) - << DeducedReturn; + << IsCPUSpecificCPUDispatchMVType << DeducedReturn; // Only allow transition to MultiVersion if it hasn't been used. if (OldFD && CausesMV && OldFD->isUsed(false)) @@ -9426,138 +9469,133 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, return false; } -/// Check the validity of a mulitversion function declaration. -/// Also sets the multiversion'ness' of the function itself. +/// Check the validity of a multiversion function declaration that is the +/// first of its kind. Also sets the multiversion'ness' of the function itself. /// /// This sets NewFD->isInvalidDecl() to true if there was an error. /// /// Returns true if there was an error, false otherwise. -static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, - bool &Redeclaration, NamedDecl *&OldDecl, - bool &MergeTypeWithPrevious, - LookupResult &Previous) { - const auto *NewTA = NewFD->getAttr(); - if (NewFD->isMain()) { - if (NewTA && NewTA->isDefaultVersion()) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main); - NewFD->setInvalidDecl(); - return true; - } +static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD, + MultiVersioning::Type MVType, + const TargetAttr *TA, + const CPUDispatchAttr *CPUDisp, + const CPUSpecificAttr *CPUSpec) { + assert(MVType != MultiVersioning::None && + "Function lacks multiversion attribute"); + + // Target only causes MV if it is default, otherwise this is a normal + // function. + if (MVType == MultiVersioning::Target && !TA->isDefaultVersion()) return false; - } - // If there is no matching previous decl, only 'default' can - // cause MultiVersioning. - if (!OldDecl) { - if (NewTA && NewTA->isDefaultVersion()) { - if (!NewFD->getType()->getAs()) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto); - NewFD->setInvalidDecl(); - return true; - } - if (CheckMultiVersionAdditionalRules(S, nullptr, NewFD, true)) { - NewFD->setInvalidDecl(); - return true; - } - if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); - NewFD->setInvalidDecl(); - return true; - } + if (MVType == MultiVersioning::Target && CheckMultiVersionValue(S, FD)) { + FD->setInvalidDecl(); + return true; + } - NewFD->setIsMultiVersion(); - } - return false; + if (CheckMultiVersionAdditionalRules(S, nullptr, FD, true, MVType)) { + FD->setInvalidDecl(); + return true; } - if (OldDecl->getDeclContext()->getRedeclContext() != - NewFD->getDeclContext()->getRedeclContext()) - return false; + FD->setIsMultiVersion(); + return false; +} - FunctionDecl *OldFD = OldDecl->getAsFunction(); - // Unresolved 'using' statements (the other way OldDecl can be not a function) - // likely cannot cause a problem here. - if (!OldFD) - return false; +static bool CheckTargetCausesMultiVersioning( + Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA, + bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, + LookupResult &Previous) { + const auto *OldTA = OldFD->getAttr(); + TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse(); + // Sort order doesn't matter, it just needs to be consistent. + llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); - if (!OldFD->isMultiVersion() && !NewTA) + // If the old decl is NOT MultiVersioned yet, and we don't cause that + // to change, this is a simple redeclaration. + if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()) return false; - if (OldFD->isMultiVersion() && !NewTA) { - S.Diag(NewFD->getLocation(), diag::err_target_required_in_redecl); + // Otherwise, this decl causes MultiVersioning. + if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); return true; } - TargetAttr::ParsedTargetAttr NewParsed = NewTA->parse(); - // Sort order doesn't matter, it just needs to be consistent. - llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); + if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true, + MultiVersioning::Target)) { + NewFD->setInvalidDecl(); + return true; + } - const auto *OldTA = OldFD->getAttr(); - if (!OldFD->isMultiVersion()) { - // If the old decl is NOT MultiVersioned yet, and we don't cause that - // to change, this is a simple redeclaration. - if (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()) - return false; + if (CheckMultiVersionValue(S, NewFD)) { + NewFD->setInvalidDecl(); + return true; + } - // Otherwise, this decl causes MultiVersioning. - if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported); - S.Diag(OldFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; - } + if (CheckMultiVersionValue(S, OldFD)) { + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + NewFD->setInvalidDecl(); + return true; + } - if (!OldFD->getType()->getAs()) { - S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto); - S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); - NewFD->setInvalidDecl(); - return true; - } + TargetAttr::ParsedTargetAttr OldParsed = + OldTA->parse(std::less()); - if (CheckMultiVersionValue(S, NewFD)) { - NewFD->setInvalidDecl(); - return true; - } + if (OldParsed == NewParsed) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } - if (CheckMultiVersionValue(S, OldFD)) { + for (const auto *FD : OldFD->redecls()) { + const auto *CurTA = FD->getAttr(); + if (!CurTA || CurTA->isInherited()) { + S.Diag(FD->getLocation(), diag::err_multiversion_required_in_redecl) + << 0; S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); NewFD->setInvalidDecl(); return true; } + } - TargetAttr::ParsedTargetAttr OldParsed = - OldTA->parse(std::less()); - - if (OldParsed == NewParsed) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); - S.Diag(OldFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; - } - - for (const auto *FD : OldFD->redecls()) { - const auto *CurTA = FD->getAttr(); - if (!CurTA || CurTA->isInherited()) { - S.Diag(FD->getLocation(), diag::err_target_required_in_redecl); - S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); - NewFD->setInvalidDecl(); - return true; - } - } + OldFD->setIsMultiVersion(); + NewFD->setIsMultiVersion(); + Redeclaration = false; + MergeTypeWithPrevious = false; + OldDecl = nullptr; + Previous.clear(); + return false; +} - if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true)) { - NewFD->setInvalidDecl(); - return true; - } +/// Check the validity of a new function declaration being added to an existing +/// multiversioned declaration collection. +static bool CheckMultiVersionAdditionalDecl( + Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, + MultiVersioning::Type NewMVType, const TargetAttr *NewTA, + const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, + bool &Redeclaration, NamedDecl *&OldDecl, bool &MergeTypeWithPrevious, + LookupResult &Previous) { + + MultiVersioning::Type OldMVType = getMultiVersionType(OldFD); + // Disallow mixing of multiversioning types. + if ((OldMVType == MultiVersioning::Target && + NewMVType != MultiVersioning::Target) || + (NewMVType == MultiVersioning::Target && + OldMVType != MultiVersioning::Target)) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); + S.Diag(OldFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } - OldFD->setIsMultiVersion(); - NewFD->setIsMultiVersion(); - Redeclaration = false; - MergeTypeWithPrevious = false; - OldDecl = nullptr; - Previous.clear(); - return false; + TargetAttr::ParsedTargetAttr NewParsed; + if (NewTA) { + NewParsed = NewTA->parse(); + llvm::sort(NewParsed.Features.begin(), NewParsed.Features.end()); } bool UseMemberUsingDeclRules = @@ -9572,32 +9610,93 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) continue; - const auto *CurTA = CurFD->getAttr(); - if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) { - NewFD->setIsMultiVersion(); - Redeclaration = true; - OldDecl = ND; - return false; - } + if (NewMVType == MultiVersioning::Target) { + const auto *CurTA = CurFD->getAttr(); + if (CurTA->getFeaturesStr() == NewTA->getFeaturesStr()) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } - TargetAttr::ParsedTargetAttr CurParsed = - CurTA->parse(std::less()); + TargetAttr::ParsedTargetAttr CurParsed = + CurTA->parse(std::less()); + if (CurParsed == NewParsed) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else { + const auto *CurCPUSpec = CurFD->getAttr(); + const auto *CurCPUDisp = CurFD->getAttr(); + // Handle CPUDispatch/CPUSpecific versions. + // Only 1 CPUDispatch function is allowed, this will make it go through + // the redeclaration errors. + if (NewMVType == MultiVersioning::CPUDispatch && + CurFD->hasAttr()) { + if (CurCPUDisp->cpus_size() == NewCPUDisp->cpus_size() && + std::equal( + CurCPUDisp->cpus_begin(), CurCPUDisp->cpus_end(), + NewCPUDisp->cpus_begin(), + [](const IdentifierInfo *Cur, const IdentifierInfo *New) { + return Cur->getName() == New->getName(); + })) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } - if (CurParsed == NewParsed) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); - S.Diag(CurFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; + // If the declarations don't match, this is an error condition. + S.Diag(NewFD->getLocation(), diag::err_cpu_dispatch_mismatch); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + if (NewMVType == MultiVersioning::CPUSpecific && CurCPUSpec) { + + if (CurCPUSpec->cpus_size() == NewCPUSpec->cpus_size() && + std::equal( + CurCPUSpec->cpus_begin(), CurCPUSpec->cpus_end(), + NewCPUSpec->cpus_begin(), + [](const IdentifierInfo *Cur, const IdentifierInfo *New) { + return Cur->getName() == New->getName(); + })) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + + // Only 1 version of CPUSpecific is allowed for each CPU. + for (const IdentifierInfo *CurII : CurCPUSpec->cpus()) { + for (const IdentifierInfo *NewII : NewCPUSpec->cpus()) { + if (CurII == NewII) { + S.Diag(NewFD->getLocation(), diag::err_cpu_specific_multiple_defs) + << NewII; + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } + } + } + // If the two decls aren't the same MVType, there is no possible error + // condition. } } - // Else, this is simply a non-redecl case. - if (CheckMultiVersionValue(S, NewFD)) { + // Else, this is simply a non-redecl case. Checking the 'value' is only + // necessary in the Target case, since The CPUSpecific/Dispatch cases are + // handled in the attribute adding step. + if (NewMVType == MultiVersioning::Target && + CheckMultiVersionValue(S, NewFD)) { NewFD->setInvalidDecl(); return true; } - if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false)) { + if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, false, NewMVType)) { NewFD->setInvalidDecl(); return true; } @@ -9610,6 +9709,89 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, return false; } + +/// Check the validity of a mulitversion function declaration. +/// Also sets the multiversion'ness' of the function itself. +/// +/// This sets NewFD->isInvalidDecl() to true if there was an error. +/// +/// Returns true if there was an error, false otherwise. +static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, + bool &Redeclaration, NamedDecl *&OldDecl, + bool &MergeTypeWithPrevious, + LookupResult &Previous) { + const auto *NewTA = NewFD->getAttr(); + const auto *NewCPUDisp = NewFD->getAttr(); + const auto *NewCPUSpec = NewFD->getAttr(); + + // Mixing Multiversioning types is prohibited. + if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) || + (NewCPUDisp && NewCPUSpec)) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); + NewFD->setInvalidDecl(); + return true; + } + + MultiVersioning::Type MVType = getMultiVersionType(NewFD); + + // Main isn't allowed to become a multiversion function, however it IS + // permitted to have 'main' be marked with the 'target' optimization hint. + if (NewFD->isMain()) { + if ((MVType == MultiVersioning::Target && NewTA->isDefaultVersion()) || + MVType == MultiVersioning::CPUDispatch || + MVType == MultiVersioning::CPUSpecific) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_not_allowed_on_main); + NewFD->setInvalidDecl(); + return true; + } + return false; + } + + if (!OldDecl || !OldDecl->getAsFunction() || + OldDecl->getDeclContext()->getRedeclContext() != + NewFD->getDeclContext()->getRedeclContext()) { + // If there's no previous declaration, AND this isn't attempting to cause + // multiversioning, this isn't an error condition. + if (MVType == MultiVersioning::None) + return false; + return CheckMultiVersionFirstFunction(S, NewFD, MVType, NewTA, NewCPUDisp, + NewCPUSpec); + } + + FunctionDecl *OldFD = OldDecl->getAsFunction(); + + if (!OldFD->isMultiVersion() && MVType == MultiVersioning::None) + return false; + + if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_required_in_redecl) + << (getMultiVersionType(OldFD) != MultiVersioning::Target); + NewFD->setInvalidDecl(); + return true; + } + + // Handle the target potentially causes multiversioning case. + if (!OldFD->isMultiVersion() && MVType == MultiVersioning::Target) + return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA, + Redeclaration, OldDecl, + MergeTypeWithPrevious, Previous); + // Previous declarations lack CPUDispatch/CPUSpecific. + if (!OldFD->isMultiVersion()) { + S.Diag(OldFD->getLocation(), diag::err_multiversion_required_in_redecl) + << 1; + S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); + NewFD->setInvalidDecl(); + return true; + } + + // At this point, we have a multiversion function decl (in OldFD) AND an + // appropriate attribute in the current function decl. Resolve that these are + // still compatible with previous declarations. + return CheckMultiVersionAdditionalDecl( + S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, Redeclaration, + OldDecl, MergeTypeWithPrevious, Previous); +} + /// Perform semantic checking of a new function declaration. /// /// Performs semantic analysis of the new function declaration @@ -12829,6 +13011,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } } + // Warn on CPUDispatch with an actual body. + if (FD->isMultiVersion() && FD->hasAttr() && Body) + if (const auto *CmpndBody = dyn_cast(Body)) + if (!CmpndBody->body_empty()) + Diag(CmpndBody->body_front()->getLocStart(), + diag::warn_dispatch_body_ignored); + if (auto *MD = dyn_cast(FD)) { const CXXMethodDecl *KeyFunction; if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) && diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 55fb21af0d..d1786f7682 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1849,6 +1849,50 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << AL.getName() << getFunctionOrMethodResultSourceRange(D); } +static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + FunctionDecl *FD = cast(D); + if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + return; + + SmallVector CPUs; + for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) { + if (!AL.isArgIdent(ArgNo)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL.getName() << AANT_ArgumentIdentifier; + return; + } + + IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo); + StringRef CPUName = CPUArg->Ident->getName().trim(); + + if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) { + S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value) + << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch); + return; + } + + const TargetInfo &Target = S.Context.getTargetInfo(); + if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) { + return Target.CPUSpecificManglingCharacter(CPUName) == + Target.CPUSpecificManglingCharacter(Cur->getName()); + })) { + S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries); + return; + } + CPUs.push_back(CPUArg->Ident); + } + + FD->setIsMultiVersion(true); + if (AL.getKind() == ParsedAttr::AT_CPUSpecific) + D->addAttr(::new (S.Context) CPUSpecificAttr( + AL.getRange(), S.Context, CPUs.data(), CPUs.size(), + AL.getAttributeSpellingListIndex())); + else + D->addAttr(::new (S.Context) CPUDispatchAttr( + AL.getRange(), S.Context, CPUs.data(), CPUs.size(), + AL.getAttributeSpellingListIndex())); +} + static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) @@ -5967,6 +6011,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_CarriesDependency: handleDependencyAttr(S, scope, D, AL); break; + case ParsedAttr::AT_CPUDispatch: + case ParsedAttr::AT_CPUSpecific: + handleCPUSpecificAttr(S, D, AL); + break; case ParsedAttr::AT_Common: handleCommonAttr(S, D, AL); break; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 51c1c84c27..e350517946 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2728,12 +2728,23 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { return false; } +// Certain multiversion types should be treated as overloaded even when there is +// only one result. +static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) { + assert(R.isSingleResult() && "Expected only a single result"); + const auto *FD = dyn_cast(R.getFoundDecl()); + return FD && + (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()); +} + ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. - if (!NeedsADL && R.isSingleResult() && !R.getAsSingle()) + if (!NeedsADL && R.isSingleResult() && + !R.getAsSingle() && + !ShouldLookupResultBeMultiVersionOverload(R)) return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), R.getRepresentativeDecl(), nullptr, AcceptInvalidDecl); @@ -2741,7 +2752,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // We only need to check the declaration if there's exactly one // result, because in the overloaded case the results can only be // functions and function templates. - if (R.isSingleResult() && + if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) && CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 390782b35e..a0b9498cdf 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5988,7 +5988,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - if (Function->isMultiVersion() && + if (Function->isMultiVersion() && Function->hasAttr() && !Function->getAttr()->isDefaultVersion()) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; @@ -6623,7 +6623,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, return; } - if (Method->isMultiVersion() && + if (Method->isMultiVersion() && Method->hasAttr() && !Method->getAttr()->isDefaultVersion()) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; @@ -7032,7 +7032,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, return; } - if (Conversion->isMultiVersion() && + if (Conversion->isMultiVersion() && Conversion->hasAttr() && !Conversion->getAttr()->isDefaultVersion()) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; @@ -8987,6 +8987,47 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better; } +static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2) { + if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function || + !Cand2.Function->isMultiVersion()) + return false; + + // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer + // cpu_dispatch, else arbitrarily based on the identifiers. + bool Cand1CPUDisp = Cand1.Function->hasAttr(); + bool Cand2CPUDisp = Cand2.Function->hasAttr(); + const auto *Cand1CPUSpec = Cand1.Function->getAttr(); + const auto *Cand2CPUSpec = Cand2.Function->getAttr(); + + if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec) + return false; + + if (Cand1CPUDisp && !Cand2CPUDisp) + return true; + if (Cand2CPUDisp && !Cand1CPUDisp) + return false; + + if (Cand1CPUSpec && Cand2CPUSpec) { + if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size()) + return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size(); + + std::pair + FirstDiff = std::mismatch( + Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(), + Cand2CPUSpec->cpus_begin(), + [](const IdentifierInfo *LHS, const IdentifierInfo *RHS) { + return LHS->getName() == RHS->getName(); + }); + + assert(FirstDiff.first != Cand1CPUSpec->cpus_end() && + "Two different cpu-specific versions should not have the same " + "identifier list, otherwise they'd be the same decl!"); + return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName(); + } + llvm_unreachable("No way to get here unless both had cpu_dispatch"); +} + /// isBetterOverloadCandidate - Determines whether the first overload /// candidate is a better candidate than the second (C++ 13.3.3p1). bool clang::isBetterOverloadCandidate( @@ -9184,7 +9225,10 @@ bool clang::isBetterOverloadCandidate( functionHasPassObjectSizeParams(Cand1.Function); bool HasPS2 = Cand2.Function != nullptr && functionHasPassObjectSizeParams(Cand2.Function); - return HasPS1 != HasPS2 && HasPS1; + if (HasPS1 != HasPS2 && HasPS1) + return true; + + return isBetterMultiversionCandidate(Cand1, Cand2); } /// Determine whether two declarations are "equivalent" for the purposes of @@ -9503,7 +9547,8 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, QualType DestType, bool TakingAddress) { if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn)) return; - if (Fn->isMultiVersion() && !Fn->getAttr()->isDefaultVersion()) + if (Fn->isMultiVersion() && Fn->hasAttr() && + !Fn->getAttr()->isDefaultVersion()) return; std::string FnDesc; @@ -11056,8 +11101,7 @@ private: return false; if (FunDecl->isMultiVersion()) { const auto *TA = FunDecl->getAttr(); - assert(TA && "Multiversioned functions require a target attribute"); - if (!TA->isDefaultVersion()) + if (TA && !TA->isDefaultVersion()) return false; } @@ -11355,7 +11399,8 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( DeclAccessPair DAP; FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP); - if (!Found) + if (!Found || Found->isCPUDispatchMultiVersion() || + Found->isCPUSpecificMultiVersion()) return false; // Emitting multiple diagnostics for a function that is both inaccessible and diff --git a/test/CodeGen/attr-cpuspecific.c b/test/CodeGen/attr-cpuspecific.c new file mode 100644 index 0000000000..1b98b5dc96 --- /dev/null +++ b/test/CodeGen/attr-cpuspecific.c @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + + +// Each called version should have an IFunc. +// CHECK: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver +// CHECK: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver +// CHECK: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver +// CHECK: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver + +__attribute__((cpu_specific(ivybridge))) +void SingleVersion(void){} +// CHECK: define void @SingleVersion.S() #[[S:[0-9]+]] + +__attribute__((cpu_specific(ivybridge))) +void NotCalled(void){} +// CHECK: define void @NotCalled.S() #[[S]] + +// Done before any of the implementations. +__attribute__((cpu_dispatch(ivybridge, knl))) +void TwoVersions(void); +// CHECK: define void ()* @TwoVersions.resolver() +// CHECK: call void @__cpu_indicator_init +// CHECK: ret void ()* @TwoVersions.Z +// CHECK: ret void ()* @TwoVersions.S +// CHECK: call void @llvm.trap +// CHECK: unreachable + +__attribute__((cpu_specific(ivybridge))) +void TwoVersions(void){} +// CHECK: define void @TwoVersions.S() #[[S]] + +__attribute__((cpu_specific(knl))) +void TwoVersions(void){} +// CHECK: define void @TwoVersions.Z() #[[K:[0-9]+]] + +__attribute__((cpu_specific(ivybridge, knl))) +void TwoVersionsSameAttr(void){} +// CHECK: define void @TwoVersionsSameAttr.S() #[[S]] +// CHECK: define void @TwoVersionsSameAttr.Z() #[[K]] + +__attribute__((cpu_specific(atom, ivybridge, knl))) +void ThreeVersionsSameAttr(void){} +// CHECK: define void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]] +// CHECK: define void @ThreeVersionsSameAttr.S() #[[S]] +// CHECK: define void @ThreeVersionsSameAttr.Z() #[[K]] + +void usages() { + SingleVersion(); + // CHECK: @SingleVersion.ifunc() + TwoVersions(); + // CHECK: @TwoVersions.ifunc() + TwoVersionsSameAttr(); + // CHECK: @TwoVersionsSameAttr.ifunc() + ThreeVersionsSameAttr(); + // CHECK: @ThreeVersionsSameAttr.ifunc() +} + +// has an extra config to emit! +__attribute__((cpu_dispatch(ivybridge, knl, atom))) +void TwoVersionsSameAttr(void); +// CHECK: define void ()* @TwoVersionsSameAttr.resolver() +// CHECK: ret void ()* @TwoVersionsSameAttr.Z +// CHECK: ret void ()* @TwoVersionsSameAttr.S +// CHECK: ret void ()* @TwoVersionsSameAttr.O +// CHECK: call void @llvm.trap +// CHECK: unreachable + +__attribute__((cpu_dispatch(atom, ivybridge, knl))) +void ThreeVersionsSameAttr(void){} +// CHECK: define void ()* @ThreeVersionsSameAttr.resolver() +// CHECK: call void @__cpu_indicator_init +// CHECK: ret void ()* @ThreeVersionsSameAttr.Z +// CHECK: ret void ()* @ThreeVersionsSameAttr.S +// CHECK: ret void ()* @ThreeVersionsSameAttr.O +// CHECK: call void @llvm.trap +// CHECK: unreachable + +// No Cpu Specific options. +__attribute__((cpu_dispatch(atom, ivybridge, knl))) +void NoSpecifics(void); +// CHECK: define void ()* @NoSpecifics.resolver() +// CHECK: call void @__cpu_indicator_init +// CHECK: ret void ()* @NoSpecifics.Z +// CHECK: ret void ()* @NoSpecifics.S +// CHECK: ret void ()* @NoSpecifics.O +// CHECK: call void @llvm.trap +// CHECK: unreachable + +__attribute__((cpu_dispatch(atom, generic, ivybridge, knl))) +void HasGeneric(void); +// CHECK: define void ()* @HasGeneric.resolver() +// CHECK: call void @__cpu_indicator_init +// CHECK: ret void ()* @HasGeneric.Z +// CHECK: ret void ()* @HasGeneric.S +// CHECK: ret void ()* @HasGeneric.O +// CHECK: ret void ()* @HasGeneric.A +// CHECK-NOT: call void @llvm.trap + +// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" +// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" +// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87" diff --git a/test/Misc/pragma-attribute-supported-attributes-list.test b/test/Misc/pragma-attribute-supported-attributes-list.test index 675a178d31..4a3846be8d 100644 --- a/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/test/Misc/pragma-attribute-supported-attributes-list.test @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 70 attributes: +// CHECK: #pragma clang attribute supports 72 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -15,6 +15,8 @@ // CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType) // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) +// CHECK-NEXT: CPUDispatch (SubjectMatchRule_function) +// CHECK-NEXT: CPUSpecific (SubjectMatchRule_function) // CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function) // CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member) // CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) diff --git a/test/Sema/attr-cpuspecific.c b/test/Sema/attr-cpuspecific.c new file mode 100644 index 0000000000..91063c1c5b --- /dev/null +++ b/test/Sema/attr-cpuspecific.c @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s + +void __attribute__((cpu_specific(ivybridge))) no_default(void); +void __attribute__((cpu_specific(sandybridge))) no_default(void); + +void use1(void){ + // Should be OK, default not a problem. + no_default(); +} + +int __attribute__((cpu_specific(atom))) addr_of(void); +int __attribute__((cpu_specific(ivybridge))) addr_of(void); +int __attribute__((cpu_specific(ivybridge))) addr_of2(void); + +void use2(void){ + addr_of(); + addr_of2(); + // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}} + (void)+addr_of; + // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}} + (void)+addr_of2; + // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}} + (void)&addr_of; + // expected-error@+1{{reference to multiversioned function could not be resolved; did you mean to call it with no arguments?}} + (void)&addr_of2; +} + +// expected-error@+1 {{multiversioned function must have a prototype}} +int __attribute__((cpu_specific(atom))) no_proto(); + +int __attribute__((cpu_specific(atom))) redecl1(void); +int __attribute__((cpu_specific(atom))) redecl1(void) { return 1; } + +int __attribute__((cpu_dispatch(atom))) redecl2(void); +int __attribute__((cpu_dispatch(atom))) redecl2(void) { } +// expected-error@+2 {{redefinition of 'redecl2'}} +// expected-note@-2 {{previous definition is here}} +int __attribute__((cpu_dispatch(atom))) redecl2(void) { } + +int redecl3(void); +// expected-error@-1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}} +// expected-note@+1 {{function multiversioning caused by this declaration}} +int __attribute__((cpu_dispatch(atom))) redecl3(void) {} + +int __attribute__((cpu_specific(atom))) redecl4(void); +// expected-error@+1 {{function declaration is missing 'cpu_specific' or 'cpu_dispatch' attribute in a multiversioned function}} +int redecl4(void); + +// expected-warning@+1 {{CPU list contains duplicate entries; attribute ignored}} +int __attribute__((cpu_specific(atom, atom))) dup_procs(void); + +int __attribute__((cpu_specific(ivybridge, atom))) dup_procs2(void); +// expected-error@+2 {{multiple 'cpu_specific' functions cannot specify the same CPU: 'atom'}} +// expected-note@-2 {{previous declaration is here}} +int __attribute__((cpu_specific(atom))) dup_procs2(void); + +int __attribute__((cpu_specific(ivybridge, atom))) dup_procs3(void); +// expected-error@+2 {{multiple 'cpu_specific' functions cannot specify the same CPU: 'ivybridge'}} +// expected-note@-2 {{previous declaration is here}} +int __attribute__((cpu_specific(atom, ivybridge))) dup_procs3(void); + +int __attribute__((cpu_specific(atom))) redef(void) { return 1; } +// expected-error@+2 {{redefinition of 'redef'}} +// expected-note@-2 {{previous definition is here}} +int __attribute__((cpu_specific(atom))) redef(void) { return 2; } + +int __attribute((cpu_dispatch(atom))) mult_dispatch(void) {} +// expected-error@+2 {{'cpu_dispatch' function redeclared with different CPUs}} +// expected-note@-2 {{previous declaration is here}} +int __attribute((cpu_dispatch(ivybridge))) mult_dispatch(void) {} + +// expected-error@+1 {{'cpu_dispatch' attribute takes at least 1 argument}} +int __attribute((cpu_dispatch())) no_dispatch(void) {} +// expected-error@+1 {{'cpu_specific' attribute takes at least 1 argument}} +int __attribute((cpu_specific())) no_specific(void) {} + +//expected-error@+1 {{attribute 'cpu_specific' multiversioning cannot be combined}} +void __attribute__((used,cpu_specific(sandybridge))) addtl_attrs(void); + +void __attribute__((target("default"))) addtl_attrs2(void); +// expected-error@+2 {{multiversioning attributes cannot be combined}} +// expected-note@-2 {{previous declaration is here}} +void __attribute__((cpu_specific(sandybridge))) addtl_attrs2(void); + +// expected-error@+2 {{multiversioning attributes cannot be combined}} +void __attribute((cpu_specific(sandybridge), cpu_dispatch(atom, sandybridge))) +combine_attrs(void); + +int __attribute__((cpu_dispatch(ivybridge))) diff_cc(void){} +// expected-error@+1 {{multiversioned function declaration has a different calling convention}} +__vectorcall int __attribute__((cpu_specific(sandybridge))) diff_cc(void); + +// expected-warning@+2 {{body of cpu_dispatch function will be ignored}} +int __attribute__((cpu_dispatch(atom))) disp_with_body(void) { + return 5; +} diff --git a/test/SemaCXX/attr-cpuspecific.cpp b/test/SemaCXX/attr-cpuspecific.cpp new file mode 100644 index 0000000000..a881b6c4e2 --- /dev/null +++ b/test/SemaCXX/attr-cpuspecific.cpp @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14 + +// expected-error@+1{{invalid option 'invalid' for cpu_dispatch}} +void __attribute__((cpu_dispatch(atom, invalid))) invalid_cpu(); + +void __attribute__((cpu_specific(atom))) no_default(void); +void __attribute__((cpu_specific(sandybridge))) no_default(void); + +struct MVReference { + int __attribute__((cpu_specific(sandybridge))) bar(void); + int __attribute__((cpu_specific(ivybridge))) bar(void); + int __attribute__((cpu_specific(sandybridge))) foo(void); +}; + +void use1(void){ + // OK, will fail in the linker, unless another TU provides the cpu_dispatch. + no_default(); + + // expected-error@+1 {{call to non-static member function without an object argument}} + +MVReference::bar; + // expected-error@+1 {{call to non-static member function without an object argument}} + +MVReference::foo; + // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}} + &MVReference::bar; + // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}} + &MVReference::foo; +} + +//expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}} +constexpr int __attribute__((cpu_specific(sandybridge))) foo(void); + +int __attribute__((cpu_specific(sandybridge))) foo2(void); +//expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}} +constexpr int __attribute__((cpu_specific(ivybridge))) foo2(void); + +static int __attribute__((cpu_specific(sandybridge))) bar(void); +//expected-error@+1 {{multiversioned function declaration has a different storage class}} +int __attribute__((cpu_dispatch(ivybridge))) bar(void) {} + +inline int __attribute__((cpu_specific(sandybridge))) baz(void); +//expected-error@+1 {{multiversioned function declaration has a different inline specification}} +int __attribute__((cpu_specific(ivybridge))) baz(void) {return 1;} + +void __attribute__((cpu_specific(atom))) diff_return(void); +//expected-error@+1 {{multiversioned function declaration has a different return type}} +int __attribute__((cpu_specific(sandybridge))) diff_return(void); + +int __attribute__((cpu_specific(atom))) diff_noexcept(void) noexcept(true); +//expected-error@+2 {{exception specification in declaration does not match previous declaration}} +//expected-note@-2 {{previous declaration is here}} +int __attribute__((cpu_specific(sandybridge))) diff_noexcept(void) noexcept(false); + +// FIXME: Add support for templates and virtual functions! +// expected-error@+2 {{multiversioned functions do not yet support function templates}} +template +int __attribute__((cpu_specific(atom))) foo(T) { return 0; } +// expected-error@+2 {{multiversioned functions do not yet support function templates}} +template +int __attribute__((cpu_specific(sandybridge))) foo2(T); + +struct S { + // expected-error@+2 {{multiversioned functions do not yet support function templates}} + template + int __attribute__((cpu_specific(atom))) foo(T) { return 0; } + + // expected-error@+2 {{multiversioned functions do not yet support function templates}} + template + int __attribute__((cpu_dispatch(ivybridge))) foo2(T) {} + + // expected-error@+1 {{multiversioned functions do not yet support virtual functions}} + virtual void __attribute__((cpu_specific(atom))) virt(); +}; + +extern "C" { +int __attribute__((cpu_specific(atom))) diff_mangle(void) { return 0; } +} +//expected-error@+1 {{multiversioned function declaration has a different linkage}} +int __attribute__((cpu_specific(sandybridge))) diff_mangle(void) { return 0; } + +__attribute__((cpu_specific(atom))) void DiffDecl(); +namespace N { +using ::DiffDecl; +// expected-error@+3 {{declaration conflicts with target of using declaration already in scope}} +// expected-note@-4 {{target of using declaration}} +// expected-note@-3 {{using declaration}} +__attribute__((cpu_dispatch(atom))) void DiffDecl(); +} // namespace N + +struct SpecialFuncs { + // expected-error@+1 {{multiversioned functions do not yet support constructors}} + __attribute__((cpu_specific(atom))) SpecialFuncs(); + // expected-error@+1 {{multiversioned functions do not yet support destructors}} + __attribute__((cpu_specific(atom))) ~SpecialFuncs(); + + // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}} + SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(const SpecialFuncs&) = default; + // expected-error@+1 {{multiversioned functions do not yet support deleted functions}} + SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(SpecialFuncs&&) = delete; +}; + +struct BadOutOfLine { + int __attribute__((cpu_specific(atom, ivybridge))) foo(int); +}; + +int __attribute__((cpu_specific(atom, ivybridge))) BadOutOfLine::foo(int) { return 0; } +// expected-error@+2 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}} +// expected-note@-2 {{member declaration nearly matches}} +int __attribute__((cpu_specific(sandybridge))) BadOutOfLine::foo(int) { return 1; } + +// Ensure Cpp Spelling works. +[[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){} diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index bddd51e9d1..0bf7a07cf6 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -1173,6 +1173,13 @@ namespace { } }; + class VariadicIdentifierArgument : public VariadicArgument { + public: + VariadicIdentifierArgument(const Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "IdentifierInfo *") + {} + }; + class VariadicStringArgument : public VariadicArgument { public: VariadicStringArgument(const Record &Arg, StringRef Attr) @@ -1278,6 +1285,8 @@ createArgument(const Record &Arg, StringRef Attr, Ptr = llvm::make_unique(Arg, Attr); else if (ArgName == "ParamIdxArgument") Ptr = llvm::make_unique(Arg, Attr, "ParamIdx"); + else if (ArgName == "VariadicIdentifierArgument") + Ptr = llvm::make_unique(Arg, Attr); else if (ArgName == "VersionArgument") Ptr = llvm::make_unique(Arg, Attr); @@ -2106,6 +2115,34 @@ static bool isIdentifierArgument(Record *Arg) { .Default(false); } +static bool isVariadicIdentifierArgument(Record *Arg) { + return !Arg->getSuperClasses().empty() && + llvm::StringSwitch( + Arg->getSuperClasses().back().first->getName()) + .Case("VariadicIdentifierArgument", true) + .Default(false); +} + +static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records, + raw_ostream &OS) { + OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n"; + std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); + for (const auto *A : Attrs) { + // Determine whether the first argument is a variadic identifier. + std::vector Args = A->getValueAsListOfDefs("Args"); + if (Args.empty() || !isVariadicIdentifierArgument(Args[0])) + continue; + + // All these spellings take an identifier argument. + forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " + << "true" + << ")\n"; + }); + } + OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n"; +} + // Emits the first-argument-is-identifier property for attributes. static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n"; @@ -3697,6 +3734,7 @@ void EmitClangAttrParserStringSwitches(RecordKeeper &Records, emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS); emitClangAttrArgContextList(Records, OS); emitClangAttrIdentifierArgList(Records, OS); + emitClangAttrVariadicIdentifierArgList(Records, OS); emitClangAttrTypeArgList(Records, OS); emitClangAttrLateParsedList(Records, OS); } -- GitLab From 287e569d6781aaf89e09fffc1dae32fa20b0402c Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Fri, 20 Jul 2018 14:46:10 +0000 Subject: [PATCH 0632/1023] [www] Add CodeCompass and CodeChecker to Clang Related Projects page git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337555 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/related.html | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/www/related.html b/www/related.html index ee4ccd5d97..d14880f3c1 100644 --- a/www/related.html +++ b/www/related.html @@ -93,6 +93,28 @@

+
CodeCompass
+
+

+ Site: + http://github.com/Ericsson/CodeCompass +

+

+ CodeCompass is an open-source, extensible code comprehension framework which uses LLVM/Clang to analyze and visualize C and C++ projects. It also supports both regex-based text search, discovering complex C/C++ language elements, with advanced navigation and visualisation. +

+
+ +
CodeChecker
+
+

+ Site: + http://github.com/Ericsson/CodeChecker +

+

+ CodeChecker is a static analysis infrastructure built on the LLVM/Clang Static Analyzer toolchain. It provides a user interface to execute analysis of C/C++ projects with Clang SA and Clang-Tidy, which outputs are then stored into a database navigable via a web application. This web application and a corresponding command-line tool supports a variety of report management and issue triaging options, such as difference view between analyses, automatic incremental analysis, marking and commenting on individual reports. +

+
+ -- GitLab From b400322f6ca5e63dbadafee558953f650e4394bf Mon Sep 17 00:00:00 2001 From: Reka Kovacs Date: Fri, 20 Jul 2018 15:14:49 +0000 Subject: [PATCH 0633/1023] [analyzer] Rename DanglingInternalBufferChecker to InnerPointerChecker. Differential Revision: https://reviews.llvm.org/D49553 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337559 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 9 ++--- lib/StaticAnalyzer/Checkers/AllocationState.h | 4 +- lib/StaticAnalyzer/Checkers/CMakeLists.txt | 2 +- ...ferChecker.cpp => InnerPointerChecker.cpp} | 37 +++++++++---------- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 26 ++++++------- ...-internal-buffer.cpp => inner-pointer.cpp} | 2 +- 6 files changed, 39 insertions(+), 41 deletions(-) rename lib/StaticAnalyzer/Checkers/{DanglingInternalBufferChecker.cpp => InnerPointerChecker.cpp} (87%) rename test/Analysis/{dangling-internal-buffer.cpp => inner-pointer.cpp} (98%) diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 5e450bdb4a..38fd687e16 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -300,16 +300,15 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { -def DanglingInternalBufferChecker : Checker<"DanglingInternalBuffer">, - HelpText<"Check for internal raw pointers of C++ standard library containers " - "used after deallocation">, - DescFile<"DanglingInternalBufferChecker.cpp">; - def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; +def InnerPointerChecker : Checker<"InnerPointer">, + HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, + DescFile<"InnerPointerChecker.cpp">; + def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, DescFile<"IteratorChecker.cpp">; diff --git a/lib/StaticAnalyzer/Checkers/AllocationState.h b/lib/StaticAnalyzer/Checkers/AllocationState.h index 16d3eb6476..a6908bd7a6 100644 --- a/lib/StaticAnalyzer/Checkers/AllocationState.h +++ b/lib/StaticAnalyzer/Checkers/AllocationState.h @@ -23,8 +23,8 @@ ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, /// This function provides an additional visitor that augments the bug report /// with information relevant to memory errors caused by the misuse of -/// AF_InternalBuffer symbols. -std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym); +/// AF_InnerBuffer symbols. +std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym); } // end namespace allocation_state diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index af88c0bfd3..94093b82f3 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -27,7 +27,6 @@ add_clang_library(clangStaticAnalyzerCheckers CloneChecker.cpp ConversionChecker.cpp CXXSelfAssignmentChecker.cpp - DanglingInternalBufferChecker.cpp DeadStoresChecker.cpp DebugCheckers.cpp DeleteWithNonVirtualDtorChecker.cpp @@ -42,6 +41,7 @@ add_clang_library(clangStaticAnalyzerCheckers GenericTaintChecker.cpp GTestChecker.cpp IdenticalExprChecker.cpp + InnerPointerChecker.cpp IteratorChecker.cpp IvarInvalidationChecker.cpp LLVMConventionsChecker.cpp diff --git a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp similarity index 87% rename from lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp rename to lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp index 4515b4e453..ed877ab345 100644 --- a/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp @@ -1,4 +1,4 @@ -//=== DanglingInternalBufferChecker.cpp ---------------------------*- C++ -*--// +//=== InnerPointerChecker.cpp -------------------------------------*- C++ -*--// // // The LLVM Compiler Infrastructure // @@ -44,7 +44,7 @@ struct ProgramStateTrait : public ProgramStatePartialTrait { namespace { -class DanglingInternalBufferChecker +class InnerPointerChecker : public Checker { CallDescription AppendFn, AssignFn, ClearFn, CStrFn, DataFn, EraseFn, @@ -52,11 +52,11 @@ class DanglingInternalBufferChecker ShrinkToFitFn, SwapFn; public: - class DanglingBufferBRVisitor : public BugReporterVisitor { + class InnerPointerBRVisitor : public BugReporterVisitor { SymbolRef PtrToBuf; public: - DanglingBufferBRVisitor(SymbolRef Sym) : PtrToBuf(Sym) {} + InnerPointerBRVisitor(SymbolRef Sym) : PtrToBuf(Sym) {} static void *getTag() { static int Tag = 0; @@ -84,7 +84,7 @@ public: } }; - DanglingInternalBufferChecker() + InnerPointerChecker() : AppendFn("append"), AssignFn("assign"), ClearFn("clear"), CStrFn("c_str"), DataFn("data"), EraseFn("erase"), InsertFn("insert"), PopBackFn("pop_back"), PushBackFn("push_back"), ReplaceFn("replace"), @@ -121,8 +121,7 @@ public: // -- Calling non-const member functions, except operator[], at, front, back, // begin, rbegin, end, and rend." // -bool DanglingInternalBufferChecker::mayInvalidateBuffer( - const CallEvent &Call) const { +bool InnerPointerChecker::mayInvalidateBuffer(const CallEvent &Call) const { if (const auto *MemOpCall = dyn_cast(&Call)) { OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator(); if (Opc == OO_Equal || Opc == OO_PlusEqual) @@ -138,8 +137,8 @@ bool DanglingInternalBufferChecker::mayInvalidateBuffer( Call.isCalled(SwapFn)); } -void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, - CheckerContext &C) const { +void InnerPointerChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { const auto *ICall = dyn_cast(&Call); if (!ICall) return; @@ -187,8 +186,8 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call, } } -void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, - CheckerContext &C) const { +void InnerPointerChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { ProgramStateRef State = C.getState(); PtrSet::Factory &F = State->getStateManager().get_context(); RawPtrMapTy RPM = State->get(); @@ -213,9 +212,10 @@ void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper, } std::shared_ptr -DanglingInternalBufferChecker::DanglingBufferBRVisitor::VisitNode( - const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR) { +InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) { if (!isSymbolTracked(N->getState(), PtrToBuf) || isSymbolTracked(PrevN->getState(), PtrToBuf)) @@ -238,16 +238,15 @@ namespace clang { namespace ento { namespace allocation_state { -std::unique_ptr getDanglingBufferBRVisitor(SymbolRef Sym) { - return llvm::make_unique< - DanglingInternalBufferChecker::DanglingBufferBRVisitor>(Sym); +std::unique_ptr getInnerPointerBRVisitor(SymbolRef Sym) { + return llvm::make_unique(Sym); } } // end namespace allocation_state } // end namespace ento } // end namespace clang -void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) { +void ento::registerInnerPointerChecker(CheckerManager &Mgr) { registerNewDeleteChecker(Mgr); - Mgr.registerChecker(); + Mgr.registerChecker(); } diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index be3289a395..8f07f413e8 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -47,7 +47,7 @@ enum AllocationFamily { AF_CXXNewArray, AF_IfNameIndex, AF_Alloca, - AF_InternalBuffer + AF_InnerBuffer }; class RefState { @@ -485,7 +485,7 @@ private: (!SPrev || !SPrev->isReleased()); assert(!IsReleased || (Stmt && (isa(Stmt) || isa(Stmt))) || - (!Stmt && S->getAllocationFamily() == AF_InternalBuffer)); + (!Stmt && S->getAllocationFamily() == AF_InnerBuffer)); return IsReleased; } @@ -1473,7 +1473,7 @@ void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C, case AF_CXXNew: os << "'new'"; return; case AF_CXXNewArray: os << "'new[]'"; return; case AF_IfNameIndex: os << "'if_nameindex()'"; return; - case AF_InternalBuffer: os << "container-specific allocator"; return; + case AF_InnerBuffer: os << "container-specific allocator"; return; case AF_Alloca: case AF_None: llvm_unreachable("not a deallocation expression"); } @@ -1486,7 +1486,7 @@ void MallocChecker::printExpectedDeallocName(raw_ostream &os, case AF_CXXNew: os << "'delete'"; return; case AF_CXXNewArray: os << "'delete[]'"; return; case AF_IfNameIndex: os << "'if_freenameindex()'"; return; - case AF_InternalBuffer: os << "container-specific deallocator"; return; + case AF_InnerBuffer: os << "container-specific deallocator"; return; case AF_Alloca: case AF_None: llvm_unreachable("suspicious argument"); } @@ -1662,8 +1662,8 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family, } case AF_CXXNew: case AF_CXXNewArray: - // FIXME: Add new CheckKind for AF_InternalBuffer. - case AF_InternalBuffer: { + // FIXME: Add new CheckKind for AF_InnerBuffer. + case AF_InnerBuffer: { if (IsALeakCheck) { if (ChecksEnabled[CK_NewDeleteLeaksChecker]) return CK_NewDeleteLeaksChecker; @@ -1995,8 +1995,8 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range, R->addVisitor(llvm::make_unique(Sym)); const RefState *RS = C.getState()->get(Sym); - if (RS->getAllocationFamily() == AF_InternalBuffer) - R->addVisitor(allocation_state::getDanglingBufferBRVisitor(Sym)); + if (RS->getAllocationFamily() == AF_InnerBuffer) + R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym)); C.emitReport(std::move(R)); } @@ -2870,7 +2870,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( const Stmt *S = PathDiagnosticLocation::getStmt(N); // When dealing with containers, we sometimes want to give a note // even if the statement is missing. - if (!S && (!RS || RS->getAllocationFamily() != AF_InternalBuffer)) + if (!S && (!RS || RS->getAllocationFamily() != AF_InnerBuffer)) return nullptr; const LocationContext *CurrentLC = N->getLocationContext(); @@ -2903,7 +2903,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( StackHintGeneratorForSymbol *StackHint = nullptr; SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); - + if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { Msg = "Memory is allocated"; @@ -2919,7 +2919,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( case AF_IfNameIndex: Msg = "Memory is released"; break; - case AF_InternalBuffer: { + case AF_InnerBuffer: { OS << "Inner pointer invalidated by call to "; if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) { OS << "destructor"; @@ -3011,7 +3011,7 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode( // Generate the extra diagnostic. PathDiagnosticLocation Pos; if (!S) { - assert(RS->getAllocationFamily() == AF_InternalBuffer); + assert(RS->getAllocationFamily() == AF_InnerBuffer); auto PostImplCall = N->getLocation().getAs(); if (!PostImplCall) return nullptr; @@ -3055,7 +3055,7 @@ namespace allocation_state { ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) { - AllocationFamily Family = AF_InternalBuffer; + AllocationFamily Family = AF_InnerBuffer; return State->set(Sym, RefState::getReleased(Family, Origin)); } diff --git a/test/Analysis/dangling-internal-buffer.cpp b/test/Analysis/inner-pointer.cpp similarity index 98% rename from test/Analysis/dangling-internal-buffer.cpp rename to test/Analysis/inner-pointer.cpp index fa8d5e154b..db9bf43109 100644 --- a/test/Analysis/dangling-internal-buffer.cpp +++ b/test/Analysis/inner-pointer.cpp @@ -1,4 +1,4 @@ -//RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.DanglingInternalBuffer %s -analyzer-output=text -verify +//RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.InnerPointer %s -analyzer-output=text -verify namespace std { -- GitLab From dca1b442e96b8d768c34bae0c4dda84a1f06ce09 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 20 Jul 2018 16:30:02 +0000 Subject: [PATCH 0634/1023] Rewrite the VS integration scripts. This is a new modernized VS integration installer. It adds a Visual Studio .sln file which, when built, outputs a VSIX that can be used to install ourselves as a "real" Visual Studio Extension. We can even upload this extension to the visual studio marketplace. This fixes a longstanding problem where we didn't support installing into VS 2017 and higher. In addition to supporting VS 2017, due to the way this is written we now longer need to do anything special to support future versions of VS as well. Everything should "just work". This also fixes several bugs with our old integration, such as MSBuild triggering full rebuilds when /Zi was used. Finally, we add a new UI page called "LLVM" which becomes visible when the LLVM toolchain is selected. For now this only contains one option which is the path to clang-cl.exe, but in the future we can add more things here. Differential Revision: https://reviews.llvm.org/D42762 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337572 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/driver/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index db7055e886..15b0519e41 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -63,10 +63,6 @@ add_dependencies(clang clang-headers) if(NOT CLANG_LINKS_TO_CREATE) set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp) - - if (MSVC) - list(APPEND CLANG_LINKS_TO_CREATE ../msbuild-bin/cl) - endif() endif() foreach(link ${CLANG_LINKS_TO_CREATE}) -- GitLab From 4e2bc94eda9c2a7ea117f8b1131899f28d2d446c Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 20 Jul 2018 17:10:32 +0000 Subject: [PATCH 0635/1023] [CodeGen][ObjC] Make copying and disposing of a non-escaping block no-ops. A non-escaping block on the stack will never be called after its lifetime ends, so it doesn't have to be copied to the heap. To prevent a non-escaping block from being copied to the heap, this patch sets field 'isa' of the block object to NSConcreteGlobalBlock and sets the BLOCK_IS_GLOBAL bit of field 'flags', which causes the runtime to treat the block as if it were a global block (calling _Block_copy on the block just returns the original block and calling _Block_release is a no-op). Also, a new flag bit 'BLOCK_IS_NOESCAPE' is added, which allows the runtime or tools to distinguish between true global blocks and non-escaping blocks. rdar://problem/39352313 Differential Revision: https://reviews.llvm.org/D49303 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337580 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/Block-ABI-Apple.rst | 8 +++++++ lib/CodeGen/CGBlocks.cpp | 16 +++++++++---- lib/CodeGen/CGBlocks.h | 9 ++++++- test/CodeGenObjC/noescape.m | 47 ++++++++++++++++++++++++++++++++++++- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/docs/Block-ABI-Apple.rst b/docs/Block-ABI-Apple.rst index 7f49bbd40d..e48a24b43c 100644 --- a/docs/Block-ABI-Apple.rst +++ b/docs/Block-ABI-Apple.rst @@ -61,6 +61,14 @@ The following flags bits are in use thusly for a possible ABI.2010.3.16: .. code-block:: c enum { + // Set to true on blocks that have captures (and thus are not true + // global blocks) but are known not to escape for various other + // reasons. For backward compatiblity with old runtimes, whenever + // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a + // non-escaping block returns the original block and releasing such a + // block is a no-op, which is exactly how global blocks are handled. + BLOCK_IS_NOESCAPE = (1 << 23), + BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code BLOCK_IS_GLOBAL = (1 << 28), diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 926683db93..352a02db2b 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -104,7 +104,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, elements.addInt(ulong, blockInfo.BlockSize.getQuantity()); // Optional copy/dispose helpers. - if (blockInfo.NeedsCopyDispose) { + if (blockInfo.needsCopyDisposeHelpers()) { // copy_func_helper_decl elements.add(buildCopyHelper(CGM, blockInfo)); @@ -159,6 +159,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, /// These are the flags (with corresponding bit number) that the /// compiler is actually supposed to know about. + /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block /// descriptor provides copy and dispose helper functions /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured @@ -778,8 +779,13 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { llvm::Constant *descriptor; BlockFlags flags; if (!IsOpenCL) { - isa = llvm::ConstantExpr::getBitCast(CGM.getNSConcreteStackBlock(), - VoidPtrTy); + // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock + // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping + // block just returns the original block and releasing it is a no-op. + llvm::Constant *blockISA = blockInfo.getBlockDecl()->doesNotEscape() + ? CGM.getNSConcreteGlobalBlock() + : CGM.getNSConcreteStackBlock(); + isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy); // Build the block descriptor. descriptor = buildBlockDescriptor(CGM, blockInfo); @@ -788,12 +794,14 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { flags = BLOCK_HAS_SIGNATURE; if (blockInfo.HasCapturedVariableLayout) flags |= BLOCK_HAS_EXTENDED_LAYOUT; - if (blockInfo.NeedsCopyDispose) + if (blockInfo.needsCopyDisposeHelpers()) flags |= BLOCK_HAS_COPY_DISPOSE; if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; + if (blockInfo.getBlockDecl()->doesNotEscape()) + flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL; } auto projectField = diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 80e255f754..5a8e960ffc 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -54,6 +54,7 @@ enum BlockByrefFlags { }; enum BlockLiteralFlags { + BLOCK_IS_NOESCAPE = (1 << 23), BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CXX_OBJ = (1 << 26), BLOCK_IS_GLOBAL = (1 << 28), @@ -214,7 +215,8 @@ public: /// no non-constant captures. bool CanBeGlobal : 1; - /// True if the block needs a custom copy or dispose function. + /// True if the block has captures that would necessitate custom copy or + /// dispose helper functions if the block were escaping. bool NeedsCopyDispose : 1; /// HasCXXObject - True if the block's custom copy/dispose functions @@ -276,6 +278,11 @@ public: } CGBlockInfo(const BlockDecl *blockDecl, StringRef Name); + + // Indicates whether the block needs a custom copy or dispose function. + bool needsCopyDisposeHelpers() const { + return NeedsCopyDispose && !Block->doesNotEscape(); + } }; } // end namespace CodeGen diff --git a/test/CodeGenObjC/noescape.m b/test/CodeGenObjC/noescape.m index 49bc0e4a7d..56e1e51e5d 100644 --- a/test/CodeGenObjC/noescape.m +++ b/test/CodeGenObjC/noescape.m @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-NOARC %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fblocks -emit-llvm -fobjc-arc -o - %s | FileCheck -check-prefix CHECK -check-prefix CHECK-ARC %s typedef void (^BlockTy)(void); @@ -12,6 +13,12 @@ void noescapeFunc1(__attribute__((noescape)) int *); void noescapeFunc2(__attribute__((noescape)) id); void noescapeFunc3(__attribute__((noescape)) union U); +// Block descriptors of non-escaping blocks don't need pointers to copy/dispose +// helper functions. + +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } +// CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*]] = internal constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8 + // CHECK-LABEL: define void @test0( // CHECK: call void @noescapeFunc0({{.*}}, {{.*}} nocapture {{.*}}) // CHECK: declare void @noescapeFunc0(i8*, {{.*}} nocapture) @@ -69,3 +76,41 @@ void test5(BlockTy2 b, int *p) { ^(int *__attribute__((noescape)) p0){}(p); b(p); } + +// If the block is non-escaping, set the BLOCK_IS_NOESCAPE and BLOCK_IS_GLOBAL +// bits of field 'flags' and set the 'isa' field to 'NSConcreteGlobalBlock'. + +// CHECK: define void @test6(i8* %{{.*}}, i8* %[[B:.*]]) +// CHECK: %{{.*}} = alloca i8*, align 8 +// CHECK: %[[B_ADDR:.*]] = alloca i8*, align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 +// CHECK-NOARC: store i8* %[[B]], i8** %[[B_ADDR]], align 8 +// CHECK-ARC: store i8* null, i8** %[[B_ADDR]], align 8 +// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* %[[B]]) +// CHECK-ARC: %[[V0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: %[[BLOCK_ISA:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 0 +// CHECK: store i8* bitcast (i8** @_NSConcreteGlobalBlock to i8*), i8** %[[BLOCK_ISA]], align 8 +// CHECK: %[[BLOCK_FLAGS:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 1 +// CHECK: store i32 -796917760, i32* %[[BLOCK_FLAGS]], align 8 +// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i64 }* @[[BLOCK_DESCIPTOR_TMP_2]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK-NOARC: %[[V1:.*]] = load i8*, i8** %[[B_ADDR]], align 8 +// CHECK-NOARC: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8 +// CHECK-ARC: %[[V2:.*]] = load i8*, i8** %[[B_ADDR]], align 8 +// CHECK-ARC: %[[V3:.*]] = call i8* @objc_retain(i8* %[[V2]]) #3 +// CHECK-ARC: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED]], align 8 +// CHECK: call void @noescapeFunc0( +// CHECK-ARC: call void @objc_storeStrong(i8** %[[V0]], i8* null) +// CHECK-ARC: call void @objc_storeStrong(i8** %[[B_ADDR]], i8* null) + +// Non-escaping blocks don't need copy/dispose helper functions. + +// CHECK-NOT: define internal void @__copy_helper_block_ +// CHECK-NOT: define internal void @__destroy_helper_block_ + +void func(id); + +void test6(id a, id b) { + noescapeFunc0(a, ^{ func(b); }); +} -- GitLab From 3afc7e3fc438b0982f1daddcfa274a0a840b7587 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 20 Jul 2018 17:42:09 +0000 Subject: [PATCH 0636/1023] Prevent Scoped Enums from being Integral constant expressions: Discovered because of: https://bugs.llvm.org/show_bug.cgi?id=38235 It seems to me that a scoped enum should NOT be an integral constant expression without a cast, so this seems like a sensical change. Attributes that check for an integer parameter simply use this function to ensure that they have an integer, so it was previously allowing a scoped enum. Also added a test based on Richard's feedback to ensure that case labels still work. Differential Revision: https://reviews.llvm.org/D49599 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337585 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 2 +- test/SemaCXX/PR38235.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/SemaCXX/PR38235.cpp diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index bf21bc65e2..e69914f25d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -11142,7 +11142,7 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, llvm::APSInt *Value, SourceLocation *Loc) { - if (!E->getType()->isIntegralOrEnumerationType()) { + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { if (Loc) *Loc = E->getExprLoc(); return false; } diff --git a/test/SemaCXX/PR38235.cpp b/test/SemaCXX/PR38235.cpp new file mode 100644 index 0000000000..11874c837b --- /dev/null +++ b/test/SemaCXX/PR38235.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +enum class E { Foo, Bar = 97119 }; + +void f() __attribute__((constructor(E::Foo))); // expected-error{{'constructor' attribute requires an integer constant}} +void f2() __attribute__((constructor(E::Bar)));// expected-error{{'constructor' attribute requires an integer constant}} + +void switch_me(E e) { + switch (e) { + case E::Foo: + case E::Bar: + break; + } +} -- GitLab From 769fd39841d862d24f81ac3e968a6d007626ccda Mon Sep 17 00:00:00 2001 From: Artem Belevich Date: Fri, 20 Jul 2018 17:44:34 +0000 Subject: [PATCH 0637/1023] [CUDA] Provide integer SIMD functions for CUDA-9.2 CUDA-9.2 made all integer SIMD functions into compiler builtins, so clang no longer has access to the implementation of these functions in either headers of libdevice and has to provide its own implementation. This is mostly a 1:1 mapping to a corresponding PTX instructions with an exception of vhadd2/vhadd4 that don't have an equivalent instruction and had to be implemented with a bit hack. Performance of this implementation will be suboptimal for SM_50 and newer GPUs where PTXAS generates noticeably worse code for the SIMD instructions compared to the code it generates for the inline assembly generated by nvcc (or used to come with CUDA headers). Differential Revision: https://reviews.llvm.org/D49274 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337587 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/__clang_cuda_device_functions.h | 427 ++++++++++++++++++ lib/Headers/__clang_cuda_libdevice_declares.h | 3 +- 2 files changed, 429 insertions(+), 1 deletion(-) diff --git a/lib/Headers/__clang_cuda_device_functions.h b/lib/Headers/__clang_cuda_device_functions.h index c4c21769b8..67bbc68b16 100644 --- a/lib/Headers/__clang_cuda_device_functions.h +++ b/lib/Headers/__clang_cuda_device_functions.h @@ -803,6 +803,8 @@ __DEVICE__ unsigned int __usad(unsigned int __a, unsigned int __b, unsigned int __c) { return __nv_usad(__a, __b, __c); } + +#if CUDA_VERSION >= 9000 && CUDA_VERSION < 9020 __DEVICE__ unsigned int __vabs2(unsigned int __a) { return __nv_vabs2(__a); } __DEVICE__ unsigned int __vabs4(unsigned int __a) { return __nv_vabs4(__a); } __DEVICE__ unsigned int __vabsdiffs2(unsigned int __a, unsigned int __b) { @@ -1041,6 +1043,431 @@ __DEVICE__ unsigned int __vsubus2(unsigned int __a, unsigned int __b) { __DEVICE__ unsigned int __vsubus4(unsigned int __a, unsigned int __b) { return __nv_vsubus4(__a, __b); } +#else // CUDA_VERSION >= 9020 +// CUDA no longer provides inline assembly (or bitcode) implementation of these +// functions, so we have to reimplment them. The implementation is naive and is +// not optimized for performance. + +// Helper function to convert N-bit boolean subfields into all-0 or all-1. +// E.g. __bool2mask(0x01000100,8) -> 0xff00ff00 +// __bool2mask(0x00010000,16) -> 0xffff0000 +__DEVICE__ unsigned int __bool2mask(unsigned int __a, int shift) { + return (__a << shift) - __a; +} +__DEVICE__ unsigned int __vabs2(unsigned int __a) { + unsigned int r; + asm("vabsdiff2.s32.s32.s32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(0), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabs4(unsigned int __a) { + unsigned int r; + asm("vabsdiff4.s32.s32.s32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(0), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabsdiffs2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff2.s32.s32.s32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} + +__DEVICE__ unsigned int __vabsdiffs4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff4.s32.s32.s32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabsdiffu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff2.u32.u32.u32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabsdiffu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff4.u32.u32.u32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabsss2(unsigned int __a) { + unsigned int r; + asm("vabsdiff2.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(0), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vabsss4(unsigned int __a) { + unsigned int r; + asm("vabsdiff4.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(0), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vadd2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vadd4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vaddss2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd2.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vaddss4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd4.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vaddus2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd2.u32.u32.u32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vaddus4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vadd4.u32.u32.u32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vavgs2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vavrg2.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vavgs4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vavrg4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vavgu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vavrg2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vavgu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vavrg4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vseteq2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.eq %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpeq2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vseteq2(__a, __b), 16); +} +__DEVICE__ unsigned int __vseteq4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.eq %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpeq4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vseteq4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetges2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.s32.s32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpges2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetges2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetges4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.s32.s32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpges4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetges4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetgeu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgeu2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgeu2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetgeu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.ge %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgeu4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgeu4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetgts2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.s32.s32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgts2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgts2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetgts4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.s32.s32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgts4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgts4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetgtu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgtu2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgtu2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetgtu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.gt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpgtu4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetgtu4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetles2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.s32.s32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmples2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetles2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetles4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.s32.s32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmples4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetles4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetleu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpleu2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetleu2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetleu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.le %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpleu4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetleu4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetlts2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.s32.s32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmplts2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetlts2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetlts4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.s32.s32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmplts4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetlts4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetltu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpltu2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetltu2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetltu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.lt %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpltu4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetltu4(__a, __b), 8); +} +__DEVICE__ unsigned int __vsetne2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset2.u32.u32.ne %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpne2(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetne2(__a, __b), 16); +} +__DEVICE__ unsigned int __vsetne4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vset4.u32.u32.ne %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vcmpne4(unsigned int __a, unsigned int __b) { + return __bool2mask(__vsetne4(__a, __b), 8); +} + +// Based on ITEM 23 in AIM-239: http://dspace.mit.edu/handle/1721.1/6086 +// (a & b) + (a | b) = a + b = (a ^ b) + 2 * (a & b) => +// (a + b) / 2 = ((a ^ b) >> 1) + (a & b) +// To operate on multiple sub-elements we need to make sure to mask out bits +// that crossed over into adjacent elements during the shift. +__DEVICE__ unsigned int __vhaddu2(unsigned int __a, unsigned int __b) { + return (((__a ^ __b) >> 1) & ~0x80008000u) + (__a & __b); +} +__DEVICE__ unsigned int __vhaddu4(unsigned int __a, unsigned int __b) { + return (((__a ^ __b) >> 1) & ~0x80808080u) + (__a & __b); +} + +__DEVICE__ unsigned int __vmaxs2(unsigned int __a, unsigned int __b) { + unsigned int r; + if ((__a & 0x8000) && (__b & 0x8000)) { + // Work around a bug in ptxas which produces invalid result if low element + // is negative. + unsigned mask = __vcmpgts2(__a, __b); + r = (__a & mask) | (__b & ~mask); + } else { + asm("vmax2.s32.s32.s32 %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + } + return r; +} +__DEVICE__ unsigned int __vmaxs4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmax4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vmaxu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmax2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vmaxu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmax4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vmins2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmin2.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vmins4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmin4.s32.s32.s32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vminu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmin2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vminu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vmin4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vsads2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff2.s32.s32.s32.add %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vsads4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff4.s32.s32.s32.add %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vsadu2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff2.u32.u32.u32.add %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vsadu4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vabsdiff4.u32.u32.u32.add %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} + +__DEVICE__ unsigned int __vsub2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub2.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vneg2(unsigned int __a) { return __vsub2(0, __a); } + +__DEVICE__ unsigned int __vsub4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub4.u32.u32.u32 %0,%1,%2,%3;" : "=r"(r) : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vneg4(unsigned int __a) { return __vsub4(0, __a); } +__DEVICE__ unsigned int __vsubss2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub2.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vnegss2(unsigned int __a) { + return __vsubss2(0, __a); +} +__DEVICE__ unsigned int __vsubss4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub4.s32.s32.s32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vnegss4(unsigned int __a) { + return __vsubss4(0, __a); +} +__DEVICE__ unsigned int __vsubus2(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub2.u32.u32.u32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +__DEVICE__ unsigned int __vsubus4(unsigned int __a, unsigned int __b) { + unsigned int r; + asm("vsub4.u32.u32.u32.sat %0,%1,%2,%3;" + : "=r"(r) + : "r"(__a), "r"(__b), "r"(0)); + return r; +} +#endif // CUDA_VERSION >= 9020 __DEVICE__ int abs(int __a) { return __nv_abs(__a); } __DEVICE__ double acos(double __a) { return __nv_acos(__a); } __DEVICE__ float acosf(float __a) { return __nv_acosf(__a); } diff --git a/lib/Headers/__clang_cuda_libdevice_declares.h b/lib/Headers/__clang_cuda_libdevice_declares.h index 73ea8f8781..71df7f849d 100644 --- a/lib/Headers/__clang_cuda_libdevice_declares.h +++ b/lib/Headers/__clang_cuda_libdevice_declares.h @@ -372,6 +372,7 @@ __device__ unsigned int __nv_umulhi(unsigned int __a, unsigned int __b); __device__ unsigned int __nv_urhadd(unsigned int __a, unsigned int __b); __device__ unsigned int __nv_usad(unsigned int __a, unsigned int __b, unsigned int __c); +#if CUDA_VERSION >= 9000 && CUDA_VERSION < 9020 __device__ int __nv_vabs2(int __a); __device__ int __nv_vabs4(int __a); __device__ int __nv_vabsdiffs2(int __a, int __b); @@ -454,12 +455,12 @@ __device__ int __nv_vsubss2(int __a, int __b); __device__ int __nv_vsubss4(int __a, int __b); __device__ int __nv_vsubus2(int __a, int __b); __device__ int __nv_vsubus4(int __a, int __b); +#endif // CUDA_VERSION __device__ double __nv_y0(double __a); __device__ float __nv_y0f(float __a); __device__ double __nv_y1(double __a); __device__ float __nv_y1f(float __a); __device__ float __nv_ynf(int __a, float __b); __device__ double __nv_yn(int __a, double __b); - } // extern "C" #endif // __CLANG_CUDA_LIBDEVICE_DECLARES_H__ -- GitLab From d642af48b03c96e5b32b80cc56e66c9bbd41fe44 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 20 Jul 2018 20:13:08 +0000 Subject: [PATCH 0638/1023] [AST] Various micro-optimizations in CXXInheritance 1. Pack std::pair in CXXBasePaths::ClassSubobjects. 2. Use a SmallPtrSet instead of a SmallDenseSet for CXXBasePaths::VisitedDependentRecords. 3. Reorder some members of CXXBasePaths to save 8 bytes. 4. Use a SmallSetVector instead of a SetVector in CXXBasePaths::ComputeDeclsFound to avoid some allocations. This speeds up an -fsyntax-only on all of Boost by approx 0.15%, mainly by speeding up CXXBasePaths::lookupInBases by approx 10%. No functional changes. Patch by Bruno Ricci! Differential Revision: https://reviews.llvm.org/D49302 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337607 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/CXXInheritance.h | 41 +++++++++++++++++------------- lib/AST/CXXInheritance.cpp | 20 +++++++-------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 4c031c450b..2ae1d8b258 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -125,18 +125,36 @@ class CXXBasePaths { /// Paths - The actual set of paths that can be taken from the /// derived class to the same base class. std::list Paths; - + /// ClassSubobjects - Records the class subobjects for each class - /// type that we've seen. The first element in the pair says + /// type that we've seen. The first element IsVirtBase says /// whether we found a path to a virtual base for that class type, - /// while the element contains the number of non-virtual base + /// while NumberOfNonVirtBases contains the number of non-virtual base /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. - llvm::SmallDenseMap, 8> ClassSubobjects; + struct IsVirtBaseAndNumberNonVirtBases { + unsigned IsVirtBase : 1; + unsigned NumberOfNonVirtBases : 31; + }; + llvm::SmallDenseMap + ClassSubobjects; /// VisitedDependentRecords - Records the dependent records that have been /// already visited. - llvm::SmallDenseSet VisitedDependentRecords; + llvm::SmallPtrSet VisitedDependentRecords; + + /// DetectedVirtual - The base class that is virtual. + const RecordType *DetectedVirtual = nullptr; + + /// ScratchPath - A BasePath that is used by Sema::lookupInBases + /// to help build the set of paths. + CXXBasePath ScratchPath; + + /// Array of the declarations that have been found. This + /// array is constructed only if needed, e.g., to iterate over the + /// results within LookupResult. + std::unique_ptr DeclsFound; + unsigned NumDeclsFound = 0; /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find /// ambiguous paths while it is looking for a path from a derived @@ -152,20 +170,7 @@ class CXXBasePaths { /// if it finds a path that goes across a virtual base. The virtual class /// is also recorded. bool DetectVirtual; - - /// ScratchPath - A BasePath that is used by Sema::lookupInBases - /// to help build the set of paths. - CXXBasePath ScratchPath; - /// DetectedVirtual - The base class that is virtual. - const RecordType *DetectedVirtual = nullptr; - - /// Array of the declarations that have been found. This - /// array is constructed only if needed, e.g., to iterate over the - /// results within LookupResult. - std::unique_ptr DeclsFound; - unsigned NumDeclsFound = 0; - void ComputeDeclsFound(); bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 374ddac60b..2825329775 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -40,7 +40,7 @@ void CXXBasePaths::ComputeDeclsFound() { assert(NumDeclsFound == 0 && !DeclsFound && "Already computed the set of declarations"); - llvm::SetVector> Decls; + llvm::SmallSetVector Decls; for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) Decls.insert(Path->Decls.front()); @@ -63,8 +63,8 @@ CXXBasePaths::decl_range CXXBasePaths::found_decls() { /// an unqualified, canonical class type. bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { BaseType = BaseType.getUnqualifiedType(); - std::pair& Subobjects = ClassSubobjects[BaseType]; - return Subobjects.second + (Subobjects.first? 1 : 0) > 1; + IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType]; + return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1; } /// clear - Clear out all prior path information. @@ -217,21 +217,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // Determine whether we need to visit this base class at all, // updating the count of subobjects appropriately. - std::pair& Subobjects = ClassSubobjects[BaseType]; + IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType]; bool VisitBase = true; bool SetVirtual = false; if (BaseSpec.isVirtual()) { - VisitBase = !Subobjects.first; - Subobjects.first = true; + VisitBase = !Subobjects.IsVirtBase; + Subobjects.IsVirtBase = true; if (isDetectingVirtual() && DetectedVirtual == nullptr) { // If this is the first virtual we find, remember it. If it turns out // there is no base path here, we'll reset it later. DetectedVirtual = BaseType->getAs(); SetVirtual = true; } - } else - ++Subobjects.second; - + } else { + ++Subobjects.NumberOfNonVirtBases; + } if (isRecordingPaths()) { // Add this base specifier to the current path. CXXBasePathElement Element; @@ -240,7 +240,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, if (BaseSpec.isVirtual()) Element.SubobjectNumber = 0; else - Element.SubobjectNumber = Subobjects.second; + Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases; ScratchPath.push_back(Element); // Calculate the "top-down" access to this base class. -- GitLab From a6d5050bf7bc445d17b7076f7f03a9cd6f2b5dc8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Jul 2018 20:39:49 +0000 Subject: [PATCH 0639/1023] [CStringSyntaxChecker] Fix build bot builds != x86 archs Reviewers: NoQ,george.karpenkov Reviewed By: NoQ Differential Revision: https://reviews.llvm.org/D49588 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337611 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CStringSyntaxChecker.cpp | 17 +++++++++-------- test/Analysis/cstring-syntax.c | 4 ++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp index 6654e822e1..b1f37f5a34 100644 --- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp @@ -147,7 +147,7 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { const Expr *DstArg = CE->getArg(0); const Expr *LenArg = CE->getArg(2); - const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenCasts()); + const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts()); const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts()); // - size_t dstlen = sizeof(dst) if (LenArgDecl) { @@ -159,14 +159,15 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { // - integral value // We try to figure out if the last argument is possibly longer // than the destination can possibly handle if its size can be defined - if (const auto *IL = dyn_cast(LenArg->IgnoreParenCasts())) { + if (const auto *IL = dyn_cast(LenArg->IgnoreParenImpCasts())) { uint64_t ILRawVal = IL->getValue().getZExtValue(); - if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) { - ASTContext &C = BR.getContext(); - uint64_t Usize = C.getTypeSizeInChars(DstArg->getType()).getQuantity(); - uint64_t BufferLen = BR.getContext().getTypeSize(Buffer) / Usize; - if (BufferLen < ILRawVal) - return true; + if (DstArgDecl) { + if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) { + ASTContext &C = BR.getContext(); + uint64_t BufferLen = C.getTypeSize(Buffer) / 8; + if (BufferLen < ILRawVal) + return true; + } } } diff --git a/test/Analysis/cstring-syntax.c b/test/Analysis/cstring-syntax.c index d7df3f082c..f64682b418 100644 --- a/test/Analysis/cstring-syntax.c +++ b/test/Analysis/cstring-syntax.c @@ -1,4 +1,7 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s +// RUN: %clang_analyze_cc1 -triple armv7-a15-linux -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s +// RUN: %clang_analyze_cc1 -triple aarch64_be-none-linux-gnu -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=unix.cstring.BadSizeArg -analyzer-store=region -Wno-strncat-size -Wno-strlcpy-strlcat-size -Wno-sizeof-array-argument -Wno-sizeof-pointer-memaccess -verify %s typedef __SIZE_TYPE__ size_t; char *strncat(char *, const char *, size_t); @@ -27,4 +30,5 @@ void testStrlcpy(const char *src) { strlcpy(dest, src, 20); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}} strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}} strlcpy(dest, src, ulen); + strlcpy(dest + 5, src, 5); } -- GitLab From 3f8eb57cfceb2c8c7b0adee006d9826e3f4d2cbc Mon Sep 17 00:00:00 2001 From: Konstantin Zhuravlyov Date: Fri, 20 Jul 2018 20:46:25 +0000 Subject: [PATCH 0640/1023] AMDGPU: Switch default dwarf version to 2 There were some problems unearthed with version 5, which I am going to look at. Differential Revision: https://reviews.llvm.org/D49613 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337612 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/AMDGPU.h | 2 +- test/Driver/amdgpu-toolchain.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/AMDGPU.h b/lib/Driver/ToolChains/AMDGPU.h index 588c24032b..36114d0dab 100644 --- a/lib/Driver/ToolChains/AMDGPU.h +++ b/lib/Driver/ToolChains/AMDGPU.h @@ -56,7 +56,7 @@ protected: public: AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - unsigned GetDefaultDwarfVersion() const override { return 5; } + unsigned GetDefaultDwarfVersion() const override { return 2; } bool IsIntegratedAssemblerDefault() const override { return true; } llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, diff --git a/test/Driver/amdgpu-toolchain.c b/test/Driver/amdgpu-toolchain.c index bd6bf7e341..52a71975b7 100644 --- a/test/Driver/amdgpu-toolchain.c +++ b/test/Driver/amdgpu-toolchain.c @@ -3,4 +3,4 @@ // AS_LINK: ld.lld{{.*}} "-shared" // RUN: %clang -### -g -target amdgcn--amdhsa -mcpu=kaveri %s 2>&1 | FileCheck -check-prefix=DWARF_VER %s -// DWARF_VER: "-dwarf-version=5" +// DWARF_VER: "-dwarf-version=2" -- GitLab From 906cfe1bf36df2d0efbea663dcc91f9e36e2e097 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 20 Jul 2018 20:55:00 +0000 Subject: [PATCH 0641/1023] [codeview] Don't emit variable templates as class members MSVC doesn't, so neither should we. Fixes PR38004, which is a crash that happens when we try to emit debug info for a still-dependent partial variable template specialization. As a follow-up, we should review what we're doing for function and class member templates. It looks like we don't filter those out, but I can't seem to get clang to emit any. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337616 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 15 +++++--- .../debug-info-codeview-var-templates.cpp | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 test/CodeGenCXX/debug-info-codeview-var-templates.cpp diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 08447f895e..10fc22a098 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1298,10 +1298,6 @@ void CGDebugInfo::CollectRecordFields( else { const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); - // Debug info for nested types is included in the member list only for - // CodeView. - bool IncludeNestedTypes = CGM.getCodeGenOpts().EmitCodeView; - // Field number for non-static fields. unsigned fieldNo = 0; @@ -1311,6 +1307,13 @@ void CGDebugInfo::CollectRecordFields( if (const auto *V = dyn_cast(I)) { if (V->hasAttr()) continue; + + // Skip variable template specializations when emitting CodeView. MSVC + // doesn't emit them. + if (CGM.getCodeGenOpts().EmitCodeView && + isa(V)) + continue; + // Reuse the existing static member declaration if one exists auto MI = StaticDataMemberCache.find(V->getCanonicalDecl()); if (MI != StaticDataMemberCache.end()) { @@ -1327,7 +1330,9 @@ void CGDebugInfo::CollectRecordFields( // Bump field number for next field. ++fieldNo; - } else if (IncludeNestedTypes) { + } else if (CGM.getCodeGenOpts().EmitCodeView) { + // Debug info for nested types is included in the member list only for + // CodeView. if (const auto *nestedType = dyn_cast(I)) if (!nestedType->isImplicit() && nestedType->getDeclContext() == record) diff --git a/test/CodeGenCXX/debug-info-codeview-var-templates.cpp b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp new file mode 100644 index 0000000000..0470c13368 --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -std=c++14 -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s + +// Don't emit static data member debug info for variable templates. +// PR38004 + +struct TestImplicit { + template + static const __SIZE_TYPE__ size_var = sizeof(T); +}; +int instantiate_test1() { return TestImplicit::size_var + TestImplicit::size_var; } +TestImplicit gv1; + +// CHECK: ![[empty:[0-9]+]] = !{} + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestImplicit", +// CHECK-SAME: elements: ![[empty]] + +template bool vtpl; +struct TestSpecialization { + template static const auto sdm = vtpl; + template <> static const auto sdm = false; +} gv2; + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestSpecialization", +// CHECK-SAME: elements: ![[empty]] + +template bool a; +template struct b; +struct TestPartial { + template static auto d = a; + template static auto d> = d; +} c; + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestPartial", +// CHECK-SAME: elements: ![[empty]] -- GitLab From c74a596b1d364a9ecf0d274fbdfd46e998cc59f7 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 20 Jul 2018 21:02:09 +0000 Subject: [PATCH 0642/1023] [ms] Add __shiftleft128 / __shiftright128 intrinsics Carefully match the pattern matched by ISel so that this produces shld / shrd (unless Subtarget->isSHLDSlow() is true). Thanks to Craig Topper for providing the LLVM IR pattern that gets successfully matched. Fixes PR37755. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337619 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/intrin.h | 14 ++++++++++++++ test/Headers/ms-intrin.cpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h index edb947eef6..91914214e2 100644 --- a/lib/Headers/intrin.h +++ b/lib/Headers/intrin.h @@ -863,6 +863,20 @@ __nop(void) { __asm__ volatile ("nop"); } #endif +#if defined(__x86_64__) +static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS +__shiftleft128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) { + unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l; + unsigned __int128 __res = __val << (__d & 63); + return (unsigned __int64)(__res >> 64); +} +static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS +__shiftright128(unsigned __int64 __l, unsigned __int64 __h, unsigned char __d) { + unsigned __int128 __val = ((unsigned __int128)__h << 64) | __l; + unsigned __int128 __res = __val >> (__d & 63); + return (unsigned __int64)__res; +} +#endif /*----------------------------------------------------------------------------*\ |* Privileged intrinsics diff --git a/test/Headers/ms-intrin.cpp b/test/Headers/ms-intrin.cpp index b0fef9cc06..d8a4d382eb 100644 --- a/test/Headers/ms-intrin.cpp +++ b/test/Headers/ms-intrin.cpp @@ -42,6 +42,8 @@ void f() { __stosw(0, 0, 0); #ifdef _M_X64 + __shiftleft128(1, 2, 3); + __shiftright128(1, 2, 3); __movsq(0, 0, 0); __stosq(0, 0, 0); #endif -- GitLab From 527c4ca969487cc6d479105a9d02a0a4690195f5 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 20 Jul 2018 21:06:41 +0000 Subject: [PATCH 0643/1023] fix typo git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337620 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 01c02f8d71..dab70f1bca 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -173,7 +173,7 @@ Windows Support the pch file (matching cl.exe). This speeds up builds using pch files by around 30%. - - The /Ycfoo.h and /Yufoo.h flags an now be used without /FIfoo.h when + - The /Ycfoo.h and /Yufoo.h flags can now be used without /FIfoo.h when foo.h is instead included by an explicit `#include` directive. This means Visual Studio's default stdafx.h setup now uses precompiled headers with clang-cl. -- GitLab From d788672fbeb6d3a05c2cb4b87841ff4c6a213a39 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 20 Jul 2018 22:25:55 +0000 Subject: [PATCH 0644/1023] Fold dangling-field warning into general initialization lifetime checks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337627 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 8 +- lib/Sema/SemaDeclCXX.cpp | 49 ---- lib/Sema/SemaInit.cpp | 252 ++++++++++++------ .../cxx-uninitialized-object-ptr-ref.cpp | 12 +- .../cxx0x-initializer-stdinitializerlist.cpp | 22 +- 5 files changed, 191 insertions(+), 152 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5ae749fa93..e45f5f3376 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7870,11 +7870,11 @@ def note_ref_var_local_bind : Note< // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< - "binding reference member %0 to stack allocated parameter %1">, - InGroup; + "binding reference member %0 to stack allocated " + "%select{variable|parameter}2 %1">, InGroup; def warn_init_ptr_member_to_parameter_addr : Warning< - "initializing pointer member %0 with the stack address of parameter %1">, - InGroup; + "initializing pointer member %0 with the stack address of " + "%select{variable|parameter}2 %1">, InGroup; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d2a2bb2020..031f8dbb38 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3946,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD, return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } -/// Checks a member initializer expression for cases where reference (or -/// pointer) members are bound to by-value parameters (or their addresses). -static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, - Expr *Init, - SourceLocation IdLoc) { - QualType MemberTy = Member->getType(); - - // We only handle pointers and references currently. - // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? - if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) - return; - - const bool IsPointer = MemberTy->isPointerType(); - if (IsPointer) { - if (const UnaryOperator *Op - = dyn_cast(Init->IgnoreParenImpCasts())) { - // The only case we're worried about with pointers requires taking the - // address. - if (Op->getOpcode() != UO_AddrOf) - return; - - Init = Op->getSubExpr(); - } else { - // We only handle address-of expression initializers for pointers. - return; - } - } - - if (const DeclRefExpr *DRE = dyn_cast(Init->IgnoreParens())) { - // We only warn when referring to a non-reference parameter declaration. - const ParmVarDecl *Parameter = dyn_cast(DRE->getDecl()); - if (!Parameter || Parameter->getType()->isReferenceType()) - return; - - S.Diag(Init->getExprLoc(), - IsPointer ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << Parameter << Init->getSourceRange(); - } else { - // Other initializers are fine. - return; - } - - S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) - << (unsigned)IsPointer; -} - MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -4047,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); - // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index f94eabd671..73643a50fc 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6227,7 +6227,7 @@ using LifetimeResult = /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. -static LifetimeResult getEntityForTemporaryLifetimeExtension( +static LifetimeResult getEntityLifetime( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: @@ -6239,8 +6239,7 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - Entity); + return getEntityLifetime(Entity->getParent(), Entity); // except: // C++17 [class.base.init]p8: @@ -6291,14 +6290,12 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - InitField); + return getEntityLifetime(Entity->getParent(), InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - InitField); + return getEntityLifetime(Entity->getParent(), InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: @@ -6311,46 +6308,61 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: - case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; + + case InitializedEntity::EK_Exception: + // FIXME: Can we diagnose lifetime problems with exceptions? + return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { -enum ExtensionKind { +enum ReferenceKind { /// Lifetime would be extended by a reference binding to a temporary. - EK_ReferenceBinding, + RK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. - EK_StdInitializerList, + RK_StdInitializerList, +}; + +/// A temporary or local variable. +using Local = llvm::PointerUnion; + +/// Expressions we stepped over when looking for the local state. Any steps +/// that would inhibit lifetime extension or take us out of subexpressions of +/// the initializer are included. +struct IndirectLocalPathEntry { + enum { + DefaultInit, + AddressOf, + } Kind; + Expr *E; }; -using IndirectTemporaryPathEntry = - llvm::PointerUnion; -using IndirectTemporaryPath = llvm::SmallVectorImpl; + +using IndirectLocalPath = llvm::SmallVectorImpl; struct RevertToOldSizeRAII { - IndirectTemporaryPath &Path; + IndirectLocalPath &Path; unsigned OldSize = Path.size(); - RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {} + RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; } -template -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, - Expr *Init, - TemporaryVisitor Visit); +template +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, + Expr *Init, LocalVisitor Visit, + bool RevisitSubinits); -/// Visit the temporaries whose lifetimes would be extended by binding a -/// reference to the glvalue expression \c Init. -template -static void -visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, - Expr *Init, ExtensionKind EK, - TemporaryVisitor Visit) { +/// Visit the locals that would be reachable through a reference bound to the +/// glvalue expression \c Init. +template +static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, + Expr *Init, ReferenceKind RK, + LocalVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. @@ -6382,7 +6394,7 @@ visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back(DIE); + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6391,25 +6403,36 @@ visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, } while (Init != Old); if (auto *MTE = dyn_cast(Init)) { - if (Visit(Path, MTE, EK)) - visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(), - Visit); + if (Visit(Path, Local(MTE), RK)) + visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, + true); + } + + // If we find the name of a local non-reference parameter, we could have a + // lifetime problem. + if (auto *DRE = dyn_cast(Init->IgnoreParens())) { + auto *VD = dyn_cast(DRE->getDecl()); + if (VD && VD->hasLocalStorage() && + !DRE->refersToEnclosingVariableOrCapture()) { + // FIXME: Recurse to the initializer of a local reference. + if (!VD->getType()->isReferenceType()) + Visit(Path, Local(VD), RK); + } } } -/// Visit the temporaries whose lifetimes would be extended by -/// lifetime-extending the object initialized by the prvalue expression \c -/// Init. -template -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, - Expr *Init, - TemporaryVisitor Visit) { +/// Visit the locals that would be reachable through an object initialized by +/// the prvalue expression \c Init. +template +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, + Expr *Init, LocalVisitor Visit, + bool RevisitSubinits) { RevertToOldSizeRAII RAII(Path); // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back(DIE); + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6426,17 +6449,24 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast(Init)) - return visitTemporariesExtendedByReferenceBinding( - Path, ILE->getSubExpr(), EK_StdInitializerList, Visit); + return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), + RK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast(Init)) { + // We already visited the elements of this initializer list while + // performing the initialization. Don't visit them again unless we've + // changed the lifetime of the initialized entity. + if (!RevisitSubinits) + return; + if (ILE->isTransparent()) - return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0), - Visit); + return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, + RevisitSubinits); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) - visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit); + visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, + RevisitSubinits); return; } @@ -6448,8 +6478,8 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) - visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0), - EK_ReferenceBinding, Visit); + visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), + RK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { @@ -6459,25 +6489,38 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) - visitTemporariesExtendedByReferenceBinding( - Path, SubInit, EK_ReferenceBinding, Visit); + visitLocalsRetainedByReferenceBinding(Path, SubInit, + RK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. - visitTemporariesExtendedByInitializer(Path, SubInit, Visit); + visitLocalsRetainedByInitializer(Path, SubInit, Visit, + RevisitSubinits); ++Index; } } } + return; + } + + // If the initializer is the address of a local, we could have a lifetime + // problem. + if (auto *Op = dyn_cast(Init->IgnoreParenImpCasts())) { + if (Op->getOpcode() == UO_AddrOf) { + Path.push_back({IndirectLocalPathEntry::AddressOf, Op}); + Init = Op->getSubExpr(); + return visitLocalsRetainedByReferenceBinding(Path, Init, + RK_ReferenceBinding, Visit); + } } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). -static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { +static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { - if (!Elem.is()) + if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) return false; } return true; @@ -6485,7 +6528,7 @@ static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { - LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity); + LifetimeResult LR = getEntityLifetime(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); @@ -6494,9 +6537,54 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, if (LK == LK_FullExpression) return; - auto TemporaryVisitor = [&](IndirectTemporaryPath &Path, - MaterializeTemporaryExpr *MTE, - ExtensionKind EK) -> bool { + auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, + ReferenceKind RK) -> bool { + // If we found a path to a local variable or similar, check whether the + // initialized object will outlive it. + if (auto *VD = L.dyn_cast()) { + switch (LK) { + case LK_FullExpression: + llvm_unreachable("already handled this"); + + case LK_Extended: + break; + + case LK_MemInitializer: { + // Paths via a default initializer can only occur during error recovery + // (there's no other way that a default initializer can refer to a + // local). Don't produce a bogus warning on those cases. + if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { + return E.Kind == IndirectLocalPathEntry::DefaultInit; + })) + break; + + if (auto *Member = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + bool AddressTaken = + !Path.empty() && + Path.back().Kind == IndirectLocalPathEntry::AddressOf; + Diag(Init->getExprLoc(), + AddressTaken ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << VD << isa(VD) << Init->getSourceRange(); + Diag(Member->getLocation(), + diag::note_ref_or_ptr_member_declared_here) + << (unsigned)AddressTaken; + } + break; + } + + case LK_New: + break; + + case LK_Return: + // FIXME: Move -Wreturn-stack-address checks here. + return false; + } + return false; + } + + auto *MTE = L.get(); switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); @@ -6520,11 +6608,11 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(MTE->getExprLoc(), - EK == EK_ReferenceBinding + RK == RK_ReferenceBinding ? diag::warn_default_member_init_temporary_not_extended : diag::warn_default_member_init_init_list_not_extended); } else { - llvm_unreachable("unexpected indirect temporary path"); + // FIXME: Warn on this. } break; @@ -6532,18 +6620,20 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. - if (auto *ExtendingDecl = ExtendingEntity->getDecl()) { + if (auto *ExtendingDecl = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary) << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember - << EK; + << RK; // Don't bother adding a note pointing to the field if we're inside its // default member initializer; our primary diagnostic points to the // same place in that case. - if (Path.empty() || !Path.back().is()) { + if (Path.empty() || + Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) - << EK << IsSubobjectMember; + << RK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this @@ -6557,7 +6647,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_New: - if (EK == EK_ReferenceBinding) { + if (RK == RK_ReferenceBinding) { Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference); } else { Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list) @@ -6573,9 +6663,14 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // FIXME: Model these as CodeSynthesisContexts to fix the note emission // order. for (auto Elem : llvm::reverse(Path)) { - if (auto *DIE = Elem.dyn_cast()) { - Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here) - << DIE->getField(); + switch (Elem.Kind) { + case IndirectLocalPathEntry::DefaultInit: + Diag(Elem.E->getExprLoc(), diag::note_in_default_member_initalizer_here) + << cast(Elem.E)->getField(); + break; + + case IndirectLocalPathEntry::AddressOf: + break; } } @@ -6584,12 +6679,12 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, return false; }; - llvm::SmallVector Path; + llvm::SmallVector Path; if (Init->isGLValue()) - visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding, - TemporaryVisitor); + visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, + TemporaryVisitor); else - visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor); + visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); } static void DiagnoseNarrowingInInitList(Sema &S, @@ -6853,6 +6948,7 @@ InitializationSequence::Perform(Sema &S, // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. + // FIXME: Fold this into checkInitializerLifetime. if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { @@ -7015,11 +7111,6 @@ InitializationSequence::Perform(Sema &S, } } - // Even though we didn't materialize a temporary, the binding may still - // extend the lifetime of a temporary. This happens if we bind a - // reference to the result of a cast to reference type. - S.checkInitializerLifetime(Entity, CurInit.get()); - CheckForNullPointerDereference(S, CurInit.get()); break; @@ -7036,10 +7127,6 @@ InitializationSequence::Perform(Sema &S, Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; - // Maybe lifetime-extend the temporary's subobjects to match the - // entity's lifetime. - S.checkInitializerLifetime(Entity, CurInit.get()); - // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && @@ -7490,10 +7577,6 @@ InitializationSequence::Perform(Sema &S, // Wrap it in a construction of a std::initializer_list. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); - // Maybe lifetime-extend the array temporary's subobjects to match the - // entity's lifetime. - S.checkInitializerLifetime(Entity, CurInit.get()); - // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) @@ -7612,6 +7695,11 @@ InitializationSequence::Perform(Sema &S, } } + // Check whether the initializer has a shorter lifetime than the initialized + // entity, and if not, either lifetime-extend or warn as appropriate. + if (auto *Init = CurInit.get()) + S.checkInitializerLifetime(Entity, Init); + // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast(Entity.getDecl())->isBitField()) diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index db025420d7..1507098c5e 100644 --- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -235,10 +235,10 @@ void fVoidPointerTest2() { } class VoidPointerRRefTest1 { - void *&&vptrrref; + void *&&vptrrref; // expected-note {{here}} public: - VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; @@ -249,10 +249,10 @@ void fVoidPointerRRefTest1() { } class VoidPointerRRefTest2 { - void **&&vpptrrref; + void **&&vpptrrref; // expected-note {{here}} public: - VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}} // All good! } }; @@ -263,10 +263,10 @@ void fVoidPointerRRefTest2() { } class VoidPointerLRefTest { - void *&vptrrref; + void *&vptrrref; // expected-note {{here}} public: - VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 0184a1d6e7..e3c7e26afa 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -72,18 +72,18 @@ std::initializer_list thread_local x = {1, 2, 3, 4}; // X86: @_ZN15partly_constant1kE = global i32 0, align 4 // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4 -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4 +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 // AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 -// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4 // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 @@ -375,7 +375,7 @@ namespace partly_constant { // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0) - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. -- GitLab From f6ec322ffdc0227034876d73801b95b338d100b0 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 20 Jul 2018 22:36:33 +0000 Subject: [PATCH 0645/1023] Disable clang crash-report-modules.m test on Windows again It still appears to be failing: http://lab.llvm.org:8011/builders/clang-x86-windows-msvc2015/builds/12825 $ "rm" "-rf" "C:\b\slave\clang-x86-windows-msvc2015\clang-x86-windows-msvc2015\stage1\tools\clang\test\Driver\Output/crmdir" Error: 'rm' command failed, [Error 3] The system cannot find the path specified: 'C:\\b\\slave\\clang-x86-windows-msvc2015\\clang-x86-windows-msvc2015\\stage1\\tools\\clang\\test\\Driver\\Output/crmdir\\crash-report-modules-300567.cache\\vfs\\b\\slave\\clang-x86-windows-msvc2015\\clang-x86-windows-msvc2015\\llvm\\tools\\clang\\test\\Driver\\Inputs\\module\\module.modulemap' error: command failed with exit status: 1 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337629 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/crash-report-modules.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/Driver/crash-report-modules.m b/test/Driver/crash-report-modules.m index 73b1e9f04b..ded31b4ed4 100644 --- a/test/Driver/crash-report-modules.m +++ b/test/Driver/crash-report-modules.m @@ -12,6 +12,10 @@ // RUN: FileCheck --check-prefix=CHECKSH %s -input-file %T/crmdir/crash-report-*.sh // REQUIRES: crash-recovery +// FIXME: This test creates excessively deep directory hierarchies that cause +// problems on Windows. +// UNSUPPORTED: system-windows + @import simple; const int x = MODULE_MACRO; -- GitLab From 67428b72eda39d9b712a128e5c6f3a6c9d6cc264 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Fri, 20 Jul 2018 22:45:24 +0000 Subject: [PATCH 0646/1023] [HIP] Register/unregister device fat binary only once HIP generates one fat binary for all devices after linking. However, for each compilation unit a ctor function is emitted which register the same fat binary. Measures need to be taken to make sure the fat binary is only registered once. Currently each ctor function calls __hipRegisterFatBinary and stores the returned value to __hip_gpubin_handle. This patch changes the linkage of __hip_gpubin_handle to be linkonce so that they are shared between LLVM modules. Then this patch adds check of value of __hip_gpubin_handle to make sure __hipRegisterFatBinary is only called once. The code is equivalent to void *_gpubin_handle; void ctor() { if (__hip_gpubin_handle == 0) { __hip_gpubin_handle = __hipRegisterFatBinary(...); } // register kernels and variables. } The patch also does similar change to dtors so that __hipUnregisterFatBinary is called once. Differential Revision: https://reviews.llvm.org/D49083 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337631 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCUDANV.cpp | 122 +++++++++++++++++++++++++++----- test/CodeGenCUDA/device-stub.cu | 23 ++++-- 2 files changed, 124 insertions(+), 21 deletions(-) diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index b541b1046f..5fcc9e011b 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -309,12 +309,24 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() { } /// Creates a global constructor function for the module: +/// +/// For CUDA: /// \code /// void __cuda_module_ctor(void*) { /// Handle = __cudaRegisterFatBinary(GpuBinaryBlob); /// __cuda_register_globals(Handle); /// } /// \endcode +/// +/// For HIP: +/// \code +/// void __hip_module_ctor(void*) { +/// if (__hip_gpubin_handle == 0) { +/// __hip_gpubin_handle = __hipRegisterFatBinary(GpuBinaryBlob); +/// __hip_register_globals(__hip_gpubin_handle); +/// } +/// } +/// \endcode llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { bool IsHIP = CGM.getLangOpts().HIP; // No need to generate ctors/dtors if there is no GPU binary. @@ -427,22 +439,68 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { /*constant*/ true); FatbinWrapper->setSection(FatbinSectionName); - // Register binary with CUDA/HIP runtime. This is substantially different in - // default mode vs. separate compilation! - if (!RelocatableDeviceCode) { - // GpuBinaryHandle = __{cuda|hip}RegisterFatBinary(&FatbinWrapper); + // There is only one HIP fat binary per linked module, however there are + // multiple constructor functions. Make sure the fat binary is registered + // only once. The constructor functions are executed by the dynamic loader + // before the program gains control. The dynamic loader cannot execute the + // constructor functions concurrently since doing that would not guarantee + // thread safety of the loaded program. Therefore we can assume sequential + // execution of constructor functions here. + if (IsHIP) { + llvm::BasicBlock *IfBlock = + llvm::BasicBlock::Create(Context, "if", ModuleCtorFunc); + llvm::BasicBlock *ExitBlock = + llvm::BasicBlock::Create(Context, "exit", ModuleCtorFunc); + // The name, size, and initialization pattern of this variable is part + // of HIP ABI. + GpuBinaryHandle = new llvm::GlobalVariable( + TheModule, VoidPtrPtrTy, /*isConstant=*/false, + llvm::GlobalValue::LinkOnceAnyLinkage, + /*Initializer=*/llvm::ConstantPointerNull::get(VoidPtrPtrTy), + "__hip_gpubin_handle"); + GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); + Address GpuBinaryAddr( + GpuBinaryHandle, + CharUnits::fromQuantity(GpuBinaryHandle->getAlignment())); + { + auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr); + llvm::Constant *Zero = + llvm::Constant::getNullValue(HandleValue->getType()); + llvm::Value *EQZero = CtorBuilder.CreateICmpEQ(HandleValue, Zero); + CtorBuilder.CreateCondBr(EQZero, IfBlock, ExitBlock); + } + { + CtorBuilder.SetInsertPoint(IfBlock); + // GpuBinaryHandle = __hipRegisterFatBinary(&FatbinWrapper); + llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall( + RegisterFatbinFunc, + CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy)); + CtorBuilder.CreateStore(RegisterFatbinCall, GpuBinaryAddr); + CtorBuilder.CreateBr(ExitBlock); + } + { + CtorBuilder.SetInsertPoint(ExitBlock); + // Call __hip_register_globals(GpuBinaryHandle); + if (RegisterGlobalsFunc) { + auto HandleValue = CtorBuilder.CreateLoad(GpuBinaryAddr); + CtorBuilder.CreateCall(RegisterGlobalsFunc, HandleValue); + } + } + } else if (!RelocatableDeviceCode) { + // Register binary with CUDA runtime. This is substantially different in + // default mode vs. separate compilation! + // GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper); llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall( RegisterFatbinFunc, CtorBuilder.CreateBitCast(FatbinWrapper, VoidPtrTy)); GpuBinaryHandle = new llvm::GlobalVariable( TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage, - llvm::ConstantPointerNull::get(VoidPtrPtrTy), - addUnderscoredPrefixToName("_gpubin_handle")); - + llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle"); + GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); CtorBuilder.CreateAlignedStore(RegisterFatbinCall, GpuBinaryHandle, CGM.getPointerAlign()); - // Call __{cuda|hip}_register_globals(GpuBinaryHandle); + // Call __cuda_register_globals(GpuBinaryHandle); if (RegisterGlobalsFunc) CtorBuilder.CreateCall(RegisterGlobalsFunc, RegisterFatbinCall); } else { @@ -453,15 +511,13 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { llvm::Constant *ModuleIDConstant = makeConstantString(ModuleID.str(), "", ModuleIDSectionName, 32); - // Create an alias for the FatbinWrapper that nvcc or hip backend will - // look for. + // Create an alias for the FatbinWrapper that nvcc will look for. llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage, Twine("__fatbinwrap") + ModuleID, FatbinWrapper); - // void __{cuda|hip}RegisterLinkedBinary%ModuleID%(void (*)(void *), void *, + // void __cudaRegisterLinkedBinary%ModuleID%(void (*)(void *), void *, // void *, void (*)(void **)) - SmallString<128> RegisterLinkedBinaryName( - addUnderscoredPrefixToName("RegisterLinkedBinary")); + SmallString<128> RegisterLinkedBinaryName("__cudaRegisterLinkedBinary"); RegisterLinkedBinaryName += ModuleID; llvm::Constant *RegisterLinkedBinaryFunc = CGM.CreateRuntimeFunction( getRegisterLinkedBinaryFnTy(), RegisterLinkedBinaryName); @@ -493,11 +549,23 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { /// Creates a global destructor function that unregisters the GPU code blob /// registered by constructor. +/// +/// For CUDA: /// \code /// void __cuda_module_dtor(void*) { /// __cudaUnregisterFatBinary(Handle); /// } /// \endcode +/// +/// For HIP: +/// \code +/// void __hip_module_dtor(void*) { +/// if (__hip_gpubin_handle) { +/// __hipUnregisterFatBinary(__hip_gpubin_handle); +/// __hip_gpubin_handle = 0; +/// } +/// } +/// \endcode llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() { // No need for destructor if we don't have a handle to unregister. if (!GpuBinaryHandle) @@ -518,10 +586,30 @@ llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() { CGBuilderTy DtorBuilder(CGM, Context); DtorBuilder.SetInsertPoint(DtorEntryBB); - auto HandleValue = - DtorBuilder.CreateAlignedLoad(GpuBinaryHandle, CGM.getPointerAlign()); - DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue); - + Address GpuBinaryAddr(GpuBinaryHandle, CharUnits::fromQuantity( + GpuBinaryHandle->getAlignment())); + auto HandleValue = DtorBuilder.CreateLoad(GpuBinaryAddr); + // There is only one HIP fat binary per linked module, however there are + // multiple destructor functions. Make sure the fat binary is unregistered + // only once. + if (CGM.getLangOpts().HIP) { + llvm::BasicBlock *IfBlock = + llvm::BasicBlock::Create(Context, "if", ModuleDtorFunc); + llvm::BasicBlock *ExitBlock = + llvm::BasicBlock::Create(Context, "exit", ModuleDtorFunc); + llvm::Constant *Zero = llvm::Constant::getNullValue(HandleValue->getType()); + llvm::Value *NEZero = DtorBuilder.CreateICmpNE(HandleValue, Zero); + DtorBuilder.CreateCondBr(NEZero, IfBlock, ExitBlock); + + DtorBuilder.SetInsertPoint(IfBlock); + DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue); + DtorBuilder.CreateStore(Zero, GpuBinaryAddr); + DtorBuilder.CreateBr(ExitBlock); + + DtorBuilder.SetInsertPoint(ExitBlock); + } else { + DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue); + } DtorBuilder.CreateRetVoid(); return ModuleDtorFunc; } diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu index 85f53c3b4f..716381b7a8 100644 --- a/test/CodeGenCUDA/device-stub.cu +++ b/test/CodeGenCUDA/device-stub.cu @@ -19,7 +19,7 @@ // RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefixes=NOGLOBALS,HIPNOGLOBALS // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s \ // RUN: -fcuda-rdc -fcuda-include-gpubinary %t -o - -x hip \ -// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,RDC,HIP,HIPRDC +// RUN: | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=ALL,NORDC,HIP // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - -x hip\ // RUN: | FileCheck -allow-deprecated-dag-overlap %s -check-prefix=NOGPUBIN @@ -79,11 +79,11 @@ void use_pointers() { // CUDA-SAME: section ".nvFatBinSegment" // HIP-SAME: section ".hipFatBinSegment" // * variable to save GPU binary handle after initialization -// NORDC: @__[[PREFIX]]_gpubin_handle = internal global i8** null +// CUDANORDC: @__[[PREFIX]]_gpubin_handle = internal global i8** null +// HIP: @__[[PREFIX]]_gpubin_handle = linkonce global i8** null // * constant unnamed string with NVModuleID // RDC: [[MODULE_ID_GLOBAL:@.*]] = private constant // CUDARDC-SAME: c"[[MODULE_ID:.+]]\00", section "__nv_module_id", align 32 -// HIPRDC-SAME: c"[[MODULE_ID:.+]]\00", section "__hip_module_id", align 32 // * Make sure our constructor was added to global ctor list. // ALL: @llvm.global_ctors = appending global {{.*}}@__[[PREFIX]]_module_ctor // * Alias to global symbol containing the NVModuleID. @@ -120,10 +120,18 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); } // ALL: define internal void @__[[PREFIX]]_module_ctor // In separate mode it calls __[[PREFIX]]RegisterFatBinary(&__[[PREFIX]]_fatbin_wrapper) +// HIP only register fat binary once. +// HIP: load i8**, i8*** @__hip_gpubin_handle +// HIP-NEXT: icmp eq i8** {{.*}}, null +// HIP-NEXT: br i1 {{.*}}, label %if, label %exit +// HIP: if: // NORDC: call{{.*}}[[PREFIX]]RegisterFatBinary{{.*}}__[[PREFIX]]_fatbin_wrapper // .. stores return value in __[[PREFIX]]_gpubin_handle // NORDC-NEXT: store{{.*}}__[[PREFIX]]_gpubin_handle // .. and then calls __[[PREFIX]]_register_globals +// HIP-NEXT: br label %exit +// HIP: exit: +// HIP-NEXT: load i8**, i8*** @__hip_gpubin_handle // NORDC-NEXT: call void @__[[PREFIX]]_register_globals // * In separate mode we also register a destructor. // NORDC-NEXT: call i32 @atexit(void (i8*)* @__[[PREFIX]]_module_dtor) @@ -136,7 +144,14 @@ void hostfunc(void) { kernelfunc<<<1, 1>>>(1, 1, 1); } // Test that we've created destructor. // NORDC: define internal void @__[[PREFIX]]_module_dtor // NORDC: load{{.*}}__[[PREFIX]]_gpubin_handle -// NORDC-NEXT: call void @__[[PREFIX]]UnregisterFatBinary +// CUDANORDC-NEXT: call void @__[[PREFIX]]UnregisterFatBinary +// HIP-NEXT: icmp ne i8** {{.*}}, null +// HIP-NEXT: br i1 {{.*}}, label %if, label %exit +// HIP: if: +// HIP-NEXT: call void @__[[PREFIX]]UnregisterFatBinary +// HIP-NEXT: store i8** null, i8*** @__hip_gpubin_handle +// HIP-NEXT: br label %exit +// HIP: exit: // There should be no __[[PREFIX]]_register_globals if we have no // device-side globals, but we still need to register GPU binary. -- GitLab From c86f04a1f2a8f98425fdfc362cb5084f17d08881 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 20 Jul 2018 23:34:39 +0000 Subject: [PATCH 0647/1023] [Driver] Sanitizer support based on runtime library presence The runtime libraries of sanitizers are built in compiler-rt, and Clang can be built without compiler-rt, or compiler-rt can be configured to only build certain sanitizers. The driver should provide reasonable diagnostics and not a link-time error when a runtime library is missing. This patch changes the driver for OS X to only support sanitizers of which we can find the runtime libraries. The discussion for this patch explains the rationale Differential Revision: https://reviews.llvm.org/D15225 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337635 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Darwin.cpp | 73 +++++++++++++------ lib/Driver/ToolChains/Darwin.h | 15 +++- .../darwin/libclang_rt.asan_ios_dynamic.dylib | 0 .../libclang_rt.asan_iossim_dynamic.dylib | 0 .../darwin/libclang_rt.asan_osx_dynamic.dylib | 0 .../libclang_rt.asan_tvos_dynamic.dylib | 0 .../libclang_rt.asan_tvossim_dynamic.dylib | 0 .../libclang_rt.asan_watchos_dynamic.dylib | 0 .../libclang_rt.asan_watchossim_dynamic.dylib | 0 .../lib/darwin/libclang_rt.fuzzer_osx.a | 0 .../darwin/libclang_rt.lsan_ios_dynamic.dylib | 0 .../libclang_rt.lsan_iossim_dynamic.dylib | 0 .../darwin/libclang_rt.lsan_osx_dynamic.dylib | 0 .../libclang_rt.lsan_tvossim_dynamic.dylib | 0 .../libclang_rt.tsan_iossim_dynamic.dylib | 0 .../darwin/libclang_rt.tsan_osx_dynamic.dylib | 0 .../libclang_rt.tsan_tvossim_dynamic.dylib | 0 test/Driver/darwin-asan-nofortify.c | 2 +- test/Driver/darwin-sanitizer-ld.c | 19 +++++ test/Driver/fsanitize.c | 26 +++---- test/Driver/fuzzer.c | 10 +-- test/Driver/sanitizer-ld.c | 3 + 22 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib create mode 100644 test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 9205dd52de..95ec8d64c2 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -916,13 +916,26 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const { return 4; } +SmallString<128> MachO::runtimeLibDir(bool IsEmbedded) const { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append( + Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin"); + return Dir; +} + +std::string Darwin::getFileNameForSanitizerLib(StringRef SanitizerName, + bool Shared) const { + return (Twine("libclang_rt.") + SanitizerName + "_" + + getOSLibraryNameSuffix() + + (Shared ? "_dynamic.dylib" : ".a")).str(); + +} + void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, StringRef DarwinLibName, RuntimeLinkOptions Opts) const { - SmallString<128> Dir(getDriver().ResourceDir); - llvm::sys::path::append( - Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin"); + SmallString<128> Dir = runtimeLibDir(Opts & RLO_IsEmbedded); SmallString<128> P(Dir); llvm::sys::path::append(P, DarwinLibName); @@ -1042,12 +1055,9 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, StringRef Sanitizer, bool Shared) const { auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U)); - AddLinkRuntimeLib(Args, CmdArgs, - (Twine("libclang_rt.") + Sanitizer + "_" + - getOSLibraryNameSuffix() + - (Shared ? "_dynamic.dylib" : ".a")) - .str(), - RLO); + std::string SanitizerRelFilename = + getFileNameForSanitizerLib(Sanitizer, Shared); + AddLinkRuntimeLib(Args, CmdArgs, SanitizerRelFilename, RLO); } ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( @@ -2285,24 +2295,43 @@ void Darwin::CheckObjCARC() const { SanitizerMask Darwin::getSupportedSanitizers() const { const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); - Res |= SanitizerKind::Address; - Res |= SanitizerKind::Leak; - Res |= SanitizerKind::Fuzzer; - Res |= SanitizerKind::FuzzerNoLink; + + { + using namespace SanitizerKind; + assert(!(Res & (Address | Leak | Fuzzer | FuzzerNoLink | Thread)) && + "Sanitizer is already registered as supported"); + } + + if (sanitizerRuntimeExists("asan")) + Res |= SanitizerKind::Address; + if (sanitizerRuntimeExists("lsan")) + Res |= SanitizerKind::Leak; + if (sanitizerRuntimeExists("fuzzer", /*Shared=*/false)) { + Res |= SanitizerKind::Fuzzer; + Res |= SanitizerKind::FuzzerNoLink; + } Res |= SanitizerKind::Function; - if (isTargetMacOS()) { - if (!isMacosxVersionLT(10, 9)) - Res |= SanitizerKind::Vptr; + if (isTargetMacOS() && !isMacosxVersionLT(10, 9)) + Res |= SanitizerKind::Vptr; + if (isTargetMacOS()) Res |= SanitizerKind::SafeStack; - if (IsX86_64) - Res |= SanitizerKind::Thread; - } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { - if (IsX86_64) - Res |= SanitizerKind::Thread; - } + + if (sanitizerRuntimeExists("tsan") && IsX86_64 && + (isTargetMacOS() || isTargetIOSSimulator() || isTargetTvOSSimulator())) + Res |= SanitizerKind::Thread; + return Res; } void Darwin::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); } + +bool Darwin::sanitizerRuntimeExists(StringRef SanitizerName, + bool Shared) const { + std::string RelName = getFileNameForSanitizerLib(SanitizerName, Shared); + SmallString<128> Dir = runtimeLibDir(); + SmallString<128> AbsName(Dir); + llvm::sys::path::append(AbsName, RelName); + return getVFS().exists(AbsName); +} diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h index 87d553bd7e..eee6e96671 100644 --- a/lib/Driver/ToolChains/Darwin.h +++ b/lib/Driver/ToolChains/Darwin.h @@ -130,6 +130,9 @@ protected: Tool *buildLinker() const override; Tool *getTool(Action::ActionClass AC) const override; + /// \return Directory to find the runtime library in. + SmallString<128> runtimeLibDir(bool IsEmbedded=false) const; + private: mutable std::unique_ptr Lipo; mutable std::unique_ptr Dsymutil; @@ -251,7 +254,6 @@ public: GetExceptionModel(const llvm::opt::ArgList &Args) const override { return llvm::ExceptionHandling::None; } - /// } }; @@ -420,6 +422,11 @@ protected: StringRef getPlatformFamily() const; StringRef getOSLibraryNameSuffix() const; + /// \return Relative path to the filename for the library + /// containing the sanitizer {@code SanitizerName}. + std::string getFileNameForSanitizerLib(StringRef SanitizerName, + bool Shared = true) const; + public: static StringRef getSDKName(StringRef isysroot); @@ -473,6 +480,12 @@ public: SanitizerMask getSupportedSanitizers() const override; void printVerboseInfo(raw_ostream &OS) const override; + +private: + /// \return Whether the runtime corresponding to the given + /// sanitizer exists in the toolchain. + bool sanitizerRuntimeExists(StringRef SanitizerName, + bool Shared = true) const; }; /// DarwinClang - The Darwin toolchain used by Clang. diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_ios_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_osx_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.fuzzer_osx.a new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_ios_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_iossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_osx_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.lsan_tvossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_iossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib b/test/Driver/Inputs/resource_dir/lib/darwin/libclang_rt.tsan_tvossim_dynamic.dylib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/darwin-asan-nofortify.c b/test/Driver/darwin-asan-nofortify.c index 58b5be9fcb..7d6da6d057 100644 --- a/test/Driver/darwin-asan-nofortify.c +++ b/test/Driver/darwin-asan-nofortify.c @@ -1,5 +1,5 @@ // Make sure AddressSanitizer disables _FORTIFY_SOURCE on Darwin. -// RUN: %clang -fsanitize=address %s -E -dM -target x86_64-darwin | FileCheck %s +// RUN: %clang -fsanitize=address %s -E -dM -target x86_64-darwin -resource-dir %S/Inputs/resource_dir | FileCheck %s // CHECK: #define _FORTIFY_SOURCE 0 diff --git a/test/Driver/darwin-sanitizer-ld.c b/test/Driver/darwin-sanitizer-ld.c index 53c7fce115..f7dfb157b4 100644 --- a/test/Driver/darwin-sanitizer-ld.c +++ b/test/Driver/darwin-sanitizer-ld.c @@ -1,6 +1,7 @@ // Test sanitizer link flags on Darwin. // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -stdlib=platform -fsanitize=address %s -o %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ASAN %s @@ -12,6 +13,14 @@ // CHECK-ASAN: "-rpath" "{{.*}}lib{{.*}}darwin" // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ +// RUN: -resource-dir %S/Inputs/fake_resource_dir \ +// RUN: -stdlib=platform -fsanitize=address %s -o %t.o 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LOAD-FAIL %s + +// CHECK-LOAD-FAIL: error: unsupported option '-fsanitize=address' for target 'x86_64--darwin' + +// RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -fPIC -shared -fsanitize=address %s -o %t.so 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-DYN-ASAN %s @@ -22,6 +31,7 @@ // CHECK-DYN-ASAN: "-rpath" "{{.*}}lib{{.*}}darwin" // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -stdlib=platform -fsanitize=undefined %s -o %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN %s @@ -34,6 +44,7 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ // RUN: -fsanitize=bounds -fsanitize-undefined-trap-on-error \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: %s -o %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-BOUNDS %s @@ -42,6 +53,7 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ // RUN: -fPIC -shared -fsanitize=undefined %s -o %t.so 2>&1 \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=CHECK-DYN-UBSAN %s // CHECK-DYN-UBSAN: "{{.*}}ld{{(.exe)?}}" @@ -52,6 +64,7 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ // RUN: -fsanitize=bounds -fsanitize-undefined-trap-on-error \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: %s -o %t.so -fPIC -shared 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-DYN-BOUNDS %s @@ -60,6 +73,7 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ // RUN: -stdlib=platform -fsanitize=address -mios-simulator-version-min=7.0 \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-IOSSIM %s // CHECK-ASAN-IOSSIM: "{{.*}}ld{{(.exe)?}}" @@ -70,6 +84,7 @@ // CHECK-ASAN-IOSSIM: "-rpath" "{{.*}}lib{{.*}}darwin" // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -stdlib=platform -fsanitize=address \ // RUN: -mtvos-simulator-version-min=8.3.0 %s -o %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-TVOSSIM %s @@ -83,6 +98,7 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-darwin \ // RUN: -stdlib=platform -fsanitize=address \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -mwatchos-simulator-version-min=2.0.0 %s -o %t.o 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-WATCHOSSIM %s @@ -94,6 +110,7 @@ // CHECK-ASAN-WATCHOSSIM: "-rpath" "{{.*}}lib{{.*}}darwin" // RUN: %clang -no-canonical-prefixes -### -target armv7-apple-ios \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: -stdlib=platform -fsanitize=address -miphoneos-version-min=7 \ // RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-IOS %s @@ -106,6 +123,7 @@ // RUN: %clang -no-canonical-prefixes -### -target arm64-apple-tvos \ // RUN: -stdlib=platform -fsanitize=address -mtvos-version-min=8.3 \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-TVOS %s // CHECK-ASAN-TVOS: "{{.*}}ld{{(.exe)?}}" @@ -117,6 +135,7 @@ // RUN: %clang -no-canonical-prefixes -### -target armv7k-apple-watchos \ // RUN: -stdlib=platform -fsanitize=address -mwatchos-version-min=2.0 \ +// RUN: -resource-dir %S/Inputs/resource_dir \ // RUN: %s -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ASAN-WATCHOS %s // CHECK-ASAN-WATCHOS: "{{.*}}ld{{(.exe)?}}" diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 946f2273cc..e6d94649f0 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -343,24 +343,24 @@ // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fno-sanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-NOMSAN-DARWIN // CHECK-MSAN-NOMSAN-DARWIN-NOT: unsupported option -// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fsanitize=thread,memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-TSAN-MSAN-DARWIN +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=memory -fsanitize=thread,memory -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-TSAN-MSAN-DARWIN // CHECK-MSAN-TSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10' // CHECK-MSAN-TSAN-MSAN-DARWIN-NOT: unsupported option -// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=thread,memory -fsanitize=memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MSAN-MSAN-DARWIN +// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=thread,memory -fsanitize=memory -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MSAN-MSAN-DARWIN // CHECK-TSAN-MSAN-MSAN-DARWIN: unsupported option '-fsanitize=memory' for target 'x86_64-apple-darwin10' // CHECK-TSAN-MSAN-MSAN-DARWIN-NOT: unsupported option -// RUN: %clang -target x86_64-apple-darwin -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-DARWIN +// RUN: %clang -target x86_64-apple-darwin -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-DARWIN // CHECK-TSAN-X86-64-DARWIN-NOT: unsupported option -// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-IOSSIMULATOR +// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-IOSSIMULATOR // CHECK-TSAN-X86-64-IOSSIMULATOR-NOT: unsupported option -// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-TVOSSIMULATOR +// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-X86-64-TVOSSIMULATOR // CHECK-TSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option -// RUN: %clang -target i386-apple-darwin -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-DARWIN +// RUN: %clang -target i386-apple-darwin -fsanitize=thread -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-DARWIN // CHECK-TSAN-I386-DARWIN: unsupported option '-fsanitize=thread' for target 'i386-apple-darwin' // RUN: %clang -target arm-apple-ios -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ARM-IOS @@ -433,25 +433,25 @@ // RUN: %clang -target i386-pc-openbsd -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-OPENBSD // CHECK-ESAN-OPENBSD: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i386-pc-openbsd' -// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN +// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN // CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option -// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR +// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR // CHECK-LSAN-X86-64-IOSSIMULATOR-NOT: unsupported option -// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR +// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR // CHECK-LSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option -// RUN: %clang -target i386-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN +// RUN: %clang -target i386-apple-darwin -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN // CHECK-LSAN-I386-DARWIN-NOT: unsupported option -// RUN: %clang -target arm-apple-ios -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS +// RUN: %clang -target arm-apple-ios -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS // CHECK-LSAN-ARM-IOS-NOT: unsupported option -// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR +// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR // CHECK-LSAN-I386-IOSSIMULATOR-NOT: unsupported option -// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR +// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR // CHECK-LSAN-I386-TVOSSIMULATOR-NOT: unsupported option // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 diff --git a/test/Driver/fuzzer.c b/test/Driver/fuzzer.c index 3fdf5ab9c9..5a371e260c 100644 --- a/test/Driver/fuzzer.c +++ b/test/Driver/fuzzer.c @@ -1,6 +1,6 @@ // Test flags inserted by -fsanitize=fuzzer. -// RUN: %clang -fsanitize=fuzzer %s -target x86_64-apple-darwin14 -### 2>&1 | FileCheck --check-prefixes=CHECK-FUZZER-LIB,CHECK-COVERAGE-FLAGS %s +// RUN: %clang -fsanitize=fuzzer %s -target x86_64-apple-darwin14 -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-FUZZER-LIB,CHECK-COVERAGE-FLAGS %s // // CHECK-FUZZER-LIB: libclang_rt.fuzzer // CHECK-COVERAGE: -fsanitize-coverage-inline-8bit-counters @@ -8,21 +8,21 @@ // CHECK-COVERAGE-SAME: -fsanitize-coverage-trace-cmp // CHECK-COVERAGE-SAME: -fsanitize-coverage-pc-table -// RUN: %clang -fsanitize=fuzzer -target i386-unknown-linux -stdlib=platform %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-LINUX %s +// RUN: %clang -fsanitize=fuzzer -target i386-unknown-linux -stdlib=platform -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-LINUX %s // // CHECK-LIBCXX-LINUX: -lstdc++ -// RUN: %clang -target x86_64-apple-darwin14 -fsanitize=fuzzer %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-DARWIN %s +// RUN: %clang -target x86_64-apple-darwin14 -fsanitize=fuzzer -resource-dir %S/Inputs/resource_dir %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LIBCXX-DARWIN %s // // CHECK-LIBCXX-DARWIN: -lc++ // Check that we don't link in libFuzzer.a when producing a shared object. -// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s +// RUN: %clang -fsanitize=fuzzer %s -shared -o %t.so -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB-SO %s // CHECK-NOLIB-SO-NOT: libclang_rt.libfuzzer // Check that we don't link in libFuzzer when compiling with -fsanitize=fuzzer-no-link. -// RUN: %clang -fsanitize=fuzzer-no-link %s -target x86_64-apple-darwin14 -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB,CHECK-COV %s +// RUN: %clang -fsanitize=fuzzer-no-link %s -target x86_64-apple-darwin14 -resource-dir %S/Inputs/resource_dir -### 2>&1 | FileCheck --check-prefixes=CHECK-NOLIB,CHECK-COV %s // CHECK-NOLIB-NOT: libclang_rt.libfuzzer // CHECK-COV: -fsanitize-coverage-inline-8bit-counters diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index 483c87a624..f07fe922ec 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -530,6 +530,7 @@ // RUN: %clangxx -fsanitize=address %s -### -o %t.o 2>&1 \ // RUN: -mmacosx-version-min=10.6 \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-DARWIN106-CXX %s @@ -539,6 +540,7 @@ // RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ // RUN: -mmacosx-version-min=10.6 \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s @@ -598,6 +600,7 @@ // RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-apple-darwin -fuse-ld=ld \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CFI-STATS-DARWIN %s // CHECK-CFI-STATS-DARWIN: "{{.*}}ld{{(.exe)?}}" -- GitLab From fb5f718cf1cae842bad8098764204e5a5b06a2d9 Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Fri, 20 Jul 2018 23:37:12 +0000 Subject: [PATCH 0648/1023] [NFC] CodeGen: rename memset to bzero The optimization looks for opportunities to emit bzero, not memset. Rename the functions accordingly (and clang-format the diff) because I want to add a fallback optimization which actually tries to generate memset. bzero is still better and it would confuse the code to merge both. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337636 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 57 ++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 9350e88f2e..89c5789c3e 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -846,11 +846,10 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, EmitStoreOfScalar(value, lvalue, /* isInitialization */ true); } -/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the -/// non-zero parts of the specified initializer with equal or fewer than -/// NumStores scalar stores. -static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, - unsigned &NumStores) { +/// Decide whether we can emit the non-zero parts of the specified initializer +/// with equal or fewer than NumStores scalar stores. +static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init, + unsigned &NumStores) { // Zero and Undef never requires any extra stores. if (isa(Init) || isa(Init) || @@ -865,7 +864,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, if (isa(Init) || isa(Init)) { for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) { llvm::Constant *Elt = cast(Init->getOperand(i)); - if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores)) + if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) return false; } return true; @@ -875,7 +874,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, dyn_cast(Init)) { for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) { llvm::Constant *Elt = CDS->getElementAsConstant(i); - if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores)) + if (!canEmitInitWithFewStoresAfterBZero(Elt, NumStores)) return false; } return true; @@ -885,15 +884,13 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, return false; } -/// emitStoresForInitAfterMemset - For inits that -/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar -/// stores that would be required. -static void emitStoresForInitAfterMemset(CodeGenModule &CGM, - llvm::Constant *Init, Address Loc, - bool isVolatile, - CGBuilderTy &Builder) { +/// For inits that canEmitInitWithFewStoresAfterBZero returned true for, emit +/// the scalar stores that would be required. +static void emitStoresForInitAfterBZero(CodeGenModule &CGM, + llvm::Constant *Init, Address Loc, + bool isVolatile, CGBuilderTy &Builder) { assert(!Init->isNullValue() && !isa(Init) && - "called emitStoresForInitAfterMemset for zero or undef value."); + "called emitStoresForInitAfterBZero for zero or undef value."); if (isa(Init) || isa(Init) || isa(Init) || isa(Init) || @@ -909,7 +906,7 @@ static void emitStoresForInitAfterMemset(CodeGenModule &CGM, // If necessary, get a pointer to the element and emit it. if (!Elt->isNullValue() && !isa(Elt)) - emitStoresForInitAfterMemset( + emitStoresForInitAfterBZero( CGM, Elt, Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), isVolatile, Builder); @@ -925,20 +922,19 @@ static void emitStoresForInitAfterMemset(CodeGenModule &CGM, // If necessary, get a pointer to the element and emit it. if (!Elt->isNullValue() && !isa(Elt)) - emitStoresForInitAfterMemset( + emitStoresForInitAfterBZero( CGM, Elt, Builder.CreateConstInBoundsGEP2_32(Loc, 0, i, CGM.getDataLayout()), isVolatile, Builder); } } -/// shouldUseMemSetPlusStoresToInitialize - Decide whether we should use memset -/// plus some stores to initialize a local variable instead of using a memcpy -/// from a constant global. It is beneficial to use memset if the global is all -/// zeros, or mostly zeros and large. -static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, - uint64_t GlobalSize) { - // If a global is all zeros, always use a memset. +/// Decide whether we should use bzero plus some stores to initialize a local +/// variable instead of using a memcpy from a constant global. It is beneficial +/// to use bzero if the global is all zeros, or mostly zeros and large. +static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, + uint64_t GlobalSize) { + // If a global is all zeros, always use a bzero. if (isa(Init)) return true; // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, @@ -949,7 +945,7 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, uint64_t SizeLimit = 32; return GlobalSize > SizeLimit && - canEmitInitWithFewStoresAfterMemset(Init, StoreBudget); + canEmitInitWithFewStoresAfterBZero(Init, StoreBudget); } /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a @@ -1405,17 +1401,18 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { if (Loc.getType() != BP) Loc = Builder.CreateBitCast(Loc, BP); - // If the initializer is all or mostly zeros, codegen with memset then do - // a few stores afterward. - if (shouldUseMemSetPlusStoresToInitialize(constant, - CGM.getDataLayout().getTypeAllocSize(constant->getType()))) { + // If the initializer is all or mostly zeros, codegen with bzero then do a + // few stores afterward. + if (shouldUseBZeroPlusStoresToInitialize( + constant, + CGM.getDataLayout().getTypeAllocSize(constant->getType()))) { Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, isVolatile); // Zero and undef don't require a stores. if (!constant->isNullValue() && !isa(constant)) { Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo(Loc.getAddressSpace())); - emitStoresForInitAfterMemset(CGM, constant, Loc, isVolatile, Builder); + emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder); } } else { // Otherwise, create a temporary global with the initializer then -- GitLab From e72aad6948944d73af10ad4246a31793f7ae43f0 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Sat, 21 Jul 2018 02:02:22 +0000 Subject: [PATCH 0649/1023] [HIP] Support -fcuda-flush-denormals-to-zero for amdgcn Differential Revision: https://reviews.llvm.org/D48287 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337639 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/LangOptions.def | 1 - lib/CodeGen/CGCall.cpp | 2 +- lib/CodeGen/CodeGenModule.cpp | 2 +- lib/Frontend/CompilerInvocation.cpp | 7 +++---- test/CodeGenCUDA/flush-denormals.cu | 15 +++++++++++++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index b1ac855715..fc38af5b03 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -209,7 +209,6 @@ LANGOPT(RenderScript , 1, 0, "RenderScript") LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code") LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__") -LANGOPT(CUDADeviceFlushDenormalsToZero, 1, 0, "flushing denormals to zero") LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions") LANGOPT(CUDARelocatableDeviceCode, 1, 0, "generate relocatable device code") diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index fcc8a3e5f6..f60136c2f1 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1800,7 +1800,7 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); // Respect -fcuda-flush-denormals-to-zero. - if (getLangOpts().CUDADeviceFlushDenormalsToZero) + if (CodeGenOpts.FlushDenorm) FuncAttrs.addAttribute("nvptx-f32ftz", "true"); } } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 627a33d8b5..ecdf78d4b3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -526,7 +526,7 @@ void CodeGenModule::Release() { // floating point values to 0. (This corresponds to its "__CUDA_FTZ" // property.) getModule().addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz", - LangOpts.CUDADeviceFlushDenormalsToZero ? 1 : 0); + CodeGenOpts.FlushDenorm ? 1 : 0); } // Emit OpenCL specific module metadata: OpenCL/SPIR version. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index a494b27a39..5878cce772 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -690,7 +690,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math)); Opts.Reassociate = Args.hasArg(OPT_mreassociate); - Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); + Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero) || + (Args.hasArg(OPT_fcuda_is_device) && + Args.hasArg(OPT_fcuda_flush_denormals_to_zero)); Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); Opts.UniformWGSize = @@ -2191,9 +2193,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_cuda_host_device_constexpr)) Opts.CUDAHostDeviceConstexpr = 0; - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero)) - Opts.CUDADeviceFlushDenormalsToZero = 1; - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals)) Opts.CUDADeviceApproxTranscendentals = 1; diff --git a/test/CodeGenCUDA/flush-denormals.cu b/test/CodeGenCUDA/flush-denormals.cu index 94285f1f33..13f2e3b287 100644 --- a/test/CodeGenCUDA/flush-denormals.cu +++ b/test/CodeGenCUDA/flush-denormals.cu @@ -5,6 +5,13 @@ // RUN: -triple nvptx-nvidia-cuda -emit-llvm -o - %s | \ // RUN: FileCheck %s -check-prefix CHECK -check-prefix FTZ +// RUN: %clang_cc1 -fcuda-is-device -x hip \ +// RUN: -triple amdgcn-amd-amdhsa -target-cpu gfx900 -emit-llvm -o - %s | \ +// RUN: FileCheck %s -check-prefix CHECK -check-prefix AMDNOFTZ +// RUN: %clang_cc1 -fcuda-is-device -x hip -fcuda-flush-denormals-to-zero \ +// RUN: -triple amdgcn-amd-amdhsa -target-cpu gfx900 -emit-llvm -o - %s | \ +// RUN: FileCheck %s -check-prefix CHECK -check-prefix AMDFTZ + #include "Inputs/cuda.h" // Checks that device function calls get emitted with the "ntpvx-f32ftz" @@ -12,11 +19,19 @@ // -fcuda-flush-denormals-to-zero. Further, check that we reflect the presence // or absence of -fcuda-flush-denormals-to-zero in a module flag. +// AMDGCN targets always have +fp64-fp16-denormals. +// AMDGCN targets without fast FMAF (e.g. gfx803) always have +fp32-denormals. +// For AMDGCN target with fast FMAF (e.g. gfx900), it has +fp32-denormals +// by default and -fp32-denormals when there is option +// -fcuda-flush-denormals-to-zero. + // CHECK-LABEL: define void @foo() #0 extern "C" __device__ void foo() {} // FTZ: attributes #0 = {{.*}} "nvptx-f32ftz"="true" // NOFTZ-NOT: attributes #0 = {{.*}} "nvptx-f32ftz" +// AMDNOFTZ: attributes #0 = {{.*}}+fp32-denormals{{.*}}+fp64-fp16-denormals +// AMDFTZ: attributes #0 = {{.*}}+fp64-fp16-denormals{{.*}}-fp32-denormals // FTZ:!llvm.module.flags = !{{{.*}}[[MODFLAG:![0-9]+]]} // FTZ:[[MODFLAG]] = !{i32 4, !"nvvm-reflect-ftz", i32 1} -- GitLab From 9d15b43884795a6a01604d5e99f6ad9242ecad39 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 22 Jul 2018 05:21:47 +0000 Subject: [PATCH 0650/1023] PR38257: don't perform ADL when instantiating a unary & operator that turns out to be forming a pointer-to-member. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337653 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 1 + lib/Sema/SemaExpr.cpp | 2 +- lib/Sema/TreeTransform.h | 8 ++-- .../argument-dependent-lookup.cpp | 45 +++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/SemaTemplate/argument-dependent-lookup.cpp diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0aa1fc42c6..ab934223b8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4262,6 +4262,7 @@ public: ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input); + bool isQualifiedMemberAccess(Expr *E); QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index e350517946..fc70c882c2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12809,7 +12809,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, /// Determine whether the given expression is a qualified member /// access expression, of a form that could be turned into a pointer to member /// with the address-of operator. -static bool isQualifiedMemberAccess(Expr *E) { +bool Sema::isQualifiedMemberAccess(Expr *E) { if (DeclRefExpr *DRE = dyn_cast(E)) { if (!DRE->getQualifier()) return false; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 5ed92aea32..1956739711 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -12658,9 +12658,11 @@ TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // -> is never a builtin operation. return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc); } else if (Second == nullptr || isPostIncDec) { - if (!First->getType()->isOverloadableType()) { - // The argument is not of overloadable type, so try to create a - // built-in unary operation. + if (!First->getType()->isOverloadableType() || + (Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) { + // The argument is not of overloadable type, or this is an expression + // of the form &Class::member, so try to create a built-in unary + // operation. UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); diff --git a/test/SemaTemplate/argument-dependent-lookup.cpp b/test/SemaTemplate/argument-dependent-lookup.cpp new file mode 100644 index 0000000000..d1603d56b9 --- /dev/null +++ b/test/SemaTemplate/argument-dependent-lookup.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify %s -DHAVE_UNQUALIFIED_LOOKUP_RESULTS +// expected-no-diagnostics + +namespace address_of { +#ifdef HAVE_UNQUALIFIED_LOOKUP_RESULTS + struct Q {}; + void operator&(Q); +#endif + + template struct A { + static constexpr auto x = &T::value; + }; + + template struct B { + constexpr int operator&() { return 123; } + }; + + template struct C { + static_assert(sizeof(T) == 123, ""); + }; + + struct X1 { + static B value; + }; + struct X2 : B { + enum E { value }; + friend constexpr int operator&(E) { return 123; } + }; + + struct Y1 { + C *value; + }; + struct Y2 { + C value(); + }; + + // ok, uses ADL to find operator&: + static_assert(A::x == 123, ""); + static_assert(A::x == 123, ""); + + // ok, does not use ADL so does not instantiate C: + static_assert(A::x == &Y1::value, ""); + static_assert(A::x == &Y2::value, ""); +} -- GitLab From e24fbbc0c4af1583fa08a21d471da8801b0cda5f Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sun, 22 Jul 2018 21:39:54 +0000 Subject: [PATCH 0651/1023] OpenBSD/arm has switched to float ABI SoftFP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337660 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Arch/ARM.cpp | 2 +- test/Driver/openbsd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index bb1685de76..886d947c58 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -232,7 +232,7 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { break; case llvm::Triple::OpenBSD: - ABI = FloatABI::Soft; + ABI = FloatABI::SoftFP; break; default: diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c index 098ecc4a27..7786969753 100644 --- a/test/Driver/openbsd.c +++ b/test/Driver/openbsd.c @@ -110,4 +110,4 @@ // Check ARM float ABI // RUN: %clang -target arm-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ARM-FLOAT-ABI %s -// CHECK-ARM-FLOAT-ABI: "-mfloat-abi" "soft" +// CHECK-ARM-FLOAT-ABI: "-mfloat-abi" "softfp" -- GitLab From 85eda8e66a1ec5948d5f10c7091f339c6fd1a2a6 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sun, 22 Jul 2018 22:04:28 +0000 Subject: [PATCH 0652/1023] Fix the test git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337663 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/openbsd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c index 7786969753..d3846b7acf 100644 --- a/test/Driver/openbsd.c +++ b/test/Driver/openbsd.c @@ -110,4 +110,5 @@ // Check ARM float ABI // RUN: %clang -target arm-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ARM-FLOAT-ABI %s -// CHECK-ARM-FLOAT-ABI: "-mfloat-abi" "softfp" +// CHECK-ARM-FLOAT-ABI-NOT: "-target-feature" "+soft-float" +// CHECK-ARM-FLOAT-ABI: "-target-feature" "+soft-float-abi" -- GitLab From 547ca57a7d60b97bcd9c9f0c9f072a6e7b2f5f5d Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Mon, 23 Jul 2018 06:32:36 +0000 Subject: [PATCH 0653/1023] Revert "Fold dangling-field warning into general initialization lifetime checks." This reverts commit r337627. After the change, clang started producing invalid warning on the following code: struct foo { foo(char *x) : x_(&x[10]) {} private: char *x_; }; 1.cpp:2:21: warning: initializing pointer member 'x_' with the stack address of parameter 'x' [-Wdangling-field] git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337671 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 8 +- lib/Sema/SemaDeclCXX.cpp | 49 ++++ lib/Sema/SemaInit.cpp | 252 ++++++------------ .../cxx-uninitialized-object-ptr-ref.cpp | 12 +- .../cxx0x-initializer-stdinitializerlist.cpp | 22 +- 5 files changed, 152 insertions(+), 191 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e45f5f3376..5ae749fa93 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7870,11 +7870,11 @@ def note_ref_var_local_bind : Note< // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< - "binding reference member %0 to stack allocated " - "%select{variable|parameter}2 %1">, InGroup; + "binding reference member %0 to stack allocated parameter %1">, + InGroup; def warn_init_ptr_member_to_parameter_addr : Warning< - "initializing pointer member %0 with the stack address of " - "%select{variable|parameter}2 %1">, InGroup; + "initializing pointer member %0 with the stack address of parameter %1">, + InGroup; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 031f8dbb38..d2a2bb2020 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3946,6 +3946,53 @@ Sema::BuildMemInitializer(Decl *ConstructorD, return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } +/// Checks a member initializer expression for cases where reference (or +/// pointer) members are bound to by-value parameters (or their addresses). +static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, + Expr *Init, + SourceLocation IdLoc) { + QualType MemberTy = Member->getType(); + + // We only handle pointers and references currently. + // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? + if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) + return; + + const bool IsPointer = MemberTy->isPointerType(); + if (IsPointer) { + if (const UnaryOperator *Op + = dyn_cast(Init->IgnoreParenImpCasts())) { + // The only case we're worried about with pointers requires taking the + // address. + if (Op->getOpcode() != UO_AddrOf) + return; + + Init = Op->getSubExpr(); + } else { + // We only handle address-of expression initializers for pointers. + return; + } + } + + if (const DeclRefExpr *DRE = dyn_cast(Init->IgnoreParens())) { + // We only warn when referring to a non-reference parameter declaration. + const ParmVarDecl *Parameter = dyn_cast(DRE->getDecl()); + if (!Parameter || Parameter->getType()->isReferenceType()) + return; + + S.Diag(Init->getExprLoc(), + IsPointer ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << Parameter << Init->getSourceRange(); + } else { + // Other initializers are fine. + return; + } + + S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) + << (unsigned)IsPointer; +} + MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -4000,6 +4047,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; + CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 73643a50fc..f94eabd671 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6227,7 +6227,7 @@ using LifetimeResult = /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. -static LifetimeResult getEntityLifetime( +static LifetimeResult getEntityForTemporaryLifetimeExtension( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: @@ -6239,7 +6239,8 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityLifetime(Entity->getParent(), Entity); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + Entity); // except: // C++17 [class.base.init]p8: @@ -6290,12 +6291,14 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. - return getEntityLifetime(Entity->getParent(), InitField); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityLifetime(Entity->getParent(), InitField); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: @@ -6308,61 +6311,46 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: + case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; - - case InitializedEntity::EK_Exception: - // FIXME: Can we diagnose lifetime problems with exceptions? - return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { -enum ReferenceKind { +enum ExtensionKind { /// Lifetime would be extended by a reference binding to a temporary. - RK_ReferenceBinding, + EK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. - RK_StdInitializerList, -}; - -/// A temporary or local variable. -using Local = llvm::PointerUnion; - -/// Expressions we stepped over when looking for the local state. Any steps -/// that would inhibit lifetime extension or take us out of subexpressions of -/// the initializer are included. -struct IndirectLocalPathEntry { - enum { - DefaultInit, - AddressOf, - } Kind; - Expr *E; + EK_StdInitializerList, }; - -using IndirectLocalPath = llvm::SmallVectorImpl; +using IndirectTemporaryPathEntry = + llvm::PointerUnion; +using IndirectTemporaryPath = llvm::SmallVectorImpl; struct RevertToOldSizeRAII { - IndirectLocalPath &Path; + IndirectTemporaryPath &Path; unsigned OldSize = Path.size(); - RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} + RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; } -template -static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, - Expr *Init, LocalVisitor Visit, - bool RevisitSubinits); +template +static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, + Expr *Init, + TemporaryVisitor Visit); -/// Visit the locals that would be reachable through a reference bound to the -/// glvalue expression \c Init. -template -static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, - Expr *Init, ReferenceKind RK, - LocalVisitor Visit) { +/// Visit the temporaries whose lifetimes would be extended by binding a +/// reference to the glvalue expression \c Init. +template +static void +visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, + Expr *Init, ExtensionKind EK, + TemporaryVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. @@ -6394,7 +6382,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back(DIE); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6403,36 +6391,25 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, } while (Init != Old); if (auto *MTE = dyn_cast(Init)) { - if (Visit(Path, Local(MTE), RK)) - visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, - true); - } - - // If we find the name of a local non-reference parameter, we could have a - // lifetime problem. - if (auto *DRE = dyn_cast(Init->IgnoreParens())) { - auto *VD = dyn_cast(DRE->getDecl()); - if (VD && VD->hasLocalStorage() && - !DRE->refersToEnclosingVariableOrCapture()) { - // FIXME: Recurse to the initializer of a local reference. - if (!VD->getType()->isReferenceType()) - Visit(Path, Local(VD), RK); - } + if (Visit(Path, MTE, EK)) + visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(), + Visit); } } -/// Visit the locals that would be reachable through an object initialized by -/// the prvalue expression \c Init. -template -static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, - Expr *Init, LocalVisitor Visit, - bool RevisitSubinits) { +/// Visit the temporaries whose lifetimes would be extended by +/// lifetime-extending the object initialized by the prvalue expression \c +/// Init. +template +static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, + Expr *Init, + TemporaryVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back(DIE); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6449,24 +6426,17 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast(Init)) - return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), - RK_StdInitializerList, Visit); + return visitTemporariesExtendedByReferenceBinding( + Path, ILE->getSubExpr(), EK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast(Init)) { - // We already visited the elements of this initializer list while - // performing the initialization. Don't visit them again unless we've - // changed the lifetime of the initialized entity. - if (!RevisitSubinits) - return; - if (ILE->isTransparent()) - return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, - RevisitSubinits); + return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0), + Visit); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) - visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, - RevisitSubinits); + visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit); return; } @@ -6478,8 +6448,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) - visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), - RK_ReferenceBinding, Visit); + visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0), + EK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { @@ -6489,38 +6459,25 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) - visitLocalsRetainedByReferenceBinding(Path, SubInit, - RK_ReferenceBinding, Visit); + visitTemporariesExtendedByReferenceBinding( + Path, SubInit, EK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. - visitLocalsRetainedByInitializer(Path, SubInit, Visit, - RevisitSubinits); + visitTemporariesExtendedByInitializer(Path, SubInit, Visit); ++Index; } } } - return; - } - - // If the initializer is the address of a local, we could have a lifetime - // problem. - if (auto *Op = dyn_cast(Init->IgnoreParenImpCasts())) { - if (Op->getOpcode() == UO_AddrOf) { - Path.push_back({IndirectLocalPathEntry::AddressOf, Op}); - Init = Op->getSubExpr(); - return visitLocalsRetainedByReferenceBinding(Path, Init, - RK_ReferenceBinding, Visit); - } } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). -static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { +static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { for (auto Elem : Path) { - if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) + if (!Elem.is()) return false; } return true; @@ -6528,7 +6485,7 @@ static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { - LifetimeResult LR = getEntityLifetime(&Entity); + LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); @@ -6537,54 +6494,9 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, if (LK == LK_FullExpression) return; - auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, - ReferenceKind RK) -> bool { - // If we found a path to a local variable or similar, check whether the - // initialized object will outlive it. - if (auto *VD = L.dyn_cast()) { - switch (LK) { - case LK_FullExpression: - llvm_unreachable("already handled this"); - - case LK_Extended: - break; - - case LK_MemInitializer: { - // Paths via a default initializer can only occur during error recovery - // (there's no other way that a default initializer can refer to a - // local). Don't produce a bogus warning on those cases. - if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { - return E.Kind == IndirectLocalPathEntry::DefaultInit; - })) - break; - - if (auto *Member = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { - bool AddressTaken = - !Path.empty() && - Path.back().Kind == IndirectLocalPathEntry::AddressOf; - Diag(Init->getExprLoc(), - AddressTaken ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << VD << isa(VD) << Init->getSourceRange(); - Diag(Member->getLocation(), - diag::note_ref_or_ptr_member_declared_here) - << (unsigned)AddressTaken; - } - break; - } - - case LK_New: - break; - - case LK_Return: - // FIXME: Move -Wreturn-stack-address checks here. - return false; - } - return false; - } - - auto *MTE = L.get(); + auto TemporaryVisitor = [&](IndirectTemporaryPath &Path, + MaterializeTemporaryExpr *MTE, + ExtensionKind EK) -> bool { switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); @@ -6608,11 +6520,11 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(MTE->getExprLoc(), - RK == RK_ReferenceBinding + EK == EK_ReferenceBinding ? diag::warn_default_member_init_temporary_not_extended : diag::warn_default_member_init_init_list_not_extended); } else { - // FIXME: Warn on this. + llvm_unreachable("unexpected indirect temporary path"); } break; @@ -6620,20 +6532,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. - if (auto *ExtendingDecl = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + if (auto *ExtendingDecl = ExtendingEntity->getDecl()) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary) << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember - << RK; + << EK; // Don't bother adding a note pointing to the field if we're inside its // default member initializer; our primary diagnostic points to the // same place in that case. - if (Path.empty() || - Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { + if (Path.empty() || !Path.back().is()) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) - << RK << IsSubobjectMember; + << EK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this @@ -6647,7 +6557,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_New: - if (RK == RK_ReferenceBinding) { + if (EK == EK_ReferenceBinding) { Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference); } else { Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list) @@ -6663,14 +6573,9 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // FIXME: Model these as CodeSynthesisContexts to fix the note emission // order. for (auto Elem : llvm::reverse(Path)) { - switch (Elem.Kind) { - case IndirectLocalPathEntry::DefaultInit: - Diag(Elem.E->getExprLoc(), diag::note_in_default_member_initalizer_here) - << cast(Elem.E)->getField(); - break; - - case IndirectLocalPathEntry::AddressOf: - break; + if (auto *DIE = Elem.dyn_cast()) { + Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here) + << DIE->getField(); } } @@ -6679,12 +6584,12 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, return false; }; - llvm::SmallVector Path; + llvm::SmallVector Path; if (Init->isGLValue()) - visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, - TemporaryVisitor); + visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding, + TemporaryVisitor); else - visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); + visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor); } static void DiagnoseNarrowingInInitList(Sema &S, @@ -6948,7 +6853,6 @@ InitializationSequence::Perform(Sema &S, // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. - // FIXME: Fold this into checkInitializerLifetime. if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { @@ -7111,6 +7015,11 @@ InitializationSequence::Perform(Sema &S, } } + // Even though we didn't materialize a temporary, the binding may still + // extend the lifetime of a temporary. This happens if we bind a + // reference to the result of a cast to reference type. + S.checkInitializerLifetime(Entity, CurInit.get()); + CheckForNullPointerDereference(S, CurInit.get()); break; @@ -7127,6 +7036,10 @@ InitializationSequence::Perform(Sema &S, Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; + // Maybe lifetime-extend the temporary's subobjects to match the + // entity's lifetime. + S.checkInitializerLifetime(Entity, CurInit.get()); + // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && @@ -7577,6 +7490,10 @@ InitializationSequence::Perform(Sema &S, // Wrap it in a construction of a std::initializer_list. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); + // Maybe lifetime-extend the array temporary's subobjects to match the + // entity's lifetime. + S.checkInitializerLifetime(Entity, CurInit.get()); + // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) @@ -7695,11 +7612,6 @@ InitializationSequence::Perform(Sema &S, } } - // Check whether the initializer has a shorter lifetime than the initialized - // entity, and if not, either lifetime-extend or warn as appropriate. - if (auto *Init = CurInit.get()) - S.checkInitializerLifetime(Entity, Init); - // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast(Entity.getDecl())->isBitField()) diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index 1507098c5e..db025420d7 100644 --- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -235,10 +235,10 @@ void fVoidPointerTest2() { } class VoidPointerRRefTest1 { - void *&&vptrrref; // expected-note {{here}} + void *&&vptrrref; public: - VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { // All good! } }; @@ -249,10 +249,10 @@ void fVoidPointerRRefTest1() { } class VoidPointerRRefTest2 { - void **&&vpptrrref; // expected-note {{here}} + void **&&vpptrrref; public: - VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}} + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { // All good! } }; @@ -263,10 +263,10 @@ void fVoidPointerRRefTest2() { } class VoidPointerLRefTest { - void *&vptrrref; // expected-note {{here}} + void *&vptrrref; public: - VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { // All good! } }; diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index e3c7e26afa..0184a1d6e7 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -72,18 +72,18 @@ std::initializer_list thread_local x = {1, 2, 3, 4}; // X86: @_ZN15partly_constant1kE = global i32 0, align 4 // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4 -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4 +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 // AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 -// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4 // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 @@ -375,7 +375,7 @@ namespace partly_constant { // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0) - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. -- GitLab From 102621ddc920e837847d95bd933623cb5ada02f5 Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Mon, 23 Jul 2018 10:50:20 +0000 Subject: [PATCH 0654/1023] [Analyzer] Quick Fix for exponential execution time when simpilifying complex additive expressions Patch https://reviews.llvm.org/rC329780 not only rearranges comparisons but also binary expressions. This latter behavior is not protected by the analyzer option. Hower, since no complexity threshold is enforced to the symbols this may result in exponential execution time if the expressions are too complex: https://bugs.llvm.org/show_bug.cgi?id=38208. For a quick fix we extended the analyzer option to also cover the additive cases. This is only a temporary fix, the final solution should be enforcing the complexity threshold to the symbols. Differential Revision: https://reviews.llvm.org/D49536 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337678 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../StaticAnalyzer/Core/AnalyzerOptions.h | 30 ++++----- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 10 +-- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 11 ++-- .../constraint_manager_negate_difference.c | 2 +- test/Analysis/iterator-range.cpp | 4 +- test/Analysis/plist-macros.cpp | 63 +++++++++++++++++++ .../svalbuilder-rearrange-comparisons.c | 2 +- 7 files changed, 94 insertions(+), 28 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index aa59d6ff53..9d292cfddb 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -318,8 +318,8 @@ private: /// \sa shouldDisplayNotesAsEvents Optional DisplayNotesAsEvents; - /// \sa shouldAggressivelySimplifyRelationalComparison - Optional AggressiveRelationalComparisonSimplification; + /// \sa shouldAggressivelySimplifyBinaryOperation + Optional AggressiveBinaryOperationSimplification; /// \sa getCTUDir Optional CTUDir; @@ -690,19 +690,19 @@ public: /// to false when unset. bool shouldDisplayNotesAsEvents(); - /// Returns true if SValBuilder should rearrange comparisons of symbolic - /// expressions which consist of a sum of a symbol and a concrete integer - /// into the format where symbols are on the left-hand side and the integer - /// is on the right. This is only done if both symbols and both concrete - /// integers are signed, greater than or equal to the quarter of the minimum - /// value of the type and less than or equal to the quarter of the maximum - /// value of that type. - /// - /// A + n B + m becomes A - B m - n, where A and B symbolic, - /// n and m are integers. is any of '==', '!=', '<', '<=', '>' or '>='. - /// The rearrangement also happens with '-' instead of '+' on either or both - /// side and also if any or both integers are missing. - bool shouldAggressivelySimplifyRelationalComparison(); + /// Returns true if SValBuilder should rearrange comparisons and additive + /// operations of symbolic expressions which consist of a sum of a symbol and + /// a concrete integer into the format where symbols are on the left-hand + /// side and the integer is on the right. This is only done if both symbols + /// and both concrete integers are signed, greater than or equal to the + /// quarter of the minimum value of the type and less than or equal to the + /// quarter of the maximum value of that type. + /// + /// A + n B + m becomes A - B m - n, where A and B symbolic, + /// n and m are integers. is any of '==', '!=', '<', '<=', '>', '>=', + /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on + // either or both side and also if any or both integers are missing. + bool shouldAggressivelySimplifyBinaryOperation(); /// Returns the directory containing the CTU related files. StringRef getCTUDir(); diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index eac07e659d..9b2dc32e06 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -463,12 +463,12 @@ bool AnalyzerOptions::shouldDisplayNotesAsEvents() { return DisplayNotesAsEvents.getValue(); } -bool AnalyzerOptions::shouldAggressivelySimplifyRelationalComparison() { - if (!AggressiveRelationalComparisonSimplification.hasValue()) - AggressiveRelationalComparisonSimplification = - getBooleanOption("aggressive-relational-comparison-simplification", +bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() { + if (!AggressiveBinaryOperationSimplification.hasValue()) + AggressiveBinaryOperationSimplification = + getBooleanOption("aggressive-binary-operation-simplification", /*Default=*/false); - return AggressiveRelationalComparisonSimplification.getValue(); + return AggressiveBinaryOperationSimplification.getValue(); } StringRef AnalyzerOptions::getCTUDir() { diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 7163e380e6..beae0dfae2 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -456,14 +456,17 @@ static Optional tryRearrange(ProgramStateRef State, auto &Opts = StateMgr.getOwningEngine()->getAnalysisManager().getAnalyzerOptions(); + // FIXME: After putting complexity threshold to the symbols we can always + // rearrange additive operations but rearrange comparisons only if + // option is set. + if(!Opts.shouldAggressivelySimplifyBinaryOperation()) + return None; + SymbolRef LSym = Lhs.getAsSymbol(); if (!LSym) return None; - // Always rearrange additive operations but rearrange comparisons only if - // option is set. - if (BinaryOperator::isComparisonOp(Op) && - Opts.shouldAggressivelySimplifyRelationalComparison()) { + if (BinaryOperator::isComparisonOp(Op)) { SingleTy = LSym->getType(); if (ResultTy != SVB.getConditionType()) return None; diff --git a/test/Analysis/constraint_manager_negate_difference.c b/test/Analysis/constraint_manager_negate_difference.c index 6856f48bb0..2236c1693b 100644 --- a/test/Analysis/constraint_manager_negate_difference.c +++ b/test/Analysis/constraint_manager_negate_difference.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-relational-comparison-simplification=true -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s void clang_analyzer_eval(int); diff --git a/test/Analysis/iterator-range.cpp b/test/Analysis/iterator-range.cpp index 45d9f194d4..8a4ba29b0c 100644 --- a/test/Analysis/iterator-range.cpp +++ b/test/Analysis/iterator-range.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-relational-comparison-simplification=true -analyzer-config c++-container-inlining=false %s -verify -// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-relational-comparison-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-eagerly-assume -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify #include "Inputs/system-header-simulator-cxx.h" diff --git a/test/Analysis/plist-macros.cpp b/test/Analysis/plist-macros.cpp index 53f7a19c13..4f7d3a2545 100644 --- a/test/Analysis/plist-macros.cpp +++ b/test/Analysis/plist-macros.cpp @@ -637,6 +637,69 @@ void test2(int *p) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col25 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: message +// CHECK-NEXT: Assuming the condition is true +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line36 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: line37 // CHECK-NEXT: col5 // CHECK-NEXT: file0 diff --git a/test/Analysis/svalbuilder-rearrange-comparisons.c b/test/Analysis/svalbuilder-rearrange-comparisons.c index 2303ce693c..ac186120fe 100644 --- a/test/Analysis/svalbuilder-rearrange-comparisons.c +++ b/test/Analysis/svalbuilder-rearrange-comparisons.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-relational-comparison-simplification=true -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s void clang_analyzer_dump(int x); void clang_analyzer_eval(int x); -- GitLab From f2c1a12c18bda617e32a79ac1c2adcc0cf2e883e Mon Sep 17 00:00:00 2001 From: Adam Balogh Date: Mon, 23 Jul 2018 10:53:02 +0000 Subject: [PATCH 0655/1023] Fix for last commit: adding new test file forgotten. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337679 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/PR38208.c | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 test/Analysis/PR38208.c diff --git a/test/Analysis/PR38208.c b/test/Analysis/PR38208.c new file mode 100644 index 0000000000..fb0a5a15ea --- /dev/null +++ b/test/Analysis/PR38208.c @@ -0,0 +1,43 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s + +// expected-no-diagnostics + +int foo(int a, int b) { + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + a += b; b -= a; + return a + b; +} -- GitLab From 2e2d5d03cb9ce174c39c2975c6d9d510058e8421 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Mon, 23 Jul 2018 11:25:25 +0000 Subject: [PATCH 0656/1023] [Tooling] Use UniqueStringSaver. NFC git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337682 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Tooling/Execution.h | 5 ++--- lib/Tooling/Execution.cpp | 11 +---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h index 71c97f3db1..68aef53cb5 100644 --- a/include/clang/Tooling/Execution.h +++ b/include/clang/Tooling/Execution.h @@ -57,7 +57,7 @@ public: /// set of different results, or a large set of duplicated results. class InMemoryToolResults : public ToolResults { public: - InMemoryToolResults() : StringsPool(Arena) {} + InMemoryToolResults() : Strings(Arena) {} void addResult(StringRef Key, StringRef Value) override; std::vector> AllKVResults() override; @@ -66,8 +66,7 @@ public: private: llvm::BumpPtrAllocator Arena; - llvm::StringSaver StringsPool; - llvm::DenseSet Strings; + llvm::UniqueStringSaver Strings; std::vector> KVResults; }; diff --git a/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp index 5d6559fb2b..7ae67747ac 100644 --- a/lib/Tooling/Execution.cpp +++ b/lib/Tooling/Execution.cpp @@ -21,16 +21,7 @@ static llvm::cl::opt llvm::cl::init("standalone")); void InMemoryToolResults::addResult(StringRef Key, StringRef Value) { - auto Intern = [&](StringRef &V) { - auto R = Strings.insert(V); - if (R.second) { // A new entry, create a new string copy. - *R.first = StringsPool.save(V); - } - V = *R.first; - }; - Intern(Key); - Intern(Value); - KVResults.push_back({Key, Value}); + KVResults.push_back({Strings.save(Key), Strings.save(Value)}); } std::vector> -- GitLab From e08d24e89fbaf9178e70e9ffcec8ecdfedd2b2fb Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 23 Jul 2018 12:45:24 +0000 Subject: [PATCH 0657/1023] [AST] Use llvm::TrailingObjects in CXXTryStmt 1. Use llvm::TrailingObjects in CXXTryStmt instead of manually doing the reinterpret_casts + pointer arithmetic. This is more consistent with other classes using this idiom and this make it clearer that this class has trailing objects. 2. Make the class CXXTryStmt final since it has trailing objects. 3. Move the friend declarations together. No functional changes. Patch by Bruno Ricci! Differential Revision: https://reviews.llvm.org/D48873 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337688 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/StmtCXX.h | 19 +++++++++---------- lib/AST/StmtCXX.cpp | 10 +++------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 3dfdde5d8a..34553741eb 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -62,21 +62,22 @@ public: /// CXXTryStmt - A C++ try block, including all handlers. /// -class CXXTryStmt : public Stmt { +class CXXTryStmt final : public Stmt, + private llvm::TrailingObjects { + + friend TrailingObjects; + friend class ASTStmtReader; + SourceLocation TryLoc; unsigned NumHandlers; + size_t numTrailingObjects(OverloadToken) const { return NumHandlers; } CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef handlers); - CXXTryStmt(EmptyShell Empty, unsigned numHandlers) : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } - Stmt const * const *getStmts() const { - return reinterpret_cast(this + 1); - } - Stmt **getStmts() { - return reinterpret_cast(this + 1); - } + Stmt *const *getStmts() const { return getTrailingObjects(); } + Stmt **getStmts() { return getTrailingObjects(); } public: static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, @@ -115,8 +116,6 @@ public: child_range children() { return child_range(getStmts(), getStmts() + getNumHandlers() + 1); } - - friend class ASTStmtReader; }; /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index 666f5dcc9d..bf2d6a16fb 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -25,18 +25,14 @@ QualType CXXCatchStmt::getCaughtType() const { CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, ArrayRef handlers) { - std::size_t Size = sizeof(CXXTryStmt); - Size += ((handlers.size() + 1) * sizeof(Stmt *)); - + const size_t Size = totalSizeToAlloc(handlers.size() + 1); void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); } CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, unsigned numHandlers) { - std::size_t Size = sizeof(CXXTryStmt); - Size += ((numHandlers + 1) * sizeof(Stmt *)); - + const size_t Size = totalSizeToAlloc(numHandlers + 1); void *Mem = C.Allocate(Size, alignof(CXXTryStmt)); return new (Mem) CXXTryStmt(Empty, numHandlers); } @@ -44,7 +40,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef handlers) : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) { - Stmt **Stmts = reinterpret_cast(this + 1); + Stmt **Stmts = getStmts(); Stmts[0] = tryBlock; std::copy(handlers.begin(), handlers.end(), Stmts + 1); } -- GitLab From e701fd894955856e47459113e09b0ff3e6b8590c Mon Sep 17 00:00:00 2001 From: "Ivan A. Kosarev" Date: Mon, 23 Jul 2018 13:26:37 +0000 Subject: [PATCH 0658/1023] [NEON] Fix support for vrndi_f32(), vrndiq_f32() and vrndns_f32() intrinsics This patch adds support for vrndi_f32() and vrndiq_f32() intrinsics in AArch32 mode and for vrndns_f32() intrinsic in AArch64 mode. Differential Revision: https://reviews.llvm.org/D48829 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337690 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 3 +- lib/CodeGen/CGBuiltin.cpp | 19 ++-- test/CodeGen/aarch64-neon-misc.c | 112 ---------------------- test/CodeGen/arm-neon-directed-rounding.c | 112 ++++++++++++++-------- test/CodeGen/arm64-vrnd.c | 29 ------ 5 files changed, 87 insertions(+), 188 deletions(-) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index f7c8ea5281..9b03091e14 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -988,6 +988,7 @@ def FRINTP_S32 : SInst<"vrndp", "dd", "fQf">; def FRINTM_S32 : SInst<"vrndm", "dd", "fQf">; def FRINTX_S32 : SInst<"vrndx", "dd", "fQf">; def FRINTZ_S32 : SInst<"vrnd", "dd", "fQf">; +def FRINTI_S32 : SInst<"vrndi", "dd", "fQf">; } let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in { @@ -997,7 +998,7 @@ def FRINTP_S64 : SInst<"vrndp", "dd", "dQd">; def FRINTM_S64 : SInst<"vrndm", "dd", "dQd">; def FRINTX_S64 : SInst<"vrndx", "dd", "dQd">; def FRINTZ_S64 : SInst<"vrnd", "dd", "dQd">; -def FRINTI_S64 : SInst<"vrndi", "dd", "fdQfQd">; +def FRINTI_S64 : SInst<"vrndi", "dd", "dQd">; } //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index b6d30a956d..0892e84a04 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -4158,6 +4158,8 @@ static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = { NEONMAP1(vrnd_v, arm_neon_vrintz, Add1ArgType), NEONMAP1(vrnda_v, arm_neon_vrinta, Add1ArgType), NEONMAP1(vrndaq_v, arm_neon_vrinta, Add1ArgType), + NEONMAP0(vrndi_v), + NEONMAP0(vrndiq_v), NEONMAP1(vrndm_v, arm_neon_vrintm, Add1ArgType), NEONMAP1(vrndmq_v, arm_neon_vrintm, Add1ArgType), NEONMAP1(vrndn_v, arm_neon_vrintn, Add1ArgType), @@ -4334,6 +4336,8 @@ static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = { NEONMAP1(vrecpsq_v, aarch64_neon_frecps, Add1ArgType), NEONMAP2(vrhadd_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts), NEONMAP2(vrhaddq_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts), + NEONMAP0(vrndi_v), + NEONMAP0(vrndiq_v), NEONMAP2(vrshl_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts), NEONMAP2(vrshlq_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts), NEONMAP2(vrshr_n_v, aarch64_neon_urshl, aarch64_neon_srshl, UnsignedAlts), @@ -5094,7 +5098,10 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vrsqrteq_v: Int = Ty->isFPOrFPVectorTy() ? LLVMIntrinsic : AltLLVMIntrinsic; return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint); - + case NEON::BI__builtin_neon_vrndi_v: + case NEON::BI__builtin_neon_vrndiq_v: + Int = Intrinsic::nearbyint; + return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, NameHint); case NEON::BI__builtin_neon_vrshr_n_v: case NEON::BI__builtin_neon_vrshrq_n_v: return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n", @@ -7486,11 +7493,6 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, Int = Intrinsic::nearbyint; return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndi"); } - case NEON::BI__builtin_neon_vrndi_v: - case NEON::BI__builtin_neon_vrndiq_v: { - Int = Intrinsic::nearbyint; - return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndi"); - } case NEON::BI__builtin_neon_vrndmh_f16: { Ops.push_back(EmitScalarExpr(E->getArg(0))); Int = Intrinsic::floor; @@ -7511,6 +7513,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, Int = Intrinsic::aarch64_neon_frintn; return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn"); } + case NEON::BI__builtin_neon_vrndns_f32: { + Ops.push_back(EmitScalarExpr(E->getArg(0))); + Int = Intrinsic::aarch64_neon_frintn; + return EmitNeonCall(CGM.getIntrinsic(Int, FloatTy), Ops, "vrndn"); + } case NEON::BI__builtin_neon_vrndph_f16: { Ops.push_back(EmitScalarExpr(E->getArg(0))); Int = Intrinsic::ceil; diff --git a/test/CodeGen/aarch64-neon-misc.c b/test/CodeGen/aarch64-neon-misc.c index 0772d4fc67..f8ba7ee712 100644 --- a/test/CodeGen/aarch64-neon-misc.c +++ b/test/CodeGen/aarch64-neon-misc.c @@ -2253,22 +2253,6 @@ float64x2_t test_vcvt_high_f64_f32(float32x4_t a) { return vcvt_high_f64_f32(a); } -// CHECK-LABEL: @test_vrndn_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDN1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDN1_I]] -float32x2_t test_vrndn_f32(float32x2_t a) { - return vrndn_f32(a); -} - -// CHECK-LABEL: @test_vrndnq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDN1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDN1_I]] -float32x4_t test_vrndnq_f32(float32x4_t a) { - return vrndnq_f32(a); -} - // CHECK-LABEL: @test_vrndnq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDN1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> %a) @@ -2277,22 +2261,6 @@ float64x2_t test_vrndnq_f64(float64x2_t a) { return vrndnq_f64(a); } -// CHECK-LABEL: @test_vrnda_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDA1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDA1_I]] -float32x2_t test_vrnda_f32(float32x2_t a) { - return vrnda_f32(a); -} - -// CHECK-LABEL: @test_vrndaq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDA1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDA1_I]] -float32x4_t test_vrndaq_f32(float32x4_t a) { - return vrndaq_f32(a); -} - // CHECK-LABEL: @test_vrndaq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDA1_I:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> %a) @@ -2301,22 +2269,6 @@ float64x2_t test_vrndaq_f64(float64x2_t a) { return vrndaq_f64(a); } -// CHECK-LABEL: @test_vrndp_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDP1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDP1_I]] -float32x2_t test_vrndp_f32(float32x2_t a) { - return vrndp_f32(a); -} - -// CHECK-LABEL: @test_vrndpq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDP1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDP1_I]] -float32x4_t test_vrndpq_f32(float32x4_t a) { - return vrndpq_f32(a); -} - // CHECK-LABEL: @test_vrndpq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDP1_I:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> %a) @@ -2325,22 +2277,6 @@ float64x2_t test_vrndpq_f64(float64x2_t a) { return vrndpq_f64(a); } -// CHECK-LABEL: @test_vrndm_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDM1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDM1_I]] -float32x2_t test_vrndm_f32(float32x2_t a) { - return vrndm_f32(a); -} - -// CHECK-LABEL: @test_vrndmq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDM1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDM1_I]] -float32x4_t test_vrndmq_f32(float32x4_t a) { - return vrndmq_f32(a); -} - // CHECK-LABEL: @test_vrndmq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDM1_I:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> %a) @@ -2349,22 +2285,6 @@ float64x2_t test_vrndmq_f64(float64x2_t a) { return vrndmq_f64(a); } -// CHECK-LABEL: @test_vrndx_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDX1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDX1_I]] -float32x2_t test_vrndx_f32(float32x2_t a) { - return vrndx_f32(a); -} - -// CHECK-LABEL: @test_vrndxq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDX1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDX1_I]] -float32x4_t test_vrndxq_f32(float32x4_t a) { - return vrndxq_f32(a); -} - // CHECK-LABEL: @test_vrndxq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDX1_I:%.*]] = call <2 x double> @llvm.rint.v2f64(<2 x double> %a) @@ -2373,22 +2293,6 @@ float64x2_t test_vrndxq_f64(float64x2_t a) { return vrndxq_f64(a); } -// CHECK-LABEL: @test_vrnd_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDZ1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDZ1_I]] -float32x2_t test_vrnd_f32(float32x2_t a) { - return vrnd_f32(a); -} - -// CHECK-LABEL: @test_vrndq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDZ1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDZ1_I]] -float32x4_t test_vrndq_f32(float32x4_t a) { - return vrndq_f32(a); -} - // CHECK-LABEL: @test_vrndq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDZ1_I:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> %a) @@ -2397,22 +2301,6 @@ float64x2_t test_vrndq_f64(float64x2_t a) { return vrndq_f64(a); } -// CHECK-LABEL: @test_vrndi_f32( -// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> -// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> %a) -// CHECK: ret <2 x float> [[VRNDI1_I]] -float32x2_t test_vrndi_f32(float32x2_t a) { - return vrndi_f32(a); -} - -// CHECK-LABEL: @test_vrndiq_f32( -// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> -// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a) -// CHECK: ret <4 x float> [[VRNDI1_I]] -float32x4_t test_vrndiq_f32(float32x4_t a) { - return vrndiq_f32(a); -} - // CHECK-LABEL: @test_vrndiq_f64( // CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8> // CHECK: [[VRNDI1_I:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %a) diff --git a/test/CodeGen/arm-neon-directed-rounding.c b/test/CodeGen/arm-neon-directed-rounding.c index 9f30ac7cb0..5119f9dbf4 100644 --- a/test/CodeGen/arm-neon-directed-rounding.c +++ b/test/CodeGen/arm-neon-directed-rounding.c @@ -1,96 +1,128 @@ // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 \ // RUN: -ffreestanding -disable-O0-optnone -emit-llvm %s -o - | \ -// RUN: opt -S -mem2reg | FileCheck %s +// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A32 %s +// RUN: %clang_cc1 -triple arm64-linux-gnueabihf -target-feature +neon \ +// RUN: -ffreestanding -disable-O0-optnone -emit-llvm %s -o - | \ +// RUN: opt -S -mem2reg | FileCheck -check-prefixes=CHECK,CHECK-A64 %s #include -// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a) #0 { -// CHECK: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRNDA_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a) +// CHECK-A32: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> %a) +// CHECK-A64: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDA_V1_I]] float32x2_t test_vrnda_f32(float32x2_t a) { return vrnda_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndaq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDAQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndaq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDAQ_V1_I]] float32x4_t test_vrndaq_f32(float32x4_t a) { return vrndaq_f32(a); } -// CHECK-LABEL: define <2 x float> @test_vrndm_f32(<2 x float> %a) #0 { -// CHECK: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRNDM_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrndm_f32(<2 x float> %a) +// CHECK-A32: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> %a) +// CHECK-A64: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDM_V1_I]] float32x2_t test_vrndm_f32(float32x2_t a) { return vrndm_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndmq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDMQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndmq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDMQ_V1_I]] float32x4_t test_vrndmq_f32(float32x4_t a) { return vrndmq_f32(a); } -// CHECK-LABEL: define <2 x float> @test_vrndn_f32(<2 x float> %a) #0 { -// CHECK: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRNDN_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrndn_f32(<2 x float> %a) +// CHECK-A32: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> %a) +// CHECK-A64: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDN_V1_I]] float32x2_t test_vrndn_f32(float32x2_t a) { return vrndn_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndnq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDNQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndnq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDNQ_V1_I]] float32x4_t test_vrndnq_f32(float32x4_t a) { return vrndnq_f32(a); } -// CHECK-LABEL: define <2 x float> @test_vrndp_f32(<2 x float> %a) #0 { -// CHECK: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRNDP_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrndp_f32(<2 x float> %a) +// CHECK-A32: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> %a) +// CHECK-A64: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDP_V1_I]] float32x2_t test_vrndp_f32(float32x2_t a) { return vrndp_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndpq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDPQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndpq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDPQ_V1_I]] float32x4_t test_vrndpq_f32(float32x4_t a) { return vrndpq_f32(a); } -// CHECK-LABEL: define <2 x float> @test_vrndx_f32(<2 x float> %a) #0 { -// CHECK: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRNDX_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrndx_f32(<2 x float> %a) +// CHECK-A32: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> %a) +// CHECK-A64: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDX_V1_I]] float32x2_t test_vrndx_f32(float32x2_t a) { return vrndx_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndxq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDXQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndxq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDXQ_V1_I]] float32x4_t test_vrndxq_f32(float32x4_t a) { return vrndxq_f32(a); } -// CHECK-LABEL: define <2 x float> @test_vrnd_f32(<2 x float> %a) #0 { -// CHECK: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> %a) #2 -// CHECK: ret <2 x float> [[VRND_V1_I]] +// CHECK-LABEL: define <2 x float> @test_vrnd_f32(<2 x float> %a) +// CHECK-A32: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> %a) +// CHECK-A64: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRND_V1_I]] float32x2_t test_vrnd_f32(float32x2_t a) { return vrnd_f32(a); } -// CHECK-LABEL: define <4 x float> @test_vrndq_f32(<4 x float> %a) #0 { -// CHECK: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> %a) #2 -// CHECK: ret <4 x float> [[VRNDQ_V1_I]] +// CHECK-LABEL: define <4 x float> @test_vrndq_f32(<4 x float> %a) +// CHECK-A32: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> %a) +// CHECK-A64: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDQ_V1_I]] float32x4_t test_vrndq_f32(float32x4_t a) { return vrndq_f32(a); } -// CHECK-LABEL: define float @test_vrndns_f32(float %a) #0 { -// CHECK: [[VRNDN_I:%.*]] = call float @llvm.arm.neon.vrintn.f32(float %a) #2 -// CHECK: ret float [[VRNDN_I]] +// CHECK-LABEL: define float @test_vrndns_f32(float %a) +// CHECK-A32: [[VRNDN_I:%.*]] = call float @llvm.arm.neon.vrintn.f32(float %a) +// CHECK-A64: [[VRNDN_I:%.*]] = call float @llvm.aarch64.neon.frintn.f32(float %a) +// CHECK: ret float [[VRNDN_I]] float32_t test_vrndns_f32(float32_t a) { return vrndns_f32(a); } + +// CHECK-LABEL: define <2 x float> @test_vrndi_f32(<2 x float> %a) +// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8> +// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> %a) +// CHECK: ret <2 x float> [[VRNDI1_I]] +float32x2_t test_vrndi_f32(float32x2_t a) { + return vrndi_f32(a); +} + +// CHECK-LABEL: define <4 x float> @test_vrndiq_f32(<4 x float> %a) +// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8> +// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a) +// CHECK: ret <4 x float> [[VRNDI1_I]] +float32x4_t test_vrndiq_f32(float32x4_t a) { + return vrndiq_f32(a); +} diff --git a/test/CodeGen/arm64-vrnd.c b/test/CodeGen/arm64-vrnd.c index 2c1bb8f46a..7729c094a2 100644 --- a/test/CodeGen/arm64-vrnd.c +++ b/test/CodeGen/arm64-vrnd.c @@ -2,50 +2,21 @@ #include -int32x2_t rnd1(float32x2_t a) { return vrnd_f32(a); } -// CHECK: call <2 x float> @llvm.trunc.v2f32(<2 x float> -int32x4_t rnd3(float32x4_t a) { return vrndq_f32(a); } -// CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float> int64x2_t rnd5(float64x2_t a) { return vrndq_f64(a); } // CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> - -int32x2_t rnd7(float32x2_t a) { return vrndn_f32(a); } -// CHECK: call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> -int32x4_t rnd8(float32x4_t a) { return vrndnq_f32(a); } -// CHECK: call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> int64x2_t rnd9(float64x2_t a) { return vrndnq_f64(a); } // CHECK: call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> -int64x2_t rnd10(float64x2_t a) { return vrndnq_f64(a); } -// CHECK: call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> -int32x2_t rnd11(float32x2_t a) { return vrndm_f32(a); } -// CHECK: call <2 x float> @llvm.floor.v2f32(<2 x float> -int32x4_t rnd12(float32x4_t a) { return vrndmq_f32(a); } -// CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float> int64x2_t rnd13(float64x2_t a) { return vrndmq_f64(a); } // CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> -int64x2_t rnd14(float64x2_t a) { return vrndmq_f64(a); } -// CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> -int32x2_t rnd15(float32x2_t a) { return vrndp_f32(a); } -// CHECK: call <2 x float> @llvm.ceil.v2f32(<2 x float> -int32x4_t rnd16(float32x4_t a) { return vrndpq_f32(a); } -// CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float> int64x2_t rnd18(float64x2_t a) { return vrndpq_f64(a); } // CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> -int32x2_t rnd19(float32x2_t a) { return vrnda_f32(a); } -// CHECK: call <2 x float> @llvm.round.v2f32(<2 x float> -int32x4_t rnd20(float32x4_t a) { return vrndaq_f32(a); } -// CHECK: call <4 x float> @llvm.round.v4f32(<4 x float> int64x2_t rnd22(float64x2_t a) { return vrndaq_f64(a); } // CHECK: call <2 x double> @llvm.round.v2f64(<2 x double> -int32x2_t rnd23(float32x2_t a) { return vrndx_f32(a); } -// CHECK: call <2 x float> @llvm.rint.v2f32(<2 x float> -int32x4_t rnd24(float32x4_t a) { return vrndxq_f32(a); } -// CHECK: call <4 x float> @llvm.rint.v4f32(<4 x float> int64x2_t rnd25(float64x2_t a) { return vrndxq_f64(a); } // CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double> -- GitLab From 652c337ae039a437c83a5884f8be76cbc2102113 Mon Sep 17 00:00:00 2001 From: "Ivan A. Kosarev" Date: Mon, 23 Jul 2018 14:53:44 +0000 Subject: [PATCH 0659/1023] [NEON] Define half-precision vrnd intrinsics only when available Differential Revision: https://reviews.llvm.org/D49376 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337699 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 14 +++++---- test/Sema/arm-no-fp16.c | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 9b03091e14..ad7b3aecd3 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -1417,12 +1417,14 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { def VCVTP_U16 : SInst<"vcvtp_u16", "ud", "hQh">; // Vector rounding - def FRINTZH : SInst<"vrnd", "dd", "hQh">; - def FRINTNH : SInst<"vrndn", "dd", "hQh">; - def FRINTAH : SInst<"vrnda", "dd", "hQh">; - def FRINTPH : SInst<"vrndp", "dd", "hQh">; - def FRINTMH : SInst<"vrndm", "dd", "hQh">; - def FRINTXH : SInst<"vrndx", "dd", "hQh">; + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { + def FRINTZH : SInst<"vrnd", "dd", "hQh">; + def FRINTNH : SInst<"vrndn", "dd", "hQh">; + def FRINTAH : SInst<"vrnda", "dd", "hQh">; + def FRINTPH : SInst<"vrndp", "dd", "hQh">; + def FRINTMH : SInst<"vrndm", "dd", "hQh">; + def FRINTXH : SInst<"vrndx", "dd", "hQh">; + } // Misc. def VABSH : SInst<"vabs", "dd", "hQh">; diff --git a/test/Sema/arm-no-fp16.c b/test/Sema/arm-no-fp16.c index 6443d83198..2193c52fc5 100644 --- a/test/Sema/arm-no-fp16.c +++ b/test/Sema/arm-no-fp16.c @@ -9,3 +9,59 @@ float16x4_t test_vcvt_f16_f32(float32x4_t a) { float32x4_t test_vcvt_f32_f16(float16x4_t a) { return vcvt_f32_f16(a); // expected-warning{{implicit declaration of function 'vcvt_f32_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float32x4_t'}} } + +float16x4_t test_vrnda_f16(float16x4_t a) { + return vrnda_f16(a); // expected-warning{{implicit declaration of function 'vrnda_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndaq_f16(float16x8_t a) { + return vrndaq_f16(a); // expected-warning{{implicit declaration of function 'vrndaq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrnd_f16(float16x4_t a) { + return vrnd_f16(a); // expected-warning{{implicit declaration of function 'vrnd_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndq_f16(float16x8_t a) { + return vrndq_f16(a); // expected-warning{{implicit declaration of function 'vrndq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrndi_f16(float16x4_t a) { + return vrndi_f16(a); // expected-warning{{implicit declaration of function 'vrndi_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndiq_f16(float16x8_t a) { + return vrndiq_f16(a); // expected-warning{{implicit declaration of function 'vrndiq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrndm_f16(float16x4_t a) { + return vrndm_f16(a); // expected-warning{{implicit declaration of function 'vrndm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndmq_f16(float16x8_t a) { + return vrndmq_f16(a); // expected-warning{{implicit declaration of function 'vrndmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrndn_f16(float16x4_t a) { + return vrndn_f16(a); // expected-warning{{implicit declaration of function 'vrndn_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndnq_f16(float16x8_t a) { + return vrndnq_f16(a); // expected-warning{{implicit declaration of function 'vrndnq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrndp_f16(float16x4_t a) { + return vrndp_f16(a); // expected-warning{{implicit declaration of function 'vrndp_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndpq_f16(float16x8_t a) { + return vrndpq_f16(a); // expected-warning{{implicit declaration of function 'vrndpq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vrndx_f16(float16x4_t a) { + return vrndx_f16(a); // expected-warning{{implicit declaration of function 'vrndx_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vrndxq_f16(float16x8_t a) { + return vrndxq_f16(a); // expected-warning{{implicit declaration of function 'vrndxq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} -- GitLab From fbd6d5e462c9daeba44d2c0787265f47575ad5f3 Mon Sep 17 00:00:00 2001 From: Jonas Toth Date: Mon, 23 Jul 2018 15:59:27 +0000 Subject: [PATCH 0660/1023] [ASTMatchers] add matcher for decltypeType and its underlyingType Summary: This patch introduces a new matcher for `DecltypeType` and its underlying type in order to fix a bug in clang-tidy, see https://reviews.llvm.org/D48717 for more. Reviewers: aaron.ballman, alexfh, NoQ, dcoughlin Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48759 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337703 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchers.h | 26 +++++++++++++++++++ lib/ASTMatchers/ASTMatchersInternal.cpp | 1 + lib/ASTMatchers/Dynamic/Registry.cpp | 1 + unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 6 +++++ 4 files changed, 34 insertions(+) diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 5c8ec31066..850caf63c7 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -5111,6 +5111,18 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue, /// matches "auto n" and "auto i" extern const AstTypeMatcher autoType; +/// Matches types nodes representing C++11 decltype() types. +/// +/// Given: +/// \code +/// short i = 1; +/// int j = 42; +/// decltype(i + j) result = i + j; +/// \endcode +/// decltypeType() +/// matches "decltype(i + j)" +extern const AstTypeMatcher decltypeType; + /// Matches \c AutoType nodes where the deduced type is a specific type. /// /// Note: There is no \c TypeLoc for the deduced type and thus no @@ -5128,6 +5140,20 @@ extern const AstTypeMatcher autoType; AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType)); +/// Matches \c DecltypeType nodes to find out the underlying type. +/// +/// Given +/// \code +/// decltype(1) a = 1; +/// decltype(2.0) b = 2.0; +/// \endcode +/// decltypeType(hasUnderlyingType(isInteger())) +/// matches "auto a" +/// +/// Usable as: Matcher +AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType, + AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType)); + /// Matches \c FunctionType nodes. /// /// Given diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp index d8af47d750..0c5902d20c 100644 --- a/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -800,6 +800,7 @@ const AstTypeMatcher incompleteArrayType; const AstTypeMatcher variableArrayType; const AstTypeMatcher atomicType; const AstTypeMatcher autoType; +const AstTypeMatcher decltypeType; const AstTypeMatcher functionType; const AstTypeMatcher functionProtoType; const AstTypeMatcher parenType; diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 769d985c05..5a01c5d1f9 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -188,6 +188,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(decayedType); REGISTER_MATCHER(decl); REGISTER_MATCHER(declaratorDecl); + REGISTER_MATCHER(decltypeType); REGISTER_MATCHER(declCountIs); REGISTER_MATCHER(declRefExpr); REGISTER_MATCHER(declStmt); diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index fc1a57c488..e521940983 100644 --- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1206,6 +1206,12 @@ TEST(TypeMatching, MatchesAutoTypes) { // autoType(hasDeducedType(isInteger())))); } +TEST(TypeMatching, MatchesDeclTypes) { + EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;", decltypeType())); + EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;", + decltypeType(hasUnderlyingType(isInteger())))); +} + TEST(TypeMatching, MatchesFunctionTypes) { EXPECT_TRUE(matches("int (*f)(int);", functionType())); EXPECT_TRUE(matches("void f(int i) {}", functionType())); -- GitLab From 697089101c24c2e1c46f0af39ad5d2dbdaa37ddf Mon Sep 17 00:00:00 2001 From: "Ivan A. Kosarev" Date: Mon, 23 Jul 2018 16:01:35 +0000 Subject: [PATCH 0661/1023] [NEON] Define half-precision vmaxnm intrinsics only when available Differential Revision: https://reviews.llvm.org/D49375 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337704 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 6 ++++-- test/Sema/arm-no-fp16.c | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index ad7b3aecd3..d405aac106 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -1466,8 +1466,10 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { // Max/Min def VMAXH : SInst<"vmax", "ddd", "hQh">; def VMINH : SInst<"vmin", "ddd", "hQh">; - def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">; - def FMINNMH : SInst<"vminnm", "ddd", "hQh">; + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { + def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">; + def FMINNMH : SInst<"vminnm", "ddd", "hQh">; + } // Multiplication/Division def VMULH : SOpInst<"vmul", "ddd", "hQh", OP_MUL>; diff --git a/test/Sema/arm-no-fp16.c b/test/Sema/arm-no-fp16.c index 2193c52fc5..2a23270e92 100644 --- a/test/Sema/arm-no-fp16.c +++ b/test/Sema/arm-no-fp16.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple thumbv7-none-eabi %s -target-feature +neon -target-feature -fp16 -fsyntax-only -verify +// RUN: %clang_cc1 -triple thumbv7-none-eabi %s -target-feature +neon \ +// RUN: -fallow-half-arguments-and-returns -target-feature -fp16 \ +// RUN: -fsyntax-only -verify #include @@ -65,3 +67,19 @@ float16x4_t test_vrndx_f16(float16x4_t a) { float16x8_t test_vrndxq_f16(float16x8_t a) { return vrndxq_f16(a); // expected-warning{{implicit declaration of function 'vrndxq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} } + +float16x4_t test_vmaxnm_f16(float16x4_t a, float16x4_t b) { + return vmaxnm_f16(a, b); // expected-warning{{implicit declaration of function 'vmaxnm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vmaxnmq_f16(float16x8_t a, float16x8_t b) { + return vmaxnmq_f16(a, b); // expected-warning{{implicit declaration of function 'vmaxnmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} + +float16x4_t test_vminnm_f16(float16x4_t a, float16x4_t b) { + return vminnm_f16(a, b); // expected-warning{{implicit declaration of function 'vminnm_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x4_t'}} +} + +float16x8_t test_vminnmq_f16(float16x8_t a, float16x8_t b) { + return vminnmq_f16(a, b); // expected-warning{{implicit declaration of function 'vminnmq_f16'}} expected-error{{returning 'int' from a function with incompatible result type 'float16x8_t'}} +} -- GitLab From 31fe70446bc81aa70778c3d3eaa20263eba3c4e5 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Mon, 23 Jul 2018 16:24:14 +0000 Subject: [PATCH 0662/1023] [Sema] Don't emit -Wmemset-transposed-args for memset(p,0,0) Thanks to Arthur O'Dwyer for the suggestion! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337706 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 9 ++++++--- test/Sema/transpose-memset.c | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 1e72083f3c..6492346f6a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -8788,11 +8788,14 @@ static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) { const Expr *SizeArg = Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts(); + auto isLiteralZero = [](const Expr *E) { + return isa(E) && cast(E)->getValue() == 0; + }; + // If we're memsetting or bzeroing 0 bytes, then this is likely an error. SourceLocation CallLoc = Call->getRParenLoc(); SourceManager &SM = S.getSourceManager(); - if (isa(SizeArg) && - cast(SizeArg)->getValue() == 0 && + if (isLiteralZero(SizeArg) && !isArgumentExpandedFromMacro(SM, CallLoc, SizeArg->getExprLoc())) { SourceLocation DiagLoc = SizeArg->getExprLoc(); @@ -8804,7 +8807,7 @@ static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) { CallLoc, SM, S.getLangOpts()) == "bzero")) { S.Diag(DiagLoc, diag::warn_suspicious_bzero_size); S.Diag(DiagLoc, diag::note_suspicious_bzero_size_silence); - } else { + } else if (!isLiteralZero(Call->getArg(1)->IgnoreImpCasts())) { S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0; S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0; } diff --git a/test/Sema/transpose-memset.c b/test/Sema/transpose-memset.c index 0180d5051e..6112fde340 100644 --- a/test/Sema/transpose-memset.c +++ b/test/Sema/transpose-memset.c @@ -22,6 +22,7 @@ int main() { memset(array, (int)sizeof(array), (0)); // no warning memset(array, (int)sizeof(array), 32); // no warning memset(array, 32, (0)); // no warning + memset(array, 0, 0); // no warning bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}} real_bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}} @@ -55,6 +56,6 @@ void macros() { __builtin_memset(array, 0, ZERO); // no warning __builtin_bzero(array, ZERO); - __builtin_memset(array, 0, 0); // expected-warning{{'size' argument to memset}} // expected-note{{parenthesize}} + __builtin_memset(array, 1, 0); // expected-warning{{'size' argument to memset}} // expected-note{{parenthesize}} __builtin_bzero(array, 0); // expected-warning{{'size' argument to bzero}} // expected-note{{parenthesize}} } -- GitLab From 6038d90129eb0899e5e2ccfc819e27a9e0c93ef1 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 23 Jul 2018 17:44:00 +0000 Subject: [PATCH 0663/1023] [MS] Update _MSVC_LANG values for C++17 and C++2a Fixes PR38262 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337715 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/OSTargets.h | 6 +- test/Preprocessor/predefined-macros.c | 103 -------------------- test/Preprocessor/predefined-win-macros.c | 110 ++++++++++++++++++++++ 3 files changed, 114 insertions(+), 105 deletions(-) create mode 100644 test/Preprocessor/predefined-win-macros.c diff --git a/lib/Basic/Targets/OSTargets.h b/lib/Basic/Targets/OSTargets.h index cb7f089c09..d0354784ac 100644 --- a/lib/Basic/Targets/OSTargets.h +++ b/lib/Basic/Targets/OSTargets.h @@ -617,8 +617,10 @@ protected: Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1)); if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) { - if (Opts.CPlusPlus17) - Builder.defineMacro("_MSVC_LANG", "201403L"); + if (Opts.CPlusPlus2a) + Builder.defineMacro("_MSVC_LANG", "201704L"); + else if (Opts.CPlusPlus17) + Builder.defineMacro("_MSVC_LANG", "201703L"); else if (Opts.CPlusPlus14) Builder.defineMacro("_MSVC_LANG", "201402L"); } diff --git a/test/Preprocessor/predefined-macros.c b/test/Preprocessor/predefined-macros.c index 87ad424ee9..9296b1cf5a 100644 --- a/test/Preprocessor/predefined-macros.c +++ b/test/Preprocessor/predefined-macros.c @@ -1,33 +1,5 @@ // This test verifies that the correct macros are predefined. // -// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \ -// RUN: -fms-compatibility-version=19.00 -std=c++1z -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS -// CHECK-MS: #define _INTEGRAL_MAX_BITS 64 -// CHECK-MS: #define _MSC_EXTENSIONS 1 -// CHECK-MS: #define _MSC_VER 1900 -// CHECK-MS: #define _MSVC_LANG 201403L -// CHECK-MS: #define _M_IX86 600 -// CHECK-MS: #define _M_IX86_FP 0 -// CHECK-MS: #define _WIN32 1 -// CHECK-MS-NOT: #define __STRICT_ANSI__ -// CHECK-MS-NOT: GCC -// CHECK-MS-NOT: GNU -// CHECK-MS-NOT: GXX -// -// RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \ -// RUN: -fms-compatibility-version=19.00 -std=c++14 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64 -// CHECK-MS64: #define _INTEGRAL_MAX_BITS 64 -// CHECK-MS64: #define _MSC_EXTENSIONS 1 -// CHECK-MS64: #define _MSC_VER 1900 -// CHECK-MS64: #define _MSVC_LANG 201402L -// CHECK-MS64: #define _M_AMD64 100 -// CHECK-MS64: #define _M_X64 100 -// CHECK-MS64: #define _WIN64 1 -// CHECK-MS64-NOT: #define __STRICT_ANSI__ -// CHECK-MS64-NOT: GCC -// CHECK-MS64-NOT: GNU -// CHECK-MS64-NOT: GXX -// // RUN: %clang_cc1 %s -E -dM -triple i686-pc-win32 -fms-compatibility \ // RUN: -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS-STDINT // CHECK-MS-STDINT:#define __INT16_MAX__ 32767 @@ -199,81 +171,6 @@ // MSCOPE:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 // MSCOPE:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 -// RUN: %clang_cc1 -triple i386-windows %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-WIN - -// CHECK-X86-WIN-NOT: #define WIN32 1 -// CHECK-X86-WIN-NOT: #define WIN64 1 -// CHECK-X86-WIN-NOT: #define WINNT 1 -// CHECK-X86-WIN: #define _WIN32 1 -// CHECK-X86-WIN-NOT: #define _WIN64 1 - -// RUN: %clang_cc1 -triple thumbv7-windows %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-WIN - -// CHECK-ARM-WIN-NOT: #define WIN32 1 -// CHECK-ARM-WIN-NOT: #define WIN64 1 -// CHECK-ARM-WIN-NOT: #define WINNT 1 -// CHECK-ARM-WIN: #define _WIN32 1 -// CHECK-ARM-WIN-NOT: #define _WIN64 1 - -// RUN: %clang_cc1 -triple x86_64-windows %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-WIN - -// CHECK-AMD64-WIN-NOT: #define WIN32 1 -// CHECK-AMD64-WIN-NOT: #define WIN64 1 -// CHECK-AMD64-WIN-NOT: #define WINNT 1 -// CHECK-AMD64-WIN: #define _WIN32 1 -// CHECK-AMD64-WIN: #define _WIN64 1 - -// RUN: %clang_cc1 -triple aarch64-windows %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-WIN - -// CHECK-ARM64-WIN-NOT: #define WIN32 1 -// CHECK-ARM64-WIN-NOT: #define WIN64 1 -// CHECK-ARM64-WIN-NOT: #define WINNT 1 -// CHECK-ARM64-WIN: #define _M_ARM64 1 -// CHECK-ARM64-WIN: #define _WIN32 1 -// CHECK-ARM64-WIN: #define _WIN64 1 - -// RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW - -// CHECK-X86-MINGW: #define WIN32 1 -// CHECK-X86-MINGW-NOT: #define WIN64 1 -// CHECK-X86-MINGW: #define WINNT 1 -// CHECK-X86-MINGW: #define _WIN32 1 -// CHECK-X86-MINGW-NOT: #define _WIN64 1 - -// RUN: %clang_cc1 -triple thumbv7-windows-gnu %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-MINGW - -// CHECK-ARM-MINGW: #define WIN32 1 -// CHECK-ARM-MINGW-NOT: #define WIN64 1 -// CHECK-ARM-MINGW: #define WINNT 1 -// CHECK-ARM-MINGW: #define _WIN32 1 -// CHECK-ARM-MINGW-NOT: #define _WIN64 1 - -// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-MINGW - -// CHECK-AMD64-MINGW: #define WIN32 1 -// CHECK-AMD64-MINGW: #define WIN64 1 -// CHECK-AMD64-MINGW: #define WINNT 1 -// CHECK-AMD64-MINGW: #define _WIN32 1 -// CHECK-AMD64-MINGW: #define _WIN64 1 - -// RUN: %clang_cc1 -triple aarch64-windows-gnu %s -E -dM -o - \ -// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-MINGW - -// CHECK-ARM64-MINGW-NOT: #define _M_ARM64 1 -// CHECK-ARM64-MINGW: #define WIN32 1 -// CHECK-ARM64-MINGW: #define WIN64 1 -// CHECK-ARM64-MINGW: #define WINNT 1 -// CHECK-ARM64-MINGW: #define _WIN32 1 -// CHECK-ARM64-MINGW: #define _WIN64 1 -// CHECK-ARM64-MINGW: #define __aarch64__ 1 - // RUN: %clang_cc1 %s -E -dM -o - -x cl -triple spir-unknown-unknown \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-SPIR // CHECK-SPIR: #define __IMAGE_SUPPORT__ 1 diff --git a/test/Preprocessor/predefined-win-macros.c b/test/Preprocessor/predefined-win-macros.c new file mode 100644 index 0000000000..0979e34860 --- /dev/null +++ b/test/Preprocessor/predefined-win-macros.c @@ -0,0 +1,110 @@ +// This test verifies that the correct macros are predefined. +// +// RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \ +// RUN: -fms-compatibility-version=19.00 -std=c++14 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64 +// CHECK-MS64: #define _INTEGRAL_MAX_BITS 64 +// CHECK-MS64: #define _MSC_EXTENSIONS 1 +// CHECK-MS64: #define _MSC_VER 1900 +// CHECK-MS64: #define _MSVC_LANG 201402L +// CHECK-MS64: #define _M_AMD64 100 +// CHECK-MS64: #define _M_X64 100 +// CHECK-MS64: #define _WIN64 1 +// CHECK-MS64-NOT: #define __STRICT_ANSI__ +// CHECK-MS64-NOT: GCC +// CHECK-MS64-NOT: GNU +// CHECK-MS64-NOT: GXX + +// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \ +// RUN: -fms-compatibility-version=19.00 -std=c++17 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS +// CHECK-MS: #define _INTEGRAL_MAX_BITS 64 +// CHECK-MS: #define _MSC_EXTENSIONS 1 +// CHECK-MS: #define _MSC_VER 1900 +// CHECK-MS: #define _MSVC_LANG 201703L +// CHECK-MS: #define _M_IX86 600 +// CHECK-MS: #define _M_IX86_FP 0 +// CHECK-MS: #define _WIN32 1 +// CHECK-MS-NOT: #define __STRICT_ANSI__ +// CHECK-MS-NOT: GCC +// CHECK-MS-NOT: GNU +// CHECK-MS-NOT: GXX + +// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \ +// RUN: -fms-compatibility-version=19.00 -std=c++2a -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS-CPP2A +// CHECK-MS-CPP2A: #define _MSC_VER 1900 +// CHECK-MS-CPP2A: #define _MSVC_LANG 201704L + +// RUN: %clang_cc1 -triple i386-windows %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-WIN + +// CHECK-X86-WIN-NOT: #define WIN32 1 +// CHECK-X86-WIN-NOT: #define WIN64 1 +// CHECK-X86-WIN-NOT: #define WINNT 1 +// CHECK-X86-WIN: #define _WIN32 1 +// CHECK-X86-WIN-NOT: #define _WIN64 1 + +// RUN: %clang_cc1 -triple thumbv7-windows %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-WIN + +// CHECK-ARM-WIN-NOT: #define WIN32 1 +// CHECK-ARM-WIN-NOT: #define WIN64 1 +// CHECK-ARM-WIN-NOT: #define WINNT 1 +// CHECK-ARM-WIN: #define _WIN32 1 +// CHECK-ARM-WIN-NOT: #define _WIN64 1 + +// RUN: %clang_cc1 -triple x86_64-windows %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-WIN + +// CHECK-AMD64-WIN-NOT: #define WIN32 1 +// CHECK-AMD64-WIN-NOT: #define WIN64 1 +// CHECK-AMD64-WIN-NOT: #define WINNT 1 +// CHECK-AMD64-WIN: #define _WIN32 1 +// CHECK-AMD64-WIN: #define _WIN64 1 + +// RUN: %clang_cc1 -triple aarch64-windows %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-WIN + +// CHECK-ARM64-WIN-NOT: #define WIN32 1 +// CHECK-ARM64-WIN-NOT: #define WIN64 1 +// CHECK-ARM64-WIN-NOT: #define WINNT 1 +// CHECK-ARM64-WIN: #define _M_ARM64 1 +// CHECK-ARM64-WIN: #define _WIN32 1 +// CHECK-ARM64-WIN: #define _WIN64 1 + +// RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW + +// CHECK-X86-MINGW: #define WIN32 1 +// CHECK-X86-MINGW-NOT: #define WIN64 1 +// CHECK-X86-MINGW: #define WINNT 1 +// CHECK-X86-MINGW: #define _WIN32 1 +// CHECK-X86-MINGW-NOT: #define _WIN64 1 + +// RUN: %clang_cc1 -triple thumbv7-windows-gnu %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM-MINGW + +// CHECK-ARM-MINGW: #define WIN32 1 +// CHECK-ARM-MINGW-NOT: #define WIN64 1 +// CHECK-ARM-MINGW: #define WINNT 1 +// CHECK-ARM-MINGW: #define _WIN32 1 +// CHECK-ARM-MINGW-NOT: #define _WIN64 1 + +// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-AMD64-MINGW + +// CHECK-AMD64-MINGW: #define WIN32 1 +// CHECK-AMD64-MINGW: #define WIN64 1 +// CHECK-AMD64-MINGW: #define WINNT 1 +// CHECK-AMD64-MINGW: #define _WIN32 1 +// CHECK-AMD64-MINGW: #define _WIN64 1 + +// RUN: %clang_cc1 -triple aarch64-windows-gnu %s -E -dM -o - \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-ARM64-MINGW + +// CHECK-ARM64-MINGW-NOT: #define _M_ARM64 1 +// CHECK-ARM64-MINGW: #define WIN32 1 +// CHECK-ARM64-MINGW: #define WIN64 1 +// CHECK-ARM64-MINGW: #define WINNT 1 +// CHECK-ARM64-MINGW: #define _WIN32 1 +// CHECK-ARM64-MINGW: #define _WIN64 1 +// CHECK-ARM64-MINGW: #define __aarch64__ 1 + -- GitLab From 66ee19cc1c81aa009a7fba74fc9d082268ec1e06 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 23 Jul 2018 17:50:15 +0000 Subject: [PATCH 0664/1023] [DebugInfo] Error out when enabling -fdebug-types-section on non-ELF target. Currently, support for debug_types is only present for ELF and trying to pass -fdebug-types-section for other targets results in a crash in the backend. Until this is fixed, we should emit a diagnostic in the front end when the option is passed for non-linux targets. Differential revision: https://reviews.llvm.org/D49594 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337717 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Clang.cpp | 5 +++++ test/Driver/debug-options.c | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index e23ff16699..a95080bbec 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3028,6 +3028,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { + if (!T.isOSBinFormatELF()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_fdebug_types_section) + ->getAsString(Args) + << T.getTriple(); CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-generate-type-units"); } diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c index 6d28a7169d..0dd32e983a 100644 --- a/test/Driver/debug-options.c +++ b/test/Driver/debug-options.c @@ -139,12 +139,18 @@ // // RUN: %clang -### -c -gdwarf-aranges %s 2>&1 | FileCheck -check-prefix=GARANGE %s // -// RUN: %clang -### -fdebug-types-section %s 2>&1 \ +// RUN: %clang -### -fdebug-types-section -target x86_64-unknown-linux %s 2>&1 \ // RUN: | FileCheck -check-prefix=FDTS %s // -// RUN: %clang -### -fdebug-types-section -fno-debug-types-section %s 2>&1 \ +// RUN: %clang -### -fdebug-types-section -fno-debug-types-section -target x86_64-unknown-linux %s 2>&1 \ // RUN: | FileCheck -check-prefix=NOFDTS %s // +// RUN: %clang -### -fdebug-types-section -target x86_64-apple-darwin %s 2>&1 \ +// RUN: | FileCheck -check-prefix=FDTSE %s +// +// RUN: %clang -### -fdebug-types-section -fno-debug-types-section -target x86_64-apple-darwin %s 2>&1 \ +// RUN: | FileCheck -check-prefix=NOFDTSE %s +// // RUN: %clang -### -g -gno-column-info %s 2>&1 \ // RUN: | FileCheck -check-prefix=NOCI %s // @@ -229,8 +235,10 @@ // GARANGE: -generate-arange-section // // FDTS: "-mllvm" "-generate-type-units" +// FDTSE: error: unsupported option '-fdebug-types-section' for target 'x86_64-apple-darwin' // // NOFDTS-NOT: "-mllvm" "-generate-type-units" +// NOFDTSE-NOT: error: unsupported option '-fdebug-types-section' for target 'x86_64-apple-darwin' // // CI: "-dwarf-column-info" // -- GitLab From 13a9f8e3e69510f353bdeb029f135ff77c236567 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 23 Jul 2018 18:26:38 +0000 Subject: [PATCH 0665/1023] [CStringSyntaxChecker] Improvements of strlcpy check Adding an additional check whenwe offset fro the buffer base address. Reviewers: george.karpenkov,NoQ Reviewed By: george.karpenkov Differential Revision: https://reviews.llvm.org/D49633 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337721 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CStringSyntaxChecker.cpp | 20 +++++++++++++++++-- test/Analysis/cstring-syntax.c | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp index b1f37f5a34..8b4aa857e7 100644 --- a/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp @@ -88,6 +88,7 @@ class WalkAST: public StmtVisitor { /// size_t cpy = 4; /// strlcpy(dst, "abcd", sizeof("abcd") - 1); /// strlcpy(dst, "abcd", 4); + /// strlcpy(dst + 3, "abcd", 2); /// strlcpy(dst, "abcd", cpy); bool containsBadStrlcpyPattern(const CallExpr *CE); @@ -149,6 +150,7 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { const auto *DstArgDecl = dyn_cast(DstArg->IgnoreParenImpCasts()); const auto *LenArgDecl = dyn_cast(LenArg->IgnoreParenLValueCasts()); + uint64_t DstOff = 0; // - size_t dstlen = sizeof(dst) if (LenArgDecl) { const auto *LenArgVal = dyn_cast(LenArgDecl->getDecl()); @@ -158,14 +160,28 @@ bool WalkAST::containsBadStrlcpyPattern(const CallExpr *CE) { // - integral value // We try to figure out if the last argument is possibly longer - // than the destination can possibly handle if its size can be defined + // than the destination can possibly handle if its size can be defined. if (const auto *IL = dyn_cast(LenArg->IgnoreParenImpCasts())) { uint64_t ILRawVal = IL->getValue().getZExtValue(); + + // Case when there is pointer arithmetic on the destination buffer + // especially when we offset from the base decreasing the + // buffer length accordingly. + if (!DstArgDecl) { + if (const auto *BE = dyn_cast(DstArg->IgnoreParenImpCasts())) { + DstArgDecl = dyn_cast(BE->getLHS()->IgnoreParenImpCasts()); + if (BE->getOpcode() == BO_Add) { + if ((IL = dyn_cast(BE->getRHS()->IgnoreParenImpCasts()))) { + DstOff = IL->getValue().getZExtValue(); + } + } + } + } if (DstArgDecl) { if (const auto *Buffer = dyn_cast(DstArgDecl->getType())) { ASTContext &C = BR.getContext(); uint64_t BufferLen = C.getTypeSize(Buffer) / 8; - if (BufferLen < ILRawVal) + if ((BufferLen - DstOff) < ILRawVal) return true; } } diff --git a/test/Analysis/cstring-syntax.c b/test/Analysis/cstring-syntax.c index f64682b418..fe1253bedb 100644 --- a/test/Analysis/cstring-syntax.c +++ b/test/Analysis/cstring-syntax.c @@ -31,4 +31,5 @@ void testStrlcpy(const char *src) { strlcpy(dest, src, badlen); // expected-warning {{The third argument is larger than the size of the input buffer. Replace with the value 'sizeof(dest)` or lower}} strlcpy(dest, src, ulen); strlcpy(dest + 5, src, 5); + strlcpy(dest + 5, src, 10); // expected-warning {{The third argument is larger than the size of the input buffer.}} } -- GitLab From adb6124d50c905547379a1b6571582da8644daa7 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Mon, 23 Jul 2018 18:27:09 +0000 Subject: [PATCH 0666/1023] Revert "[OPENMP] Fix PR38026: Link -latomic when -fopenmp is used." This reverts commit r336467: libatomic is not available on all Linux systems and this commit completely breaks OpenMP on them, even if there are no atomic operations or all of them can be lowered to hardware instructions. See http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20180716/234816.html for post-commit discussion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337722 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Gnu.cpp | 6 +----- test/OpenMP/linking.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index ee3096813e..1ecf127c4b 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -479,7 +479,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, bool WantPthread = Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads); - bool WantAtomic = false; // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. @@ -488,16 +487,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. // FIXME: Does this really make sense for all GNU toolchains? - WantAtomic = WantPthread = true; + WantPthread = true; AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (WantPthread && !isAndroid) CmdArgs.push_back("-lpthread"); - if (WantAtomic) - CmdArgs.push_back("-latomic"); - if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("--wrap=pthread_create"); diff --git a/test/OpenMP/linking.c b/test/OpenMP/linking.c index e2f83f9571..802553c1be 100644 --- a/test/OpenMP/linking.c +++ b/test/OpenMP/linking.c @@ -8,14 +8,14 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s // CHECK-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-LD-32: "-lpthread" "-latomic" "-lc" +// CHECK-LD-32: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-LD-64 %s // CHECK-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-LD-64: "-lpthread" "-latomic" "-lc" +// CHECK-LD-64: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libgomp -target i386-unknown-linux -rtlib=platform \ @@ -27,7 +27,7 @@ // SIMD-ONLY2-NOT: liomp // CHECK-GOMP-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-GOMP-LD-32: "-lgomp" "-lrt" -// CHECK-GOMP-LD-32: "-lpthread" "-latomic" "-lc" +// CHECK-GOMP-LD-32: "-lpthread" "-lc" // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 -fopenmp-simd -target i386-unknown-linux -rtlib=platform | FileCheck --check-prefix SIMD-ONLY2 %s // SIMD-ONLY2-NOT: lgomp @@ -39,21 +39,21 @@ // RUN: | FileCheck --check-prefix=CHECK-GOMP-LD-64 %s // CHECK-GOMP-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-GOMP-LD-64: "-lgomp" "-lrt" -// CHECK-GOMP-LD-64: "-lpthread" "-latomic" "-lc" +// CHECK-GOMP-LD-64: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target i386-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-32 %s // CHECK-IOMP5-LD-32: "{{.*}}ld{{(.exe)?}}" // CHECK-IOMP5-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-IOMP5-LD-32: "-lpthread" "-latomic" "-lc" +// CHECK-IOMP5-LD-32: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-64 %s // CHECK-IOMP5-LD-64: "{{.*}}ld{{(.exe)?}}" // CHECK-IOMP5-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" -// CHECK-IOMP5-LD-64: "-lpthread" "-latomic" "-lc" +// CHECK-IOMP5-LD-64: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=lib -target i386-unknown-linux \ @@ -71,7 +71,7 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-32 %s // CHECK-LD-OVERRIDE-32: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-OVERRIDE-32: "-lgomp" "-lrt" -// CHECK-LD-OVERRIDE-32: "-lpthread" "-latomic" "-lc" +// CHECK-LD-OVERRIDE-32: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp -fopenmp=libgomp -target x86_64-unknown-linux \ @@ -79,7 +79,7 @@ // RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-64 %s // CHECK-LD-OVERRIDE-64: "{{.*}}ld{{(.exe)?}}" // CHECK-LD-OVERRIDE-64: "-lgomp" "-lrt" -// CHECK-LD-OVERRIDE-64: "-lpthread" "-latomic" "-lc" +// CHECK-LD-OVERRIDE-64: "-lpthread" "-lc" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libomp -target x86_64-msvc-win32 -rtlib=platform \ -- GitLab From 05ff991ac22224ff97affdd4e24737551c4540c7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 23 Jul 2018 18:50:26 +0000 Subject: [PATCH 0667/1023] Fold dangling-field warning into general initialization lifetime checks. This reinstates r337627, reverted in r337671, with a fix to correctly handle the lvalueness of array subscript expressions on pointers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337726 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 8 +- lib/Sema/SemaDeclCXX.cpp | 49 ---- lib/Sema/SemaInit.cpp | 262 ++++++++++++------ .../cxx-uninitialized-object-ptr-ref.cpp | 12 +- .../cxx0x-initializer-stdinitializerlist.cpp | 22 +- test/SemaCXX/warn-dangling-field.cpp | 5 + 6 files changed, 203 insertions(+), 155 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5ae749fa93..e45f5f3376 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7870,11 +7870,11 @@ def note_ref_var_local_bind : Note< // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< - "binding reference member %0 to stack allocated parameter %1">, - InGroup; + "binding reference member %0 to stack allocated " + "%select{variable|parameter}2 %1">, InGroup; def warn_init_ptr_member_to_parameter_addr : Warning< - "initializing pointer member %0 with the stack address of parameter %1">, - InGroup; + "initializing pointer member %0 with the stack address of " + "%select{variable|parameter}2 %1">, InGroup; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d2a2bb2020..031f8dbb38 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3946,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *ConstructorD, return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } -/// Checks a member initializer expression for cases where reference (or -/// pointer) members are bound to by-value parameters (or their addresses). -static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, - Expr *Init, - SourceLocation IdLoc) { - QualType MemberTy = Member->getType(); - - // We only handle pointers and references currently. - // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? - if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) - return; - - const bool IsPointer = MemberTy->isPointerType(); - if (IsPointer) { - if (const UnaryOperator *Op - = dyn_cast(Init->IgnoreParenImpCasts())) { - // The only case we're worried about with pointers requires taking the - // address. - if (Op->getOpcode() != UO_AddrOf) - return; - - Init = Op->getSubExpr(); - } else { - // We only handle address-of expression initializers for pointers. - return; - } - } - - if (const DeclRefExpr *DRE = dyn_cast(Init->IgnoreParens())) { - // We only warn when referring to a non-reference parameter declaration. - const ParmVarDecl *Parameter = dyn_cast(DRE->getDecl()); - if (!Parameter || Parameter->getType()->isReferenceType()) - return; - - S.Diag(Init->getExprLoc(), - IsPointer ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << Parameter << Init->getSourceRange(); - } else { - // Other initializers are fine. - return; - } - - S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) - << (unsigned)IsPointer; -} - MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -4047,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); - // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index f94eabd671..6c2c6d143d 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6227,7 +6227,7 @@ using LifetimeResult = /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. -static LifetimeResult getEntityForTemporaryLifetimeExtension( +static LifetimeResult getEntityLifetime( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: @@ -6239,8 +6239,7 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - Entity); + return getEntityLifetime(Entity->getParent(), Entity); // except: // C++17 [class.base.init]p8: @@ -6291,14 +6290,12 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - InitField); + return getEntityLifetime(Entity->getParent(), InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityForTemporaryLifetimeExtension(Entity->getParent(), - InitField); + return getEntityLifetime(Entity->getParent(), InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: @@ -6311,46 +6308,61 @@ static LifetimeResult getEntityForTemporaryLifetimeExtension( case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: - case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; + + case InitializedEntity::EK_Exception: + // FIXME: Can we diagnose lifetime problems with exceptions? + return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { -enum ExtensionKind { +enum ReferenceKind { /// Lifetime would be extended by a reference binding to a temporary. - EK_ReferenceBinding, + RK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. - EK_StdInitializerList, + RK_StdInitializerList, +}; + +/// A temporary or local variable. +using Local = llvm::PointerUnion; + +/// Expressions we stepped over when looking for the local state. Any steps +/// that would inhibit lifetime extension or take us out of subexpressions of +/// the initializer are included. +struct IndirectLocalPathEntry { + enum { + DefaultInit, + AddressOf, + } Kind; + Expr *E; }; -using IndirectTemporaryPathEntry = - llvm::PointerUnion; -using IndirectTemporaryPath = llvm::SmallVectorImpl; + +using IndirectLocalPath = llvm::SmallVectorImpl; struct RevertToOldSizeRAII { - IndirectTemporaryPath &Path; + IndirectLocalPath &Path; unsigned OldSize = Path.size(); - RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {} + RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; } -template -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, - Expr *Init, - TemporaryVisitor Visit); +template +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, + Expr *Init, LocalVisitor Visit, + bool RevisitSubinits); -/// Visit the temporaries whose lifetimes would be extended by binding a -/// reference to the glvalue expression \c Init. -template -static void -visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, - Expr *Init, ExtensionKind EK, - TemporaryVisitor Visit) { +/// Visit the locals that would be reachable through a reference bound to the +/// glvalue expression \c Init. +template +static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, + Expr *Init, ReferenceKind RK, + LocalVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. @@ -6375,14 +6387,18 @@ visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, Init = CE->getSubExpr(); // Per the current approach for DR1299, look through array element access - // when performing lifetime extension. - if (auto *ASE = dyn_cast(Init)) - Init = ASE->getBase(); + // on array glvalues when performing lifetime extension. + if (auto *ASE = dyn_cast(Init)) { + auto *ICE = dyn_cast(ASE->getBase()); + if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay) + return; + Init = ICE->getSubExpr(); + } // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back(DIE); + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6391,25 +6407,36 @@ visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, } while (Init != Old); if (auto *MTE = dyn_cast(Init)) { - if (Visit(Path, MTE, EK)) - visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(), - Visit); + if (Visit(Path, Local(MTE), RK)) + visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, + true); + } + + // If we find the name of a local non-reference parameter, we could have a + // lifetime problem. + if (auto *DRE = dyn_cast(Init->IgnoreParens())) { + auto *VD = dyn_cast(DRE->getDecl()); + if (VD && VD->hasLocalStorage() && + !DRE->refersToEnclosingVariableOrCapture()) { + // FIXME: Recurse to the initializer of a local reference. + if (!VD->getType()->isReferenceType()) + Visit(Path, Local(VD), RK); + } } } -/// Visit the temporaries whose lifetimes would be extended by -/// lifetime-extending the object initialized by the prvalue expression \c -/// Init. -template -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, - Expr *Init, - TemporaryVisitor Visit) { +/// Visit the locals that would be reachable through an object initialized by +/// the prvalue expression \c Init. +template +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, + Expr *Init, LocalVisitor Visit, + bool RevisitSubinits) { RevertToOldSizeRAII RAII(Path); // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back(DIE); + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); Init = DIE->getExpr(); if (auto *EWC = dyn_cast(Init)) @@ -6426,17 +6453,24 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast(Init)) - return visitTemporariesExtendedByReferenceBinding( - Path, ILE->getSubExpr(), EK_StdInitializerList, Visit); + return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), + RK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast(Init)) { + // We already visited the elements of this initializer list while + // performing the initialization. Don't visit them again unless we've + // changed the lifetime of the initialized entity. + if (!RevisitSubinits) + return; + if (ILE->isTransparent()) - return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0), - Visit); + return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, + RevisitSubinits); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) - visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit); + visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, + RevisitSubinits); return; } @@ -6448,8 +6482,8 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) - visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0), - EK_ReferenceBinding, Visit); + visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), + RK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { @@ -6459,25 +6493,38 @@ static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) - visitTemporariesExtendedByReferenceBinding( - Path, SubInit, EK_ReferenceBinding, Visit); + visitLocalsRetainedByReferenceBinding(Path, SubInit, + RK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. - visitTemporariesExtendedByInitializer(Path, SubInit, Visit); + visitLocalsRetainedByInitializer(Path, SubInit, Visit, + RevisitSubinits); ++Index; } } } + return; + } + + // If the initializer is the address of a local, we could have a lifetime + // problem. + if (auto *Op = dyn_cast(Init->IgnoreParenImpCasts())) { + if (Op->getOpcode() == UO_AddrOf) { + Path.push_back({IndirectLocalPathEntry::AddressOf, Op}); + Init = Op->getSubExpr(); + return visitLocalsRetainedByReferenceBinding(Path, Init, + RK_ReferenceBinding, Visit); + } } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). -static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { +static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { - if (!Elem.is()) + if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) return false; } return true; @@ -6485,7 +6532,7 @@ static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { - LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity); + LifetimeResult LR = getEntityLifetime(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); @@ -6494,9 +6541,54 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, if (LK == LK_FullExpression) return; - auto TemporaryVisitor = [&](IndirectTemporaryPath &Path, - MaterializeTemporaryExpr *MTE, - ExtensionKind EK) -> bool { + auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, + ReferenceKind RK) -> bool { + // If we found a path to a local variable or similar, check whether the + // initialized object will outlive it. + if (auto *VD = L.dyn_cast()) { + switch (LK) { + case LK_FullExpression: + llvm_unreachable("already handled this"); + + case LK_Extended: + break; + + case LK_MemInitializer: { + // Paths via a default initializer can only occur during error recovery + // (there's no other way that a default initializer can refer to a + // local). Don't produce a bogus warning on those cases. + if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { + return E.Kind == IndirectLocalPathEntry::DefaultInit; + })) + break; + + if (auto *Member = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + bool AddressTaken = + !Path.empty() && + Path.back().Kind == IndirectLocalPathEntry::AddressOf; + Diag(Init->getExprLoc(), + AddressTaken ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << VD << isa(VD) << Init->getSourceRange(); + Diag(Member->getLocation(), + diag::note_ref_or_ptr_member_declared_here) + << (unsigned)AddressTaken; + } + break; + } + + case LK_New: + break; + + case LK_Return: + // FIXME: Move -Wreturn-stack-address checks here. + return false; + } + return false; + } + + auto *MTE = L.get(); switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); @@ -6520,11 +6612,11 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(MTE->getExprLoc(), - EK == EK_ReferenceBinding + RK == RK_ReferenceBinding ? diag::warn_default_member_init_temporary_not_extended : diag::warn_default_member_init_init_list_not_extended); } else { - llvm_unreachable("unexpected indirect temporary path"); + // FIXME: Warn on this. } break; @@ -6532,18 +6624,20 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. - if (auto *ExtendingDecl = ExtendingEntity->getDecl()) { + if (auto *ExtendingDecl = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary) << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember - << EK; + << RK; // Don't bother adding a note pointing to the field if we're inside its // default member initializer; our primary diagnostic points to the // same place in that case. - if (Path.empty() || !Path.back().is()) { + if (Path.empty() || + Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) - << EK << IsSubobjectMember; + << RK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this @@ -6557,7 +6651,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_New: - if (EK == EK_ReferenceBinding) { + if (RK == RK_ReferenceBinding) { Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference); } else { Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list) @@ -6573,9 +6667,14 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // FIXME: Model these as CodeSynthesisContexts to fix the note emission // order. for (auto Elem : llvm::reverse(Path)) { - if (auto *DIE = Elem.dyn_cast()) { - Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here) - << DIE->getField(); + switch (Elem.Kind) { + case IndirectLocalPathEntry::DefaultInit: + Diag(Elem.E->getExprLoc(), diag::note_in_default_member_initalizer_here) + << cast(Elem.E)->getField(); + break; + + case IndirectLocalPathEntry::AddressOf: + break; } } @@ -6584,12 +6683,12 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, return false; }; - llvm::SmallVector Path; + llvm::SmallVector Path; if (Init->isGLValue()) - visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding, - TemporaryVisitor); + visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, + TemporaryVisitor); else - visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor); + visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); } static void DiagnoseNarrowingInInitList(Sema &S, @@ -6853,6 +6952,7 @@ InitializationSequence::Perform(Sema &S, // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. + // FIXME: Fold this into checkInitializerLifetime. if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { @@ -7015,11 +7115,6 @@ InitializationSequence::Perform(Sema &S, } } - // Even though we didn't materialize a temporary, the binding may still - // extend the lifetime of a temporary. This happens if we bind a - // reference to the result of a cast to reference type. - S.checkInitializerLifetime(Entity, CurInit.get()); - CheckForNullPointerDereference(S, CurInit.get()); break; @@ -7036,10 +7131,6 @@ InitializationSequence::Perform(Sema &S, Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; - // Maybe lifetime-extend the temporary's subobjects to match the - // entity's lifetime. - S.checkInitializerLifetime(Entity, CurInit.get()); - // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && @@ -7490,10 +7581,6 @@ InitializationSequence::Perform(Sema &S, // Wrap it in a construction of a std::initializer_list. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); - // Maybe lifetime-extend the array temporary's subobjects to match the - // entity's lifetime. - S.checkInitializerLifetime(Entity, CurInit.get()); - // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) @@ -7612,6 +7699,11 @@ InitializationSequence::Perform(Sema &S, } } + // Check whether the initializer has a shorter lifetime than the initialized + // entity, and if not, either lifetime-extend or warn as appropriate. + if (auto *Init = CurInit.get()) + S.checkInitializerLifetime(Entity, Init); + // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast(Entity.getDecl())->isBitField()) diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index db025420d7..1507098c5e 100644 --- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -235,10 +235,10 @@ void fVoidPointerTest2() { } class VoidPointerRRefTest1 { - void *&&vptrrref; + void *&&vptrrref; // expected-note {{here}} public: - VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; @@ -249,10 +249,10 @@ void fVoidPointerRRefTest1() { } class VoidPointerRRefTest2 { - void **&&vpptrrref; + void **&&vpptrrref; // expected-note {{here}} public: - VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}} // All good! } }; @@ -263,10 +263,10 @@ void fVoidPointerRRefTest2() { } class VoidPointerLRefTest { - void *&vptrrref; + void *&vptrrref; // expected-note {{here}} public: - VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 0184a1d6e7..e3c7e26afa 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -72,18 +72,18 @@ std::initializer_list thread_local x = {1, 2, 3, 4}; // X86: @_ZN15partly_constant1kE = global i32 0, align 4 // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4 -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4 +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 // AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 -// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4 // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 @@ -375,7 +375,7 @@ namespace partly_constant { // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0) - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp index 97d4331c1f..578f3df654 100644 --- a/test/SemaCXX/warn-dangling-field.cpp +++ b/test/SemaCXX/warn-dangling-field.cpp @@ -49,3 +49,8 @@ struct S6 { struct S7 : S5 { S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a temporary}} }; + +struct S8 { + int *p; + S8(int *a) : p(&a[0]) {} +}; -- GitLab From c2add0a67604106d9460c0f6e8169e050f682a71 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 23 Jul 2018 19:19:08 +0000 Subject: [PATCH 0668/1023] Separate out the initialization kind for a statement expression result from that for a return value. No functionality change intended: I don't believe any of the diagnostics affected by this patch are reachable when initializing the result of statement expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337728 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 38 ++++++++++------------ include/clang/Sema/Initialization.h | 8 +++++ lib/Sema/SemaExpr.cpp | 7 ++-- lib/Sema/SemaInit.cpp | 24 +++++++++++++- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e45f5f3376..c6f263dc8c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1804,7 +1804,8 @@ def err_destructor_template : Error< // C++ initialization def err_init_conversion_failed : Error< - "cannot initialize %select{a variable|a parameter|return object|an " + "cannot initialize %select{a variable|a parameter|return object|" + "statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " @@ -1939,34 +1940,29 @@ def warn_unsequenced_mod_mod : Warning< def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup; +def select_initialized_entity_kind : TextSubstitution< + "%select{copying variable|copying parameter|" + "returning object|initializing statement expression result|" + "throwing object|copying member subobject|copying array element|" + "allocating object|copying temporary|initializing base subobject|" + "initializing vector element|capturing value}0">; + def err_temp_copy_no_viable : Error< - "no viable constructor %select{copying variable|copying parameter|" - "returning object|throwing object|copying member subobject|copying array " - "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1">; + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">; def ext_rvalue_to_reference_temp_copy_no_viable : Extension< - "no viable constructor %select{copying variable|copying parameter|" - "returning object|throwing object|copying member subobject|copying array " - "element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1; C++98 requires a copy " - "constructor when binding a reference to a temporary">, + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1; " + "C++98 requires a copy constructor when binding a reference to a temporary">, InGroup; def err_temp_copy_ambiguous : Error< - "ambiguous constructor call when %select{copying variable|copying " - "parameter|returning object|throwing object|copying member subobject|copying " - "array element|allocating object|copying temporary|initializing base subobject|" - "initializing vector element|capturing value}0 of type %1">; + "ambiguous constructor call when %sub{select_initialized_entity_kind}0 " + "of type %1">; def err_temp_copy_deleted : Error< - "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element|" - "capturing value}0 of type %1 invokes deleted constructor">; + "%sub{select_initialized_entity_kind}0 of type %1 " + "invokes deleted constructor">; def err_temp_copy_incomplete : Error< "copying a temporary object of incomplete type %0">; def warn_cxx98_compat_temp_copy : Warning< - "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element}1 " + "%sub{select_initialized_entity_kind}1 " "of type %2 when binding a reference to a temporary would %select{invoke " "an inaccessible constructor|find no viable constructor|find ambiguous " "constructors|invoke a deleted constructor}0 in C++98">, diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index b7ef8d0f47..7a510f391b 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -59,6 +59,9 @@ public: /// The entity being initialized is the result of a function call. EK_Result, + /// The entity being initialized is the result of a statement expression. + EK_StmtExprResult, + /// The entity being initialized is an exception object that /// is being thrown. EK_Exception, @@ -285,6 +288,11 @@ public: return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO); } + static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc, + QualType Type) { + return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type); + } + static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc, QualType Type, bool NRVO) { return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fc70c882c2..a72f6c3796 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12992,11 +12992,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, LastExpr = rebuiltLastStmt; } else { LastExpr = PerformCopyInitialization( - InitializedEntity::InitializeResult(LPLoc, - Ty, - false), - SourceLocation(), - LastExpr); + InitializedEntity::InitializeStmtExprResult(LPLoc, Ty), + SourceLocation(), LastExpr); } if (LastExpr.isInvalid()) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6c2c6d143d..e457de4dcc 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1020,6 +1020,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_Binding: + case InitializedEntity::EK_StmtExprResult: llvm_unreachable("unexpected braced scalar init"); } @@ -3000,6 +3001,7 @@ DeclarationName InitializedEntity::getName() const { return DeclarationName(Capture.VarID); case EK_Result: + case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: @@ -3030,6 +3032,7 @@ ValueDecl *InitializedEntity::getDecl() const { return reinterpret_cast(Parameter & ~0x1); case EK_Result: + case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: @@ -3055,6 +3058,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Exception: return LocAndNRVO.NRVO; + case EK_StmtExprResult: case EK_Variable: case EK_Parameter: case EK_Parameter_CF_Audited: @@ -3090,6 +3094,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; break; case EK_Result: OS << "Result"; break; + case EK_StmtExprResult: OS << "StmtExprResult"; break; case EK_Exception: OS << "Exception"; break; case EK_Member: OS << "Member"; break; case EK_Binding: OS << "Binding"; break; @@ -3534,7 +3539,8 @@ static void MaybeProduceObjCObject(Sema &S, /// retainable type, then returns need to immediately retain the /// object. If an autorelease is required, it will be done at the /// last instant. - } else if (Entity.getKind() == InitializedEntity::EK_Result) { + } else if (Entity.getKind() == InitializedEntity::EK_Result || + Entity.getKind() == InitializedEntity::EK_StmtExprResult) { if (!Entity.getType()->isObjCRetainableType()) return; @@ -5632,6 +5638,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited; case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right. return Sema::AA_Returning; case InitializedEntity::EK_Temporary: @@ -5661,6 +5668,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: @@ -5690,6 +5698,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { static bool shouldDestroyEntity(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: @@ -5721,6 +5730,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, Expr *Initializer) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: return Entity.getReturnLoc(); case InitializedEntity::EK_Exception: @@ -6168,6 +6178,7 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { switch (Top->getKind()) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_Result: + case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: @@ -6216,6 +6227,10 @@ enum LifetimeKind { /// the entity is a return object. LK_Return, + /// The lifetime of a temporary bound to this entity ends too soon, because + /// the entity is the result of a statement expression. + LK_StmtExprResult, + /// This is a mem-initializer: if it would extend a temporary (other than via /// a default member initializer), the program is ill-formed. LK_MemInitializer, @@ -6274,6 +6289,11 @@ static LifetimeResult getEntityLifetime( // destroyed at the end of the full-expression in the return statement. return {nullptr, LK_Return}; + case InitializedEntity::EK_StmtExprResult: + // FIXME: Should we lifetime-extend through the result of a statement + // expression? + return {nullptr, LK_StmtExprResult}; + case InitializedEntity::EK_New: // -- A temporary bound to a reference in a new-initializer persists // until the completion of the full-expression containing the @@ -6582,6 +6602,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_Return: + case LK_StmtExprResult: // FIXME: Move -Wreturn-stack-address checks here. return false; } @@ -6660,6 +6681,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, break; case LK_Return: + case LK_StmtExprResult: // FIXME: Move -Wreturn-stack-address checks here. return false; } -- GitLab From 7adf860add9f877f6e463c4e3d10c01d493b19aa Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 23 Jul 2018 20:04:00 +0000 Subject: [PATCH 0669/1023] [ms] Fix mangling of vector types in QMM_Result contexts. If QMM_Result is set (which it is for return types, RTTI descriptors, and exception type descriptors), tag types (structs, enums, classes, unions) get their qualifiers mangled in. __m64 and friends is a struct/union thingy in MSVC, but not in clang's headers. To make mangling work, we call mangleArtificalTagType(TTK_Union/TTK_Struct for the vector types to mangle them as tag types -- but the isa check when mangling in QMM_Result mode isn't true for these vector types. Add an isArtificialTagType() function and check for that too. Fixes PR37276 and some other issues. I tried to audit all references to TagDecl and TagType in MicrosoftMangle.cpp to find other places where we need to call mangleArtificalTagType(), but couldn't find any. I tried to audit all calls to mangleArtificalTagType() to see if isArtificialTagType() needs to handle more than just the vector types, but as far as I can tell all other types we use it for are types that MSVC can't handle at all (Objective-C types etc). https://reviews.llvm.org/D49597 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337732 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/MicrosoftMangle.cpp | 26 ++++++++- test/CodeGenCXX/mangle-ms-vector-types.cpp | 63 +++++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index f9cd24ce9a..e45f9f7902 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -337,6 +337,8 @@ private: void mangleArgumentType(QualType T, SourceRange Range); void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA); + bool isArtificialTagType(QualType T) const; + // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) @@ -1751,7 +1753,7 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, Quals.removeUnaligned(); if (Quals.hasObjCLifetime()) Quals = Quals.withoutObjCLifetime(); - if ((!IsPointer && Quals) || isa(T)) { + if ((!IsPointer && Quals) || isa(T) || isArtificialTagType(T)) { Out << '?'; mangleQualifiers(Quals, false); } @@ -2280,6 +2282,8 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { mangleTagTypeKind(TD->getTagKind()); mangleName(TD); } + +// If you add a call to this, consider updating isArtificialTagType() too. void MicrosoftCXXNameMangler::mangleArtificalTagType( TagTypeKind TK, StringRef UnqualifiedName, ArrayRef NestedNames) { // ::= {[]+ | []}? @ @@ -2468,6 +2472,26 @@ void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers, mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); } +// Returns true for types that mangleArtificalTagType() gets called for with +// TTK_Union, TTK_Struct, TTK_Class and where compatibility with MSVC's +// mangling matters. +// (It doesn't matter for Objective-C types and the like that cl.exe doesn't +// support.) +bool MicrosoftCXXNameMangler::isArtificialTagType(QualType T) const { + const Type *ty = T.getTypePtr(); + switch (ty->getTypeClass()) { + default: + return false; + + case Type::Vector: { + // For ABI compatibility only __m64, __m128(id), and __m256(id) matter, + // but since mangleType(VectorType*) always calls mangleArtificalTagType() + // just always return true (the other vector types are clang-only). + return true; + } + } +} + void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, SourceRange Range) { const BuiltinType *ET = T->getElementType()->getAs(); diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp index 5b676284a8..f55713e6c0 100644 --- a/test/CodeGenCXX/mangle-ms-vector-types.cpp +++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp @@ -1,30 +1,91 @@ -// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -fcxx-exceptions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s #include #include #include +void thow(int i) { + switch (i) { + case 0: throw __m64(); + // CHECK: ??_R0?AT__m64@@@8 + // CHECK: _CT??_R0?AT__m64@@@88 + // CHECK: _CTA1?AT__m64@@ + // CHECK: _TI1?AT__m64@@ + case 1: throw __m128(); + // CHECK: ??_R0?AT__m128@@@8 + // CHECK: _CT??_R0?AT__m128@@@816 + // CHECK: _CTA1?AT__m128@@ + // CHECK: _TI1?AT__m128@@ + case 2: throw __m128d(); + // CHECK: ??_R0?AU__m128d@@@8 + // CHECK: _CT??_R0?AU__m128d@@@816 + // CHECK: _CTA1?AU__m128d@@ + // CHECK: _TI1?AU__m128d@@ + case 3: throw __m128i(); + // CHECK: ??_R0?AT__m128i@@@8 + // CHECK: _CT??_R0?AT__m128i@@@816 + // CHECK: _CTA1?AT__m128i@@ + // CHECK: _TI1?AT__m128i@@ + case 4: throw __m256(); + // CHECK: ??_R0?AT__m256@@@8 + // CHECK: _CT??_R0?AT__m256@@@832 + // CHECK: _CTA1?AT__m256@@ + // CHECK: _TI1?AT__m256@@ + case 5: throw __m256d(); + // CHECK: ??_R0?AU__m256d@@@8 + // CHECK: _CT??_R0?AU__m256d@@@832 + // CHECK: _CTA1?AU__m256d@@ + // CHECK: _TI1?AU__m256d@@ + case 6: throw __m256i(); + // CHECK: ??_R0?AT__m256@@@8 + // CHECK: _CT??_R0?AT__m256@@@832 + // CHECK: _CTA1?AT__m256@@ + // CHECK: _TI1?AT__m256@@ + } +} + void foo64(__m64) {} // CHECK: define dso_local void @"?foo64@@YAXT__m64@@@Z" +__m64 rfoo64() { return __m64(); } +// CHECK: define dso_local <1 x i64> @"?rfoo64@@YA?AT__m64@@XZ" + void foo128(__m128) {} // CHECK: define dso_local void @"?foo128@@YAXT__m128@@@Z" +const __m128 rfoo128() { return __m128(); } +// CHECK: define dso_local <4 x float> @"?rfoo128@@YA?BT__m128@@XZ" + void foo128d(__m128d) {} // CHECK: define dso_local void @"?foo128d@@YAXU__m128d@@@Z" +volatile __m128d rfoo128d() { return __m128d(); } +// CHECK: define dso_local <2 x double> @"?rfoo128d@@YA?CU__m128d@@XZ" + void foo128i(__m128i) {} // CHECK: define dso_local void @"?foo128i@@YAXT__m128i@@@Z" +const volatile __m128i rfoo128i() { return __m128i(); } +// CHECK: define dso_local <2 x i64> @"?rfoo128i@@YA?DT__m128i@@XZ" + void foo256(__m256) {} // CHECK: define dso_local void @"?foo256@@YAXT__m256@@@Z" +__m256 rfoo256() { return __m256(); } +// CHECK: define dso_local <8 x float> @"?rfoo256@@YA?AT__m256@@XZ" + void foo256d(__m256d) {} // CHECK: define dso_local void @"?foo256d@@YAXU__m256d@@@Z" +__m256d rfoo256d() { return __m256d(); } +// CHECK: define dso_local <4 x double> @"?rfoo256d@@YA?AU__m256d@@XZ" + void foo256i(__m256i) {} // CHECK: define dso_local void @"?foo256i@@YAXT__m256i@@@Z" +__m256i rfoo256i() { return __m256i(); } +// CHECK: define dso_local <4 x i64> @"?rfoo256i@@YA?AT__m256i@@XZ" + // We have a custom mangling for vector types not standardized by Intel. void foov8hi(__v8hi) {} // CHECK: define dso_local void @"?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z" -- GitLab From 7ce68dd9c052f3842479ed8bcdcc44e165663e10 Mon Sep 17 00:00:00 2001 From: Aaron Smith Date: Mon, 23 Jul 2018 20:49:07 +0000 Subject: [PATCH 0670/1023] [CodeGen] Record if a C++ record is a trivial type Summary: This has a dependence on D45122 Reviewers: rnk, zturner, llvm-commits, aleksandr.urakov Reviewed By: rnk Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D45124 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337736 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 10fc22a098..097a1e0430 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2908,6 +2908,10 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { Flags |= llvm::DINode::FlagTypePassByReference; else Flags |= llvm::DINode::FlagTypePassByValue; + + // Record if a C++ record is trivial type. + if (CXXRD->isTrivial()) + Flags |= llvm::DINode::FlagTrivial; } llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( -- GitLab From e0fc906d1ded282705cc90b923fb58b5d3cba759 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 23 Jul 2018 21:08:13 +0000 Subject: [PATCH 0671/1023] Update to -r337585, allow scoped enum inits in -pedantic git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337738 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 3 +++ lib/AST/Type.cpp | 6 ++++++ lib/Sema/SemaDecl.cpp | 3 +++ test/SemaCXX/PR38235.cpp | 8 +++++++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index cbdbc529f7..c692707847 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1784,6 +1784,9 @@ public: /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) bool isEnumeralType() const; + + /// Determine whether this type is a scoped enumeration type. + bool isScopedEnumeralType() const; bool isBooleanType() const; bool isCharType() const; bool isWideCharType() const; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index cd30bc16d0..fad8c0d1c6 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -481,6 +481,12 @@ bool Type::isComplexIntegerType() const { return getAsComplexIntegerType(); } +bool Type::isScopedEnumeralType() const { + if (const auto *ET = getAs()) + return ET->getDecl()->isScoped(); + return false; +} + const ComplexType *Type::getAsComplexIntegerType() const { if (const auto *Complex = getAs()) if (Complex->getElementType()->isIntegerType()) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e91e9d3ac1..55542828f7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11165,6 +11165,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { ; // Nothing to check. else if (Init->isIntegerConstantExpr(Context, &Loc)) ; // Ok, it's an ICE! + else if (Init->getType()->isScopedEnumeralType() && + Init->isCXX11ConstantExpr(Context)) + ; // Ok, it is a scoped-enum constant expression. else if (Init->isEvaluatable(Context)) { // If we can constant fold the initializer through heroics, accept it, // but report this as a use of an extension for -pedantic. diff --git a/test/SemaCXX/PR38235.cpp b/test/SemaCXX/PR38235.cpp index 11874c837b..c3fd38ab04 100644 --- a/test/SemaCXX/PR38235.cpp +++ b/test/SemaCXX/PR38235.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s enum class E { Foo, Bar = 97119 }; @@ -12,3 +12,9 @@ void switch_me(E e) { break; } } + +enum class E2; + +struct S { + static const E e = E::Foo; +}; -- GitLab From 354438d88cbb857858ffcbde72d4723b8548ce0a Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 23 Jul 2018 21:21:22 +0000 Subject: [PATCH 0672/1023] Fold -Wreturn-stack-address into general initialization lifetime checking. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337743 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 12 +- lib/Sema/SemaChecking.cpp | 409 ---------------- lib/Sema/SemaInit.cpp | 436 +++++++++++++----- test/Analysis/stack-addr-ps.c | 2 +- test/Analysis/stack-addr-ps.cpp | 4 +- test/Analysis/stackaddrleak.c | 2 +- test/CXX/drs/dr16xx.cpp | 28 +- test/CXX/drs/dr18xx.cpp | 6 +- test/CXX/special/class.copy/p11.0x.copy.cpp | 7 +- test/CXX/special/class.ctor/p5-0x.cpp | 2 +- test/CXX/temp/temp.param/p5.cpp | 8 +- test/SemaCXX/constexpr-default-arg.cpp | 4 +- .../cxx0x-initializer-stdinitializerlist.cpp | 4 +- test/SemaCXX/eval-crashes.cpp | 4 +- test/SemaCXX/return-stack-addr-2.cpp | 2 +- test/SemaCXX/return-stack-addr.cpp | 3 +- test/SemaCXX/rval-references.cpp | 5 +- 17 files changed, 365 insertions(+), 573 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c6f263dc8c..0d000e72a5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7849,8 +7849,8 @@ def warn_null_ret : Warning< // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< - "%select{address of|reference to}0 stack memory associated with local " - "variable %1 returned">, + "%select{address of|reference to}0 stack memory associated with " + "%select{local variable|parameter}2 %1 returned">, InGroup; def warn_ret_local_temp_addr_ref : Warning< "returning %select{address of|reference to}0 local temporary object">, @@ -7860,8 +7860,10 @@ def warn_ret_addr_label : Warning< InGroup; def err_ret_local_block : Error< "returning block that lives on the local stack">; -def note_ref_var_local_bind : Note< - "binding reference variable %0 here">; +def note_local_var_initializer : Note< + "%select{via initialization of|binding reference}0 variable %1 here">; +def note_init_with_default_member_initalizer : Note< + "initializing field %0 with default member initializer">; // Check for initializing a member variable with the address or a reference to // a constructor parameter. @@ -7902,8 +7904,6 @@ def warn_default_member_init_init_list_not_extended : Warning< "created by aggregate initialization using default member initializer " "is not supported; lifetime of backing array will end at the end of the " "full-expression">, InGroup; -def note_in_default_member_initalizer_here : Note< - "in default member initializer for field %0 used here">; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6492346f6a..8d953b6ef3 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -9232,421 +9232,12 @@ void Sema::CheckStrncatArguments(const CallExpr *CE, << FixItHint::CreateReplacement(SR, OS.str()); } -//===--- CHECK: Return Address of Stack Variable --------------------------===// - -static const Expr *EvalVal(const Expr *E, - SmallVectorImpl &refVars, - const Decl *ParentDecl); -static const Expr *EvalAddr(const Expr *E, - SmallVectorImpl &refVars, - const Decl *ParentDecl); - -/// CheckReturnStackAddr - Check if a return statement returns the address -/// of a stack variable. -static void -CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, - SourceLocation ReturnLoc) { - const Expr *stackE = nullptr; - SmallVector refVars; - - // Perform checking for returned stack addresses, local blocks, - // label addresses or references to temporaries. - if (lhsType->isPointerType() || - (!S.getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) { - stackE = EvalAddr(RetValExp, refVars, /*ParentDecl=*/nullptr); - } else if (lhsType->isReferenceType()) { - stackE = EvalVal(RetValExp, refVars, /*ParentDecl=*/nullptr); - } - - if (!stackE) - return; // Nothing suspicious was found. - - // Parameters are initialized in the calling scope, so taking the address - // of a parameter reference doesn't need a warning. - for (auto *DRE : refVars) - if (isa(DRE->getDecl())) - return; - - SourceLocation diagLoc; - SourceRange diagRange; - if (refVars.empty()) { - diagLoc = stackE->getLocStart(); - diagRange = stackE->getSourceRange(); - } else { - // We followed through a reference variable. 'stackE' contains the - // problematic expression but we will warn at the return statement pointing - // at the reference variable. We will later display the "trail" of - // reference variables using notes. - diagLoc = refVars[0]->getLocStart(); - diagRange = refVars[0]->getSourceRange(); - } - - if (const DeclRefExpr *DR = dyn_cast(stackE)) { - // address of local var - S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType() - << DR->getDecl()->getDeclName() << diagRange; - } else if (isa(stackE)) { // local block. - S.Diag(diagLoc, diag::err_ret_local_block) << diagRange; - } else if (isa(stackE)) { // address of label. - S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; - } else { // local temporary. - // If there is an LValue->RValue conversion, then the value of the - // reference type is used, not the reference. - if (auto *ICE = dyn_cast(RetValExp)) { - if (ICE->getCastKind() == CK_LValueToRValue) { - return; - } - } - S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref) - << lhsType->isReferenceType() << diagRange; - } - - // Display the "trail" of reference variables that we followed until we - // found the problematic expression using notes. - for (unsigned i = 0, e = refVars.size(); i != e; ++i) { - const VarDecl *VD = cast(refVars[i]->getDecl()); - // If this var binds to another reference var, show the range of the next - // var, otherwise the var binds to the problematic expression, in which case - // show the range of the expression. - SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange() - : stackE->getSourceRange(); - S.Diag(VD->getLocation(), diag::note_ref_var_local_bind) - << VD->getDeclName() << range; - } -} - -/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that -/// check if the expression in a return statement evaluates to an address -/// to a location on the stack, a local block, an address of a label, or a -/// reference to local temporary. The recursion is used to traverse the -/// AST of the return expression, with recursion backtracking when we -/// encounter a subexpression that (1) clearly does not lead to one of the -/// above problematic expressions (2) is something we cannot determine leads to -/// a problematic expression based on such local checking. -/// -/// Both EvalAddr and EvalVal follow through reference variables to evaluate -/// the expression that they point to. Such variables are added to the -/// 'refVars' vector so that we know what the reference variable "trail" was. -/// -/// EvalAddr processes expressions that are pointers that are used as -/// references (and not L-values). EvalVal handles all other values. -/// At the base case of the recursion is a check for the above problematic -/// expressions. -/// -/// This implementation handles: -/// -/// * pointer-to-pointer casts -/// * implicit conversions from array references to pointers -/// * taking the address of fields -/// * arbitrary interplay between "&" and "*" operators -/// * pointer arithmetic from an address of a stack variable -/// * taking the address of an array element where the array is on the stack -static const Expr *EvalAddr(const Expr *E, - SmallVectorImpl &refVars, - const Decl *ParentDecl) { - if (E->isTypeDependent()) - return nullptr; - - // We should only be called for evaluating pointer expressions. - assert((E->getType()->isAnyPointerType() || - E->getType()->isBlockPointerType() || - E->getType()->isObjCQualifiedIdType()) && - "EvalAddr only works on pointers"); - - E = E->IgnoreParens(); - - // Our "symbolic interpreter" is just a dispatch off the currently - // viewed AST node. We then recursively traverse the AST by calling - // EvalAddr and EvalVal appropriately. - switch (E->getStmtClass()) { - case Stmt::DeclRefExprClass: { - const DeclRefExpr *DR = cast(E); - - // If we leave the immediate function, the lifetime isn't about to end. - if (DR->refersToEnclosingVariableOrCapture()) - return nullptr; - - if (const VarDecl *V = dyn_cast(DR->getDecl())) - // If this is a reference variable, follow through to the expression that - // it points to. - if (V->hasLocalStorage() && - V->getType()->isReferenceType() && V->hasInit()) { - // Add the reference variable to the "trail". - refVars.push_back(DR); - return EvalAddr(V->getInit(), refVars, ParentDecl); - } - - return nullptr; - } - - case Stmt::UnaryOperatorClass: { - // The only unary operator that make sense to handle here - // is AddrOf. All others don't make sense as pointers. - const UnaryOperator *U = cast(E); - - if (U->getOpcode() == UO_AddrOf) - return EvalVal(U->getSubExpr(), refVars, ParentDecl); - return nullptr; - } - - case Stmt::BinaryOperatorClass: { - // Handle pointer arithmetic. All other binary operators are not valid - // in this context. - const BinaryOperator *B = cast(E); - BinaryOperatorKind op = B->getOpcode(); - - if (op != BO_Add && op != BO_Sub) - return nullptr; - - const Expr *Base = B->getLHS(); - - // Determine which argument is the real pointer base. It could be - // the RHS argument instead of the LHS. - if (!Base->getType()->isPointerType()) - Base = B->getRHS(); - - assert(Base->getType()->isPointerType()); - return EvalAddr(Base, refVars, ParentDecl); - } - - // For conditional operators we need to see if either the LHS or RHS are - // valid DeclRefExpr*s. If one of them is valid, we return it. - case Stmt::ConditionalOperatorClass: { - const ConditionalOperator *C = cast(E); - - // Handle the GNU extension for missing LHS. - // FIXME: That isn't a ConditionalOperator, so doesn't get here. - if (const Expr *LHSExpr = C->getLHS()) { - // In C++, we can have a throw-expression, which has 'void' type. - if (!LHSExpr->getType()->isVoidType()) - if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl)) - return LHS; - } - - // In C++, we can have a throw-expression, which has 'void' type. - if (C->getRHS()->getType()->isVoidType()) - return nullptr; - - return EvalAddr(C->getRHS(), refVars, ParentDecl); - } - - case Stmt::BlockExprClass: - if (cast(E)->getBlockDecl()->hasCaptures()) - return E; // local block. - return nullptr; - - case Stmt::AddrLabelExprClass: - return E; // address of label. - - case Stmt::ExprWithCleanupsClass: - return EvalAddr(cast(E)->getSubExpr(), refVars, - ParentDecl); - - // For casts, we need to handle conversions from arrays to - // pointer values, and pointer-to-pointer conversions. - case Stmt::ImplicitCastExprClass: - case Stmt::CStyleCastExprClass: - case Stmt::CXXFunctionalCastExprClass: - case Stmt::ObjCBridgedCastExprClass: - case Stmt::CXXStaticCastExprClass: - case Stmt::CXXDynamicCastExprClass: - case Stmt::CXXConstCastExprClass: - case Stmt::CXXReinterpretCastExprClass: { - const Expr* SubExpr = cast(E)->getSubExpr(); - switch (cast(E)->getCastKind()) { - case CK_LValueToRValue: - case CK_NoOp: - case CK_BaseToDerived: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - case CK_Dynamic: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - return EvalAddr(SubExpr, refVars, ParentDecl); - - case CK_ArrayToPointerDecay: - return EvalVal(SubExpr, refVars, ParentDecl); - - case CK_BitCast: - if (SubExpr->getType()->isAnyPointerType() || - SubExpr->getType()->isBlockPointerType() || - SubExpr->getType()->isObjCQualifiedIdType()) - return EvalAddr(SubExpr, refVars, ParentDecl); - else - return nullptr; - - default: - return nullptr; - } - } - - case Stmt::MaterializeTemporaryExprClass: - if (const Expr *Result = - EvalAddr(cast(E)->GetTemporaryExpr(), - refVars, ParentDecl)) - return Result; - return E; - - // Everything else: we simply don't reason about them. - default: - return nullptr; - } -} - -/// EvalVal - This function is complements EvalAddr in the mutual recursion. -/// See the comments for EvalAddr for more details. -static const Expr *EvalVal(const Expr *E, - SmallVectorImpl &refVars, - const Decl *ParentDecl) { - do { - // We should only be called for evaluating non-pointer expressions, or - // expressions with a pointer type that are not used as references but - // instead - // are l-values (e.g., DeclRefExpr with a pointer type). - - // Our "symbolic interpreter" is just a dispatch off the currently - // viewed AST node. We then recursively traverse the AST by calling - // EvalAddr and EvalVal appropriately. - - E = E->IgnoreParens(); - switch (E->getStmtClass()) { - case Stmt::ImplicitCastExprClass: { - const ImplicitCastExpr *IE = cast(E); - if (IE->getValueKind() == VK_LValue) { - E = IE->getSubExpr(); - continue; - } - return nullptr; - } - - case Stmt::ExprWithCleanupsClass: - return EvalVal(cast(E)->getSubExpr(), refVars, - ParentDecl); - - case Stmt::DeclRefExprClass: { - // When we hit a DeclRefExpr we are looking at code that refers to a - // variable's name. If it's not a reference variable we check if it has - // local storage within the function, and if so, return the expression. - const DeclRefExpr *DR = cast(E); - - // If we leave the immediate function, the lifetime isn't about to end. - if (DR->refersToEnclosingVariableOrCapture()) - return nullptr; - - if (const VarDecl *V = dyn_cast(DR->getDecl())) { - // Check if it refers to itself, e.g. "int& i = i;". - if (V == ParentDecl) - return DR; - - if (V->hasLocalStorage()) { - if (!V->getType()->isReferenceType()) - return DR; - - // Reference variable, follow through to the expression that - // it points to. - if (V->hasInit()) { - // Add the reference variable to the "trail". - refVars.push_back(DR); - return EvalVal(V->getInit(), refVars, V); - } - } - } - - return nullptr; - } - - case Stmt::UnaryOperatorClass: { - // The only unary operator that make sense to handle here - // is Deref. All others don't resolve to a "name." This includes - // handling all sorts of rvalues passed to a unary operator. - const UnaryOperator *U = cast(E); - - if (U->getOpcode() == UO_Deref) - return EvalAddr(U->getSubExpr(), refVars, ParentDecl); - - return nullptr; - } - - case Stmt::ArraySubscriptExprClass: { - // Array subscripts are potential references to data on the stack. We - // retrieve the DeclRefExpr* for the array variable if it indeed - // has local storage. - const auto *ASE = cast(E); - if (ASE->isTypeDependent()) - return nullptr; - return EvalAddr(ASE->getBase(), refVars, ParentDecl); - } - - case Stmt::OMPArraySectionExprClass: { - return EvalAddr(cast(E)->getBase(), refVars, - ParentDecl); - } - - case Stmt::ConditionalOperatorClass: { - // For conditional operators we need to see if either the LHS or RHS are - // non-NULL Expr's. If one is non-NULL, we return it. - const ConditionalOperator *C = cast(E); - - // Handle the GNU extension for missing LHS. - if (const Expr *LHSExpr = C->getLHS()) { - // In C++, we can have a throw-expression, which has 'void' type. - if (!LHSExpr->getType()->isVoidType()) - if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl)) - return LHS; - } - - // In C++, we can have a throw-expression, which has 'void' type. - if (C->getRHS()->getType()->isVoidType()) - return nullptr; - - return EvalVal(C->getRHS(), refVars, ParentDecl); - } - - // Accesses to members are potential references to data on the stack. - case Stmt::MemberExprClass: { - const MemberExpr *M = cast(E); - - // Check for indirect access. We only want direct field accesses. - if (M->isArrow()) - return nullptr; - - // Check whether the member type is itself a reference, in which case - // we're not going to refer to the member, but to what the member refers - // to. - if (M->getMemberDecl()->getType()->isReferenceType()) - return nullptr; - - return EvalVal(M->getBase(), refVars, ParentDecl); - } - - case Stmt::MaterializeTemporaryExprClass: - if (const Expr *Result = - EvalVal(cast(E)->GetTemporaryExpr(), - refVars, ParentDecl)) - return Result; - return E; - - default: - // Check that we don't return or take the address of a reference to a - // temporary. This is only useful in C++. - if (!E->isTypeDependent() && E->isRValue()) - return E; - - // Everything else: we simply don't reason about them. - return nullptr; - } - } while (true); -} - void Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc, bool isObjCMethod, const AttrVec *Attrs, const FunctionDecl *FD) { - CheckReturnStackAddr(*this, RetValExp, lhsType, ReturnLoc); - // Check if the return value is null but should not be. if (((Attrs && hasSpecificAttr(*Attrs)) || (!isObjCMethod && isNonNullType(Context, lhsType))) && diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index e457de4dcc..5c891bebea 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" @@ -6348,18 +6349,28 @@ enum ReferenceKind { RK_StdInitializerList, }; -/// A temporary or local variable. -using Local = llvm::PointerUnion; +/// A temporary or local variable. This will be one of: +/// * A MaterializeTemporaryExpr. +/// * A DeclRefExpr whose declaration is a local. +/// * An AddrLabelExpr. +/// * A BlockExpr for a block with captures. +using Local = Expr*; /// Expressions we stepped over when looking for the local state. Any steps /// that would inhibit lifetime extension or take us out of subexpressions of /// the initializer are included. struct IndirectLocalPathEntry { - enum { + enum EntryKind { DefaultInit, AddressOf, + VarInit, + LValToRVal, } Kind; Expr *E; + Decl *D = nullptr; + IndirectLocalPathEntry() {} + IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {} + IndirectLocalPathEntry(EntryKind K, Expr *E, Decl *D) : Kind(K), E(E), D(D) {} }; using IndirectLocalPath = llvm::SmallVectorImpl; @@ -6370,16 +6381,24 @@ struct RevertToOldSizeRAII { RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; + +using LocalVisitor = llvm::function_ref; +} + +static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) { + for (auto E : Path) + if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD) + return true; + return false; } -template static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits); /// Visit the locals that would be reachable through a reference bound to the /// glvalue expression \c Init. -template static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit) { @@ -6390,6 +6409,9 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, do { Old = Init; + if (auto *EWC = dyn_cast(Init)) + Init = EWC->getSubExpr(); + if (InitListExpr *ILE = dyn_cast(Init)) { // If this is just redundant braces around an initializer, step over it. if (ILE->isTransparent()) @@ -6409,20 +6431,22 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, // Per the current approach for DR1299, look through array element access // on array glvalues when performing lifetime extension. if (auto *ASE = dyn_cast(Init)) { - auto *ICE = dyn_cast(ASE->getBase()); - if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay) - return; - Init = ICE->getSubExpr(); + Init = ASE->getBase(); + auto *ICE = dyn_cast(Init); + if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay) + Init = ICE->getSubExpr(); + else + // We can't lifetime extend through this but we might still find some + // retained temporaries. + return visitLocalsRetainedByInitializer(Path, Init, Visit, true); } // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back( + {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); - - if (auto *EWC = dyn_cast(Init)) - Init = EWC->getSubExpr(); } } while (Init != Old); @@ -6432,22 +6456,64 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, true); } - // If we find the name of a local non-reference parameter, we could have a - // lifetime problem. - if (auto *DRE = dyn_cast(Init->IgnoreParens())) { + switch (Init->getStmtClass()) { + case Stmt::DeclRefExprClass: { + // If we find the name of a local non-reference parameter, we could have a + // lifetime problem. + auto *DRE = cast(Init); auto *VD = dyn_cast(DRE->getDecl()); if (VD && VD->hasLocalStorage() && !DRE->refersToEnclosingVariableOrCapture()) { - // FIXME: Recurse to the initializer of a local reference. - if (!VD->getType()->isReferenceType()) - Visit(Path, Local(VD), RK); + if (!VD->getType()->isReferenceType()) { + Visit(Path, Local(DRE), RK); + } else if (isa(DRE->getDecl())) { + // The lifetime of a reference parameter is unknown; assume it's OK + // for now. + break; + } else if (VD->getInit() && !isVarOnPath(Path, VD)) { + Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); + visitLocalsRetainedByReferenceBinding(Path, VD->getInit(), + RK_ReferenceBinding, Visit); + } } + break; + } + + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is Deref. All others don't resolve to a "name." This includes + // handling all sorts of rvalues passed to a unary operator. + const UnaryOperator *U = cast(Init); + if (U->getOpcode() == UO_Deref) + visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true); + break; + } + + case Stmt::OMPArraySectionExprClass: { + visitLocalsRetainedByInitializer( + Path, cast(Init)->getBase(), Visit, true); + break; + } + + case Stmt::ConditionalOperatorClass: + case Stmt::BinaryConditionalOperatorClass: { + auto *C = cast(Init); + if (!C->getTrueExpr()->getType()->isVoidType()) + visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); + if (!C->getFalseExpr()->getType()->isVoidType()) + visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit); + break; + } + + // FIXME: Visit the left-hand side of an -> or ->*. + + default: + break; } } /// Visit the locals that would be reachable through an object initialized by /// the prvalue expression \c Init. -template static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits) { @@ -6456,13 +6522,13 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); - - if (auto *EWC = dyn_cast(Init)) - Init = EWC->getSubExpr(); } + if (auto *EWC = dyn_cast(Init)) + Init = EWC->getSubExpr(); + // Dig out the expression which constructs the extended temporary. Init = const_cast(Init->skipRValueSubobjectAdjustments()); @@ -6528,15 +6594,119 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, return; } - // If the initializer is the address of a local, we could have a lifetime - // problem. - if (auto *Op = dyn_cast(Init->IgnoreParenImpCasts())) { - if (Op->getOpcode() == UO_AddrOf) { - Path.push_back({IndirectLocalPathEntry::AddressOf, Op}); - Init = Op->getSubExpr(); - return visitLocalsRetainedByReferenceBinding(Path, Init, + // Step over value-preserving rvalue casts. + while (auto *CE = dyn_cast(Init)) { + switch (CE->getCastKind()) { + case CK_LValueToRValue: + // If we can match the lvalue to a const object, we can look at its + // initializer. + Path.push_back({IndirectLocalPathEntry::LValToRVal, CE}); + return visitLocalsRetainedByReferenceBinding( + Path, Init, RK_ReferenceBinding, + [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { + if (auto *DRE = dyn_cast(L)) { + auto *VD = dyn_cast(DRE->getDecl()); + if (VD && VD->getType().isConstQualified() && VD->getInit()) { + Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); + visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true); + } + } else if (auto *MTE = dyn_cast(L)) { + if (MTE->getType().isConstQualified()) + visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), + Visit, true); + } + return false; + }); + + // We assume that objects can be retained by pointers cast to integers, + // but not if the integer is cast to floating-point type or to _Complex. + // We assume that casts to 'bool' do not preserve enough information to + // retain a local object. + case CK_NoOp: + case CK_BitCast: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_ToUnion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_AddressSpaceConversion: + break; + + case CK_ArrayToPointerDecay: + // Model array-to-pointer decay as taking the address of the array + // lvalue. + Path.push_back({IndirectLocalPathEntry::AddressOf, CE}); + return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(), RK_ReferenceBinding, Visit); + + default: + return; + } + + Init = CE->getSubExpr(); + } + + Init = Init->IgnoreParens(); + switch (Init->getStmtClass()) { + case Stmt::UnaryOperatorClass: { + auto *UO = cast(Init); + // If the initializer is the address of a local, we could have a lifetime + // problem. + if (UO->getOpcode() == UO_AddrOf) { + Path.push_back({IndirectLocalPathEntry::AddressOf, UO}); + visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(), + RK_ReferenceBinding, Visit); + } + break; + } + + case Stmt::BinaryOperatorClass: { + // Handle pointer arithmetic. + auto *BO = cast(Init); + BinaryOperatorKind BOK = BO->getOpcode(); + if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub)) + break; + + if (BO->getLHS()->getType()->isPointerType()) + visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true); + else if (BO->getRHS()->getType()->isPointerType()) + visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true); + break; + } + + case Stmt::ConditionalOperatorClass: + case Stmt::BinaryConditionalOperatorClass: { + auto *C = cast(Init); + // In C++, we can have a throw-expression operand, which has 'void' type + // and isn't interesting from a lifetime perspective. + if (!C->getTrueExpr()->getType()->isVoidType()) + visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true); + if (!C->getFalseExpr()->getType()->isVoidType()) + visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true); + break; + } + + case Stmt::BlockExprClass: + if (cast(Init)->getBlockDecl()->hasCaptures()) { + // This is a local block, whose lifetime is that of the function. + Visit(Path, Local(cast(Init)), RK_ReferenceBinding); } + break; + + case Stmt::AddrLabelExprClass: + // We want to warn if the address of a label would escape the function. + Visit(Path, Local(cast(Init)), RK_ReferenceBinding); + break; + + default: + break; } } @@ -6563,58 +6733,20 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { - // If we found a path to a local variable or similar, check whether the - // initialized object will outlive it. - if (auto *VD = L.dyn_cast()) { - switch (LK) { - case LK_FullExpression: - llvm_unreachable("already handled this"); - - case LK_Extended: - break; - - case LK_MemInitializer: { - // Paths via a default initializer can only occur during error recovery - // (there's no other way that a default initializer can refer to a - // local). Don't produce a bogus warning on those cases. - if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { - return E.Kind == IndirectLocalPathEntry::DefaultInit; - })) - break; - - if (auto *Member = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { - bool AddressTaken = - !Path.empty() && - Path.back().Kind == IndirectLocalPathEntry::AddressOf; - Diag(Init->getExprLoc(), - AddressTaken ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << VD << isa(VD) << Init->getSourceRange(); - Diag(Member->getLocation(), - diag::note_ref_or_ptr_member_declared_here) - << (unsigned)AddressTaken; - } - break; - } - - case LK_New: - break; - - case LK_Return: - case LK_StmtExprResult: - // FIXME: Move -Wreturn-stack-address checks here. - return false; - } - return false; - } + Expr *First = Path.empty() ? L : Path.front().E; + SourceLocation DiagLoc = First->getLocStart(); + SourceRange DiagRange = First->getSourceRange(); - auto *MTE = L.get(); switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); - case LK_Extended: + case LK_Extended: { + auto *MTE = dyn_cast(L); + if (!MTE) + // FIXME: Warn on this. + return false; + // Lifetime-extend the temporary. if (Path.empty()) { // Update the storage duration of the materialized temporary. @@ -6632,70 +6764,138 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // FIXME: Properly handle this situation. Perhaps the easiest approach // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. - Diag(MTE->getExprLoc(), + Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_default_member_init_temporary_not_extended - : diag::warn_default_member_init_init_list_not_extended); + : diag::warn_default_member_init_init_list_not_extended) + << DiagRange; } else { // FIXME: Warn on this. + return false; } break; + } - case LK_MemInitializer: - // Under C++ DR1696, if a mem-initializer (or a default member - // initializer used by the absence of one) would lifetime-extend a - // temporary, the program is ill-formed. - if (auto *ExtendingDecl = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { - bool IsSubobjectMember = ExtendingEntity != &Entity; - Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary) - << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember - << RK; - // Don't bother adding a note pointing to the field if we're inside its - // default member initializer; our primary diagnostic points to the - // same place in that case. - if (Path.empty() || - Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { - Diag(ExtendingDecl->getLocation(), - diag::note_lifetime_extending_member_declared_here) - << RK << IsSubobjectMember; + case LK_MemInitializer: { + if (auto *MTE = dyn_cast(L)) { + // Under C++ DR1696, if a mem-initializer (or a default member + // initializer used by the absence of one) would lifetime-extend a + // temporary, the program is ill-formed. + if (auto *ExtendingDecl = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + bool IsSubobjectMember = ExtendingEntity != &Entity; + Diag(DiagLoc, diag::err_bind_ref_member_to_temporary) + << ExtendingDecl << IsSubobjectMember << RK << DiagRange; + // Don't bother adding a note pointing to the field if we're inside + // its default member initializer; our primary diagnostic points to + // the same place in that case. + if (Path.empty() || + Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { + Diag(ExtendingDecl->getLocation(), + diag::note_lifetime_extending_member_declared_here) + << RK << IsSubobjectMember; + } + } else { + // We have a mem-initializer but no particular field within it; this + // is either a base class or a delegating initializer directly + // initializing the base-class from something that doesn't live long + // enough. + // + // FIXME: Warn on this. + return false; } } else { - // We have a mem-initializer but no particular field within it; this - // is either a base class or a delegating initializer directly - // initializing the base-class from something that doesn't live long - // enough. Either way, that can't happen. - // FIXME: Move CheckForDanglingReferenceOrPointer checks here. - llvm_unreachable( - "temporary initializer for base class / delegating ctor"); + // Paths via a default initializer can only occur during error recovery + // (there's no other way that a default initializer can refer to a + // local). Don't produce a bogus warning on those cases. + if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { + return E.Kind == IndirectLocalPathEntry::DefaultInit; + })) + return false; + + auto *DRE = dyn_cast(L); + auto *VD = DRE ? dyn_cast(DRE->getDecl()) : nullptr; + if (!VD) { + // A member was initialized to a local block. + // FIXME: Warn on this. + return false; + } + + if (auto *Member = + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + bool IsPointer = Member->getType()->isAnyPointerType(); + Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << VD << isa(VD) << DiagRange; + Diag(Member->getLocation(), + diag::note_ref_or_ptr_member_declared_here) + << (unsigned)IsPointer; + } } break; + } case LK_New: - if (RK == RK_ReferenceBinding) { - Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference); + if (auto *MTE = dyn_cast(L)) { + Diag(DiagLoc, RK == RK_ReferenceBinding + ? diag::warn_new_dangling_reference + : diag::warn_new_dangling_initializer_list) + << (ExtendingEntity != &Entity) << DiagRange; } else { - Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list) - << (ExtendingEntity != &Entity); + // We can't determine if the allocation outlives the local declaration. + return false; } break; case LK_Return: case LK_StmtExprResult: - // FIXME: Move -Wreturn-stack-address checks here. - return false; + if (auto *DRE = dyn_cast(L)) { + // We can't determine if the local variable outlives the statement + // expression. + if (LK == LK_StmtExprResult) + return false; + Diag(DiagLoc, diag::warn_ret_stack_addr_ref) + << Entity.getType()->isReferenceType() << DRE->getDecl() + << isa(DRE->getDecl()) << DiagRange; + } else if (isa(L)) { + Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; + } else if (isa(L)) { + Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; + } else { + Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) + << Entity.getType()->isReferenceType() << DiagRange; + } + break; } - // FIXME: Model these as CodeSynthesisContexts to fix the note emission - // order. - for (auto Elem : llvm::reverse(Path)) { + for (unsigned I = 0; I != Path.size(); ++I) { + auto Elem = Path[I]; + + // Highlight the range of the next step within this path element. + SourceRange Range; + if (I < Path.size() - 1) + Range = Path[I + 1].E->getSourceRange(); + else + Range = L->getSourceRange(); + switch (Elem.Kind) { - case IndirectLocalPathEntry::DefaultInit: - Diag(Elem.E->getExprLoc(), diag::note_in_default_member_initalizer_here) - << cast(Elem.E)->getField(); + case IndirectLocalPathEntry::AddressOf: + case IndirectLocalPathEntry::LValToRVal: + // These exist primarily to mark the path as not permitting lifetime + // extension. break; - case IndirectLocalPathEntry::AddressOf: + case IndirectLocalPathEntry::DefaultInit: { + auto *FD = cast(Elem.D); + Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer) + << FD << Range; + break; + } + + case IndirectLocalPathEntry::VarInit: + const VarDecl *VD = cast(Elem.D); + Diag(VD->getLocation(), diag::note_local_var_initializer) + << VD->getType()->isReferenceType() << VD->getDeclName() << Range; break; } } diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c index 4026cee90b..721051ffaf 100644 --- a/test/Analysis/stack-addr-ps.c +++ b/test/Analysis/stack-addr-ps.c @@ -6,7 +6,7 @@ int* f1() { } int* f2(int y) { - return &y; // expected-warning{{Address of stack memory associated with local variable 'y' returned}} expected-warning{{address of stack memory associated with local variable 'y' returned}} + return &y; // expected-warning{{Address of stack memory associated with local variable 'y' returned}} expected-warning{{address of stack memory associated with parameter 'y' returned}} } int* f3(int x, int *y) { diff --git a/test/Analysis/stack-addr-ps.cpp b/test/Analysis/stack-addr-ps.cpp index 79afd18e18..e1f06835c7 100644 --- a/test/Analysis/stack-addr-ps.cpp +++ b/test/Analysis/stack-addr-ps.cpp @@ -91,8 +91,8 @@ struct TS { // rdar://11345441 int* f5() { - int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-note {{binding reference variable 'i' here}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}} - return &i; // expected-warning {{address of stack memory associated with local variable 'i' returned}} + int& i = i; // expected-warning {{Assigned value is garbage or undefined}} expected-warning{{reference 'i' is not yet bound to a value when used within its own initialization}} + return &i; } void *radar13226577() { diff --git a/test/Analysis/stackaddrleak.c b/test/Analysis/stackaddrleak.c index a037d12fe4..8a1519e787 100644 --- a/test/Analysis/stackaddrleak.c +++ b/test/Analysis/stackaddrleak.c @@ -37,7 +37,7 @@ void test_multi_return() { intptr_t returnAsNonLoc() { int x; - return (intptr_t)&x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}} + return (intptr_t)&x; // expected-warning{{Address of stack memory associated with local variable 'x' returned to caller}} expected-warning{{address of stack memory associated with local variable 'x' returned}} } bool returnAsBool() { diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index 54648cfe96..d9d404c0c2 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -317,23 +317,25 @@ namespace dr1696 { // dr1696: 7 // D1 d1 = {A()}; // ... which lifetime-extends the A temporary. struct D1 { - const A &a = A(); #if __cplusplus < 201402L // expected-error@-2 {{binds to a temporary}} - // expected-note@-4 {{here}} -#else - // expected-warning-re@-5 {{sorry, lifetime extension {{.*}} not supported}} #endif + const A &a = A(); // expected-note {{default member init}} }; - D1 d1 = {}; // expected-note {{here}} + D1 d1 = {}; +#if __cplusplus < 201402L + // expected-note@-2 {{first required here}} +#else + // expected-warning-re@-4 {{sorry, lifetime extension {{.*}} not supported}} +#endif struct D2 { - const A &a = A(); // expected-error {{binds to a temporary}} - D2() {} // expected-note {{used here}} + const A &a = A(); // expected-note {{default member init}} + D2() {} // expected-error {{binds to a temporary}} }; - struct D3 { // expected-note {{used here}} - const A &a = A(); // expected-error {{binds to a temporary}} + struct D3 { // expected-error {{binds to a temporary}} + const A &a = A(); // expected-note {{default member init}} }; D3 d3; // expected-note {{first required here}} @@ -352,14 +354,14 @@ namespace dr1696 { // dr1696: 7 std::initializer_list il = {1, 2, 3}; }; - struct haslist4 { // expected-note {{in default member initializer}} - std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} + struct haslist4 { // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} + std::initializer_list il = {1, 2, 3}; // expected-note {{default member initializer}} }; haslist4 hl4; // expected-note {{in implicit default constructor}} struct haslist5 { - std::initializer_list il = {1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} - haslist5() {} // expected-note {{in default member initializer}} + std::initializer_list il = {1, 2, 3}; // expected-note {{default member initializer}} + haslist5() {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} }; #endif } diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp index f6a4676bc7..16f967b656 100644 --- a/test/CXX/drs/dr18xx.cpp +++ b/test/CXX/drs/dr18xx.cpp @@ -33,10 +33,10 @@ namespace dr1813 { // dr1813: 7 namespace dr1815 { // dr1815: no #if __cplusplus >= 201402L // FIXME: needs codegen test - struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}} - A a = {}; // expected-note {{here}} + struct A { int &&r = 0; }; // expected-note {{default member init}} + A a = {}; // FIXME expected-warning {{not supported}} - struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{here}} + struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{default member init}} B b; // expected-note {{here}} #endif } diff --git a/test/CXX/special/class.copy/p11.0x.copy.cpp b/test/CXX/special/class.copy/p11.0x.copy.cpp index a4d0cdcdc7..e7256bcf94 100644 --- a/test/CXX/special/class.copy/p11.0x.copy.cpp +++ b/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -128,11 +128,10 @@ struct RValue { RValue RVa; RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}} -// FIXME: The note on the class-name is attached to the location of the +// FIXME: The error on the class-name is attached to the location of the // constructor. This is not especially clear. -struct RValueTmp { // expected-note {{used here}} - int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} - // expected-error@-1 {{reference member 'ri' binds to a temporary}} +struct RValueTmp { // expected-error {{reference member 'ri' binds to a temporary}} + int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} // expected-note {{default member init}} }; RValueTmp RVTa; // expected-note {{implicit default constructor for 'RValueTmp' first required here}} RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy constructor}} diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp index 5558313ce7..061a3d1f07 100644 --- a/test/CXX/special/class.ctor/p5-0x.cpp +++ b/test/CXX/special/class.ctor/p5-0x.cpp @@ -47,7 +47,7 @@ class NotDeleted2c { int &&a = static_cast(n); }; NotDeleted2c nd2c; // Note: this one does not have a deleted default constructor even though the // implicit default constructor is ill-formed! -class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{here}} +class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member 'a' binds to a temporary object}} expected-note {{default member init}} NotDeleted2d nd2d; // expected-note {{first required here}} // - any non-variant non-static data member of const qualified type (or array diff --git a/test/CXX/temp/temp.param/p5.cpp b/test/CXX/temp/temp.param/p5.cpp index de902a5e4d..4cb2d4343a 100644 --- a/test/CXX/temp/temp.param/p5.cpp +++ b/test/CXX/temp/temp.param/p5.cpp @@ -1,13 +1,13 @@ // RUN: %clang_cc1 -verify %s -std=c++14 -template struct S { // expected-note {{in default member initializer}} +template struct S { // expected-error {{reference member 'r' binds to a temporary object}} decltype(I) n; - int &&r = I; // expected-error {{reference member 'r' binds to a temporary object}} + int &&r = I; // expected-note {{default member initializer}} }; S<5> s; // expected-note {{implicit default constructor}} -template struct U { // expected-note {{in default member initializer}} +template struct U { // expected-error {{reference member 'r' binds to a temporary object}} decltype(v) n; - int &&r = v; // expected-error {{reference member 'r' binds to a temporary object}} + int &&r = v; // expected-note {{default member initializer}} }; U u; // expected-note {{implicit default constructor}} diff --git a/test/SemaCXX/constexpr-default-arg.cpp b/test/SemaCXX/constexpr-default-arg.cpp index 165c31aab6..0cef4aa578 100644 --- a/test/SemaCXX/constexpr-default-arg.cpp +++ b/test/SemaCXX/constexpr-default-arg.cpp @@ -31,8 +31,8 @@ void test_default_arg2() { } // Check that multiple CXXDefaultInitExprs don't cause an assertion failure. -struct A { int &&r = 0; }; // expected-warning 2{{not supported}} +struct A { int &&r = 0; }; // expected-note 2{{default member initializer}} struct B { A x, y; }; -B b = {}; // expected-note 2{{in default member initializer for field 'r' used here}} +B b = {}; // expected-warning 2{{not supported}} } diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index ece014d93a..f371891e54 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -155,11 +155,11 @@ void dangle() { struct haslist1 { std::initializer_list il // expected-note {{declared here}} = {1, 2, 3}; // ok, unused - std::initializer_list jl{1, 2, 3}; // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}} + std::initializer_list jl{1, 2, 3}; // expected-note {{default member init}} haslist1(); }; -haslist1::haslist1() // expected-note {{used here}} +haslist1::haslist1() // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}} : il{1, 2, 3} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} {} diff --git a/test/SemaCXX/eval-crashes.cpp b/test/SemaCXX/eval-crashes.cpp index 33bde75de6..60c2deed4d 100644 --- a/test/SemaCXX/eval-crashes.cpp +++ b/test/SemaCXX/eval-crashes.cpp @@ -27,9 +27,9 @@ namespace pr33140_0b { namespace pr33140_2 { // FIXME: The declaration of 'b' below should lifetime-extend two int // temporaries. - struct A { int &&r = 0; }; // expected-warning 2{{not supported}} + struct A { int &&r = 0; }; // expected-note 2{{initializing field 'r' with default member initializer}} struct B { A x, y; }; - B b = {}; // expected-note 2{{used here}} + B b = {}; // expected-warning 2{{not supported}} } namespace pr33140_3 { diff --git a/test/SemaCXX/return-stack-addr-2.cpp b/test/SemaCXX/return-stack-addr-2.cpp index 47b45957e9..e848189bde 100644 --- a/test/SemaCXX/return-stack-addr-2.cpp +++ b/test/SemaCXX/return-stack-addr-2.cpp @@ -65,7 +65,7 @@ const int *int6() { const int *int7(int x) { const int &x2 = x; // expected-note{{binding reference variable 'x2' here}} - return &x2; // expected-warning{{address of stack memory associated with local variable 'x' returned}} + return &x2; // expected-warning{{address of stack memory associated with parameter 'x' returned}} } const int *int8(const int &x = 5) { diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp index 7670798ecb..a5f84adf0b 100644 --- a/test/SemaCXX/return-stack-addr.cpp +++ b/test/SemaCXX/return-stack-addr.cpp @@ -63,7 +63,8 @@ int& ret_local_field_ref() { int* ret_conditional(bool cond) { int x = 1; int y = 2; - return cond ? &x : &y; // expected-warning {{address of stack memory}} + return cond ? &x // expected-warning {{address of stack memory associated with local variable 'x' returned}} + : &y; // expected-warning {{address of stack memory associated with local variable 'y' returned}} } int* ret_conditional_rhs(int *x, bool cond) { diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index 94b09ce2cb..838bf484fe 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -65,10 +65,9 @@ void f() { } int&& should_warn(int i) { - // FIXME: The stack address return test doesn't reason about casts. - return static_cast(i); // xpected-warning {{returning reference to temporary}} + return static_cast(i); // expected-warning {{reference to stack memory associated with parameter 'i' returned}} } -int&& should_not_warn(int&& i) { // But GCC 4.4 does +int&& should_not_warn(int&& i) { return static_cast(i); } -- GitLab From d61977eb486f9bc591c48a8266c41e6f90358d2b Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 23 Jul 2018 21:21:24 +0000 Subject: [PATCH 0673/1023] Do not try to perform lifetime-extension through conditional expressions. CodeGen can't cope with that yet. Instead, produce a "not supported" warning for now and don't extend lifetime. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337744 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 15 +++--- lib/Sema/SemaInit.cpp | 59 ++++++++++++++-------- test/SemaCXX/conditional-expr.cpp | 22 +++++++- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0d000e72a5..98770935d1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7895,13 +7895,16 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_default_member_init_temporary_not_extended : Warning< - "sorry, lifetime extension of temporary created by aggregate initialization " - "using default member initializer is not supported; lifetime of temporary " +def warn_unsupported_temporary_not_extended : Warning< + "sorry, lifetime extension of temporary created " + "%select{by aggregate initialization using default member initializer|" + "within conditional expression}0 " + "is not supported; lifetime of temporary " "will end at the end of the full-expression">, InGroup; -def warn_default_member_init_init_list_not_extended : Warning< - "sorry, lifetime extension of backing array of initializer list " - "created by aggregate initialization using default member initializer " +def warn_unsupported_init_list_not_extended : Warning< + "sorry, lifetime extension of backing array of initializer list created " + "%select{by aggregate initialization using default member initializer|" + "within conditional expression}0 " "is not supported; lifetime of backing array will end at the end of the " "full-expression">, InGroup; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 5c891bebea..208576e75d 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6362,6 +6362,7 @@ using Local = Expr*; struct IndirectLocalPathEntry { enum EntryKind { DefaultInit, + Conditional, AddressOf, VarInit, LValToRVal, @@ -6497,6 +6498,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { + Path.push_back({IndirectLocalPathEntry::Conditional, Init}); auto *C = cast(Init); if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); @@ -6683,6 +6685,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { + Path.push_back({IndirectLocalPathEntry::Conditional, Init}); auto *C = cast(Init); // In C++, we can have a throw-expression operand, which has 'void' type // and isn't interesting from a lifetime perspective. @@ -6714,12 +6717,33 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, /// supposed to lifetime-extend along (but don't). static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { - if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) + if (Elem.Kind != IndirectLocalPathEntry::DefaultInit && + Elem.Kind != IndirectLocalPathEntry::Conditional) return false; } return true; } +/// Find the range for the first interesting entry in the path at or after I. +static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, + Expr *E) { + for (unsigned N = Path.size(); I != N; ++I) { + switch (Path[I].Kind) { + case IndirectLocalPathEntry::AddressOf: + case IndirectLocalPathEntry::LValToRVal: + case IndirectLocalPathEntry::Conditional: + // These exist primarily to mark the path as not permitting or + // supporting lifetime extension. + break; + + case IndirectLocalPathEntry::DefaultInit: + case IndirectLocalPathEntry::VarInit: + return Path[I].E->getSourceRange(); + } + } + return E->getSourceRange(); +} + void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { LifetimeResult LR = getEntityLifetime(&Entity); @@ -6733,9 +6757,8 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { - Expr *First = Path.empty() ? L : Path.front().E; - SourceLocation DiagLoc = First->getLocStart(); - SourceRange DiagRange = First->getSourceRange(); + SourceRange DiagRange = nextPathEntryRange(Path, 0, L); + SourceLocation DiagLoc = DiagRange.getBegin(); switch (LK) { case LK_FullExpression: @@ -6761,13 +6784,14 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // We're supposed to lifetime-extend the temporary along this path (per // the resolution of DR1815), but we don't support that yet. // - // FIXME: Properly handle this situation. Perhaps the easiest approach + // FIXME: Properly handle these situations. + // For the default member initializer case, perhaps the easiest approach // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. - Diag(DiagLoc, - RK == RK_ReferenceBinding - ? diag::warn_default_member_init_temporary_not_extended - : diag::warn_default_member_init_init_list_not_extended) + Diag(DiagLoc, RK == RK_ReferenceBinding + ? diag::warn_unsupported_temporary_not_extended + : diag::warn_unsupported_init_list_not_extended) + << (Path.front().Kind == IndirectLocalPathEntry::Conditional) << DiagRange; } else { // FIXME: Warn on this. @@ -6871,31 +6895,26 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, for (unsigned I = 0; I != Path.size(); ++I) { auto Elem = Path[I]; - // Highlight the range of the next step within this path element. - SourceRange Range; - if (I < Path.size() - 1) - Range = Path[I + 1].E->getSourceRange(); - else - Range = L->getSourceRange(); - switch (Elem.Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: - // These exist primarily to mark the path as not permitting lifetime - // extension. + case IndirectLocalPathEntry::Conditional: + // These exist primarily to mark the path as not permitting or + // supporting lifetime extension. break; case IndirectLocalPathEntry::DefaultInit: { auto *FD = cast(Elem.D); Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer) - << FD << Range; + << FD << nextPathEntryRange(Path, I + 1, L); break; } case IndirectLocalPathEntry::VarInit: const VarDecl *VD = cast(Elem.D); Diag(VD->getLocation(), diag::note_local_var_initializer) - << VD->getType()->isReferenceType() << VD->getDeclName() << Range; + << VD->getType()->isReferenceType() << VD->getDeclName() + << nextPathEntryRange(Path, I + 1, L); break; } } diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 7e6b0ce8e8..ab19ce54b6 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wsign-conversion %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++17 -Wsign-conversion %s // C++ rules for ?: are a lot stricter than C rules, and have to take into // account more conversion options. @@ -228,7 +229,7 @@ void test() // be properly tested at runtime, though. const Abstract &abstract1 = true ? static_cast(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}} - const Abstract &abstract2 = true ? static_cast(Derived1()) : throw 3; // ok + const Abstract &abstract2 = true ? static_cast(Derived1()) : throw 3; // expected-warning-re {{sorry, lifetime extension {{.*}} not supported}} } namespace PR6595 { @@ -393,3 +394,22 @@ Derived d; typedef decltype(true ? static_cast(b) : static_cast(d)) x; typedef Base &&x; } + +namespace lifetime_extension { + struct A {}; + struct B : A { B(); ~B(); }; + struct C : A { C(); ~C(); }; + + void f(bool b) { + // expected-warning@+1 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}} + A &&r = b ? static_cast(B()) : static_cast(C()); + } + + struct D { A &&a; }; + void f_indirect(bool b) { +#if __cplusplus >= 201702L + // expected-warning@+2 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}} +#endif + D d = b ? D{B()} : D{C()}; + } +} -- GitLab From 9c96ba60ab2112270bb08d20ac18f1e135481626 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 23 Jul 2018 21:29:43 +0000 Subject: [PATCH 0674/1023] [clang-cl] Expose -fblocks and -fno-builtin as driver flags Users have requested them. Helps with PR36427. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337746 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 10 +++++----- test/Driver/cl-options.c | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index d0a31f9495..2470638bec 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -762,12 +762,12 @@ def faddrsig : Flag<["-"], "faddrsig">, Group, Flags<[CoreOption, CC1Op HelpText<"Emit an address-significance table">; def fno_addrsig : Flag<["-"], "fno-addrsig">, Group, Flags<[CoreOption]>, HelpText<"Don't emit an address-significance table">; -def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CC1Option]>, +def fblocks : Flag<["-"], "fblocks">, Group, Flags<[CoreOption, CC1Option]>, HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group; def fborland_extensions : Flag<["-"], "fborland-extensions">, Group, Flags<[CC1Option]>, HelpText<"Accept non-standard constructs supported by the Borland compiler">; -def fbuiltin : Flag<["-"], "fbuiltin">, Group; +def fbuiltin : Flag<["-"], "fbuiltin">, Group, Flags<[CoreOption]>; def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group, Flags<[DriverOption]>, HelpText<"Load the clang builtins module map file.">; def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group; @@ -1320,11 +1320,11 @@ def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, Flags<[CC1Option]>; -def fno_blocks : Flag<["-"], "fno-blocks">, Group; +def fno_blocks : Flag<["-"], "fno-blocks">, Group, Flags<[CoreOption]>; def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group; -def fno_builtin : Flag<["-"], "fno-builtin">, Group, Flags<[CC1Option]>, +def fno_builtin : Flag<["-"], "fno-builtin">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Disable implicit builtin knowledge of functions">; -def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, Flags<[CC1Option]>, +def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Disable implicit builtin knowledge of a specific function">; def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group, Flags<[CC1Option]>; diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c index b105146c37..9aa6ced349 100644 --- a/test/Driver/cl-options.c +++ b/test/Driver/cl-options.c @@ -565,6 +565,11 @@ // (/Zs is for syntax-only, -Werror makes it fail hard on unknown options) // RUN: %clang_cl \ // RUN: --driver-mode=cl \ +// RUN: -fblocks \ +// RUN: -fno-blocks \ +// RUN: -fbuiltin \ +// RUN: -fno-builtin \ +// RUN: -fno-builtin-strcpy \ // RUN: -fcolor-diagnostics \ // RUN: -fno-color-diagnostics \ // RUN: -fcoverage-mapping \ -- GitLab From 3787b2b6af82e095ea3d2123db225566abf957d0 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 23 Jul 2018 22:29:10 +0000 Subject: [PATCH 0675/1023] [ASTMatchers] [NFC] Regenerate HTML docs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337760 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index a41424d89a..3a32c6ca6c 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -3275,9 +3275,9 @@ Example matcher = objcMessagaeExpr(isInstanceMessage()) matches NSString *x = @"hello"; - [x containsString:@"h"] + [x containsString:@"h"]; but not - [NSString stringWithFormat:@"format"] + [NSString stringWithFormat:@"format"];
@@ -5894,7 +5894,7 @@ and the inner matcher matches on that instance. For example the method call in NSString *x = @"hello"; - [x containsString:@"h"] + [x containsString:@"h"]; is matched by objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
@@ -6564,7 +6564,7 @@ type of the matched node. For example, in: class A {}; using B = A; -The matcher type(hasUnqualifeidDesugaredType(recordType())) matches +The matcher type(hasUnqualifiedDesugaredType(recordType())) matches both B and A. -- GitLab From bcd3d176cb4d5d3e31749a571cc6573259edec02 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 23 Jul 2018 22:29:35 +0000 Subject: [PATCH 0676/1023] [ASTMatchers] Add an isMain() matcher Differential Revision: https://reviews.llvm.org/D49615 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337761 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 6 ++++++ include/clang/ASTMatchers/ASTMatchers.h | 6 ++++++ lib/ASTMatchers/Dynamic/Registry.cpp | 1 + unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 3a32c6ca6c..49899c3086 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -2919,6 +2919,12 @@ namespaceDecl(isInline()) will match n::m. +Matcher<FunctionDecl>isMain +
Determines whether the function is "main", which is the entry point
+into an executable program.
+
+ + Matcher<FunctionDecl>isNoReturn
Matches FunctionDecls that have a noreturn attribute.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 850caf63c7..75dc654905 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -616,6 +616,12 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher,
           InnerMatcher.matches(*Initializer, Finder, Builder));
 }
 
+/// Determines whether the function is "main", which is the entry point
+/// into an executable program.
+AST_MATCHER(FunctionDecl, isMain) {
+  return Node.isMain();
+}
+
 /// Matches the specialized template of a specialization declaration.
 ///
 /// Given
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 5a01c5d1f9..982156f6dc 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -359,6 +359,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isInTemplateInstantiation);
   REGISTER_MATCHER(isLambda);
   REGISTER_MATCHER(isListInitialization);
+  REGISTER_MATCHER(isMain);
   REGISTER_MATCHER(isMemberInitializer);
   REGISTER_MATCHER(isMoveAssignmentOperator);
   REGISTER_MATCHER(isMoveConstructor);
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index ef385e7f18..7426dd926d 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2158,5 +2158,13 @@ TEST(IsAssignmentOperator, Basic) {
       notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
 }
 
+TEST(Matcher, isMain) {
+  EXPECT_TRUE(
+    matches("int main() {}", functionDecl(isMain())));
+
+  EXPECT_TRUE(
+    notMatches("int main2() {}", functionDecl(isMain())));
+}
+
 } // namespace ast_matchers
 } // namespace clang
-- 
GitLab


From fc6962eb2acb82e92637824fd3bb02b28619a195 Mon Sep 17 00:00:00 2001
From: Erik Pilkington 
Date: Mon, 23 Jul 2018 22:47:37 +0000
Subject: [PATCH 0677/1023] [Sema] Fix crash on BlockExprs in a default member
 initializers

Clang would crash when instantiating a BlockDecl that appeared in a
default-member-initializer of a class template. Fix this by deferring the
instantiation until we instantate the BlockExpr.

rdar://41200624

Differential revision: https://reviews.llvm.org/D49688

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337766 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaTemplateInstantiate.cpp | 5 +++++
 test/SemaCXX/instantiate-blocks.cpp  | 9 +++++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 5a4a6bd033..3cf584344c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2083,6 +2083,11 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
     if (Member->getDeclContext() != Pattern)
       continue;
 
+    // BlockDecls can appear in a default-member-initializer. They must be the
+    // child of a BlockExpr, so we only know how to instantiate them from there.
+    if (isa(Member))
+      continue;
+
     if (Member->isInvalidDecl()) {
       Instantiation->setInvalidDecl();
       continue;
diff --git a/test/SemaCXX/instantiate-blocks.cpp b/test/SemaCXX/instantiate-blocks.cpp
index bb0f8d881d..dbcef500b5 100644
--- a/test/SemaCXX/instantiate-blocks.cpp
+++ b/test/SemaCXX/instantiate-blocks.cpp
@@ -30,3 +30,12 @@ int main(void)
    noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret' requested here}}
 }
 
+namespace rdar41200624 {
+template 
+struct S {
+  int (^p)() = ^{ return 0; };
+  T (^t)() = ^{ return T{}; };
+  T s = ^{ return T{}; }();
+};
+S x;
+}
-- 
GitLab


From b68cfed35f46283d6a8df0a96dacc806720384a2 Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Mon, 23 Jul 2018 22:56:45 +0000
Subject: [PATCH 0678/1023] Support lifetime-extension of conditional
 temporaries.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337767 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td |   6 +-
 lib/CodeGen/CGCleanup.cpp                  |  15 +-
 lib/CodeGen/CGDecl.cpp                     |   3 -
 lib/CodeGen/CodeGenFunction.h              | 239 ++++++++++++---------
 lib/Sema/SemaInit.cpp                      |   9 +-
 test/CodeGenCXX/temporaries.cpp            |  98 ++++++++-
 test/SemaCXX/conditional-expr.cpp          |   6 +-
 7 files changed, 247 insertions(+), 129 deletions(-)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 98770935d1..62fd7de8bb 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7897,14 +7897,12 @@ def warn_new_dangling_initializer_list : Warning<
   InGroup;
 def warn_unsupported_temporary_not_extended : Warning<
   "sorry, lifetime extension of temporary created "
-  "%select{by aggregate initialization using default member initializer|"
-  "within conditional expression}0 "
+  "by aggregate initialization using default member initializer "
   "is not supported; lifetime of temporary "
   "will end at the end of the full-expression">, InGroup;
 def warn_unsupported_init_list_not_extended : Warning<
   "sorry, lifetime extension of backing array of initializer list created "
-  "%select{by aggregate initialization using default member initializer|"
-  "within conditional expression}0 "
+  "by aggregate initialization using default member initializer "
   "is not supported; lifetime of backing array will end at the end of the "
   "full-expression">, InGroup;
 
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 34bfd07caf..cfd230997e 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -281,7 +281,7 @@ void EHScopeStack::popNullFixups() {
     BranchFixups.pop_back();
 }
 
-void CodeGenFunction::initFullExprCleanup() {
+Address CodeGenFunction::createCleanupActiveFlag() {
   // Create a variable to decide whether the cleanup needs to be run.
   Address active = CreateTempAllocaWithoutCast(
       Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond");
@@ -293,10 +293,14 @@ void CodeGenFunction::initFullExprCleanup() {
   // Initialize it to true at the current location.
   Builder.CreateStore(Builder.getTrue(), active);
 
+  return active;
+}
+
+void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) {
   // Set that as the active flag in the cleanup.
   EHCleanupScope &cleanup = cast(*EHStack.begin());
   assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?");
-  cleanup.setActiveFlag(active);
+  cleanup.setActiveFlag(ActiveFlag);
 
   if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup();
   if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup();
@@ -494,6 +498,13 @@ void CodeGenFunction::PopCleanupBlocks(
                               &LifetimeExtendedCleanupStack[I],
                               Header.getSize());
     I += Header.getSize();
+
+    if (Header.isConditional()) {
+      Address ActiveFlag =
+          reinterpret_cast
(LifetimeExtendedCleanupStack[I]); + initFullExprCleanupWithFlag(ActiveFlag); + I += sizeof(ActiveFlag); + } } LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize); } diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 89c5789c3e..16646f0a6a 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -1651,9 +1651,6 @@ void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) { void CodeGenFunction::pushLifetimeExtendedDestroy( CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { - assert(!isInConditionalBranch() && - "performing lifetime extension from within conditional"); - // Push an EH-only cleanup for the object now. // FIXME: When popping normal cleanups, we need to keep this EH cleanup // around in case a temporary's destructor throws an exception. diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 1fc445c66d..752d670a5f 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -138,6 +138,88 @@ enum SanitizerHandler { #undef SANITIZER_CHECK }; +/// Helper class with most of the code for saving a value for a +/// conditional expression cleanup. +struct DominatingLLVMValue { + typedef llvm::PointerIntPair saved_type; + + /// Answer whether the given value needs extra work to be saved. + static bool needsSaving(llvm::Value *value) { + // If it's not an instruction, we don't need to save. + if (!isa(value)) return false; + + // If it's an instruction in the entry block, we don't need to save. + llvm::BasicBlock *block = cast(value)->getParent(); + return (block != &block->getParent()->getEntryBlock()); + } + + static saved_type save(CodeGenFunction &CGF, llvm::Value *value); + static llvm::Value *restore(CodeGenFunction &CGF, saved_type value); +}; + +/// A partial specialization of DominatingValue for llvm::Values that +/// might be llvm::Instructions. +template struct DominatingPointer : DominatingLLVMValue { + typedef T *type; + static type restore(CodeGenFunction &CGF, saved_type value) { + return static_cast(DominatingLLVMValue::restore(CGF, value)); + } +}; + +/// A specialization of DominatingValue for Address. +template <> struct DominatingValue
{ + typedef Address type; + + struct saved_type { + DominatingLLVMValue::saved_type SavedValue; + CharUnits Alignment; + }; + + static bool needsSaving(type value) { + return DominatingLLVMValue::needsSaving(value.getPointer()); + } + static saved_type save(CodeGenFunction &CGF, type value) { + return { DominatingLLVMValue::save(CGF, value.getPointer()), + value.getAlignment() }; + } + static type restore(CodeGenFunction &CGF, saved_type value) { + return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), + value.Alignment); + } +}; + +/// A specialization of DominatingValue for RValue. +template <> struct DominatingValue { + typedef RValue type; + class saved_type { + enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, + AggregateAddress, ComplexAddress }; + + llvm::Value *Value; + unsigned K : 3; + unsigned Align : 29; + saved_type(llvm::Value *v, Kind k, unsigned a = 0) + : Value(v), K(k), Align(a) {} + + public: + static bool needsSaving(RValue value); + static saved_type save(CodeGenFunction &CGF, RValue value); + RValue restore(CodeGenFunction &CGF); + + // implementations in CGCleanup.cpp + }; + + static bool needsSaving(type value) { + return saved_type::needsSaving(value); + } + static saved_type save(CodeGenFunction &CGF, type value) { + return saved_type::save(CGF, value); + } + static type restore(CodeGenFunction &CGF, saved_type value) { + return value.restore(CGF); + } +}; + /// CodeGenFunction - This class organizes the per-function state that is used /// while generating LLVM code. class CodeGenFunction : public CodeGenTypeCache { @@ -427,10 +509,13 @@ public: /// The size of the following cleanup object. unsigned Size; /// The kind of cleanup to push: a value from the CleanupKind enumeration. - CleanupKind Kind; + unsigned Kind : 31; + /// Whether this is a conditional cleanup. + unsigned IsConditional : 1; size_t getSize() const { return Size; } - CleanupKind getKind() const { return Kind; } + CleanupKind getKind() const { return (CleanupKind)Kind; } + bool isConditional() const { return IsConditional; } }; /// i32s containing the indexes of the cleanup destinations. @@ -529,24 +614,48 @@ public: /// full-expression. template void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { - assert(!isInConditionalBranch() && "can't defer conditional cleanup"); + if (!isInConditionalBranch()) + return pushCleanupAfterFullExprImpl(Kind, Address::invalid(), A...); + + Address ActiveFlag = createCleanupActiveFlag(); + assert(!DominatingValue
::needsSaving(ActiveFlag) && + "cleanup active flag should never need saving"); + + typedef std::tuple::saved_type...> SavedTuple; + SavedTuple Saved{saveValueInCond(A)...}; + + typedef EHScopeStack::ConditionalCleanup CleanupType; + pushCleanupAfterFullExprImpl(Kind, ActiveFlag, Saved); + } - LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind }; + template + void pushCleanupAfterFullExprImpl(CleanupKind Kind, Address ActiveFlag, + As... A) { + LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, + ActiveFlag.isValid()}; size_t OldSize = LifetimeExtendedCleanupStack.size(); LifetimeExtendedCleanupStack.resize( - LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size); + LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size + + (Header.IsConditional ? sizeof(ActiveFlag) : 0)); static_assert(sizeof(Header) % alignof(T) == 0, "Cleanup will be allocated on misaligned address"); char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); + if (Header.IsConditional) + new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); } - /// Set up the last cleaup that was pushed as a conditional + /// Set up the last cleanup that was pushed as a conditional /// full-expression cleanup. - void initFullExprCleanup(); + void initFullExprCleanup() { + initFullExprCleanupWithFlag(createCleanupActiveFlag()); + } + + void initFullExprCleanupWithFlag(Address ActiveFlag); + Address createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -4176,107 +4285,29 @@ private: FormResolverCondition(const TargetMultiVersionResolverOption &RO); }; -/// Helper class with most of the code for saving a value for a -/// conditional expression cleanup. -struct DominatingLLVMValue { - typedef llvm::PointerIntPair saved_type; - - /// Answer whether the given value needs extra work to be saved. - static bool needsSaving(llvm::Value *value) { - // If it's not an instruction, we don't need to save. - if (!isa(value)) return false; - - // If it's an instruction in the entry block, we don't need to save. - llvm::BasicBlock *block = cast(value)->getParent(); - return (block != &block->getParent()->getEntryBlock()); - } - - /// Try to save the given value. - static saved_type save(CodeGenFunction &CGF, llvm::Value *value) { - if (!needsSaving(value)) return saved_type(value, false); - - // Otherwise, we need an alloca. - auto align = CharUnits::fromQuantity( - CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType())); - Address alloca = - CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); - CGF.Builder.CreateStore(value, alloca); - - return saved_type(alloca.getPointer(), true); - } - - static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) { - // If the value says it wasn't saved, trust that it's still dominating. - if (!value.getInt()) return value.getPointer(); - - // Otherwise, it should be an alloca instruction, as set up in save(). - auto alloca = cast(value.getPointer()); - return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment()); - } -}; - -/// A partial specialization of DominatingValue for llvm::Values that -/// might be llvm::Instructions. -template struct DominatingPointer : DominatingLLVMValue { - typedef T *type; - static type restore(CodeGenFunction &CGF, saved_type value) { - return static_cast(DominatingLLVMValue::restore(CGF, value)); - } -}; - -/// A specialization of DominatingValue for Address. -template <> struct DominatingValue
{ - typedef Address type; +inline DominatingLLVMValue::saved_type +DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { + if (!needsSaving(value)) return saved_type(value, false); - struct saved_type { - DominatingLLVMValue::saved_type SavedValue; - CharUnits Alignment; - }; + // Otherwise, we need an alloca. + auto align = CharUnits::fromQuantity( + CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType())); + Address alloca = + CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); + CGF.Builder.CreateStore(value, alloca); - static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); - } - static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getAlignment() }; - } - static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.Alignment); - } -}; - -/// A specialization of DominatingValue for RValue. -template <> struct DominatingValue { - typedef RValue type; - class saved_type { - enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, - AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, Kind k, unsigned a = 0) - : Value(v), K(k), Align(a) {} - - public: - static bool needsSaving(RValue value); - static saved_type save(CodeGenFunction &CGF, RValue value); - RValue restore(CodeGenFunction &CGF); + return saved_type(alloca.getPointer(), true); +} - // implementations in CGCleanup.cpp - }; +inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, + saved_type value) { + // If the value says it wasn't saved, trust that it's still dominating. + if (!value.getInt()) return value.getPointer(); - static bool needsSaving(type value) { - return saved_type::needsSaving(value); - } - static saved_type save(CodeGenFunction &CGF, type value) { - return saved_type::save(CGF, value); - } - static type restore(CodeGenFunction &CGF, saved_type value) { - return value.restore(CGF); - } -}; + // Otherwise, it should be an alloca instruction, as set up in save(). + auto alloca = cast(value.getPointer()); + return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment()); +} } // end namespace CodeGen } // end namespace clang diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 208576e75d..be284daab0 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6362,7 +6362,6 @@ using Local = Expr*; struct IndirectLocalPathEntry { enum EntryKind { DefaultInit, - Conditional, AddressOf, VarInit, LValToRVal, @@ -6498,7 +6497,6 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { - Path.push_back({IndirectLocalPathEntry::Conditional, Init}); auto *C = cast(Init); if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); @@ -6685,7 +6683,6 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { - Path.push_back({IndirectLocalPathEntry::Conditional, Init}); auto *C = cast(Init); // In C++, we can have a throw-expression operand, which has 'void' type // and isn't interesting from a lifetime perspective. @@ -6717,8 +6714,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, /// supposed to lifetime-extend along (but don't). static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { - if (Elem.Kind != IndirectLocalPathEntry::DefaultInit && - Elem.Kind != IndirectLocalPathEntry::Conditional) + if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) return false; } return true; @@ -6731,7 +6727,6 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, switch (Path[I].Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: - case IndirectLocalPathEntry::Conditional: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; @@ -6791,7 +6786,6 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_unsupported_temporary_not_extended : diag::warn_unsupported_init_list_not_extended) - << (Path.front().Kind == IndirectLocalPathEntry::Conditional) << DiagRange; } else { // FIXME: Warn on this. @@ -6898,7 +6892,6 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, switch (Elem.Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: - case IndirectLocalPathEntry::Conditional: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index 2eb27e71cb..294ff29a8e 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX11 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++17 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX17 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID,CHECK-CXX11 namespace PR16263 { const unsigned int n = 1234; @@ -46,7 +47,9 @@ namespace PR20227 { namespace BraceInit { typedef const int &CIR; CIR x = CIR{3}; - // CHECK: @_ZGRN9BraceInit1xE_ = internal constant i32 3 + // CHECK-CXX11: @_ZGRN9BraceInit1xE_ = internal constant i32 3 + // FIXME: This should still be emitted as 'constant' in C++17. + // CHECK-CXX17: @_ZGRN9BraceInit1xE_ = internal global i32 3 // CHECK: @_ZN9BraceInit1xE = constant i32* @_ZGRN9BraceInit1xE_ } @@ -804,3 +807,92 @@ namespace PR14130 { // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0) // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE } + +namespace Conditional { + struct A {}; + struct B : A { B(); ~B(); }; + struct C : A { C(); ~C(); }; + + void g(); + + // CHECK-LABEL: define {{.*}} @_ZN11Conditional1fEb( + void f(bool b) { + // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]], + // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]], + // CHECK: br i1 + // + // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev( + // CHECK: store i1 true, i1* %[[CLEANUP_B]], + // CHECK: br label + // + // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev( + // CHECK: store i1 true, i1* %[[CLEANUP_C]], + // CHECK: br label + A &&r = b ? static_cast(B()) : static_cast(C()); + + // CHECK: call {{.*}} @_ZN11Conditional1gEv( + g(); + + // CHECK: load {{.*}} %[[CLEANUP_C]] + // CHECK: br i1 + // CHECK: call {{.*}} @_ZN11Conditional1CD1Ev( + // CHECK: br label + + // CHECK: load {{.*}} %[[CLEANUP_B]] + // CHECK: br i1 + // CHECK: call {{.*}} @_ZN11Conditional1BD1Ev( + // CHECK: br label + } + + struct D { A &&a; }; + // CHECK-LABEL: define {{.*}} @_ZN11Conditional10f_indirectEb( + void f_indirect(bool b) { + // CHECK: store i1 false, i1* %[[CLEANUP_B:.*]], + // CHECK: store i1 false, i1* %[[CLEANUP_C:.*]], + // CHECK: br i1 + // + // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev( + // CHECK: store i1 true, i1* %[[CLEANUP_B]], + // CHECK: br label + // + // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev( + // CHECK: store i1 true, i1* %[[CLEANUP_C]], + // CHECK: br label + D d = b ? D{B()} : D{C()}; + + // In C++17, the expression D{...} directly initializes the 'd' object, so + // lifetime-extending the temporaries to the lifetime of the D object + // extends them past the call to g(). + // + // In C++14 and before, D is move-constructed from the result of the + // conditional expression, so no lifetime extension occurs. + + // CHECK-CXX17: call {{.*}} @_ZN11Conditional1gEv( + + // CHECK: load {{.*}} %[[CLEANUP_C]] + // CHECK: br i1 + // CHECK: call {{.*}} @_ZN11Conditional1CD1Ev( + // CHECK: br label + + // CHECK: load {{.*}} %[[CLEANUP_B]] + // CHECK: br i1 + // CHECK: call {{.*}} @_ZN11Conditional1BD1Ev( + // CHECK: br label + + // CHECK-CXX11: call {{.*}} @_ZN11Conditional1gEv( + g(); + } + + extern bool b; + // CHECK: load {{.*}} @_ZN11Conditional1b + // CHECK: br i1 + // + // CHECK: call {{.*}} @_ZN11Conditional1BC1Ev({{.*}} @_ZGRN11Conditional1rE_) + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1BD1Ev {{.*}} @_ZGRN11Conditional1rE_, + // CHECK: br label + // + // CHECK: call {{.*}} @_ZN11Conditional1CC1Ev({{.*}} @_ZGRN11Conditional1rE0_) + // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1CD1Ev {{.*}} @_ZGRN11Conditional1rE0_, + // CHECK: br label + A &&r = b ? static_cast(B()) : static_cast(C()); +} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index ab19ce54b6..8d0555ea50 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -229,7 +229,7 @@ void test() // be properly tested at runtime, though. const Abstract &abstract1 = true ? static_cast(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}} - const Abstract &abstract2 = true ? static_cast(Derived1()) : throw 3; // expected-warning-re {{sorry, lifetime extension {{.*}} not supported}} + const Abstract &abstract2 = true ? static_cast(Derived1()) : throw 3; } namespace PR6595 { @@ -401,15 +401,11 @@ namespace lifetime_extension { struct C : A { C(); ~C(); }; void f(bool b) { - // expected-warning@+1 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}} A &&r = b ? static_cast(B()) : static_cast(C()); } struct D { A &&a; }; void f_indirect(bool b) { -#if __cplusplus >= 201702L - // expected-warning@+2 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}} -#endif D d = b ? D{B()} : D{C()}; } } -- GitLab From 6748c6fecb10eaebe06850aaf5d16f7075e92431 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 23 Jul 2018 23:09:44 +0000 Subject: [PATCH 0679/1023] [analyzer] pr38273: Legalize Loc<>NonLoc comparison symbols. Remove an assertion in RangeConstraintManager that expects such symbols to never appear, while admitting that the constraint manager doesn't yet handle them. Differential Revision: https://reviews.llvm.org/D49703 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337769 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 6 ++++-- test/Analysis/casts.c | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 1d2b94d6f7..e8c7bdbde3 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -343,9 +343,11 @@ bool RangeConstraintManager::canReasonAbout(SVal X) const { if (BinaryOperator::isEqualityOp(SSE->getOpcode()) || BinaryOperator::isRelationalOp(SSE->getOpcode())) { // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc. + // We've recently started producing Loc <> NonLoc comparisons (that + // result from casts of one of the operands between eg. intptr_t and + // void *), but we can't reason about them yet. if (Loc::isLocType(SSE->getLHS()->getType())) { - assert(Loc::isLocType(SSE->getRHS()->getType())); - return true; + return Loc::isLocType(SSE->getRHS()->getType()); } } } diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c index 548b4223b6..49db822aa1 100644 --- a/test/Analysis/casts.c +++ b/test/Analysis/casts.c @@ -171,3 +171,7 @@ void testCastVoidPtrToIntPtrThroughUIntTypedAssignment() { (*((int *)(&x))) = (int)(unsigned *)getVoidPtr(); *x = 1; // no-crash } + +void testLocNonLocSymbolAssume(int a, int *b) { + if ((int)b < a) {} +} -- GitLab From 4ff1ebdfcef861c85ab1f74edd5f05e1c1f39f0a Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Mon, 23 Jul 2018 23:48:13 +0000 Subject: [PATCH 0680/1023] [analyzer] Add a no-crash to a recently added test. No functional change intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337776 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Analysis/casts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c index 49db822aa1..eccb67812a 100644 --- a/test/Analysis/casts.c +++ b/test/Analysis/casts.c @@ -173,5 +173,5 @@ void testCastVoidPtrToIntPtrThroughUIntTypedAssignment() { } void testLocNonLocSymbolAssume(int a, int *b) { - if ((int)b < a) {} + if ((int)b < a) {} // no-crash } -- GitLab From db6649baa2a2f6e3a8ca27e13e086827fd192abf Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Tue, 24 Jul 2018 00:07:49 +0000 Subject: [PATCH 0681/1023] NFC: Add the emacs c++ mode hint "-*- C++ -*-" to the headers that don't have it https://llvm.org/docs/CodingStandards.html#file-headers git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337780 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/TypeOrdering.h | 2 +- include/clang/Basic/CharInfo.h | 2 +- include/clang/CodeGen/SwiftCallingConv.h | 2 +- include/clang/Frontend/LayoutOverrideSource.h | 2 +- include/clang/Frontend/SerializedDiagnosticPrinter.h | 2 +- include/clang/Index/IndexDataConsumer.h | 2 +- include/clang/Index/IndexSymbol.h | 2 +- include/clang/Index/IndexingAction.h | 2 +- include/clang/Index/USRGeneration.h | 2 +- include/clang/Sema/SemaFixItUtils.h | 2 +- lib/Basic/Targets.h | 2 +- lib/Basic/Targets/Sparc.h | 2 +- lib/Format/BreakableToken.h | 2 +- lib/Format/Encoding.h | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 5f16969dca..d29dd6d601 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -1,4 +1,4 @@ -//===-------------- TypeOrdering.h - Total ordering for types -------------===// +//===-------------- TypeOrdering.h - Total ordering for types ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h index be49f360d6..e6c5e90d34 100644 --- a/include/clang/Basic/CharInfo.h +++ b/include/clang/Basic/CharInfo.h @@ -1,4 +1,4 @@ -//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters ------------===// +//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters --*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/CodeGen/SwiftCallingConv.h b/include/clang/CodeGen/SwiftCallingConv.h index a5ea900185..45b3145ed9 100644 --- a/include/clang/CodeGen/SwiftCallingConv.h +++ b/include/clang/CodeGen/SwiftCallingConv.h @@ -1,4 +1,4 @@ -//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==// +//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Frontend/LayoutOverrideSource.h b/include/clang/Frontend/LayoutOverrideSource.h index f7a5c87b77..0b7f7dc7a7 100644 --- a/include/clang/Frontend/LayoutOverrideSource.h +++ b/include/clang/Frontend/LayoutOverrideSource.h @@ -1,4 +1,4 @@ -//===--- LayoutOverrideSource.h --Override Record Layouts -----------------===// +//===--- LayoutOverrideSource.h --Override Record Layouts -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index 2906a6f6a5..dc68c32fb1 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -1,4 +1,4 @@ -//===--- SerializedDiagnosticPrinter.h - Serializer for diagnostics -------===// +//===--- SerializedDiagnosticPrinter.h - Diagnostics serializer -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h index 8115b04af6..6e11455661 100644 --- a/include/clang/Index/IndexDataConsumer.h +++ b/include/clang/Index/IndexDataConsumer.h @@ -1,4 +1,4 @@ -//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===// +//===--- IndexDataConsumer.h - Abstract index data consumer -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 1e8439ed5a..068796141d 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -1,4 +1,4 @@ -//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===// +//===- IndexSymbol.h - Types and functions for indexing symbols -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h index 64496a21ec..0d09c40348 100644 --- a/include/clang/Index/IndexingAction.h +++ b/include/clang/Index/IndexingAction.h @@ -1,4 +1,4 @@ -//===--- IndexingAction.h - Frontend index action -------------------------===// +//===--- IndexingAction.h - Frontend index action ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h index 4ff142ac99..1ece321746 100644 --- a/include/clang/Index/USRGeneration.h +++ b/include/clang/Index/USRGeneration.h @@ -1,4 +1,4 @@ -//===- USRGeneration.h - Routines for USR generation ----------------------===// +//===- USRGeneration.h - Routines for USR generation ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Sema/SemaFixItUtils.h b/include/clang/Sema/SemaFixItUtils.h index 343ccfb3d6..84dc58754b 100644 --- a/include/clang/Sema/SemaFixItUtils.h +++ b/include/clang/Sema/SemaFixItUtils.h @@ -1,4 +1,4 @@ -//===--- SemaFixItUtils.h - Sema FixIts -----------------------------------===// +//===--- SemaFixItUtils.h - Sema FixIts -------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Basic/Targets.h b/lib/Basic/Targets.h index 6fc967ddab..d450aa3f37 100644 --- a/lib/Basic/Targets.h +++ b/lib/Basic/Targets.h @@ -1,4 +1,4 @@ -//===------- Targets.h - Declare target feature support -------------------===// +//===------- Targets.h - Declare target feature support ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Basic/Targets/Sparc.h b/lib/Basic/Targets/Sparc.h index 674a9cce3f..af2189f214 100644 --- a/lib/Basic/Targets/Sparc.h +++ b/lib/Basic/Targets/Sparc.h @@ -1,4 +1,4 @@ -//===--- Sparc.h - Declare Sparc target feature support -------------------===// +//===--- Sparc.h - declare sparc target feature support ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h index d9713be398..0fac8f08c0 100644 --- a/lib/Format/BreakableToken.h +++ b/lib/Format/BreakableToken.h @@ -1,4 +1,4 @@ -//===--- BreakableToken.h - Format C++ code -------------------------------===// +//===--- BreakableToken.h - Format C++ code ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Format/Encoding.h b/lib/Format/Encoding.h index 404a443abc..4c877e7e49 100644 --- a/lib/Format/Encoding.h +++ b/lib/Format/Encoding.h @@ -1,4 +1,4 @@ -//===--- Encoding.h - Format C++ code -------------------------------------===// +//===--- Encoding.h - Format C++ code ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // -- GitLab From 4c4d20cbc7d9f7a5d45071f965f3f8950c9b78cf Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 24 Jul 2018 00:29:58 +0000 Subject: [PATCH 0682/1023] [WebAssembly] Change size_t to `unsigned long`. Changing it to unsigned long (which is 32-bit on wasm32) makes it the same type as wasm64 (where unsigned long is 64-bit), which would eliminate the most common cause for mangled names being different between wasm32 and wasm64. For example, export lists containing symbol names could now often be the same between wasm32 and wasm64. Differential Revision: https://reviews.llvm.org/D40526 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337783 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/WebAssembly.h | 8 ++++--- test/Preprocessor/init.c | 40 ++++++++++++++++----------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/Basic/Targets/WebAssembly.h b/lib/Basic/Targets/WebAssembly.h index b0e466b8d8..c04c5cb6fb 100644 --- a/lib/Basic/Targets/WebAssembly.h +++ b/lib/Basic/Targets/WebAssembly.h @@ -47,9 +47,11 @@ public: LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; - SizeType = UnsignedInt; - PtrDiffType = SignedInt; - IntPtrType = SignedInt; + // size_t being unsigned long for both wasm32 and wasm64 makes mangled names + // more consistent between the two. + SizeType = UnsignedLong; + PtrDiffType = SignedLong; + IntPtrType = SignedLong; } protected: diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c index ac65f15acd..68d057d87b 100644 --- a/test/Preprocessor/init.c +++ b/test/Preprocessor/init.c @@ -9171,10 +9171,10 @@ // WEBASSEMBLY32-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL // WEBASSEMBLY32-NEXT:#define __INTMAX_TYPE__ long long int // WEBASSEMBLY32-NEXT:#define __INTMAX_WIDTH__ 64 -// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "d" -// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "i" -// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ int +// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "ld" +// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "li" +// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647L +// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ long int // WEBASSEMBLY32-NEXT:#define __INTPTR_WIDTH__ 32 // WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTd__ "hd" // WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTi__ "hi" @@ -9239,10 +9239,10 @@ // WEBASSEMBLY32-NEXT:#define __ORDER_PDP_ENDIAN__ 3412 // WEBASSEMBLY32-NEXT:#define __POINTER_WIDTH__ 32 // WEBASSEMBLY32-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1 -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "d" -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "i" -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ int +// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "ld" +// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "li" +// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647L +// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ long int // WEBASSEMBLY32-NEXT:#define __PTRDIFF_WIDTH__ 32 // WEBASSEMBLY32-NOT:#define __REGISTER_PREFIX__ // WEBASSEMBLY32-NEXT:#define __SCHAR_MAX__ 127 @@ -9262,12 +9262,12 @@ // WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4 // WEBASSEMBLY32-NEXT:#define __SIZEOF_WCHAR_T__ 4 // WEBASSEMBLY32-NEXT:#define __SIZEOF_WINT_T__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "X" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "o" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "u" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "x" -// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295U -// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ unsigned int +// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "lX" +// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "lo" +// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "lu" +// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "lx" +// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL +// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ long unsigned int // WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32 // WEBASSEMBLY32-NEXT:#define __STDC_HOSTED__ 0 // WEBASSEMBLY32-NOT:#define __STDC_MB_MIGHT_NEQ_WC__ @@ -9315,12 +9315,12 @@ // WEBASSEMBLY32-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL // WEBASSEMBLY32-NEXT:#define __UINTMAX_TYPE__ long long unsigned int // WEBASSEMBLY32-NEXT:#define __UINTMAX_WIDTH__ 64 -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "X" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "o" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "u" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "x" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295U -// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ unsigned int +// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "lX" +// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "lo" +// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "lu" +// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "lx" +// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL +// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ long unsigned int // WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32 // WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTX__ "hX" // WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTo__ "ho" -- GitLab From 5feb21c1c6720e01d992a852ee6f2c3984f266e7 Mon Sep 17 00:00:00 2001 From: Thomas Anderson Date: Tue, 24 Jul 2018 00:43:47 +0000 Subject: [PATCH 0683/1023] Borrow visibility from __fundamental_type_info for generated fundamental type infos This is necessary so the clang gives hidden visibility to fundamental types when -fvisibility=hidden is passed. Fixes https://bugs.llvm.org/show_bug.cgi?id=35066 Differential Revision: https://reviews.llvm.org/D49109 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337788 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ItaniumCXXABI.cpp | 127 ++++++++++++++------------- test/CodeGenCXX/rtti-fundamental.cpp | 71 ++++++++++++++- 2 files changed, 137 insertions(+), 61 deletions(-) diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index d156ffab56..16fdd1c16a 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -31,6 +31,7 @@ #include "clang/AST/StmtCXX.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Value.h" @@ -181,8 +182,7 @@ public: emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn) override; - void EmitFundamentalRTTIDescriptor(QualType Type, bool DLLExport); - void EmitFundamentalRTTIDescriptors(bool DLLExport); + void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD); llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, @@ -1613,7 +1613,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, isa(DC) && cast(DC)->getIdentifier() && cast(DC)->getIdentifier()->isStr("__cxxabiv1") && DC->getParent()->isTranslationUnit()) - EmitFundamentalRTTIDescriptors(RD->hasAttr()); + EmitFundamentalRTTIDescriptors(RD); if (!VTable->isDeclarationForLinker()) CGM.EmitVTableTypeMetadata(VTable, VTLayout); @@ -2698,12 +2698,16 @@ public: BCTI_Public = 0x2 }; + /// BuildTypeInfo - Build the RTTI type info struct for the given type, or + /// link to an existing RTTI descriptor if one already exists. + llvm::Constant *BuildTypeInfo(QualType Ty); + /// BuildTypeInfo - Build the RTTI type info struct for the given type. - /// - /// \param Force - true to force the creation of this RTTI value - /// \param DLLExport - true to mark the RTTI value as DLLExport - llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false, - bool DLLExport = false); + llvm::Constant *BuildTypeInfo( + QualType Ty, + llvm::GlobalVariable::LinkageTypes Linkage, + llvm::GlobalValue::VisibilityTypes Visibility, + llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass); }; } @@ -3172,8 +3176,7 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, llvm_unreachable("Invalid linkage!"); } -llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, - bool DLLExport) { +llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) { // We want to operate on the canonical type. Ty = Ty.getCanonicalType(); @@ -3191,17 +3194,41 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, } // Check if there is already an external RTTI descriptor for this type. - bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); - if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty))) + if (IsStandardLibraryRTTIDescriptor(Ty) || + ShouldUseExternalRTTIDescriptor(CGM, Ty)) return GetAddrOfExternalRTTIDescriptor(Ty); // Emit the standard library with external linkage. - llvm::GlobalVariable::LinkageTypes Linkage; - if (IsStdLib) - Linkage = llvm::GlobalValue::ExternalLinkage; + llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty); + + // Give the type_info object and name the formal visibility of the + // type itself. + llvm::GlobalValue::VisibilityTypes llvmVisibility; + if (llvm::GlobalValue::isLocalLinkage(Linkage)) + // If the linkage is local, only default visibility makes sense. + llvmVisibility = llvm::GlobalValue::DefaultVisibility; + else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) == + ItaniumCXXABI::RUK_NonUniqueHidden) + llvmVisibility = llvm::GlobalValue::HiddenVisibility; else - Linkage = getTypeInfoLinkage(CGM, Ty); + llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); + + llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = + llvm::GlobalValue::DefaultStorageClass; + if (CGM.getTriple().isWindowsItaniumEnvironment()) { + auto RD = Ty->getAsCXXRecordDecl(); + if (RD && RD->hasAttr()) + DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass; + } + return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass); +} + +llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( + QualType Ty, + llvm::GlobalVariable::LinkageTypes Linkage, + llvm::GlobalValue::VisibilityTypes Visibility, + llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) { // Add the vtable pointer. BuildVTablePointer(cast(Ty)); @@ -3315,7 +3342,11 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); + SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); llvm::Module &M = CGM.getModule(); + llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); llvm::GlobalVariable *GV = new llvm::GlobalVariable(M, Init->getType(), /*Constant=*/true, Linkage, Init, Name); @@ -3347,40 +3378,14 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, // All of this is to say that it's important that both the type_info // object and the type_info name be uniqued when weakly emitted. - // Give the type_info object and name the formal visibility of the - // type itself. - llvm::GlobalValue::VisibilityTypes llvmVisibility; - if (llvm::GlobalValue::isLocalLinkage(Linkage)) - // If the linkage is local, only default visibility makes sense. - llvmVisibility = llvm::GlobalValue::DefaultVisibility; - else if (RTTIUniqueness == ItaniumCXXABI::RUK_NonUniqueHidden) - llvmVisibility = llvm::GlobalValue::HiddenVisibility; - else - llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); - - TypeName->setVisibility(llvmVisibility); + TypeName->setVisibility(Visibility); CGM.setDSOLocal(TypeName); - GV->setVisibility(llvmVisibility); + GV->setVisibility(Visibility); CGM.setDSOLocal(GV); - if (CGM.getTriple().isWindowsItaniumEnvironment()) { - auto RD = Ty->getAsCXXRecordDecl(); - if (DLLExport || (RD && RD->hasAttr())) { - TypeName->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); - } else if (RD && RD->hasAttr() && - ShouldUseExternalRTTIDescriptor(CGM, Ty)) { - TypeName->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - - // Because the typename and the typeinfo are DLL import, convert them to - // declarations rather than definitions. The initializers still need to - // be constructed to calculate the type for the declarations. - TypeName->setInitializer(nullptr); - GV->setInitializer(nullptr); - } - } + TypeName->setDLLStorageClass(DLLStorageClass); + GV->setDLLStorageClass(DLLStorageClass); return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); } @@ -3655,18 +3660,7 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty); } -void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type, - bool DLLExport) { - QualType PointerType = getContext().getPointerType(Type); - QualType PointerTypeConst = getContext().getPointerType(Type.withConst()); - ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, /*Force=*/true, DLLExport); - ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, /*Force=*/true, - DLLExport); - ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, /*Force=*/true, - DLLExport); -} - -void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) { +void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) { // Types added here must also be added to TypeInfoIsInStandardLibrary. QualType FundamentalTypes[] = { getContext().VoidTy, getContext().NullPtrTy, @@ -3683,8 +3677,21 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) { getContext().Char8Ty, getContext().Char16Ty, getContext().Char32Ty }; - for (const QualType &FundamentalType : FundamentalTypes) - EmitFundamentalRTTIDescriptor(FundamentalType, DLLExport); + llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = + RD->hasAttr() + ? llvm::GlobalValue::DLLExportStorageClass + : llvm::GlobalValue::DefaultStorageClass; + llvm::GlobalValue::VisibilityTypes Visibility = + CodeGenModule::GetLLVMVisibility(RD->getVisibility()); + for (const QualType &FundamentalType : FundamentalTypes) { + QualType PointerType = getContext().getPointerType(FundamentalType); + QualType PointerTypeConst = getContext().getPointerType( + FundamentalType.withConst()); + for (QualType Type : {FundamentalType, PointerType, PointerTypeConst}) + ItaniumRTTIBuilder(*this).BuildTypeInfo( + Type, llvm::GlobalValue::ExternalLinkage, + Visibility, DLLStorageClass); + } } /// What sort of uniqueness rules should we use for the RTTI for the diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp index a0ad80d7c9..d0e5890f89 100644 --- a/test/CodeGenCXX/rtti-fundamental.cpp +++ b/test/CodeGenCXX/rtti-fundamental.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -fvisibility hidden -o - | FileCheck %s -check-prefix=CHECK-HIDDEN #include @@ -16,116 +17,184 @@ namespace __cxxabiv1 { // void // CHECK: @_ZTIv = constant +// CHECK-HIDDEN: @_ZTIv = hidden constant // CHECK: @_ZTIPv = constant +// CHECK-HIDDEN: @_ZTIPv = hidden constant // CHECK: @_ZTIPKv = constant +// CHECK-HIDDEN: @_ZTIPKv = hidden constant // std::nullptr_t // CHECK: @_ZTIDn = constant +// CHECK-HIDDEN: @_ZTIDn = hidden constant // CHECK: @_ZTIPDn = constant +// CHECK-HIDDEN: @_ZTIPDn = hidden constant // CHECK: @_ZTIPKDn = constant +// CHECK-HIDDEN: @_ZTIPKDn = hidden constant // bool // CHECK: @_ZTIb = constant +// CHECK-HIDDEN: @_ZTIb = hidden constant // CHECK: @_ZTIPb = constant +// CHECK-HIDDEN: @_ZTIPb = hidden constant // CHECK: @_ZTIPKb = constant +// CHECK-HIDDEN: @_ZTIPKb = hidden constant // wchar_t // CHECK: @_ZTIw = constant +// CHECK-HIDDEN: @_ZTIw = hidden constant // CHECK: @_ZTIPw = constant +// CHECK-HIDDEN: @_ZTIPw = hidden constant // CHECK: @_ZTIPKw = constant +// CHECK-HIDDEN: @_ZTIPKw = hidden constant // char // CHECK: @_ZTIc = constant +// CHECK-HIDDEN: @_ZTIc = hidden constant // CHECK: @_ZTIPc = constant +// CHECK-HIDDEN: @_ZTIPc = hidden constant // CHECK: @_ZTIPKc = constant +// CHECK-HIDDEN: @_ZTIPKc = hidden constant // unsigned char // CHECK: @_ZTIh = constant +// CHECK-HIDDEN: @_ZTIh = hidden constant // CHECK: @_ZTIPh = constant +// CHECK-HIDDEN: @_ZTIPh = hidden constant // CHECK: @_ZTIPKh = constant +// CHECK-HIDDEN: @_ZTIPKh = hidden constant // signed char // CHECK: @_ZTIa = constant +// CHECK-HIDDEN: @_ZTIa = hidden constant // CHECK: @_ZTIPa = constant +// CHECK-HIDDEN: @_ZTIPa = hidden constant // CHECK: @_ZTIPKa = constant +// CHECK-HIDDEN: @_ZTIPKa = hidden constant // short // CHECK: @_ZTIs = constant +// CHECK-HIDDEN: @_ZTIs = hidden constant // CHECK: @_ZTIPs = constant +// CHECK-HIDDEN: @_ZTIPs = hidden constant // CHECK: @_ZTIPKs = constant +// CHECK-HIDDEN: @_ZTIPKs = hidden constant // unsigned short // CHECK: @_ZTIt = constant +// CHECK-HIDDEN: @_ZTIt = hidden constant // CHECK: @_ZTIPt = constant +// CHECK-HIDDEN: @_ZTIPt = hidden constant // CHECK: @_ZTIPKt = constant +// CHECK-HIDDEN: @_ZTIPKt = hidden constant // int // CHECK: @_ZTIi = constant +// CHECK-HIDDEN: @_ZTIi = hidden constant // CHECK: @_ZTIPi = constant +// CHECK-HIDDEN: @_ZTIPi = hidden constant // CHECK: @_ZTIPKi = constant +// CHECK-HIDDEN: @_ZTIPKi = hidden constant // unsigned int // CHECK: @_ZTIj = constant +// CHECK-HIDDEN: @_ZTIj = hidden constant // CHECK: @_ZTIPj = constant +// CHECK-HIDDEN: @_ZTIPj = hidden constant // CHECK: @_ZTIPKj = constant +// CHECK-HIDDEN: @_ZTIPKj = hidden constant // long // CHECK: @_ZTIl = constant +// CHECK-HIDDEN: @_ZTIl = hidden constant // CHECK: @_ZTIPl = constant +// CHECK-HIDDEN: @_ZTIPl = hidden constant // CHECK: @_ZTIPKl = constant +// CHECK-HIDDEN: @_ZTIPKl = hidden constant // unsigned long // CHECK: @_ZTIm = constant +// CHECK-HIDDEN: @_ZTIm = hidden constant // CHECK: @_ZTIPm = constant +// CHECK-HIDDEN: @_ZTIPm = hidden constant // CHECK: @_ZTIPKm = constant +// CHECK-HIDDEN: @_ZTIPKm = hidden constant // long long // CHECK: @_ZTIx = constant +// CHECK-HIDDEN: @_ZTIx = hidden constant // CHECK: @_ZTIPx = constant +// CHECK-HIDDEN: @_ZTIPx = hidden constant // CHECK: @_ZTIPKx = constant +// CHECK-HIDDEN: @_ZTIPKx = hidden constant // unsigned long long // CHECK: @_ZTIy = constant +// CHECK-HIDDEN: @_ZTIy = hidden constant // CHECK: @_ZTIPy = constant +// CHECK-HIDDEN: @_ZTIPy = hidden constant // CHECK: @_ZTIPKy = constant +// CHECK-HIDDEN: @_ZTIPKy = hidden constant // __int128 // CHECK: @_ZTIn = constant +// CHECK-HIDDEN: @_ZTIn = hidden constant // CHECK: @_ZTIPn = constant +// CHECK-HIDDEN: @_ZTIPn = hidden constant // CHECK: @_ZTIPKn = constant +// CHECK-HIDDEN: @_ZTIPKn = hidden constant // unsigned __int128 // CHECK: @_ZTIo = constant +// CHECK-HIDDEN: @_ZTIo = hidden constant // CHECK: @_ZTIPo = constant +// CHECK-HIDDEN: @_ZTIPo = hidden constant // CHECK: @_ZTIPKo = constant +// CHECK-HIDDEN: @_ZTIPKo = hidden constant // half // CHECK: @_ZTIDh = constant +// CHECK-HIDDEN: @_ZTIDh = hidden constant // CHECK: @_ZTIPDh = constant +// CHECK-HIDDEN: @_ZTIPDh = hidden constant // CHECK: @_ZTIPKDh = constant +// CHECK-HIDDEN: @_ZTIPKDh = hidden constant // float // CHECK: @_ZTIf = constant +// CHECK-HIDDEN: @_ZTIf = hidden constant // CHECK: @_ZTIPf = constant +// CHECK-HIDDEN: @_ZTIPf = hidden constant // CHECK: @_ZTIPKf = constant +// CHECK-HIDDEN: @_ZTIPKf = hidden constant // double // CHECK: @_ZTId = constant +// CHECK-HIDDEN: @_ZTId = hidden constant // CHECK: @_ZTIPd = constant +// CHECK-HIDDEN: @_ZTIPd = hidden constant // CHECK: @_ZTIPKd = constant +// CHECK-HIDDEN: @_ZTIPKd = hidden constant // long double // CHECK: @_ZTIe = constant +// CHECK-HIDDEN: @_ZTIe = hidden constant // CHECK: @_ZTIPe = constant +// CHECK-HIDDEN: @_ZTIPe = hidden constant // CHECK: @_ZTIPKe = constant +// CHECK-HIDDEN: @_ZTIPKe = hidden constant // char16_t // CHECK: @_ZTIDs = constant +// CHECK-HIDDEN: @_ZTIDs = hidden constant // CHECK: @_ZTIPDs = constant +// CHECK-HIDDEN: @_ZTIPDs = hidden constant // CHECK: @_ZTIPKDs = constant +// CHECK-HIDDEN: @_ZTIPKDs = hidden constant // char32_t // CHECK: @_ZTIDi = constant +// CHECK-HIDDEN: @_ZTIDi = hidden constant // CHECK: @_ZTIPDi = constant +// CHECK-HIDDEN: @_ZTIPDi = hidden constant // CHECK: @_ZTIPKDi = constant - +// CHECK-HIDDEN: @_ZTIPKDi = hidden constant -- GitLab From 288c3cd43fb42321763a5685c6e6c40fe97f2fbb Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Jul 2018 00:55:08 +0000 Subject: [PATCH 0684/1023] Warn if a local variable's initializer retains a pointer/reference to a non-lifetime-extended temporary object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337790 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 5 +- include/clang/Basic/DiagnosticSemaKinds.td | 38 ++++--- lib/Sema/SemaInit.cpp | 110 +++++++-------------- test/CXX/drs/dr16xx.cpp | 4 +- test/SemaCXX/address-of-temporary.cpp | 19 ++-- test/SemaCXX/warn-dangling-local.cpp | 20 ++++ 6 files changed, 96 insertions(+), 100 deletions(-) create mode 100644 test/SemaCXX/warn-dangling-local.cpp diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index ab0a556713..7087db7f0f 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -273,6 +273,10 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DanglingInitializerList : DiagGroup<"dangling-initializer-list">; +def ReturnStackAddress : DiagGroup<"return-stack-address">; +def Dangling : DiagGroup<"dangling", [DanglingField, + DanglingInitializerList, + ReturnStackAddress]>; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; def ExpansionToDefined : DiagGroup<"expansion-to-defined">; def FlagEnum : DiagGroup<"flag-enum">; @@ -407,7 +411,6 @@ def RedeclaredClassMember : DiagGroup<"redeclared-class-member">; def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">; def RedundantMove : DiagGroup<"redundant-move">; def Register : DiagGroup<"register", [DeprecatedRegister]>; -def ReturnStackAddress : DiagGroup<"return-stack-address">; def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 62fd7de8bb..33634c8c8b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1845,10 +1845,6 @@ def err_reference_bind_failed : Error< "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">; def err_reference_bind_init_list : Error< "reference to type %0 cannot bind to an initializer list">; -def warn_temporary_array_to_pointer_decay : Warning< - "pointer is initialized by a temporary array, which will be destroyed at the " - "end of the full-expression">, - InGroup>; def err_init_list_bad_dest_type : Error< "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " "list">; @@ -7876,15 +7872,31 @@ def warn_init_ptr_member_to_parameter_addr : Warning< def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; -def err_bind_ref_member_to_temporary : Error< +def err_dangling_member : Error< "%select{reference|backing array for 'std::initializer_list'}2 " "%select{|subobject of }1member %0 " "%select{binds to|is}2 a temporary object " - "whose lifetime would be shorter than the constructed object">; + "whose lifetime would be shorter than the lifetime of " + "the constructed object">; +def warn_dangling_member : Warning< + "%select{reference|backing array for 'std::initializer_list'}2 " + "%select{|subobject of }1member %0 " + "%select{binds to|is}2 a temporary object " + "whose lifetime is shorter than the lifetime of the constructed object">, + InGroup; def note_lifetime_extending_member_declared_here : Note< "%select{%select{reference|'std::initializer_list'}0 member|" "member with %select{reference|'std::initializer_list'}0 subobject}1 " "declared here">; +def warn_dangling_variable : Warning< + "%select{temporary %select{whose address is used as value of|bound to}3 " + "%select{%select{|reference }3member of local variable|" + "local %select{variable|reference}3}1|" + "array backing " + "%select{initializer list subobject of local variable|" + "local initializer list}1}0 " + "%2 will be destroyed at the end of the full-expression">, + InGroup; def warn_new_dangling_reference : Warning< "temporary bound to reference member of allocated object " "will be destroyed at the end of the full-expression">, @@ -7895,16 +7907,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_temporary_not_extended : Warning< - "sorry, lifetime extension of temporary created " - "by aggregate initialization using default member initializer " - "is not supported; lifetime of temporary " - "will end at the end of the full-expression">, InGroup; -def warn_unsupported_init_list_not_extended : Warning< - "sorry, lifetime extension of backing array of initializer list created " +def warn_unsupported_lifetime_extension : Warning< + "sorry, lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " "by aggregate initialization using default member initializer " - "is not supported; lifetime of backing array will end at the end of the " - "full-expression">, InGroup; + "is not supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index be284daab0..76044ee521 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6167,49 +6167,6 @@ PerformConstructorInitialization(Sema &S, return CurInit; } -/// Determine whether the specified InitializedEntity definitely has a lifetime -/// longer than the current full-expression. Conservatively returns false if -/// it's unclear. -static bool -InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { - const InitializedEntity *Top = &Entity; - while (Top->getParent()) - Top = Top->getParent(); - - switch (Top->getKind()) { - case InitializedEntity::EK_Variable: - case InitializedEntity::EK_Result: - case InitializedEntity::EK_StmtExprResult: - case InitializedEntity::EK_Exception: - case InitializedEntity::EK_Member: - case InitializedEntity::EK_Binding: - case InitializedEntity::EK_New: - case InitializedEntity::EK_Base: - case InitializedEntity::EK_Delegating: - return true; - - case InitializedEntity::EK_ArrayElement: - case InitializedEntity::EK_VectorElement: - case InitializedEntity::EK_BlockElement: - case InitializedEntity::EK_LambdaToBlockConversionBlockElement: - case InitializedEntity::EK_ComplexElement: - // Could not determine what the full initialization is. Assume it might not - // outlive the full-expression. - return false; - - case InitializedEntity::EK_Parameter: - case InitializedEntity::EK_Parameter_CF_Audited: - case InitializedEntity::EK_Temporary: - case InitializedEntity::EK_LambdaCapture: - case InitializedEntity::EK_CompoundLiteralInit: - case InitializedEntity::EK_RelatedResult: - // The entity being initialized might not outlive the full-expression. - return false; - } - - llvm_unreachable("unknown entity kind"); -} - namespace { enum LifetimeKind { /// The lifetime of a temporary bound to this entity ends at the end of the @@ -6393,6 +6350,13 @@ static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) { return false; } +static bool pathContainsInit(IndirectLocalPath &Path) { + return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) { + return E.Kind == IndirectLocalPathEntry::DefaultInit || + E.Kind == IndirectLocalPathEntry::VarInit; + }); +} + static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits); @@ -6660,6 +6624,12 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, // If the initializer is the address of a local, we could have a lifetime // problem. if (UO->getOpcode() == UO_AddrOf) { + // If this is &rvalue, then it's ill-formed and we have already diagnosed + // it. Don't produce a redundant warning about the lifetime of the + // temporary. + if (isa(UO->getSubExpr())) + return; + Path.push_back({IndirectLocalPathEntry::AddressOf, UO}); visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(), RK_ReferenceBinding, Visit); @@ -6761,9 +6731,14 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, case LK_Extended: { auto *MTE = dyn_cast(L); - if (!MTE) - // FIXME: Warn on this. + if (!MTE) { + // The initialized entity has lifetime beyond the full-expression, + // and the local entity does too, so don't warn. + // + // FIXME: We should consider warning if a static / thread storage + // duration variable retains an automatic storage duration local. return false; + } // Lifetime-extend the temporary. if (Path.empty()) { @@ -6779,17 +6754,21 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // We're supposed to lifetime-extend the temporary along this path (per // the resolution of DR1815), but we don't support that yet. // - // FIXME: Properly handle these situations. - // For the default member initializer case, perhaps the easiest approach + // FIXME: Properly handle this situation. Perhaps the easiest approach // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. - Diag(DiagLoc, RK == RK_ReferenceBinding - ? diag::warn_unsupported_temporary_not_extended - : diag::warn_unsupported_init_list_not_extended) - << DiagRange; + Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) + << RK << DiagRange; } else { - // FIXME: Warn on this. - return false; + // If the path goes through the initialization of a variable or field, + // it can't possibly reach a temporary created in this full-expression. + // We will have already diagnosed any problems with the initializer. + if (pathContainsInit(Path)) + return false; + + Diag(DiagLoc, diag::warn_dangling_variable) + << RK << !Entity.getParent() << ExtendingEntity->getDecl() + << Init->isGLValue() << DiagRange; } break; } @@ -6802,7 +6781,9 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, if (auto *ExtendingDecl = ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsSubobjectMember = ExtendingEntity != &Entity; - Diag(DiagLoc, diag::err_bind_ref_member_to_temporary) + Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) + ? diag::err_dangling_member + : diag::warn_dangling_member) << ExtendingDecl << IsSubobjectMember << RK << DiagRange; // Don't bother adding a note pointing to the field if we're inside // its default member initializer; our primary diagnostic points to @@ -6826,9 +6807,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Paths via a default initializer can only occur during error recovery // (there's no other way that a default initializer can refer to a // local). Don't produce a bogus warning on those cases. - if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { - return E.Kind == IndirectLocalPathEntry::DefaultInit; - })) + if (pathContainsInit(Path)) return false; auto *DRE = dyn_cast(L); @@ -6858,7 +6837,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_new_dangling_reference : diag::warn_new_dangling_initializer_list) - << (ExtendingEntity != &Entity) << DiagRange; + << !Entity.getParent() << DiagRange; } else { // We can't determine if the allocation outlives the local declaration. return false; @@ -7184,21 +7163,6 @@ InitializationSequence::Perform(Sema &S, return ExprError(); } - // Diagnose cases where we initialize a pointer to an array temporary, and the - // pointer obviously outlives the temporary. - // FIXME: Fold this into checkInitializerLifetime. - if (Args.size() == 1 && Args[0]->getType()->isArrayType() && - Entity.getType()->isPointerType() && - InitializedEntityOutlivesFullExpression(Entity)) { - const Expr *Init = Args[0]->skipRValueSubobjectAdjustments(); - if (auto *MTE = dyn_cast(Init)) - Init = MTE->GetTemporaryExpr(); - Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context); - if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary) - S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay) - << Init->getSourceRange(); - } - QualType DestType = Entity.getType().getNonReferenceType(); // FIXME: Ugly hack around the fact that Entity.getType() is not // the same as Entity.getDecl()->getType() in cases involving type merging, diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index d9d404c0c2..4f2f06e0d0 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -300,7 +300,7 @@ namespace dr1696 { // dr1696: 7 #if __cplusplus >= 201103L struct B { A &&a; // expected-note {{declared here}} - B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}} + B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} } b; #endif @@ -308,7 +308,7 @@ namespace dr1696 { // dr1696: 7 C(); const A &a; // expected-note {{declared here}} }; - C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the constructed object}} + C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} #if __cplusplus >= 201103L // This is OK in C++14 onwards, per DR1815, though we don't support that yet: diff --git a/test/SemaCXX/address-of-temporary.cpp b/test/SemaCXX/address-of-temporary.cpp index 5eef1c5521..eb0ca3c4a7 100644 --- a/test/SemaCXX/address-of-temporary.cpp +++ b/test/SemaCXX/address-of-temporary.cpp @@ -26,11 +26,12 @@ namespace PointerToArrayDecay { template void consume(T); struct S { int *p; }; - void g0() { int *p = Y().a; } // expected-warning{{pointer is initialized by a temporary array}} - void g1() { int *p = Y{}.a; } // expected-warning{{pointer is initialized by a temporary array}} - void g2() { int *p = A{}; } // expected-warning{{pointer is initialized by a temporary array}} - void g3() { int *p = (A){}; } // expected-warning{{pointer is initialized by a temporary array}} - void g4() { Z *p = AZ{}; } // expected-warning{{pointer is initialized by a temporary array}} + void g0() { int *p = Y().a; } // expected-warning{{will be destroyed at the end of the full-expression}} + void g1() { int *p = Y{}.a; } // expected-warning{{will be destroyed at the end of the full-expression}} + void g2() { int *p = A{}; } // expected-warning{{will be destroyed at the end of the full-expression}} + void g3() { int *p = (A){}; } // expected-warning{{will be destroyed at the end of the full-expression}} + void g4() { Z *p = AZ{}; } // expected-warning{{will be destroyed at the end of the full-expression}} + void g5() { Z *p = &(Z&)(AZ{}[0]); } // expected-warning{{will be destroyed at the end of the full-expression}} void h0() { consume(Y().a); } void h1() { consume(Y{}.a); } @@ -38,10 +39,10 @@ namespace PointerToArrayDecay { void h3() { consume((A){}); } void h4() { consume(AZ{}); } - void i0() { S s = { Y().a }; } // expected-warning{{pointer is initialized by a temporary array}} - void i1() { S s = { Y{}.a }; } // expected-warning{{pointer is initialized by a temporary array}} - void i2() { S s = { A{} }; } // expected-warning{{pointer is initialized by a temporary array}} - void i3() { S s = { (A){} }; } // expected-warning{{pointer is initialized by a temporary array}} + void i0() { S s = { Y().a }; } // expected-warning{{will be destroyed at the end of the full-expression}} + void i1() { S s = { Y{}.a }; } // expected-warning{{will be destroyed at the end of the full-expression}} + void i2() { S s = { A{} }; } // expected-warning{{will be destroyed at the end of the full-expression}} + void i3() { S s = { (A){} }; } // expected-warning{{will be destroyed at the end of the full-expression}} void j0() { (void)S { Y().a }; } void j1() { (void)S { Y{}.a }; } diff --git a/test/SemaCXX/warn-dangling-local.cpp b/test/SemaCXX/warn-dangling-local.cpp new file mode 100644 index 0000000000..19a722f84d --- /dev/null +++ b/test/SemaCXX/warn-dangling-local.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +using T = int[]; + +void f() { + int *p = &(int&)(int&&)0; // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}} + + int *q = (int *const &)T{1, 2, 3}; // expected-warning {{temporary whose address is used as value of local variable 'q' will be destroyed at the end of the full-expression}} + + // FIXME: We don't warn here because the 'int*' temporary is not const, but + // it also can't have actually changed since it was created, so we could + // still warn. + int *r = (int *&&)T{1, 2, 3}; + + // FIXME: The wording of this warning is not quite right. There are two + // temporaries here: an 'int* const' temporary that points to the array, and + // is lifetime-extended, and an array temporary that the pointer temporary + // points to, which doesn't live long enough. + int *const &s = (int *const &)T{1, 2, 3}; // expected-warning {{temporary bound to local reference 's' will be destroyed at the end of the full-expression}} +} -- GitLab From ae25258b2efa17e692b239826f65ede1b17a8dd5 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 24 Jul 2018 01:03:44 +0000 Subject: [PATCH 0685/1023] Enable .hip files for test/Driver Partially revert r334128 due to regressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337791 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/Driver.cpp | 4 ++-- test/Driver/lit.local.cfg | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 9e92f64f66..1dfcacc75e 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2809,7 +2809,7 @@ public: C.MakeAction(HostAction); UnbundlingHostAction->registerDependentActionInfo( C.getSingleOffloadToolChain(), - /*BoundArch=*/"all", Action::OFK_Host); + /*BoundArch=*/StringRef(), Action::OFK_Host); HostAction = UnbundlingHostAction; } @@ -3868,7 +3868,7 @@ InputInfo Driver::BuildJobsForActionNoCache( StringRef Arch; if (TargetDeviceOffloadKind == Action::OFK_HIP) { if (UI.DependentOffloadKind == Action::OFK_Host) - Arch = "all"; + Arch = StringRef(); else Arch = UI.DependentBoundArch; } else diff --git a/test/Driver/lit.local.cfg b/test/Driver/lit.local.cfg index ff831e7fe4..4a4ef2af23 100644 --- a/test/Driver/lit.local.cfg +++ b/test/Driver/lit.local.cfg @@ -1,5 +1,5 @@ config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.f95', - '.cu', '.rs', '.cl'] + '.cu', '.rs', '.cl', '.hip'] config.substitutions = list(config.substitutions) config.substitutions.insert(0, ('%clang_cc1', -- GitLab From 8fe774c61453bbe684ee20b4497930635cf2ec7c Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Jul 2018 01:23:36 +0000 Subject: [PATCH 0686/1023] Add missing testcase update for r337790. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337792 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/SemaCXX/constant-expression-cxx11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index e921634b1b..a64207583d 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1555,13 +1555,13 @@ namespace CompoundLiteral { // Other kinds are not. struct X { int a[2]; }; - constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary array}} + constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary}} // expected-error@-1 {{constant expression}} // expected-note@-2 {{pointer to subobject of temporary}} // expected-note@-3 {{temporary created here}} void f() { - static constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} + static constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} expected-warning {{temporary}} // expected-error@-1 {{constant expression}} // expected-note@-2 {{pointer to subobject of temporary}} // expected-note@-3 {{temporary created here}} -- GitLab From 2d67bc6909d0198852c76e1804b8f6b34121e213 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 24 Jul 2018 01:40:44 +0000 Subject: [PATCH 0687/1023] [HIP] pass -target-cpu when running the device-mode compiler Differential Revision: https://reviews.llvm.org/D49643 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337793 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/HIP.cpp | 2 ++ test/Driver/hip-toolchain.hip | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index df12faddcf..03acf45a9b 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -232,6 +232,8 @@ void HIPToolChain::addClangTargetOptions( assert(DeviceOffloadingKind == Action::OFK_HIP && "Only HIP offloading kinds are supported for GPUs."); + CC1Args.push_back("-target-cpu"); + CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch)); CC1Args.push_back("-fcuda-is-device"); if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero, diff --git a/test/Driver/hip-toolchain.hip b/test/Driver/hip-toolchain.hip index b745ab60b0..1f9d2c78f4 100644 --- a/test/Driver/hip-toolchain.hip +++ b/test/Driver/hip-toolchain.hip @@ -14,14 +14,14 @@ // CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc" -// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-fcuda-is-device" -// CHECK-SAME: {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip" +// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx803" +// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip" // CHECK-SAME: {{.*}} [[A_SRC:".*a.cu"]] // CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc" -// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-fcuda-is-device" -// CHECK-SAME: {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip" +// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx803" +// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip" // CHECK-SAME: {{.*}} [[B_SRC:".*b.hip"]] // CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC]] [[B_BC]] @@ -40,14 +40,14 @@ // CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc" -// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-fcuda-is-device" -// CHECK-SAME: {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip" +// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx900" +// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip" // CHECK-SAME: {{.*}} [[A_SRC]] // CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc" -// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-fcuda-is-device" -// CHECK-SAME: {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip" +// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-target-cpu" "gfx900" +// CHECK-SAME: "-fcuda-is-device" {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip" // CHECK-SAME: {{.*}} [[B_SRC]] // CHECK: [[LLVM_LINK]] [[A_BC]] [[B_BC]] -- GitLab From 69bd8cea125aa6e49a6a57f89456fd5105bf95fb Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Tue, 24 Jul 2018 02:10:53 +0000 Subject: [PATCH 0688/1023] Fix unused variable warnings; NFC Looks like MTE was previously used for its SourceLoc, but we're now using a seperate SourceLocation here. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 76044ee521..9b5a918b71 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6774,7 +6774,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, } case LK_MemInitializer: { - if (auto *MTE = dyn_cast(L)) { + if (isa(L)) { // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. @@ -6833,7 +6833,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, } case LK_New: - if (auto *MTE = dyn_cast(L)) { + if (isa(L)) { Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_new_dangling_reference : diag::warn_new_dangling_initializer_list) -- GitLab From 7a3515221c96733393c2e7175c97c4317c86234d Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Tue, 24 Jul 2018 02:12:24 +0000 Subject: [PATCH 0689/1023] Attempt to fix regression due to r337791 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337797 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/hip-toolchain.hip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Driver/hip-toolchain.hip b/test/Driver/hip-toolchain.hip index 1f9d2c78f4..ce24e0b4be 100644 --- a/test/Driver/hip-toolchain.hip +++ b/test/Driver/hip-toolchain.hip @@ -80,5 +80,5 @@ // CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900" // CHECK-SAME: "-inputs={{.*}},[[IMG_DEV1]],[[IMG_DEV2]]" "-outputs=[[BUNDLE:.*o]]" -// CHECK: [[LD:".*ld.lld"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]] +// CHECK: [[LD:".*ld.*"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]] // CHECK-SAME: {{.*}} "-T" "{{.*}}.lk" -- GitLab From 4288dd3bf082482e02c8a044c611c18168cb0180 Mon Sep 17 00:00:00 2001 From: Shiva Chen Date: Tue, 24 Jul 2018 02:23:59 +0000 Subject: [PATCH 0690/1023] [DebugInfo] Generate debug information for labels. (Fix PR37395) Generate DILabel metadata and call llvm.dbg.label after label statement to associate the metadata with the label. After fixing PR37395. Differential Revision: https://reviews.llvm.org/D45045 Patch by Hsiangkai Wang. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337800 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 26 ++++++++++++++++++++++++++ lib/CodeGen/CGDebugInfo.h | 3 +++ lib/CodeGen/CGStmt.cpp | 10 ++++++++++ test/CodeGen/debug-label-inline.c | 28 ++++++++++++++++++++++++++++ test/CodeGen/debug-label.c | 16 ++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 test/CodeGen/debug-label-inline.c create mode 100644 test/CodeGen/debug-label.c diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 097a1e0430..a9d463cfb5 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -3729,6 +3729,32 @@ CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, return EmitDeclare(VD, Storage, llvm::None, Builder); } +void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { + assert(DebugKind >= codegenoptions::LimitedDebugInfo); + assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); + + if (D->hasAttr()) + return; + + auto *Scope = cast(LexicalBlockStack.back()); + llvm::DIFile *Unit = getOrCreateFile(D->getLocation()); + + // Get location information. + unsigned Line = getLineNumber(D->getLocation()); + unsigned Column = getColumnNumber(D->getLocation()); + + StringRef Name = D->getName(); + + // Create the descriptor for the label. + auto *L = + DBuilder.createLabel(Scope, Name, Unit, Line, CGM.getLangOpts().Optimize); + + // Insert an llvm.dbg.label into the current block. + DBuilder.insertLabel(L, + llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), + Builder.GetInsertBlock()); +} + llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType *Ty) { llvm::DIType *CachedTy = getTypeOrNull(QualTy); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index e632806138..0047a07d9d 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -399,6 +399,9 @@ public: llvm::Value *AI, CGBuilderTy &Builder); + /// Emit call to \c llvm.dbg.label for an label. + void EmitLabel(const LabelDecl *D, CGBuilderTy &Builder); + /// Emit call to \c llvm.dbg.declare for an imported variable /// declaration in a block. void EmitDeclareOfBlockDeclRefVariable( diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 79662ec009..e6600691eb 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -531,6 +531,16 @@ void CodeGenFunction::EmitLabel(const LabelDecl *D) { } EmitBlock(Dest.getBlock()); + + // Emit debug info for labels. + if (CGDebugInfo *DI = getDebugInfo()) { + if (CGM.getCodeGenOpts().getDebugInfo() >= + codegenoptions::LimitedDebugInfo) { + DI->setLocation(D->getLocation()); + DI->EmitLabel(D, Builder); + } + } + incrementProfileCounter(D->getStmt()); } diff --git a/test/CodeGen/debug-label-inline.c b/test/CodeGen/debug-label-inline.c new file mode 100644 index 0000000000..c0b089aad8 --- /dev/null +++ b/test/CodeGen/debug-label-inline.c @@ -0,0 +1,28 @@ +// This test will test the correctness of generating DILabel and +// llvm.dbg.label when the label is in inlined functions. +// +// RUN: %clang_cc1 -O2 %s -o - -emit-llvm -debug-info-kind=limited | FileCheck %s +inline int f1(int a, int b) { + int sum; + +top: + sum = a + b; + return sum; +} + +extern int ga, gb; + +int f2(void) { + int result; + + result = f1(ga, gb); + // CHECK: call void @llvm.dbg.label(metadata [[LABEL_METADATA:!.*]]), !dbg [[LABEL_LOCATION:!.*]] + + return result; +} + +// CHECK: distinct !DISubprogram(name: "f1", {{.*}}, retainedNodes: [[ELEMENTS:!.*]]) +// CHECK: [[ELEMENTS]] = !{{{.*}}, [[LABEL_METADATA]]} +// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 8) +// CHECK: [[INLINEDAT:!.*]] = distinct !DILocation(line: 18, +// CHECK: [[LABEL_LOCATION]] = !DILocation(line: 8, {{.*}}, inlinedAt: [[INLINEDAT]]) diff --git a/test/CodeGen/debug-label.c b/test/CodeGen/debug-label.c new file mode 100644 index 0000000000..20efa49b0a --- /dev/null +++ b/test/CodeGen/debug-label.c @@ -0,0 +1,16 @@ +// This test will test the correstness of generating DILabel and +// llvm.dbg.label for labels. +// +// RUN: %clang_cc1 -emit-llvm %s -o - -emit-llvm -debug-info-kind=limited | FileCheck %s + +int f1(int a, int b) { + int sum; + +top: + // CHECK: call void @llvm.dbg.label(metadata [[LABEL_METADATA:!.*]]), !dbg [[LABEL_LOCATION:!.*]] + sum = a + b; + return sum; +} + +// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 9) +// CHECK: [[LABEL_LOCATION]] = !DILocation(line: 9, -- GitLab From 03e4db7ebd8f8127a4d9c3259e239c1a3f367650 Mon Sep 17 00:00:00 2001 From: Shiva Chen Date: Tue, 24 Jul 2018 02:57:11 +0000 Subject: [PATCH 0691/1023] Revert "[DebugInfo] Generate debug information for labels. (Fix PR37395)" This reverts commit 4288dd3bf082482e02c8a044c611c18168cb0180. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337803 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 26 -------------------------- lib/CodeGen/CGDebugInfo.h | 3 --- lib/CodeGen/CGStmt.cpp | 10 ---------- test/CodeGen/debug-label-inline.c | 28 ---------------------------- test/CodeGen/debug-label.c | 16 ---------------- 5 files changed, 83 deletions(-) delete mode 100644 test/CodeGen/debug-label-inline.c delete mode 100644 test/CodeGen/debug-label.c diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index a9d463cfb5..097a1e0430 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -3729,32 +3729,6 @@ CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, return EmitDeclare(VD, Storage, llvm::None, Builder); } -void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { - assert(DebugKind >= codegenoptions::LimitedDebugInfo); - assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); - - if (D->hasAttr()) - return; - - auto *Scope = cast(LexicalBlockStack.back()); - llvm::DIFile *Unit = getOrCreateFile(D->getLocation()); - - // Get location information. - unsigned Line = getLineNumber(D->getLocation()); - unsigned Column = getColumnNumber(D->getLocation()); - - StringRef Name = D->getName(); - - // Create the descriptor for the label. - auto *L = - DBuilder.createLabel(Scope, Name, Unit, Line, CGM.getLangOpts().Optimize); - - // Insert an llvm.dbg.label into the current block. - DBuilder.insertLabel(L, - llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), - Builder.GetInsertBlock()); -} - llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType *Ty) { llvm::DIType *CachedTy = getTypeOrNull(QualTy); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 0047a07d9d..e632806138 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -399,9 +399,6 @@ public: llvm::Value *AI, CGBuilderTy &Builder); - /// Emit call to \c llvm.dbg.label for an label. - void EmitLabel(const LabelDecl *D, CGBuilderTy &Builder); - /// Emit call to \c llvm.dbg.declare for an imported variable /// declaration in a block. void EmitDeclareOfBlockDeclRefVariable( diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index e6600691eb..79662ec009 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -531,16 +531,6 @@ void CodeGenFunction::EmitLabel(const LabelDecl *D) { } EmitBlock(Dest.getBlock()); - - // Emit debug info for labels. - if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - DI->setLocation(D->getLocation()); - DI->EmitLabel(D, Builder); - } - } - incrementProfileCounter(D->getStmt()); } diff --git a/test/CodeGen/debug-label-inline.c b/test/CodeGen/debug-label-inline.c deleted file mode 100644 index c0b089aad8..0000000000 --- a/test/CodeGen/debug-label-inline.c +++ /dev/null @@ -1,28 +0,0 @@ -// This test will test the correctness of generating DILabel and -// llvm.dbg.label when the label is in inlined functions. -// -// RUN: %clang_cc1 -O2 %s -o - -emit-llvm -debug-info-kind=limited | FileCheck %s -inline int f1(int a, int b) { - int sum; - -top: - sum = a + b; - return sum; -} - -extern int ga, gb; - -int f2(void) { - int result; - - result = f1(ga, gb); - // CHECK: call void @llvm.dbg.label(metadata [[LABEL_METADATA:!.*]]), !dbg [[LABEL_LOCATION:!.*]] - - return result; -} - -// CHECK: distinct !DISubprogram(name: "f1", {{.*}}, retainedNodes: [[ELEMENTS:!.*]]) -// CHECK: [[ELEMENTS]] = !{{{.*}}, [[LABEL_METADATA]]} -// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 8) -// CHECK: [[INLINEDAT:!.*]] = distinct !DILocation(line: 18, -// CHECK: [[LABEL_LOCATION]] = !DILocation(line: 8, {{.*}}, inlinedAt: [[INLINEDAT]]) diff --git a/test/CodeGen/debug-label.c b/test/CodeGen/debug-label.c deleted file mode 100644 index 20efa49b0a..0000000000 --- a/test/CodeGen/debug-label.c +++ /dev/null @@ -1,16 +0,0 @@ -// This test will test the correstness of generating DILabel and -// llvm.dbg.label for labels. -// -// RUN: %clang_cc1 -emit-llvm %s -o - -emit-llvm -debug-info-kind=limited | FileCheck %s - -int f1(int a, int b) { - int sum; - -top: - // CHECK: call void @llvm.dbg.label(metadata [[LABEL_METADATA:!.*]]), !dbg [[LABEL_LOCATION:!.*]] - sum = a + b; - return sum; -} - -// CHECK: [[LABEL_METADATA]] = !DILabel({{.*}}, name: "top", {{.*}}, line: 9) -// CHECK: [[LABEL_LOCATION]] = !DILocation(line: 9, -- GitLab From 561a0afd9c46b4ca38b09ee5a4b8115394cd4917 Mon Sep 17 00:00:00 2001 From: Jiading Gai Date: Tue, 24 Jul 2018 03:34:15 +0000 Subject: [PATCH 0692/1023] [Test commit] Fix a spelling error. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337807 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Basic/FileManagerTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp index 5aa1c0241a..52cb5b2f0d 100644 --- a/unittests/Basic/FileManagerTest.cpp +++ b/unittests/Basic/FileManagerTest.cpp @@ -266,7 +266,7 @@ TEST_F(FileManagerTest, addRemoveStatCache) { // getFile() Should return the same entry as getVirtualFile if the file actually // is a virtual file, even if the name is not exactly the same (but is after // normalisation done by the file system, like on Windows). This can be checked -// here by checkng the size. +// here by checking the size. TEST_F(FileManagerTest, getVirtualFileWithDifferentName) { // Inject fake files into the file system. auto statCache = llvm::make_unique(); -- GitLab From 4e8a2e378053c72fea77a46afd1f32b4bedf462f Mon Sep 17 00:00:00 2001 From: Jiading Gai Date: Tue, 24 Jul 2018 06:07:22 +0000 Subject: [PATCH 0693/1023] For x86_64, gcc 7.2 under Amazon Linux AMI sets its path to x86_64-amazon-linux. gcc 7.2 under Amazon Linux AMI sets its paths to x86_64-amazon-linux. Adding this triple to the list of search, plus a test case to cover this. The patch fixes the following bug reported in bugzilla: https://bugs.llvm.org/show_bug.cgi?id=35992 Reviewers: echristo Differential Revision: https://reviews.llvm.org/D46230 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337811 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Gnu.cpp | 3 ++- .../lib/gcc/x86_64-amazon-linux/7/crtbegin.o | 0 .../lib/gcc/x86_64-amazon-linux/7/crtbeginT.o | 0 .../lib/gcc/x86_64-amazon-linux/7/crtend.o | 0 .../Inputs/ami_linux_tree/usr/lib64/crt1.o | 0 .../Inputs/ami_linux_tree/usr/lib64/crti.o | 0 .../Inputs/ami_linux_tree/usr/lib64/crtn.o | 0 test/Driver/linux-ld.c | 22 +++++++++++++++++++ 8 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o create mode 100644 test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 1ecf127c4b..2c83598f3d 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -1834,7 +1834,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux", "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", - "x86_64-slackware-linux", "x86_64-unknown-linux"}; + "x86_64-slackware-linux", "x86_64-unknown-linux", + "x86_64-amazon-linux"}; static const char *const X32LibDirs[] = {"/libx32"}; static const char *const X86LibDirs[] = {"/lib32", "/lib"}; static const char *const X86Triples[] = { diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbegin.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtbeginT.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o b/test/Driver/Inputs/ami_linux_tree/usr/lib/gcc/x86_64-amazon-linux/7/crtend.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crt1.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crti.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o b/test/Driver/Inputs/ami_linux_tree/usr/lib64/crtn.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c index 02bb88266c..02e6618a04 100644 --- a/test/Driver/linux-ld.c +++ b/test/Driver/linux-ld.c @@ -1792,3 +1792,25 @@ // CHECK-LD-RHLE7-DTS: Selected GCC installation: [[GCC_INSTALL:[[SYSROOT]]/lib/gcc/x86_64-redhat-linux/7]] // CHECK-LD-RHEL7-DTS-NOT: /usr/bin/ld // CHECK-LD-RHLE7-DTS: [[GCC_INSTALL]/../../../bin/ld + +// Check whether gcc7 install works fine on Amazon Linux AMI +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-amazon-linux -rtlib=libgcc \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/ami_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD-AMI %s +// CHECK-LD-AMI-NOT: warning: +// CHECK-LD-AMI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-LD-AMI: "--eh-frame-hdr" +// CHECK-LD-AMI: "-m" "elf_x86_64" +// CHECK-LD-AMI: "-dynamic-linker" +// CHECK-LD-AMI: "{{.*}}/usr/lib/gcc/x86_64-amazon-linux/7{{/|\\\\}}crtbegin.o" +// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7" +// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7/../../../../lib64" +// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-amazon-linux/7/../../.." +// CHECK-LD-AMI: "-L[[SYSROOT]]/lib" +// CHECK-LD-AMI: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD-AMI: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// CHECK-LD-AMI: "-lc" +// CHECK-LD-AMI: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// -- GitLab From 8bc411272bb860c0e22764eccaef4b0f9b55e905 Mon Sep 17 00:00:00 2001 From: Jiading Gai Date: Tue, 24 Jul 2018 06:49:27 +0000 Subject: [PATCH 0694/1023] Add a .keep file to prevent svn from skipping over an empty folder. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337813 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Driver/Inputs/ami_linux_tree/lib/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/Driver/Inputs/ami_linux_tree/lib/.keep diff --git a/test/Driver/Inputs/ami_linux_tree/lib/.keep b/test/Driver/Inputs/ami_linux_tree/lib/.keep new file mode 100644 index 0000000000..e69de29bb2 -- GitLab From 03e3fc09a8ccc11a30ab6be813d4b5eb91dad1b3 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Tue, 24 Jul 2018 08:16:50 +0000 Subject: [PATCH 0695/1023] [Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166) Summary: As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=38166 | PR38166 ]], we need to be able to distinqush whether the cast we are visiting is actually a cast, or part of an `ExplicitCast`. There are at least four ways to get there: 1. Introduce a new `CastKind`, and use it instead of `IntegralCast` if we are in `ExplicitCast`. Would work, but does not scale - what if we will need more of these cast kinds? 2. Introduce a flag in `CastExprBits`, whether this cast is part of `ExplicitCast` or not. Would work, but it isn't immediately clear where it needs to be set. 2. Fix `ScalarExprEmitter::VisitCastExpr()` to visit these `NoOp` casts. As pointed out by @rsmith, CodeGenFunction::EmitMaterializeTemporaryExpr calls skipRValueSubobjectAdjustments, which steps over the CK_NoOp cast`, which explains why we currently don't visit those. This is probably impossible, as @efriedma points out, that is intentional as per `[class.temporary]` in the standard 3. And the simplest one, just record which NoOp casts we skip. It just kinda works as-is afterwards. But, the approach with a flag is the least intrusive one, and is probably the best one overall. Reviewers: rsmith, rjmccall, majnemer, efriedma Reviewed By: rsmith Subscribers: cfe-commits, aaron.ballman, vsk, llvm-commits, rsmith Differential Revision: https://reviews.llvm.org/D49508 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337815 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 8 ++ include/clang/AST/Stmt.h | 3 +- lib/AST/ASTDumper.cpp | 3 + lib/Sema/SemaCast.cpp | 9 ++ lib/Serialization/ASTReaderStmt.cpp | 1 + lib/Serialization/ASTWriterDecl.cpp | 1 + lib/Serialization/ASTWriterStmt.cpp | 1 + test/PCH/cxx_exprs.cpp | 34 ++++- test/Sema/multistep-explicit-cast.c | 70 ++++++++++ test/SemaCXX/multistep-explicit-cast.cpp | 155 +++++++++++++++++++++ test/SemaOpenCL/multistep-explicit-cast.cl | 13 ++ 11 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 test/Sema/multistep-explicit-cast.c create mode 100644 test/SemaCXX/multistep-explicit-cast.cpp create mode 100644 test/SemaOpenCL/multistep-explicit-cast.cl diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index df3cd182e0..a4c4769c1a 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2821,6 +2821,7 @@ protected: (op && op->containsUnexpandedParameterPack()))), Op(op) { CastExprBits.Kind = kind; + CastExprBits.PartOfExplicitCast = false; setBasePathSize(BasePathSize); assert(CastConsistency()); } @@ -2835,6 +2836,13 @@ public: CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } void setCastKind(CastKind K) { CastExprBits.Kind = K; } + bool getIsPartOfExplicitCast() const { + return CastExprBits.PartOfExplicitCast; + } + void setIsPartOfExplicitCast(bool PartOfExplicitCast) { + CastExprBits.PartOfExplicitCast = PartOfExplicitCast; + } + static const char *getCastKindName(CastKind CK); const char *getCastKindName() const { return getCastKindName(getCastKind()); } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 3b678dcc75..9e70b218d3 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -202,7 +202,8 @@ protected: unsigned : NumExprBits; unsigned Kind : 6; - unsigned BasePathSize : 32 - 6 - NumExprBits; + unsigned PartOfExplicitCast : 1; + unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; class CallExprBitfields { diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 6d9f24020f..6ccd913bd3 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -2117,6 +2117,9 @@ void ASTDumper::VisitCastExpr(const CastExpr *Node) { } dumpBasePath(OS, Node); OS << ">"; + + if (Node->getIsPartOfExplicitCast()) + OS << " part_of_explicit_cast"; } void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index b3f6be4aec..a669956422 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -89,6 +89,14 @@ namespace { void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization); void CheckCStyleCast(); + void updatePartOfExplicitCastFlags(CastExpr *CE) { + // Walk down from the CE to the OrigSrcExpr, and mark all immediate + // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE + // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched. + while ((CE = dyn_cast(CE->getSubExpr()))) + CE->setIsPartOfExplicitCast(true); + } + /// Complete an apparently-successful cast operation that yields /// the given expression. ExprResult complete(CastExpr *castExpr) { @@ -100,6 +108,7 @@ namespace { CK_Dependent, castExpr, nullptr, castExpr->getValueKind()); } + updatePartOfExplicitCastFlags(castExpr); return castExpr; } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 2b7de79841..ee03b6def0 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -723,6 +723,7 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { assert(NumBaseSpecs == E->path_size()); E->setSubExpr(Record.readSubExpr()); E->setCastKind((CastKind)Record.readInt()); + E->setIsPartOfExplicitCast(Record.readInt()); CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 1fac13e6ee..61d9fed480 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -2192,6 +2192,7 @@ void ASTWriter::WriteDeclAbbrevs() { // CastExpr Abv->Add(BitCodeAbbrevOp(0)); // PathSize Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast // ImplicitCastExpr ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv)); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index b79e80e122..79156dcc5c 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -665,6 +665,7 @@ void ASTStmtWriter::VisitCastExpr(CastExpr *E) { Record.push_back(E->path_size()); Record.AddStmt(E->getSubExpr()); Record.push_back(E->getCastKind()); // FIXME: stable encoding + Record.push_back(E->getIsPartOfExplicitCast()); for (CastExpr::path_iterator PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) diff --git a/test/PCH/cxx_exprs.cpp b/test/PCH/cxx_exprs.cpp index 0fb7590c68..928a21125d 100644 --- a/test/PCH/cxx_exprs.cpp +++ b/test/PCH/cxx_exprs.cpp @@ -1,9 +1,9 @@ // Test this without pch. -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx_exprs.h -std=c++11 -fsyntax-only -verify %s -ast-dump | FileCheck %s // Test with pch. Use '-ast-dump' to force deserialization of function bodies. // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -x c++-header -std=c++11 -emit-pch -o %t %S/cxx_exprs.h -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-dump-all | FileCheck %s // expected-no-diagnostics @@ -14,19 +14,49 @@ bool boolean; // CXXStaticCastExpr static_cast_result void_ptr = &integer; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}}{{(imported)?}} referenced static_cast_result 'typeof (static_cast(0))':'void *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (static_cast(0))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'void *'{{$}} +// CHECK-NEXT: CXXStaticCastExpr {{.*}} 'void *' static_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' part_of_explicit_cast{{$}} +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0{{$}} // CXXDynamicCastExpr Derived *d; dynamic_cast_result derived_ptr = d; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced dynamic_cast_result 'typeof (dynamic_cast(base_ptr))':'Derived *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (dynamic_cast(base_ptr))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'Derived *'{{$}} +// CHECK-NEXT: CXXDynamicCastExpr {{.*}} 'Derived *' dynamic_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'Base *' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *'{{$}} // CXXReinterpretCastExpr reinterpret_cast_result void_ptr2 = &integer; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced reinterpret_cast_result 'typeof (reinterpret_cast(0))':'void *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (reinterpret_cast(0))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'void *'{{$}} +// CHECK-NEXT: CXXReinterpretCastExpr {{.*}} 'void *' reinterpret_cast {{$}} +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0{{$}} // CXXConstCastExpr const_cast_result char_ptr = &character; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced const_cast_result 'typeof (const_cast(const_char_ptr_value))':'char *'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (const_cast(const_char_ptr_value))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'char *'{{$}} +// CHECK-NEXT: CXXConstCastExpr {{.*}} 'char *' const_cast {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const char *' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' lvalue Var {{.*}} 'const_char_ptr_value' 'const char *'{{$}} // CXXFunctionalCastExpr functional_cast_result *double_ptr = &floating; +// CHECK: TypedefDecl {{.*}} <{{.*}}, col:{{.*}}> col:{{.*}} referenced functional_cast_result 'typeof (double(int_value))':'double'{{$}} +// CHECK-NEXT: TypeOfExprType {{.*}} 'typeof (double(int_value))' sugar{{( imported)?}}{{$}} +// CHECK-NEXT: ParenExpr {{.*}} 'double'{{$}} +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} 'double' functional cast to double {{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' part_of_explicit_cast{{$}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} +// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'int_value' 'int'{{$}} // CXXBoolLiteralExpr bool_literal_result *bool_ptr = &boolean; diff --git a/test/Sema/multistep-explicit-cast.c b/test/Sema/multistep-explicit-cast.c new file mode 100644 index 0000000000..aeb5919618 --- /dev/null +++ b/test/Sema/multistep-explicit-cast.c @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s + +// We are checking that implicit casts don't get marked with 'part_of_explicit_cast', +// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast' + +unsigned char implicitcast_0(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return x; +} + +signed char implicitcast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return x; +} + +unsigned char implicitcast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return x; +} + +signed char implicitcast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return x; +} + +//----------------------------------------------------------------------------// + +unsigned char cstylecast_0(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return (unsigned char)x; +} + +signed char cstylecast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return (signed char)x; +} + +unsigned char cstylecast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return (unsigned char)x; +} + +signed char cstylecast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return (signed char)x; +} diff --git a/test/SemaCXX/multistep-explicit-cast.cpp b/test/SemaCXX/multistep-explicit-cast.cpp new file mode 100644 index 0000000000..5846679135 --- /dev/null +++ b/test/SemaCXX/multistep-explicit-cast.cpp @@ -0,0 +1,155 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s + +// We are checking that implicit casts don't get marked with 'part_of_explicit_cast', +// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast' + +unsigned char implicitcast_0(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return x; +} + +signed char implicitcast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return x; +} + +unsigned char implicitcast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return x; +} + +signed char implicitcast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}} + // CHECK: ImplicitCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' {{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return x; +} + +//----------------------------------------------------------------------------// + +unsigned char cstylecast_0(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return (unsigned char)x; +} + +signed char cstylecast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return (signed char)x; +} + +unsigned char cstylecast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'unsigned char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return (unsigned char)x; +} + +signed char cstylecast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'signed char' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return (signed char)x; +} + +//----------------------------------------------------------------------------// + +unsigned char cxxstaticcast_0(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_0 'unsigned char (unsigned int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'unsigned char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return static_cast(x); +} + +signed char cxxstaticcast_1(unsigned int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_1 'signed char (unsigned int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'signed char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} + return static_cast(x); +} + +unsigned char cxxstaticcast_2(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_2 'unsigned char (int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'unsigned char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return static_cast(x); +} + +signed char cxxstaticcast_3(signed int x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_3 'signed char (int)'{{$}} + // CHECK: CXXStaticCastExpr {{.*}} 'signed char' static_cast {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} + return static_cast(x); +} + +//----------------------------------------------------------------------------// + +using UnsignedChar = unsigned char; +using SignedChar = signed char; +using UnsignedInt = unsigned int; +using SignedInt = signed int; + +UnsignedChar cxxfunctionalcast_0(UnsignedInt x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_0 'UnsignedChar (UnsignedInt)'{{$}} + // CHECK: CXXFunctionalCastExpr {{.*}} 'UnsignedChar':'unsigned char' functional cast to UnsignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedChar':'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedInt':'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}} + return UnsignedChar(x); +} + +SignedChar cxxfunctionalcast_1(UnsignedInt x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_1 'SignedChar (UnsignedInt)'{{$}} + // CHECK: CXXFunctionalCastExpr {{.*}} 'SignedChar':'signed char' functional cast to SignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedChar':'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedInt':'unsigned int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}} + return SignedChar(x); +} + +UnsignedChar cxxfunctionalcast_2(SignedInt x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_2 'UnsignedChar (SignedInt)'{{$}} + // CHECK: CXXFunctionalCastExpr {{.*}} 'UnsignedChar':'unsigned char' functional cast to UnsignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'UnsignedChar':'unsigned char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedInt':'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}} + return UnsignedChar(x); +} + +SignedChar cxxfunctionalcast_3(SignedInt x) { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_3 'SignedChar (SignedInt)'{{$}} + // CHECK: CXXFunctionalCastExpr {{.*}} 'SignedChar':'signed char' functional cast to SignedChar {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedChar':'signed char' part_of_explicit_cast{{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'SignedInt':'int' part_of_explicit_cast{{$}} + // CHECK-NEXT: DeclRefExpr {{.*}} 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}} + return SignedChar(x); +} diff --git a/test/SemaOpenCL/multistep-explicit-cast.cl b/test/SemaOpenCL/multistep-explicit-cast.cl new file mode 100644 index 0000000000..5e3d12a0e4 --- /dev/null +++ b/test/SemaOpenCL/multistep-explicit-cast.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s +// expected-no-diagnostics + +typedef __attribute__((ext_vector_type(2))) char char2; + +void vectorIncrementDecrementOps() { + // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} vectorIncrementDecrementOps 'void (void)'{{$}} + // CHECK: CStyleCastExpr {{.*}} 'char2':'char __attribute__((ext_vector_type(2)))' {{$}} + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'char' part_of_explicit_cast{{$}} + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1{{$}} + char2 A = (char2)(1); + A++; +} -- GitLab From 9e67652533017e8c81d6a9c89b9cb3c69c1b23fc Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Tue, 24 Jul 2018 16:00:55 +0000 Subject: [PATCH 0696/1023] [VFS] Cleanups to VFS interfaces. Summary: - add comments clarifying semantics - Status::copyWithNewName(Status, Name) --> instance method - Status::copyWithNewName(fs::file_status, Name) --> constructor (it's not a copy) - File::getName() -> getRealPath(), reflecting its actual behavior/function and stop returning status().getName() in the base class (callers can do this fallback if they want to, it complicates the contracts). This is mostly NFC, but the behavior of File::getName() affects FileManager's FileEntry::tryGetRealPathName(), which now fails in more cases: - non-real file cases - real-file cases where the underlying vfs::File was opened in a way that doesn't call realpath(). (In these cases we don't know a distinct real name, so in principle it seems OK) Reviewers: klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49724 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337834 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/VirtualFileSystem.h | 27 ++++++++++-------- lib/Basic/FileManager.cpp | 2 +- lib/Basic/VirtualFileSystem.cpp | 37 +++++++++++++------------ 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 2480b91123..bd752c8dad 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -45,7 +45,8 @@ class MemoryBuffer; namespace clang { namespace vfs { -/// The result of a \p status operation. +/// File information from a \p File::status() operation. +/// This is roughly equivalent to a `struct stat` plus a file path. class Status { std::string Name; llvm::sys::fs::UniqueID UID; @@ -66,13 +67,14 @@ public: llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms); + Status(const llvm::sys::fs::file_status &FSStatus, StringRef Name); - /// Get a copy of a Status with a different name. - static Status copyWithNewName(const Status &In, StringRef NewName); - static Status copyWithNewName(const llvm::sys::fs::file_status &In, - StringRef NewName); + /// Get a copy of a this Status with a different name. + Status copyWithNewName(StringRef NewName); /// Returns the name that should be used for this file or directory. + /// This is usually the path that the file was opened as, without resolving + /// relative paths or symlinks. StringRef getName() const { return Name; } /// @name Status interface from llvm::sys::fs @@ -107,15 +109,16 @@ public: virtual ~File(); /// Get the status of the file. + /// This may access the filesystem (e.g. `stat()`), or return a cached value. virtual llvm::ErrorOr status() = 0; - /// Get the name of the file - virtual llvm::ErrorOr getName() { - if (auto Status = status()) - return Status->getName().str(); - else - return Status.getError(); - } + /// Get the "real name" of the file, if available. + /// This should be absolute, and typically has symlinks resolved. + /// + /// Only some VFS implementations provide this, and only sometimes. + /// FIXME: these maybe-available semantics are not very useful. It would be + /// nice if this was more consistent with FileSystem::getRealPath(). + virtual llvm::Optional getRealPath() { return llvm::None; } /// Get the contents of the file as a \p MemoryBuffer. virtual llvm::ErrorOr> diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 7e2d01c498..13a3d8f95c 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -316,7 +316,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.File = std::move(F); UFE.IsValid = true; if (UFE.File) - if (auto RealPathName = UFE.File->getName()) + if (auto RealPathName = UFE.File->getRealPath()) UFE.RealPathName = *RealPathName; return &UFE; } diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index bcfcbdbb90..b269a9fcc0 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -73,16 +73,14 @@ Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime, : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size), Type(Type), Perms(Perms) {} -Status Status::copyWithNewName(const Status &In, StringRef NewName) { - return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), - In.getUser(), In.getGroup(), In.getSize(), In.getType(), - In.getPermissions()); -} +Status::Status(const file_status &In, StringRef NewName) + : Status(NewName, In.getUniqueID(), In.getLastModificationTime(), + In.getUser(), In.getGroup(), In.getSize(), In.type(), + In.permissions()) {} -Status Status::copyWithNewName(const file_status &In, StringRef NewName) { - return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), - In.getUser(), In.getGroup(), In.getSize(), In.type(), - In.permissions()); +Status Status::copyWithNewName(StringRef NewName) { + return Status(NewName, getUniqueID(), getLastModificationTime(), getUser(), + getGroup(), getSize(), getType(), getPermissions()); } bool Status::equivalent(const Status &Other) const { @@ -178,6 +176,7 @@ class RealFile : public File { Status S; std::string RealName; + // NewRealPathName is used only if non-empty. RealFile(int FD, StringRef NewName, StringRef NewRealPathName) : FD(FD), S(NewName, {}, {}, {}, {}, {}, llvm::sys::fs::file_type::status_error, {}), @@ -189,7 +188,7 @@ public: ~RealFile() override; ErrorOr status() override; - ErrorOr getName() override; + Optional getRealPath() override; ErrorOr> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -207,13 +206,15 @@ ErrorOr RealFile::status() { file_status RealStatus; if (std::error_code EC = sys::fs::status(FD, RealStatus)) return EC; - S = Status::copyWithNewName(RealStatus, S.getName()); + S = Status(RealStatus, S.getName()); } return S; } -ErrorOr RealFile::getName() { - return RealName.empty() ? S.getName().str() : RealName; +Optional RealFile::getRealPath() { + if (RealName.empty()) + return llvm::None; + return RealName; } ErrorOr> @@ -251,7 +252,7 @@ ErrorOr RealFileSystem::status(const Twine &Path) { sys::fs::file_status RealStatus; if (std::error_code EC = sys::fs::status(Path, RealStatus)) return EC; - return Status::copyWithNewName(RealStatus, Path.str()); + return Status(RealStatus, Path.str()); } ErrorOr> @@ -303,7 +304,7 @@ public: if (Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -317,7 +318,7 @@ public: } else { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -1641,7 +1642,7 @@ static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames, Status ExternalStatus) { Status S = ExternalStatus; if (!UseExternalNames) - S = Status::copyWithNewName(S, Path.str()); + S = S.copyWithNewName(Path.str()); S.IsVFSMapped = true; return S; } @@ -1657,7 +1658,7 @@ ErrorOr RedirectingFileSystem::status(const Twine &Path, Entry *E) { return S; } else { // directory auto *DE = cast(E); - return Status::copyWithNewName(DE->getStatus(), Path.str()); + return DE->getStatus().copyWithNewName(Path.str()); } } -- GitLab From 1a29954b0aaca902131992cce6cfbf211769f550 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 24 Jul 2018 16:11:30 +0000 Subject: [PATCH 0697/1023] Remove stale documentation from InternalsManual.rst The DuplicatesAllowedWhileMerging was removed a while ago, but the documentation remained. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337835 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/InternalsManual.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst index 7d85d2be28..af15b2e51e 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -1891,11 +1891,6 @@ attribute classes. For instance, ``ParsedAttr`` is the shared parsed attribute kind, but ARMInterruptAttr and MSP430InterruptAttr are the semantic attributes generated. -By default, when declarations are merging attributes, an attribute will not be -duplicated. However, if an attribute can be duplicated during this merging -stage, set ``DuplicatesAllowedWhileMerging`` to ``1``, and the attribute will -be merged. - By default, attribute arguments are parsed in an evaluated context. If the arguments for an attribute should be parsed in an unevaluated context (akin to the way the argument to a ``sizeof`` expression is parsed), set -- GitLab From 4cedfdc027d4dc59b704d43b837c6d16ac282cf2 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Tue, 24 Jul 2018 20:28:07 +0000 Subject: [PATCH 0698/1023] Revert "[VFS] Cleanups to VFS interfaces." This reverts commit r337834 due to test failures. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337850 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/VirtualFileSystem.h | 27 ++++++++---------- lib/Basic/FileManager.cpp | 2 +- lib/Basic/VirtualFileSystem.cpp | 37 ++++++++++++------------- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index bd752c8dad..2480b91123 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -45,8 +45,7 @@ class MemoryBuffer; namespace clang { namespace vfs { -/// File information from a \p File::status() operation. -/// This is roughly equivalent to a `struct stat` plus a file path. +/// The result of a \p status operation. class Status { std::string Name; llvm::sys::fs::UniqueID UID; @@ -67,14 +66,13 @@ public: llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms); - Status(const llvm::sys::fs::file_status &FSStatus, StringRef Name); - /// Get a copy of a this Status with a different name. - Status copyWithNewName(StringRef NewName); + /// Get a copy of a Status with a different name. + static Status copyWithNewName(const Status &In, StringRef NewName); + static Status copyWithNewName(const llvm::sys::fs::file_status &In, + StringRef NewName); /// Returns the name that should be used for this file or directory. - /// This is usually the path that the file was opened as, without resolving - /// relative paths or symlinks. StringRef getName() const { return Name; } /// @name Status interface from llvm::sys::fs @@ -109,16 +107,15 @@ public: virtual ~File(); /// Get the status of the file. - /// This may access the filesystem (e.g. `stat()`), or return a cached value. virtual llvm::ErrorOr status() = 0; - /// Get the "real name" of the file, if available. - /// This should be absolute, and typically has symlinks resolved. - /// - /// Only some VFS implementations provide this, and only sometimes. - /// FIXME: these maybe-available semantics are not very useful. It would be - /// nice if this was more consistent with FileSystem::getRealPath(). - virtual llvm::Optional getRealPath() { return llvm::None; } + /// Get the name of the file + virtual llvm::ErrorOr getName() { + if (auto Status = status()) + return Status->getName().str(); + else + return Status.getError(); + } /// Get the contents of the file as a \p MemoryBuffer. virtual llvm::ErrorOr> diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 13a3d8f95c..7e2d01c498 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -316,7 +316,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.File = std::move(F); UFE.IsValid = true; if (UFE.File) - if (auto RealPathName = UFE.File->getRealPath()) + if (auto RealPathName = UFE.File->getName()) UFE.RealPathName = *RealPathName; return &UFE; } diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index b269a9fcc0..bcfcbdbb90 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -73,14 +73,16 @@ Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime, : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size), Type(Type), Perms(Perms) {} -Status::Status(const file_status &In, StringRef NewName) - : Status(NewName, In.getUniqueID(), In.getLastModificationTime(), - In.getUser(), In.getGroup(), In.getSize(), In.type(), - In.permissions()) {} +Status Status::copyWithNewName(const Status &In, StringRef NewName) { + return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), + In.getUser(), In.getGroup(), In.getSize(), In.getType(), + In.getPermissions()); +} -Status Status::copyWithNewName(StringRef NewName) { - return Status(NewName, getUniqueID(), getLastModificationTime(), getUser(), - getGroup(), getSize(), getType(), getPermissions()); +Status Status::copyWithNewName(const file_status &In, StringRef NewName) { + return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), + In.getUser(), In.getGroup(), In.getSize(), In.type(), + In.permissions()); } bool Status::equivalent(const Status &Other) const { @@ -176,7 +178,6 @@ class RealFile : public File { Status S; std::string RealName; - // NewRealPathName is used only if non-empty. RealFile(int FD, StringRef NewName, StringRef NewRealPathName) : FD(FD), S(NewName, {}, {}, {}, {}, {}, llvm::sys::fs::file_type::status_error, {}), @@ -188,7 +189,7 @@ public: ~RealFile() override; ErrorOr status() override; - Optional getRealPath() override; + ErrorOr getName() override; ErrorOr> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -206,15 +207,13 @@ ErrorOr RealFile::status() { file_status RealStatus; if (std::error_code EC = sys::fs::status(FD, RealStatus)) return EC; - S = Status(RealStatus, S.getName()); + S = Status::copyWithNewName(RealStatus, S.getName()); } return S; } -Optional RealFile::getRealPath() { - if (RealName.empty()) - return llvm::None; - return RealName; +ErrorOr RealFile::getName() { + return RealName.empty() ? S.getName().str() : RealName; } ErrorOr> @@ -252,7 +251,7 @@ ErrorOr RealFileSystem::status(const Twine &Path) { sys::fs::file_status RealStatus; if (std::error_code EC = sys::fs::status(Path, RealStatus)) return EC; - return Status(RealStatus, Path.str()); + return Status::copyWithNewName(RealStatus, Path.str()); } ErrorOr> @@ -304,7 +303,7 @@ public: if (Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status(S, Iter->path()); + CurrentEntry = Status::copyWithNewName(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -318,7 +317,7 @@ public: } else { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status(S, Iter->path()); + CurrentEntry = Status::copyWithNewName(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -1642,7 +1641,7 @@ static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames, Status ExternalStatus) { Status S = ExternalStatus; if (!UseExternalNames) - S = S.copyWithNewName(Path.str()); + S = Status::copyWithNewName(S, Path.str()); S.IsVFSMapped = true; return S; } @@ -1658,7 +1657,7 @@ ErrorOr RedirectingFileSystem::status(const Twine &Path, Entry *E) { return S; } else { // directory auto *DE = cast(E); - return DE->getStatus().copyWithNewName(Path.str()); + return Status::copyWithNewName(DE->getStatus(), Path.str()); } } -- GitLab From 8b8872507a7209e39655cec6b5fb32f91a3e328d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Jul 2018 21:18:30 +0000 Subject: [PATCH 0699/1023] Don't lifetime-extend or track lifetime problems through the LHS of '->*'. Fixes a false-positive warning found by selfhost. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337857 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Expr.cpp | 2 +- test/SemaCXX/return-stack-addr.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 3d11619ec4..7e652b778b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -108,7 +108,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments( } } } else if (const BinaryOperator *BO = dyn_cast(E)) { - if (BO->isPtrMemOp()) { + if (BO->getOpcode() == BO_PtrMemD) { assert(BO->getRHS()->isRValue()); E = BO->getLHS(); const MemberPointerType *MPT = diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp index a5f84adf0b..08aaa749b4 100644 --- a/test/SemaCXX/return-stack-addr.cpp +++ b/test/SemaCXX/return-stack-addr.cpp @@ -157,3 +157,9 @@ void ret_from_lambda() { (void) [&]() -> int& { int &a = b; return a; }; (void) [=]() mutable -> int& { int &a = b; return a; }; } + +namespace mem_ptr { + struct X {}; + int X::*f(); + int &r(X *p) { return p->*f(); } +} -- GitLab From c181c9d5baf7466efba438809443531dff877091 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Tue, 24 Jul 2018 22:47:16 +0000 Subject: [PATCH 0700/1023] [Sema] Destroy tokens in DeclaratorChunk params Otherwise this leaks in some edge cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337862 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/DeclSpec.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 40e5269c15..83d5ab2cff 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1355,8 +1355,7 @@ struct DeclaratorChunk { } void destroy() { - if (DeleteParams) - delete[] Params; + freeParams(); switch (getExceptionSpecType()) { default: break; -- GitLab From 77284fe5d8be198f3b47dd93862c2e4f6990d4c5 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 24 Jul 2018 23:14:29 +0000 Subject: [PATCH 0701/1023] [analyzer] Extend NoStoreFuncVisitor to insert a note on IVars The note is added in the following situation: - We are throwing a nullability-related warning on an IVar - The path goes through a method which *could have* (syntactically determined) written into that IVar, but did not rdar://42444460 Differential Revision: https://reviews.llvm.org/D49689 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337864 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporterVisitors.cpp | 63 +++++++++++++++---- .../diagnostics/no-store-func-path-notes.cpp | 19 +++++- .../diagnostics/no-store-func-path-notes.m | 35 ++++++++++- 3 files changed, 100 insertions(+), 17 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index f17f41a7ac..be16ce10e0 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -22,6 +22,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CFGStmtMap.h" @@ -306,15 +307,26 @@ public: CallEventRef<> Call = BRC.getStateManager().getCallEventManager().getCaller(SCtx, State); - const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy(); const SourceManager &SM = BRC.getSourceManager(); + + // Region of interest corresponds to an IVar, exiting a method + // which could have written into that IVar, but did not. + if (const auto *MC = dyn_cast(Call)) + if (const auto *IvarR = dyn_cast(RegionOfInterest)) + if (potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(), + IvarR->getDecl()) && + !isRegionOfInterestModifiedInFrame(N)) + return notModifiedMemberDiagnostics( + Ctx, SM, PP, *CallExitLoc, Call, + MC->getReceiverSVal().getAsRegion()); + if (const auto *CCall = dyn_cast(Call)) { const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion(); if (RegionOfInterest->isSubRegionOf(ThisRegion) && !CCall->getDecl()->isImplicit() && !isRegionOfInterestModifiedInFrame(N)) - return notModifiedInConstructorDiagnostics(Ctx, SM, PP, *CallExitLoc, + return notModifiedMemberDiagnostics(Ctx, SM, PP, *CallExitLoc, CCall, ThisRegion); } @@ -331,7 +343,7 @@ public: if (isRegionOfInterestModifiedInFrame(N)) return nullptr; - return notModifiedDiagnostics( + return notModifiedParameterDiagnostics( Ctx, SM, PP, *CallExitLoc, Call, PVD, R, IndirectionLevel); } QualType PT = T->getPointeeType(); @@ -346,6 +358,22 @@ public: } private: + + /// \return Whether the method declaration \p Parent + /// syntactically has a binary operation writing into the ivar \p Ivar. + bool potentiallyWritesIntoIvar(const Decl *Parent, + const ObjCIvarDecl *Ivar) { + using namespace ast_matchers; + if (!Parent) + return false; + StatementMatcher WriteIntoIvarM = binaryOperator( + hasOperatorName("="), hasLHS(ignoringParenImpCasts(objcIvarRefExpr( + hasDeclaration(equalsNode(Ivar)))))); + StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM)); + auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext()); + return !Matches.empty(); + } + /// Check and lazily calculate whether the region of interest is /// modified in the stack frame to which \p N belongs. /// The calculation is cached in FramesModifyingRegion. @@ -414,19 +442,21 @@ private: Ty->getPointeeType().getCanonicalType().isConstQualified(); } - std::shared_ptr notModifiedInConstructorDiagnostics( + /// \return Diagnostics piece for the member field not modified + /// in a given function. + std::shared_ptr notModifiedMemberDiagnostics( const LocationContext *Ctx, const SourceManager &SM, const PrintingPolicy &PP, CallExitBegin &CallExitLoc, - const CXXConstructorCall *Call, + CallEventRef<> Call, const MemRegion *ArgRegion) { + const char *TopRegionName = isa(Call) ? "self" : "this"; SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); os << DiagnosticsMsg; - bool out = prettyPrintRegionName( - "this", "->", /*IsReference=*/true, - /*IndirectionLevel=*/1, ArgRegion, os, PP); + bool out = prettyPrintRegionName(TopRegionName, "->", /*IsReference=*/true, + /*IndirectionLevel=*/1, ArgRegion, os, PP); // Return nothing if we have failed to pretty-print. if (!out) @@ -434,14 +464,16 @@ private: os << "'"; PathDiagnosticLocation L = - getPathDiagnosticLocation(nullptr, SM, Ctx, Call); + getPathDiagnosticLocation(CallExitLoc.getReturnStmt(), SM, Ctx, Call); return std::make_shared(L, os.str()); } + /// \return Diagnostics piece for the parameter \p PVD not modified + /// in a given function. /// \p IndirectionLevel How many times \c ArgRegion has to be dereferenced /// before we get to the super region of \c RegionOfInterest std::shared_ptr - notModifiedDiagnostics(const LocationContext *Ctx, + notModifiedParameterDiagnostics(const LocationContext *Ctx, const SourceManager &SM, const PrintingPolicy &PP, CallExitBegin &CallExitLoc, @@ -481,8 +513,8 @@ private: /// Pretty-print region \p ArgRegion starting from parent to \p os. /// \return whether printing has succeeded - bool prettyPrintRegionName(const char *TopRegionName, - const char *Sep, + bool prettyPrintRegionName(StringRef TopRegionName, + StringRef Sep, bool IsReference, int IndirectionLevel, const MemRegion *ArgRegion, @@ -491,7 +523,8 @@ private: SmallVector Subregions; const MemRegion *R = RegionOfInterest; while (R != ArgRegion) { - if (!(isa(R) || isa(R))) + if (!(isa(R) || isa(R) || + isa(R))) return false; // Pattern-matching failed. Subregions.push_back(R); R = cast(R)->getSuperRegion(); @@ -519,6 +552,10 @@ private: os << Sep; FR->getDecl()->getDeclName().print(os, PP); Sep = "."; + } else if (const auto *IR = dyn_cast(*I)) { + os << "->"; + IR->getDecl()->getDeclName().print(os, PP); + Sep = "."; } else if (isa(*I)) { continue; // Just keep going up to the base region. } else { diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp index b96dc4cf2a..17ec96ae5b 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp +++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp @@ -97,6 +97,14 @@ struct C { int x; int y; C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}} + + C(int pX, int pY, bool Flag) { + x = pX; + if (Flag) // expected-note{{Assuming 'Flag' is not equal to 0}} + // expected-note@-1{{Taking true branch}} + return; // expected-note{{Returning without writing to 'this->y'}} + y = pY; + } }; int use_constructor() { @@ -106,6 +114,15 @@ int use_constructor() { // expected-warning@-1{{Undefined or garbage value returned to caller}} } +int coin(); + +int use_other_constructor() { + C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}} + // expected-note@-1{{Returning from constructor for 'C'}} + return c.y; // expected-note{{Undefined or garbage value returned to caller}} + // expected-warning@-1{{Undefined or garbage value returned to caller}} +} + struct D { void initialize(int *); }; @@ -122,8 +139,6 @@ int use_d_initializer(D* d) { // expected-warning@-1{{Undefined or garbage value returned to caller}} } -int coin(); - struct S2 { int x; }; diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.m b/test/Analysis/diagnostics/no-store-func-path-notes.m index 3ae97ef564..51d1515e86 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.m +++ b/test/Analysis/diagnostics/no-store-func-path-notes.m @@ -1,6 +1,10 @@ -// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s +// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core,nullability -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s -@interface I +#include "../Inputs/system-header-simulator-for-nullability.h" + +extern int coin(); + +@interface I : NSObject - (int)initVar:(int *)var param:(int)param; @end @@ -44,3 +48,30 @@ int initFromBlock() { }(); return z; } + +extern void expectNonNull(NSString * _Nonnull a); + +@interface A : NSObject +- (void) func; +- (void) initAMaybe; +@end + +@implementation A { + NSString * a; +} + +- (void) initAMaybe { + if (coin()) // expected-note{{Assuming the condition is false}} + // expected-note@-1{{Taking false branch}} + a = @"string"; +} // expected-note{{Returning without writing to 'self->a'}} + +- (void) func { + a = nil; // expected-note{{nil object reference stored to 'a'}} + [self initAMaybe]; // expected-note{{Calling 'initAMaybe'}} + // expected-note@-1{{Returning from 'initAMaybe'}} + expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}} + // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}} +} + +@end -- GitLab From f70ff96a80f2680e5aafa2becd194e2796cf2db9 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Tue, 24 Jul 2018 23:23:33 +0000 Subject: [PATCH 0702/1023] Revert "[analyzer] Extend NoStoreFuncVisitor to insert a note on IVars" This reverts commit a9e21bd727112cd69eabc1af648c5da6b773d06e. Reverted because the dependency has not landed yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337866 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporterVisitors.cpp | 63 ++++--------------- .../diagnostics/no-store-func-path-notes.cpp | 19 +----- .../diagnostics/no-store-func-path-notes.m | 35 +---------- 3 files changed, 17 insertions(+), 100 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index be16ce10e0..f17f41a7ac 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -22,7 +22,6 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CFGStmtMap.h" @@ -307,26 +306,15 @@ public: CallEventRef<> Call = BRC.getStateManager().getCallEventManager().getCaller(SCtx, State); + const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy(); const SourceManager &SM = BRC.getSourceManager(); - - // Region of interest corresponds to an IVar, exiting a method - // which could have written into that IVar, but did not. - if (const auto *MC = dyn_cast(Call)) - if (const auto *IvarR = dyn_cast(RegionOfInterest)) - if (potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(), - IvarR->getDecl()) && - !isRegionOfInterestModifiedInFrame(N)) - return notModifiedMemberDiagnostics( - Ctx, SM, PP, *CallExitLoc, Call, - MC->getReceiverSVal().getAsRegion()); - if (const auto *CCall = dyn_cast(Call)) { const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion(); if (RegionOfInterest->isSubRegionOf(ThisRegion) && !CCall->getDecl()->isImplicit() && !isRegionOfInterestModifiedInFrame(N)) - return notModifiedMemberDiagnostics(Ctx, SM, PP, *CallExitLoc, + return notModifiedInConstructorDiagnostics(Ctx, SM, PP, *CallExitLoc, CCall, ThisRegion); } @@ -343,7 +331,7 @@ public: if (isRegionOfInterestModifiedInFrame(N)) return nullptr; - return notModifiedParameterDiagnostics( + return notModifiedDiagnostics( Ctx, SM, PP, *CallExitLoc, Call, PVD, R, IndirectionLevel); } QualType PT = T->getPointeeType(); @@ -358,22 +346,6 @@ public: } private: - - /// \return Whether the method declaration \p Parent - /// syntactically has a binary operation writing into the ivar \p Ivar. - bool potentiallyWritesIntoIvar(const Decl *Parent, - const ObjCIvarDecl *Ivar) { - using namespace ast_matchers; - if (!Parent) - return false; - StatementMatcher WriteIntoIvarM = binaryOperator( - hasOperatorName("="), hasLHS(ignoringParenImpCasts(objcIvarRefExpr( - hasDeclaration(equalsNode(Ivar)))))); - StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM)); - auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext()); - return !Matches.empty(); - } - /// Check and lazily calculate whether the region of interest is /// modified in the stack frame to which \p N belongs. /// The calculation is cached in FramesModifyingRegion. @@ -442,21 +414,19 @@ private: Ty->getPointeeType().getCanonicalType().isConstQualified(); } - /// \return Diagnostics piece for the member field not modified - /// in a given function. - std::shared_ptr notModifiedMemberDiagnostics( + std::shared_ptr notModifiedInConstructorDiagnostics( const LocationContext *Ctx, const SourceManager &SM, const PrintingPolicy &PP, CallExitBegin &CallExitLoc, - CallEventRef<> Call, + const CXXConstructorCall *Call, const MemRegion *ArgRegion) { - const char *TopRegionName = isa(Call) ? "self" : "this"; SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); os << DiagnosticsMsg; - bool out = prettyPrintRegionName(TopRegionName, "->", /*IsReference=*/true, - /*IndirectionLevel=*/1, ArgRegion, os, PP); + bool out = prettyPrintRegionName( + "this", "->", /*IsReference=*/true, + /*IndirectionLevel=*/1, ArgRegion, os, PP); // Return nothing if we have failed to pretty-print. if (!out) @@ -464,16 +434,14 @@ private: os << "'"; PathDiagnosticLocation L = - getPathDiagnosticLocation(CallExitLoc.getReturnStmt(), SM, Ctx, Call); + getPathDiagnosticLocation(nullptr, SM, Ctx, Call); return std::make_shared(L, os.str()); } - /// \return Diagnostics piece for the parameter \p PVD not modified - /// in a given function. /// \p IndirectionLevel How many times \c ArgRegion has to be dereferenced /// before we get to the super region of \c RegionOfInterest std::shared_ptr - notModifiedParameterDiagnostics(const LocationContext *Ctx, + notModifiedDiagnostics(const LocationContext *Ctx, const SourceManager &SM, const PrintingPolicy &PP, CallExitBegin &CallExitLoc, @@ -513,8 +481,8 @@ private: /// Pretty-print region \p ArgRegion starting from parent to \p os. /// \return whether printing has succeeded - bool prettyPrintRegionName(StringRef TopRegionName, - StringRef Sep, + bool prettyPrintRegionName(const char *TopRegionName, + const char *Sep, bool IsReference, int IndirectionLevel, const MemRegion *ArgRegion, @@ -523,8 +491,7 @@ private: SmallVector Subregions; const MemRegion *R = RegionOfInterest; while (R != ArgRegion) { - if (!(isa(R) || isa(R) || - isa(R))) + if (!(isa(R) || isa(R))) return false; // Pattern-matching failed. Subregions.push_back(R); R = cast(R)->getSuperRegion(); @@ -552,10 +519,6 @@ private: os << Sep; FR->getDecl()->getDeclName().print(os, PP); Sep = "."; - } else if (const auto *IR = dyn_cast(*I)) { - os << "->"; - IR->getDecl()->getDeclName().print(os, PP); - Sep = "."; } else if (isa(*I)) { continue; // Just keep going up to the base region. } else { diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp index 17ec96ae5b..b96dc4cf2a 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp +++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp @@ -97,14 +97,6 @@ struct C { int x; int y; C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}} - - C(int pX, int pY, bool Flag) { - x = pX; - if (Flag) // expected-note{{Assuming 'Flag' is not equal to 0}} - // expected-note@-1{{Taking true branch}} - return; // expected-note{{Returning without writing to 'this->y'}} - y = pY; - } }; int use_constructor() { @@ -114,15 +106,6 @@ int use_constructor() { // expected-warning@-1{{Undefined or garbage value returned to caller}} } -int coin(); - -int use_other_constructor() { - C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}} - // expected-note@-1{{Returning from constructor for 'C'}} - return c.y; // expected-note{{Undefined or garbage value returned to caller}} - // expected-warning@-1{{Undefined or garbage value returned to caller}} -} - struct D { void initialize(int *); }; @@ -139,6 +122,8 @@ int use_d_initializer(D* d) { // expected-warning@-1{{Undefined or garbage value returned to caller}} } +int coin(); + struct S2 { int x; }; diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.m b/test/Analysis/diagnostics/no-store-func-path-notes.m index 51d1515e86..3ae97ef564 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.m +++ b/test/Analysis/diagnostics/no-store-func-path-notes.m @@ -1,10 +1,6 @@ -// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core,nullability -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s +// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s -#include "../Inputs/system-header-simulator-for-nullability.h" - -extern int coin(); - -@interface I : NSObject +@interface I - (int)initVar:(int *)var param:(int)param; @end @@ -48,30 +44,3 @@ int initFromBlock() { }(); return z; } - -extern void expectNonNull(NSString * _Nonnull a); - -@interface A : NSObject -- (void) func; -- (void) initAMaybe; -@end - -@implementation A { - NSString * a; -} - -- (void) initAMaybe { - if (coin()) // expected-note{{Assuming the condition is false}} - // expected-note@-1{{Taking false branch}} - a = @"string"; -} // expected-note{{Returning without writing to 'self->a'}} - -- (void) func { - a = nil; // expected-note{{nil object reference stored to 'a'}} - [self initAMaybe]; // expected-note{{Calling 'initAMaybe'}} - // expected-note@-1{{Returning from 'initAMaybe'}} - expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}} - // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}} -} - -@end -- GitLab From cbf42820fad10b5dcd0320bfa14df151ef25cfc2 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 25 Jul 2018 01:27:15 +0000 Subject: [PATCH 0703/1023] [analyzer] Syntactic matcher for leaks associated with run loop and autoreleasepool A checker for detecting leaks resulting from allocating temporary autoreleasing objects before starting the main run loop. Checks for two antipatterns: 1. ObjCMessageExpr followed by [[NARunLoop mainRunLoop] run] in the same autorelease pool. 2. ObjCMessageExpr followed by [[NARunLoop mainRunLoop] run] in no autorelease pool. Happens-before relationship is modeled purely syntactically. rdar://39299145 Differential Revision: https://reviews.llvm.org/D49528 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337876 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 4 + lib/StaticAnalyzer/Checkers/CMakeLists.txt | 1 + .../RunLoopAutoreleaseLeakChecker.cpp | 217 ++++++++++++++++++ .../Checkers/RunLoopAutoreleaseLeakChecker.m | 104 +++++++++ ...system-header-simulator-for-objc-dealloc.h | 4 + 5 files changed, 330 insertions(+) create mode 100644 lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp create mode 100644 test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 38fd687e16..ab0e4af136 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -568,6 +568,10 @@ def ObjCPropertyChecker : Checker<"ObjCProperty">, let ParentPackage = Cocoa in { +def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">, + HelpText<"Check for leaked memory in autorelease pools that will never be drained">, + DescFile<"RunLoopAutoreleaseLeakChecker.cpp">; + def ObjCAtSyncChecker : Checker<"AtSync">, HelpText<"Check for nil pointers used as mutexes for @synchronized">, DescFile<"ObjCAtSyncChecker.cpp">; diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 94093b82f3..5bb4770b56 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -79,6 +79,7 @@ add_clang_library(clangStaticAnalyzerCheckers RetainCountChecker.cpp ReturnPointerRangeChecker.cpp ReturnUndefChecker.cpp + RunLoopAutoreleaseLeakChecker.cpp SimpleStreamChecker.cpp StackAddrEscapeChecker.cpp StdLibraryFunctionsChecker.cpp diff --git a/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp new file mode 100644 index 0000000000..64b61a0213 --- /dev/null +++ b/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp @@ -0,0 +1,217 @@ +//=- RunLoopAutoreleaseLeakChecker.cpp --------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// +// +// A checker for detecting leaks resulting from allocating temporary +// autoreleased objects before starting the main run loop. +// +// Checks for two antipatterns: +// 1. ObjCMessageExpr followed by [[NSRunLoop mainRunLoop] run] in the same +// autorelease pool. +// 2. ObjCMessageExpr followed by [[NSRunLoop mainRunLoop] run] in no +// autorelease pool. +// +// Any temporary objects autoreleased in code called in those expressions +// will not be deallocated until the program exits, and are effectively leaks. +// +//===----------------------------------------------------------------------===// +// + +#include "ClangSACheckers.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +namespace { + +const char * RunLoopBind = "NSRunLoopM"; +const char * RunLoopRunBind = "RunLoopRunM"; +const char * OtherMsgBind = "OtherMessageSentM"; +const char * AutoreleasePoolBind = "AutoreleasePoolM"; + +class RunLoopAutoreleaseLeakChecker : public Checker< + check::ASTCodeBody> { + +public: + void checkASTCodeBody(const Decl *D, + AnalysisManager &AM, + BugReporter &BR) const; + +}; + +} // end anonymous namespace + + +using TriBoolTy = Optional; +using MemoizationMapTy = llvm::DenseMap>; + +static TriBoolTy +seenBeforeRec(const Stmt *Parent, const Stmt *A, const Stmt *B, + MemoizationMapTy &Memoization) { + for (const Stmt *C : Parent->children()) { + if (C == A) + return true; + + if (C == B) + return false; + + Optional &Cached = Memoization[C]; + if (!Cached) + Cached = seenBeforeRec(C, A, B, Memoization); + + if (Cached->hasValue()) + return Cached->getValue(); + } + + return None; +} + +/// \return Whether {@code A} occurs before {@code B} in traversal of +/// {@code Parent}. +/// Conceptually a very incomplete/unsound approximation of happens-before +/// relationship (A is likely to be evaluated before B), +/// but useful enough in this case. +static bool seenBefore(const Stmt *Parent, const Stmt *A, const Stmt *B) { + MemoizationMapTy Memoization; + TriBoolTy Val = seenBeforeRec(Parent, A, B, Memoization); + return Val.getValue(); +} + +static void emitDiagnostics(BoundNodes &Match, + const Decl *D, + BugReporter &BR, + AnalysisManager &AM, + const RunLoopAutoreleaseLeakChecker *Checker) { + + assert(D->hasBody()); + const Stmt *DeclBody = D->getBody(); + + AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D); + + const auto *ME = Match.getNodeAs(OtherMsgBind); + assert(ME); + + const auto *AP = + Match.getNodeAs(AutoreleasePoolBind); + bool HasAutoreleasePool = (AP != nullptr); + + const auto *RL = Match.getNodeAs(RunLoopBind); + const auto *RLR = Match.getNodeAs(RunLoopRunBind); + assert(RLR && "Run loop launch not found"); + + assert(ME != RLR); + if (HasAutoreleasePool && seenBefore(AP, RLR, ME)) + return; + + if (!HasAutoreleasePool && seenBefore(DeclBody, RLR, ME)) + return; + + PathDiagnosticLocation Location = PathDiagnosticLocation::createBegin( + ME, BR.getSourceManager(), ADC); + SourceRange Range = ME->getSourceRange(); + + BR.EmitBasicReport(ADC->getDecl(), Checker, + /*Name=*/"Memory leak inside autorelease pool", + /*Category=*/"Memory", + /*Name=*/ + (Twine("Temporary objects allocated in the") + + " autorelease pool " + + (HasAutoreleasePool ? "" : "of last resort ") + + "followed by the launch of " + + (RL ? "main run loop " : "xpc_main ") + + "may never get released; consider moving them to a " + "separate autorelease pool") + .str(), + Location, Range); +} + +static StatementMatcher getRunLoopRunM(StatementMatcher Extra = anything()) { + StatementMatcher MainRunLoopM = + objcMessageExpr(hasSelector("mainRunLoop"), + hasReceiverType(asString("NSRunLoop")), + Extra) + .bind(RunLoopBind); + + StatementMatcher MainRunLoopRunM = objcMessageExpr(hasSelector("run"), + hasReceiver(MainRunLoopM), + Extra).bind(RunLoopRunBind); + + StatementMatcher XPCRunM = + callExpr(callee(functionDecl(hasName("xpc_main")))).bind(RunLoopRunBind); + return anyOf(MainRunLoopRunM, XPCRunM); +} + +static StatementMatcher getOtherMessageSentM(StatementMatcher Extra = anything()) { + return objcMessageExpr(unless(anyOf(equalsBoundNode(RunLoopBind), + equalsBoundNode(RunLoopRunBind))), + Extra) + .bind(OtherMsgBind); +} + +static void +checkTempObjectsInSamePool(const Decl *D, AnalysisManager &AM, BugReporter &BR, + const RunLoopAutoreleaseLeakChecker *Chkr) { + StatementMatcher RunLoopRunM = getRunLoopRunM(); + StatementMatcher OtherMessageSentM = getOtherMessageSentM(); + + StatementMatcher RunLoopInAutorelease = + autoreleasePoolStmt( + hasDescendant(RunLoopRunM), + hasDescendant(OtherMessageSentM)).bind(AutoreleasePoolBind); + + DeclarationMatcher GroupM = decl(hasDescendant(RunLoopInAutorelease)); + + auto Matches = match(GroupM, *D, AM.getASTContext()); + for (BoundNodes Match : Matches) + emitDiagnostics(Match, D, BR, AM, Chkr); +} + +static void +checkTempObjectsInNoPool(const Decl *D, AnalysisManager &AM, BugReporter &BR, + const RunLoopAutoreleaseLeakChecker *Chkr) { + + auto NoPoolM = unless(hasAncestor(autoreleasePoolStmt())); + + StatementMatcher RunLoopRunM = getRunLoopRunM(NoPoolM); + StatementMatcher OtherMessageSentM = getOtherMessageSentM(NoPoolM); + + DeclarationMatcher GroupM = functionDecl( + isMain(), + hasDescendant(RunLoopRunM), + hasDescendant(OtherMessageSentM) + ); + + auto Matches = match(GroupM, *D, AM.getASTContext()); + + for (BoundNodes Match : Matches) + emitDiagnostics(Match, D, BR, AM, Chkr); + +} + +void RunLoopAutoreleaseLeakChecker::checkASTCodeBody(const Decl *D, + AnalysisManager &AM, + BugReporter &BR) const { + checkTempObjectsInSamePool(D, AM, BR, this); + checkTempObjectsInNoPool(D, AM, BR, this); +} + +void ento::registerRunLoopAutoreleaseLeakChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m new file mode 100644 index 0000000000..4dde40e210 --- /dev/null +++ b/test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m @@ -0,0 +1,104 @@ +// UNSUPPORTED: system-windows +// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify +// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP1=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify +// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP2=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify +// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP3=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify +// RUN: %clang_analyze_cc1 -DEXTRA=1 -DAP4=1 -fobjc-arc -analyzer-checker=core,osx.cocoa.RunLoopAutoreleaseLeak %s -triple x86_64-darwin -verify + +#include "../Inputs/system-header-simulator-for-objc-dealloc.h" + +#ifndef EXTRA + +void just_runloop() { // No warning: no statements in between + @autoreleasepool { + [[NSRunLoop mainRunLoop] run]; // no-warning + } +} + +void just_xpcmain() { // No warning: no statements in between + @autoreleasepool { + xpc_main(); // no-warning + } +} + +void runloop_init_before() { // Warning: object created before the loop. + @autoreleasepool { + NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}} + (void) object; + [[NSRunLoop mainRunLoop] run]; + } +} + +void xpcmain_init_before() { // Warning: object created before the loop. + @autoreleasepool { + NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}} + (void) object; + xpc_main(); + } +} + +void runloop_init_before_two_objects() { // Warning: object created before the loop. + @autoreleasepool { + NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}} + NSObject *object2 = [[NSObject alloc] init]; // no-warning, warning on the first one is enough. + (void) object; + (void) object2; + [[NSRunLoop mainRunLoop] run]; + } +} + +void runloop_no_autoreleasepool() { + NSObject *object = [[NSObject alloc] init]; // no-warning + (void)object; + [[NSRunLoop mainRunLoop] run]; +} + +void runloop_init_after() { // No warning: objects created after the loop + @autoreleasepool { + [[NSRunLoop mainRunLoop] run]; + NSObject *object = [[NSObject alloc] init]; // no-warning + (void) object; + } +} + +#endif + +#ifdef AP1 +int main() { + NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool of last resort followed by the launch of main run loop may never get released; consider moving them to a separate autorelease pool}} + (void) object; + [[NSRunLoop mainRunLoop] run]; + return 0; +} +#endif + +#ifdef AP2 +// expected-no-diagnostics +int main() { + NSObject *object = [[NSObject alloc] init]; // no-warning + (void) object; + @autoreleasepool { + [[NSRunLoop mainRunLoop] run]; + } + return 0; +} +#endif + +#ifdef AP3 +// expected-no-diagnostics +int main() { + [[NSRunLoop mainRunLoop] run]; + NSObject *object = [[NSObject alloc] init]; // no-warning + (void) object; + return 0; +} +#endif + +#ifdef AP4 +int main() { + NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool of last resort followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}} + (void) object; + xpc_main(); + return 0; +} +#endif diff --git a/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h b/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h index 231c0bf564..f1343e30a7 100644 --- a/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h +++ b/test/Analysis/Inputs/system-header-simulator-for-objc-dealloc.h @@ -18,6 +18,8 @@ typedef signed char BOOL; @interface NSRunLoop : NSObject + (NSRunLoop *)currentRunLoop; ++ (NSRunLoop *)mainRunLoop; +- (void) run; - (void)cancelPerformSelectorsWithTarget:(id)target; @end @@ -33,3 +35,5 @@ void _Block_release(const void *aBlock); @interface CIFilter : NSObject @end + +extern void xpc_main(void); -- GitLab From 348f122f0a14a97df540a488bf5133fe6b9a6fa8 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 25 Jul 2018 01:44:22 +0000 Subject: [PATCH 0704/1023] [CMake] Link static libunwind and libc++abi into libc++ in Fuchsia toolchain When building libc++ for Fuchsia, we want to distribute shared libc++, libc++abi and libunwind as separate libraries, but for static versions we would like to link all of them into libc++ so -lc++ flag has the same effect whether shared or static library is being used. Differential Revision: https://reviews.llvm.org/D49628 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337877 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/caches/Fuchsia-stage2.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/caches/Fuchsia-stage2.cmake b/cmake/caches/Fuchsia-stage2.cmake index 7264f90d4e..28e1795134 100644 --- a/cmake/caches/Fuchsia-stage2.cmake +++ b/cmake/caches/Fuchsia-stage2.cmake @@ -100,9 +100,15 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}-fuchsia_CMAKE_SYSROOT ${FUCHSIA_${target}_SYSROOT} CACHE PATH "") set(RUNTIMES_${target}-fuchsia_LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBUNWIND_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_INSTALL_STATIC_LIBRARY OFF CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY OFF CACHE BOOL "") set(RUNTIMES_${target}-fuchsia_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") + set(RUNTIMES_${target}-fuchsia_LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY OFF CACHE BOOL "") endforeach() set(LLVM_RUNTIME_SANITIZERS "Address" CACHE STRING "") -- GitLab From 32655dde06d972cb8fab41a9d9e56f71c7093a60 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 25 Jul 2018 03:01:35 +0000 Subject: [PATCH 0705/1023] [profile] Support profiling runtime on Fuchsia This ports the profiling runtime on Fuchsia and enables the instrumentation. Unlike on other platforms, Fuchsia doesn't use files to dump the instrumentation data since on Fuchsia, filesystem may not be accessible to the instrumented process. We instead use the data sink to pass the profiling data to the system the same sanitizer runtimes do. Differential Revision: https://reviews.llvm.org/D47208 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337881 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Fuchsia.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index 459b68b55a..54c34ff159 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -109,6 +109,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, addSanitizerRuntimes(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + ToolChain.addProfileRTLibs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) -- GitLab From 1df8e57db9c247fc74542ce89cf0e90ec1d0881f Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Wed, 25 Jul 2018 04:29:03 +0000 Subject: [PATCH 0706/1023] CodeGen: use non-zero memset when possible for automatic variables Summary: Right now automatic variables are either initialized with bzero followed by a few stores, or memcpy'd from a synthesized global. We end up encountering a fair amount of code where memcpy of non-zero byte patterns would be better than memcpy from a global because it touches less memory and generates a smaller binary. The optimizer could reason about this, but it's not really worth it when clang already knows. This code could definitely be more clever but I'm not sure it's worth it. In particular we could track a histogram of bytes seen and figure out (as we do with bzero) if a memset could be followed by a handful of stores. Similarly, we could tune the heuristics for GlobalSize, but using the same as for bzero seems conservatively OK for now. Reviewers: dexonsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49771 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337887 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 167 ++++++++++++++++++++++++++++++++++------- test/CodeGen/init.c | 66 ++++++++++++++++ 2 files changed, 207 insertions(+), 26 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 16646f0a6a..d1df5b33b6 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -948,6 +948,113 @@ static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, canEmitInitWithFewStoresAfterBZero(Init, StoreBudget); } +/// A byte pattern. +/// +/// Can be "any" pattern if the value was padding or known to be undef. +/// Can be "none" pattern if a sequence doesn't exist. +class BytePattern { + uint8_t Val; + enum class ValueType : uint8_t { Specific, Any, None } Type; + BytePattern(ValueType Type) : Type(Type) {} + +public: + BytePattern(uint8_t Value) : Val(Value), Type(ValueType::Specific) {} + static BytePattern Any() { return BytePattern(ValueType::Any); } + static BytePattern None() { return BytePattern(ValueType::None); } + bool isAny() const { return Type == ValueType::Any; } + bool isNone() const { return Type == ValueType::None; } + bool isValued() const { return Type == ValueType::Specific; } + uint8_t getValue() const { + assert(isValued()); + return Val; + } + BytePattern merge(const BytePattern Other) const { + if (isNone() || Other.isNone()) + return None(); + if (isAny()) + return Other; + if (Other.isAny()) + return *this; + if (getValue() == Other.getValue()) + return *this; + return None(); + } +}; + +/// Figures out whether the constant can be initialized with memset. +static BytePattern constantIsRepeatedBytePattern(llvm::Constant *C) { + if (isa(C) || isa(C)) + return BytePattern(0x00); + if (isa(C)) + return BytePattern::Any(); + + if (isa(C)) { + auto *Int = cast(C); + if (Int->getBitWidth() % 8 != 0) + return BytePattern::None(); + const llvm::APInt &Value = Int->getValue(); + if (Value.isSplat(8)) + return BytePattern(Value.getLoBits(8).getLimitedValue()); + return BytePattern::None(); + } + + if (isa(C)) { + auto *FP = cast(C); + llvm::APInt Bits = FP->getValueAPF().bitcastToAPInt(); + if (Bits.getBitWidth() % 8 != 0) + return BytePattern::None(); + if (!Bits.isSplat(8)) + return BytePattern::None(); + return BytePattern(Bits.getLimitedValue() & 0xFF); + } + + if (isa(C)) { + llvm::Constant *Splat = cast(C)->getSplatValue(); + if (Splat) + return constantIsRepeatedBytePattern(Splat); + return BytePattern::None(); + } + + if (isa(C) || isa(C)) { + BytePattern Pattern(BytePattern::Any()); + for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) { + llvm::Constant *Elt = cast(C->getOperand(I)); + Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt)); + if (Pattern.isNone()) + return Pattern; + } + return Pattern; + } + + if (llvm::ConstantDataSequential *CDS = + dyn_cast(C)) { + BytePattern Pattern(BytePattern::Any()); + for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) { + llvm::Constant *Elt = CDS->getElementAsConstant(I); + Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt)); + if (Pattern.isNone()) + return Pattern; + } + return Pattern; + } + + // BlockAddress, ConstantExpr, and everything else is scary. + return BytePattern::None(); +} + +/// Decide whether we should use memset to initialize a local variable instead +/// of using a memcpy from a constant global. Assumes we've already decided to +/// not user bzero. +/// FIXME We could be more clever, as we are for bzero above, and generate +/// memset followed by stores. It's unclear that's worth the effort. +static BytePattern shouldUseMemSetToInitialize(llvm::Constant *Init, + uint64_t GlobalSize) { + uint64_t SizeLimit = 32; + if (GlobalSize <= SizeLimit) + return BytePattern::None(); + return constantIsRepeatedBytePattern(Init); +} + /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects, or GlobalValues depending on target. @@ -1401,11 +1508,11 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { if (Loc.getType() != BP) Loc = Builder.CreateBitCast(Loc, BP); - // If the initializer is all or mostly zeros, codegen with bzero then do a - // few stores afterward. - if (shouldUseBZeroPlusStoresToInitialize( - constant, - CGM.getDataLayout().getTypeAllocSize(constant->getType()))) { + // If the initializer is all or mostly the same, codegen with bzero / memset + // then do a few stores afterward. + uint64_t ConstantSize = + CGM.getDataLayout().getTypeAllocSize(constant->getType()); + if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) { Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, isVolatile); // Zero and undef don't require a stores. @@ -1414,28 +1521,36 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { constant->getType()->getPointerTo(Loc.getAddressSpace())); emitStoresForInitAfterBZero(CGM, constant, Loc, isVolatile, Builder); } - } else { - // Otherwise, create a temporary global with the initializer then - // memcpy from the global to the alloca. - std::string Name = getStaticDeclName(CGM, D); - unsigned AS = CGM.getContext().getTargetAddressSpace( - CGM.getStringLiteralAddressSpace()); - BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS); - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true, - llvm::GlobalValue::PrivateLinkage, - constant, Name, nullptr, - llvm::GlobalValue::NotThreadLocal, AS); - GV->setAlignment(Loc.getAlignment().getQuantity()); - GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - Address SrcPtr = Address(GV, Loc.getAlignment()); - if (SrcPtr.getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP); - - Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile); + return; + } + + BytePattern Pattern = shouldUseMemSetToInitialize(constant, ConstantSize); + if (!Pattern.isNone()) { + uint8_t Value = Pattern.isAny() ? 0x00 : Pattern.getValue(); + Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal, + isVolatile); + return; } + + // Otherwise, create a temporary global with the initializer then + // memcpy from the global to the alloca. + std::string Name = getStaticDeclName(CGM, D); + unsigned AS = CGM.getContext().getTargetAddressSpace( + CGM.getStringLiteralAddressSpace()); + BP = llvm::PointerType::getInt8PtrTy(getLLVMContext(), AS); + + llvm::GlobalVariable *GV = new llvm::GlobalVariable( + CGM.getModule(), constant->getType(), true, + llvm::GlobalValue::PrivateLinkage, constant, Name, nullptr, + llvm::GlobalValue::NotThreadLocal, AS); + GV->setAlignment(Loc.getAlignment().getQuantity()); + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + + Address SrcPtr = Address(GV, Loc.getAlignment()); + if (SrcPtr.getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP); + + Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile); } /// Emit an expression as an initializer for an object (variable, field, etc.) diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index 0353ba8be1..71aba39b12 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -140,6 +140,72 @@ void test10(int X) { // CHECK: call void @bar } +void nonzeroMemseti8() { + char arr[33] = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, }; + // CHECK-LABEL: @nonzeroMemseti8( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 42, i32 33, i1 false) +} + +void nonzeroMemseti16() { + unsigned short arr[17] = { 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, 0x4242, }; + // CHECK-LABEL: @nonzeroMemseti16( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 66, i32 34, i1 false) +} + +void nonzeroMemseti32() { + unsigned arr[9] = { 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, }; + // CHECK-LABEL: @nonzeroMemseti32( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 36, i1 false) +} + +void nonzeroMemseti64() { + unsigned long long arr[7] = { 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA, }; + // CHECK-LABEL: @nonzeroMemseti64( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -86, i32 56, i1 false) +} + +void nonzeroMemsetf32() { + float arr[9] = { 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, 0x1.cacacap+75, }; + // CHECK-LABEL: @nonzeroMemsetf32( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 101, i32 36, i1 false) +} + +void nonzeroMemsetf64() { + double arr[7] = { 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, 0x1.4444444444444p+69, }; + // CHECK-LABEL: @nonzeroMemsetf64( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 68, i32 56, i1 false) +} + +void nonzeroPaddedUnionMemset() { + union U { char c; int i; }; + union U arr[9] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, }; + // CHECK-LABEL: @nonzeroPaddedUnionMemset( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 36, i1 false) +} + +void nonzeroNestedMemset() { + union U { char c; int i; }; + struct S { union U u; short i; }; + struct S arr[5] = { { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, }; + // CHECK-LABEL: @nonzeroNestedMemset( + // CHECK-NOT: store + // CHECK-NOT: memcpy + // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 40, i1 false) +} // PR9257 struct test11S { -- GitLab From 1231be927ba509ec8e1a31f9322529748daebf94 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 25 Jul 2018 06:57:31 +0000 Subject: [PATCH 0707/1023] cc1_main: fix -Wsign-compare on FreeBSD Its __rlim_t is intentionally signed (__int64_t) because of legacy code that uses -1 for RLIM_INFINITY. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337892 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/driver/cc1_main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 952b1c1c0d..ef5a191bda 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -140,9 +140,11 @@ static void ensureSufficientStack() { // Increase the soft stack limit to our desired level, if necessary and // possible. - if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < DesiredStackSize) { + if (rlim.rlim_cur != RLIM_INFINITY && + rlim.rlim_cur < rlim_t(DesiredStackSize)) { // Try to allocate sufficient stack. - if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= DesiredStackSize) + if (rlim.rlim_max == RLIM_INFINITY || + rlim.rlim_max >= rlim_t(DesiredStackSize)) rlim.rlim_cur = DesiredStackSize; else if (rlim.rlim_cur == rlim.rlim_max) return; -- GitLab From 8a22542dc4f61b97b63bd5b53c0f9fbef656c3df Mon Sep 17 00:00:00 2001 From: Balazs Keri <1.int32@gmail.com> Date: Wed, 25 Jul 2018 10:21:06 +0000 Subject: [PATCH 0708/1023] [ASTImporter] Add support for import of CXXInheritedCtorInitExpr. Reviewers: a.sidorin, martong Reviewed By: martong Subscribers: rnkovacs, a_sidorin, martong, cfe-commits Differential Revision: https://reviews.llvm.org/D49293 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337898 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 17 +++++++++++++++++ .../inherited-ctor-init-expr/Inputs/A.cpp | 11 +++++++++++ test/Import/inherited-ctor-init-expr/test.cpp | 6 ++++++ 3 files changed, 34 insertions(+) create mode 100644 test/Import/inherited-ctor-init-expr/Inputs/A.cpp create mode 100644 test/Import/inherited-ctor-init-expr/test.cpp diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 0632da9c7f..6668067233 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -460,6 +460,7 @@ namespace clang { Expr *VisitLambdaExpr(LambdaExpr *LE); Expr *VisitInitListExpr(InitListExpr *E); Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); + Expr *VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E); Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); @@ -6772,6 +6773,22 @@ Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr( return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE); } +Expr *ASTNodeImporter::VisitCXXInheritedCtorInitExpr( + CXXInheritedCtorInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + auto *Ctor = cast_or_null(Importer.Import( + E->getConstructor())); + if (!Ctor) + return nullptr; + + return new (Importer.getToContext()) CXXInheritedCtorInitExpr( + Importer.Import(E->getLocation()), T, Ctor, + E->constructsVBase(), E->inheritedFromVBase()); +} + Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { QualType ToType = Importer.Import(E->getType()); if (ToType.isNull()) diff --git a/test/Import/inherited-ctor-init-expr/Inputs/A.cpp b/test/Import/inherited-ctor-init-expr/Inputs/A.cpp new file mode 100644 index 0000000000..2713433324 --- /dev/null +++ b/test/Import/inherited-ctor-init-expr/Inputs/A.cpp @@ -0,0 +1,11 @@ +class A { +public: + A(int a) : a(a) {} + int a; +}; +class B : public A { + using A::A; +}; +class C : public B { + C() : B(1) {} +}; diff --git a/test/Import/inherited-ctor-init-expr/test.cpp b/test/Import/inherited-ctor-init-expr/test.cpp new file mode 100644 index 0000000000..9e15e382ed --- /dev/null +++ b/test/Import/inherited-ctor-init-expr/test.cpp @@ -0,0 +1,6 @@ +// RUN: clang-import-test -dump-ast -expression=%s -import=%S/Inputs/A.cpp | FileCheck %s +// CHECK: | | | `-CXXInheritedCtorInitExpr + +void foo() { + C c; +} -- GitLab From df5b22a11e54e1f95eb943fc9906c69fdc8dce54 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 25 Jul 2018 10:21:47 +0000 Subject: [PATCH 0709/1023] [clang-format ]Extend IncludeCategories regex documentation Summary: Extend the Clang-Format IncludeCategories documentation by adding a link to the supported regular expression standard (POSIX). And extenting the example with a system header regex. [[ https://bugs.llvm.org/show_bug.cgi?id=35041 | bug 35041]] Contributed by WimLeflere! Reviewers: krasimir, Typz Reviewed By: krasimir Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48827 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337899 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ClangFormatStyleOptions.rst | 6 ++++++ docs/tools/dump_format_style.py | 4 +++- include/clang/Format/Format.h | 2 +- include/clang/Tooling/Inclusions/IncludeStyle.h | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index b6281ecae7..e4892d79b9 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -1280,6 +1280,10 @@ the configuration (without a prefix: ``Auto``). Regular expressions denoting the different ``#include`` categories used for ordering ``#includes``. + `POSIX extended + `_ + regular expressions are supported. + These regular expressions are matched against the filename of an include (including the <> or "") in order. The value belonging to the first matching regular expression is assigned and ``#includes`` are sorted first @@ -1302,6 +1306,8 @@ the configuration (without a prefix: ``Auto``). Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 + - Regex: '<[[:alnum:].]+>' + Priority: 4 - Regex: '.*' Priority: 1 diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py index 1ca050e062..3d61227f73 100755 --- a/docs/tools/dump_format_style.py +++ b/docs/tools/dump_format_style.py @@ -10,6 +10,7 @@ import urllib2 CLANG_DIR = os.path.join(os.path.dirname(__file__), '../..') FORMAT_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Format/Format.h') +INCLUDE_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Tooling/Inclusions/IncludeStyle.h') DOC_FILE = os.path.join(CLANG_DIR, 'docs/ClangFormatStyleOptions.rst') @@ -115,7 +116,7 @@ def read_options(header): for line in header: line = line.strip() if state == State.BeforeStruct: - if line == 'struct FormatStyle {': + if line == 'struct FormatStyle {' or line == 'struct IncludeStyle {': state = State.InStruct elif state == State.InStruct: if line.startswith('///'): @@ -188,6 +189,7 @@ def read_options(header): return options options = read_options(open(FORMAT_STYLE_FILE)) +options += read_options(open(INCLUDE_STYLE_FILE)) options = sorted(options, key=lambda x: x.name) options_text = '\n\n'.join(map(str, options)) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 36616e556a..85dda948c1 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -1296,7 +1296,7 @@ struct FormatStyle { /// If ``Never``, lays out Objective-C protocol conformance list items /// onto individual lines whenever they go over ``ColumnLimit``. /// - /// \code + /// \code{.objc} /// Always (or Auto, if BinPackParameters=true): /// @interface ccccccccccccc () < /// ccccccccccccc, ccccccccccccc, diff --git a/include/clang/Tooling/Inclusions/IncludeStyle.h b/include/clang/Tooling/Inclusions/IncludeStyle.h index 42d6e1a5cf..a093dff277 100644 --- a/include/clang/Tooling/Inclusions/IncludeStyle.h +++ b/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -67,6 +67,10 @@ struct IncludeStyle { /// Regular expressions denoting the different ``#include`` categories /// used for ordering ``#includes``. /// + /// `POSIX extended + /// `_ + /// regular expressions are supported. + /// /// These regular expressions are matched against the filename of an include /// (including the <> or "") in order. The value belonging to the first /// matching regular expression is assigned and ``#includes`` are sorted first @@ -87,6 +91,8 @@ struct IncludeStyle { /// Priority: 2 /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' /// Priority: 3 + /// - Regex: '<[[:alnum:].]+>' + /// Priority: 4 /// - Regex: '.*' /// Priority: 1 /// \endcode -- GitLab From 5f3a8d4376e1ed065532d9b70733ee7fc775119a Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:07 +0000 Subject: [PATCH 0710/1023] [analyzer] Create generic SMT Context class Summary: This patch creates `SMTContext` which will wrap a specific SMT context, through `SMTSolverContext`. The templated `SMTSolverContext` class it's a simple wrapper around a SMT specific context (currently only used in the Z3 backend), while `Z3Context` inherits `SMTSolverContext` and implements solver specific operations like initialization and destruction of the context. This separation was done because: 1. We might want to keep one single context, shared across different `SMTConstraintManager`s. It can be achieved by constructing a `SMTContext`, through a function like `CreateSMTContext(Z3)`, `CreateSMTContext(BOOLECTOR)`, etc. The rest of the CSA only need to know about `SMTContext`, so maybe it's a good idea moving `SMTSolverContext` to a separate header in the future. 2. Any generic SMT operation will only require one `SMTSolverContext`object, which can access the specific context by calling `getContext()`. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49233 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337914 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTContext.h | 30 +++++++++++++++++++ .../Core/Z3ConstraintManager.cpp | 16 ++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h new file mode 100644 index 0000000000..01aa1c8b6d --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h @@ -0,0 +1,30 @@ +//== SMTContext.h -----------------------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a SMT generic Context API, which will be the base class +// for every SMT solver context specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H + +namespace clang { +namespace ento { + +class SMTContext { +public: + SMTContext() = default; + virtual ~SMTContext() = default; +}; + +} // namespace ento +} // namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 66a6cf5bad..c124159cd0 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -11,6 +11,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h" #include "clang/Config/config.h" @@ -63,19 +64,22 @@ public: ~Z3Config() { Z3_del_config(Config); } }; // end class Z3Config -class Z3Context { - Z3_context ZC_P; - +class Z3Context : public SMTContext { public: static Z3_context ZC; - Z3Context() : ZC_P(Z3_mk_context_rc(Z3Config().Config)) { ZC = ZC_P; } + Z3Context() : SMTContext() { + Context = Z3_mk_context_rc(Z3Config().Config); + ZC = Context; + } ~Z3Context() { Z3_del_context(ZC); - Z3_finalize_memory(); - ZC_P = nullptr; + Context = nullptr; } + +protected: + Z3_context Context; }; // end class Z3Context class Z3Sort { -- GitLab From 7fffe4ec18d0b966fd56acc44a26e1e86fd705d6 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:11 +0000 Subject: [PATCH 0711/1023] [analyzer] Moved static Context to class member Summary: Although it is a big patch, the changes are simple: 1. There is one `Z3_Context` now, member of the `SMTConstraintManager` class. 2. `Z3Expr`, `Z3Sort`, `Z3Model` and `Z3Solver` are constructed with a reference to the `Z3_Context` in `SMTConstraintManager`. 3. All static functions are now members of `Z3Solver`, e.g, the `SMTConstraintManager` now calls `Solver.fromBoolean(false)` instead of `Z3Expr::fromBoolean(false)`. Most of the patch only move stuff around except: 1. New method `Z3Sort MkSort(const QualType &Ty, unsigned BitWidth)`, that creates a sort based on the `QualType` and its width. Used to simplify the `fromData` method. Unfortunate consequence of this patch: 1. `getInterpretation` was moved from `Z3Model` class to `Z3Solver`, because it needs to create a `Z3Sort` before returning the interpretation. This can be fixed by changing both `toAPFloat` and `toAPSInt` by removing the dependency of `Z3Sort` (it's only used to check which Sort was created and to retrieve the type width). Reviewers: NoQ, george.karpenkov, ddcc Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49236 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337915 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/Z3ConstraintManager.cpp | 921 +++++++++--------- 1 file changed, 471 insertions(+), 450 deletions(-) diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index c124159cd0..70b7c467cf 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -64,48 +64,55 @@ public: ~Z3Config() { Z3_del_config(Config); } }; // end class Z3Config +void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) { + llvm::report_fatal_error("Z3 error: " + + llvm::Twine(Z3_get_error_msg_ex(Context, Error))); +} + class Z3Context : public SMTContext { public: - static Z3_context ZC; + Z3_context Context; Z3Context() : SMTContext() { Context = Z3_mk_context_rc(Z3Config().Config); - ZC = Context; + Z3_set_error_handler(Context, Z3ErrorHandler); } - ~Z3Context() { - Z3_del_context(ZC); + virtual ~Z3Context() { + Z3_del_context(Context); Context = nullptr; } - -protected: - Z3_context Context; }; // end class Z3Context class Z3Sort { friend class Z3Expr; + friend class Z3Solver; + + Z3Context &Context; Z3_sort Sort; - Z3Sort() : Sort(nullptr) {} - Z3Sort(Z3_sort ZS) : Sort(ZS) { - Z3_inc_ref(Z3Context::ZC, reinterpret_cast(Sort)); + Z3Sort(Z3Context &C, Z3_sort ZS) : Context(C), Sort(ZS) { + assert(C.Context != nullptr); + Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } public: /// Override implicit copy constructor for correct reference counting. - Z3Sort(const Z3Sort &Copy) : Sort(Copy.Sort) { - Z3_inc_ref(Z3Context::ZC, reinterpret_cast(Sort)); + Z3Sort(const Z3Sort &Copy) : Context(Copy.Context), Sort(Copy.Sort) { + Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } /// Provide move constructor - Z3Sort(Z3Sort &&Move) : Sort(nullptr) { *this = std::move(Move); } + Z3Sort(Z3Sort &&Move) : Context(Move.Context), Sort(nullptr) { + *this = std::move(Move); + } /// Provide move assignment constructor Z3Sort &operator=(Z3Sort &&Move) { if (this != &Move) { if (Sort) - Z3_dec_ref(Z3Context::ZC, reinterpret_cast(Sort)); + Z3_dec_ref(Context.Context, reinterpret_cast(Sort)); Sort = Move.Sort; Move.Sort = nullptr; } @@ -114,75 +121,38 @@ public: ~Z3Sort() { if (Sort) - Z3_dec_ref(Z3Context::ZC, reinterpret_cast(Sort)); - } - - // Return a boolean sort. - static Z3Sort getBoolSort() { return Z3Sort(Z3_mk_bool_sort(Z3Context::ZC)); } - - // Return an appropriate bitvector sort for the given bitwidth. - static Z3Sort getBitvectorSort(unsigned BitWidth) { - return Z3Sort(Z3_mk_bv_sort(Z3Context::ZC, BitWidth)); - } - - // Return an appropriate floating-point sort for the given bitwidth. - static Z3Sort getFloatSort(unsigned BitWidth) { - Z3_sort Sort; - - switch (BitWidth) { - default: - llvm_unreachable("Unsupported floating-point bitwidth!"); - break; - case 16: - Sort = Z3_mk_fpa_sort_16(Z3Context::ZC); - break; - case 32: - Sort = Z3_mk_fpa_sort_32(Z3Context::ZC); - break; - case 64: - Sort = Z3_mk_fpa_sort_64(Z3Context::ZC); - break; - case 128: - Sort = Z3_mk_fpa_sort_128(Z3Context::ZC); - break; - } - return Z3Sort(Sort); - } - - // Return an appropriate sort for the given AST. - static Z3Sort getSort(Z3_ast AST) { - return Z3Sort(Z3_get_sort(Z3Context::ZC, AST)); + Z3_dec_ref(Context.Context, reinterpret_cast(Sort)); } Z3_sort_kind getSortKind() const { - return Z3_get_sort_kind(Z3Context::ZC, Sort); + return Z3_get_sort_kind(Context.Context, Sort); } unsigned getBitvectorSortSize() const { assert(getSortKind() == Z3_BV_SORT && "Not a bitvector sort!"); - return Z3_get_bv_sort_size(Z3Context::ZC, Sort); + return Z3_get_bv_sort_size(Context.Context, Sort); } unsigned getFloatSortSize() const { assert(getSortKind() == Z3_FLOATING_POINT_SORT && "Not a floating-point sort!"); - return Z3_fpa_get_ebits(Z3Context::ZC, Sort) + - Z3_fpa_get_sbits(Z3Context::ZC, Sort); + return Z3_fpa_get_ebits(Context.Context, Sort) + + Z3_fpa_get_sbits(Context.Context, Sort); } bool operator==(const Z3Sort &Other) const { - return Z3_is_eq_sort(Z3Context::ZC, Sort, Other.Sort); + return Z3_is_eq_sort(Context.Context, Sort, Other.Sort); } Z3Sort &operator=(const Z3Sort &Move) { - Z3_inc_ref(Z3Context::ZC, reinterpret_cast(Move.Sort)); - Z3_dec_ref(Z3Context::ZC, reinterpret_cast(Sort)); + Z3_inc_ref(Context.Context, reinterpret_cast(Move.Sort)); + Z3_dec_ref(Context.Context, reinterpret_cast(Sort)); Sort = Move.Sort; return *this; } void print(raw_ostream &OS) const { - OS << Z3_sort_to_string(Z3Context::ZC, Sort); + OS << Z3_sort_to_string(Context.Context, Sort); } LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } @@ -192,14 +162,13 @@ class Z3Expr { friend class Z3Model; friend class Z3Solver; - Z3_ast AST; + Z3Context &Context; - Z3Expr(Z3_ast ZA) : AST(ZA) { Z3_inc_ref(Z3Context::ZC, AST); } + Z3_ast AST; - // Return an appropriate floating-point rounding mode. - static Z3Expr getFloatRoundingMode() { - // TODO: Don't assume nearest ties to even rounding mode - return Z3Expr(Z3_mk_fpa_rne(Z3Context::ZC)); + Z3Expr(Z3Context &C, Z3_ast ZA) : Context(C), AST(ZA) { + assert(C.Context != nullptr); + Z3_inc_ref(Context.Context, AST); } // Determine whether two float semantics are equivalent @@ -217,16 +186,20 @@ class Z3Expr { public: /// Override implicit copy constructor for correct reference counting. - Z3Expr(const Z3Expr &Copy) : AST(Copy.AST) { Z3_inc_ref(Z3Context::ZC, AST); } + Z3Expr(const Z3Expr &Copy) : Context(Copy.Context), AST(Copy.AST) { + Z3_inc_ref(Context.Context, AST); + } /// Provide move constructor - Z3Expr(Z3Expr &&Move) : AST(nullptr) { *this = std::move(Move); } + Z3Expr(Z3Expr &&Move) : Context(Move.Context), AST(nullptr) { + *this = std::move(Move); + } /// Provide move assignment constructor Z3Expr &operator=(Z3Expr &&Move) { if (this != &Move) { if (AST) - Z3_dec_ref(Z3Context::ZC, AST); + Z3_dec_ref(Context.Context, AST); AST = Move.AST; Move.AST = nullptr; } @@ -235,7 +208,7 @@ public: ~Z3Expr() { if (AST) - Z3_dec_ref(Z3Context::ZC, AST); + Z3_dec_ref(Context.Context, AST); } /// Get the corresponding IEEE floating-point type for a given bitwidth. @@ -255,8 +228,206 @@ public: } } + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Z3_get_ast_hash(Context.Context, AST)); + } + + bool operator<(const Z3Expr &Other) const { + llvm::FoldingSetNodeID ID1, ID2; + Profile(ID1); + Other.Profile(ID2); + return ID1 < ID2; + } + + /// Comparison of AST equality, not model equivalence. + bool operator==(const Z3Expr &Other) const { + assert(Z3_is_eq_sort(Context.Context, Z3_get_sort(Context.Context, AST), + Z3_get_sort(Context.Context, Other.AST)) && + "AST's must have the same sort"); + return Z3_is_eq_ast(Context.Context, AST, Other.AST); + } + + /// Override implicit move constructor for correct reference counting. + Z3Expr &operator=(const Z3Expr &Move) { + Z3_inc_ref(Context.Context, Move.AST); + Z3_dec_ref(Context.Context, AST); + AST = Move.AST; + return *this; + } + + void print(raw_ostream &OS) const { + OS << Z3_ast_to_string(Context.Context, AST); + } + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } +}; // end class Z3Expr + +class Z3Model { + friend class Z3Solver; + + Z3Context &Context; + + Z3_model Model; + +public: + Z3Model(Z3Context &C, Z3_model ZM) : Context(C), Model(ZM) { + assert(C.Context != nullptr); + Z3_model_inc_ref(Context.Context, Model); + } + + /// Override implicit copy constructor for correct reference counting. + Z3Model(const Z3Model &Copy) : Context(Copy.Context), Model(Copy.Model) { + Z3_model_inc_ref(Context.Context, Model); + } + + /// Provide move constructor + Z3Model(Z3Model &&Move) : Context(Move.Context), Model(nullptr) { + *this = std::move(Move); + } + + /// Provide move assignment constructor + Z3Model &operator=(Z3Model &&Move) { + if (this != &Move) { + if (Model) + Z3_model_dec_ref(Context.Context, Model); + Model = Move.Model; + Move.Model = nullptr; + } + return *this; + } + + ~Z3Model() { + if (Model) + Z3_model_dec_ref(Context.Context, Model); + } + + void print(raw_ostream &OS) const { + OS << Z3_model_to_string(Context.Context, Model); + } + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } +}; // end class Z3Model + +class Z3Solver { + friend class Z3ConstraintManager; + + Z3Context Context; + + Z3_solver Solver; + + Z3Solver() : Solver(Z3_mk_simple_solver(Context.Context)) { + Z3_solver_inc_ref(Context.Context, Solver); + } + +public: + /// Override implicit copy constructor for correct reference counting. + Z3Solver(const Z3Solver &Copy) : Context(Copy.Context), Solver(Copy.Solver) { + Z3_solver_inc_ref(Context.Context, Solver); + } + + /// Provide move constructor + Z3Solver(Z3Solver &&Move) : Context(Move.Context), Solver(nullptr) { + *this = std::move(Move); + } + + /// Provide move assignment constructor + Z3Solver &operator=(Z3Solver &&Move) { + if (this != &Move) { + if (Solver) + Z3_solver_dec_ref(Context.Context, Solver); + Solver = Move.Solver; + Move.Solver = nullptr; + } + return *this; + } + + ~Z3Solver() { + if (Solver) + Z3_solver_dec_ref(Context.Context, Solver); + } + + /// Given a constraint, add it to the solver + void addConstraint(const Z3Expr &Exp) { + Z3_solver_assert(Context.Context, Solver, Exp.AST); + } + + // Return a boolean sort. + Z3Sort getBoolSort() { + return Z3Sort(Context, Z3_mk_bool_sort(Context.Context)); + } + + // Return an appropriate bitvector sort for the given bitwidth. + Z3Sort getBitvectorSort(unsigned BitWidth) { + return Z3Sort(Context, Z3_mk_bv_sort(Context.Context, BitWidth)); + } + + // Return an appropriate floating-point sort for the given bitwidth. + Z3Sort getFloatSort(unsigned BitWidth) { + Z3_sort Sort; + + switch (BitWidth) { + default: + llvm_unreachable("Unsupported floating-point bitwidth!"); + break; + case 16: + Sort = Z3_mk_fpa_sort_16(Context.Context); + break; + case 32: + Sort = Z3_mk_fpa_sort_32(Context.Context); + break; + case 64: + Sort = Z3_mk_fpa_sort_64(Context.Context); + break; + case 128: + Sort = Z3_mk_fpa_sort_128(Context.Context); + break; + } + return Z3Sort(Context, Sort); + } + + // Return an appropriate sort, given a QualType + Z3Sort MkSort(const QualType &Ty, unsigned BitWidth) { + if (Ty->isBooleanType()) + return getBoolSort(); + + if (Ty->isRealFloatingType()) + return getFloatSort(BitWidth); + + return getBitvectorSort(BitWidth); + } + + // Return an appropriate sort for the given AST. + Z3Sort getSort(Z3_ast AST) { + return Z3Sort(Context, Z3_get_sort(Context.Context, AST)); + } + + /// Given a program state, construct the logical conjunction and add it to + /// the solver + void addStateConstraints(ProgramStateRef State) { + // TODO: Don't add all the constraints, only the relevant ones + ConstraintZ3Ty CZ = State->get(); + ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); + + // Construct the logical AND of all the constraints + if (I != IE) { + std::vector ASTs; + + while (I != IE) + ASTs.push_back(I++->second.AST); + + Z3Expr Conj = fromNBinOp(BO_LAnd, ASTs); + addConstraint(Conj); + } + } + + // Return an appropriate floating-point rounding mode. + Z3Expr getFloatRoundingMode() { + // TODO: Don't assume nearest ties to even rounding mode + return Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)); + } + /// Construct a Z3Expr from a unary operator, given a Z3_context. - static Z3Expr fromUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) { + Z3Expr fromUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) { Z3_ast AST; switch (Op) { @@ -265,25 +436,24 @@ public: break; case UO_Minus: - AST = Z3_mk_bvneg(Z3Context::ZC, Exp.AST); + AST = Z3_mk_bvneg(Context.Context, Exp.AST); break; case UO_Not: - AST = Z3_mk_bvnot(Z3Context::ZC, Exp.AST); + AST = Z3_mk_bvnot(Context.Context, Exp.AST); break; case UO_LNot: - AST = Z3_mk_not(Z3Context::ZC, Exp.AST); + AST = Z3_mk_not(Context.Context, Exp.AST); break; } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a floating-point unary operator, given a /// Z3_context. - static Z3Expr fromFloatUnOp(const UnaryOperator::Opcode Op, - const Z3Expr &Exp) { + Z3Expr fromFloatUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) { Z3_ast AST; switch (Op) { @@ -292,19 +462,19 @@ public: break; case UO_Minus: - AST = Z3_mk_fpa_neg(Z3Context::ZC, Exp.AST); + AST = Z3_mk_fpa_neg(Context.Context, Exp.AST); break; case UO_LNot: - return Z3Expr::fromUnOp(Op, Exp); + return fromUnOp(Op, Exp); } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a n-ary binary operator. - static Z3Expr fromNBinOp(const BinaryOperator::Opcode Op, - const std::vector &ASTs) { + Z3Expr fromNBinOp(const BinaryOperator::Opcode Op, + const std::vector &ASTs) { Z3_ast AST; switch (Op) { @@ -313,23 +483,23 @@ public: break; case BO_LAnd: - AST = Z3_mk_and(Z3Context::ZC, ASTs.size(), ASTs.data()); + AST = Z3_mk_and(Context.Context, ASTs.size(), ASTs.data()); break; case BO_LOr: - AST = Z3_mk_or(Z3Context::ZC, ASTs.size(), ASTs.data()); + AST = Z3_mk_or(Context.Context, ASTs.size(), ASTs.data()); break; } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a binary operator, given a Z3_context. - static Z3Expr fromBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op, - const Z3Expr &RHS, bool isSigned) { + Z3Expr fromBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op, + const Z3Expr &RHS, bool isSigned) { Z3_ast AST; - assert(Z3Sort::getSort(LHS.AST) == Z3Sort::getSort(RHS.AST) && + assert(getSort(LHS.AST) == getSort(RHS.AST) && "AST's must have the same sort!"); switch (Op) { @@ -337,90 +507,89 @@ public: llvm_unreachable("Unimplemented opcode"); break; - // Multiplicative operators + // Multiplicative operators case BO_Mul: - AST = Z3_mk_bvmul(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvmul(Context.Context, LHS.AST, RHS.AST); break; case BO_Div: - AST = isSigned ? Z3_mk_bvsdiv(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvudiv(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvsdiv(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvudiv(Context.Context, LHS.AST, RHS.AST); break; case BO_Rem: - AST = isSigned ? Z3_mk_bvsrem(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvurem(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvsrem(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvurem(Context.Context, LHS.AST, RHS.AST); break; - // Additive operators + // Additive operators case BO_Add: - AST = Z3_mk_bvadd(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvadd(Context.Context, LHS.AST, RHS.AST); break; case BO_Sub: - AST = Z3_mk_bvsub(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvsub(Context.Context, LHS.AST, RHS.AST); break; - // Bitwise shift operators + // Bitwise shift operators case BO_Shl: - AST = Z3_mk_bvshl(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvshl(Context.Context, LHS.AST, RHS.AST); break; case BO_Shr: - AST = isSigned ? Z3_mk_bvashr(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvlshr(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvashr(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvlshr(Context.Context, LHS.AST, RHS.AST); break; - // Relational operators + // Relational operators case BO_LT: - AST = isSigned ? Z3_mk_bvslt(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvult(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvslt(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvult(Context.Context, LHS.AST, RHS.AST); break; case BO_GT: - AST = isSigned ? Z3_mk_bvsgt(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvugt(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvsgt(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvugt(Context.Context, LHS.AST, RHS.AST); break; case BO_LE: - AST = isSigned ? Z3_mk_bvsle(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvule(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvsle(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvule(Context.Context, LHS.AST, RHS.AST); break; case BO_GE: - AST = isSigned ? Z3_mk_bvsge(Z3Context::ZC, LHS.AST, RHS.AST) - : Z3_mk_bvuge(Z3Context::ZC, LHS.AST, RHS.AST); + AST = isSigned ? Z3_mk_bvsge(Context.Context, LHS.AST, RHS.AST) + : Z3_mk_bvuge(Context.Context, LHS.AST, RHS.AST); break; - // Equality operators + // Equality operators case BO_EQ: - AST = Z3_mk_eq(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_eq(Context.Context, LHS.AST, RHS.AST); break; case BO_NE: - return Z3Expr::fromUnOp(UO_LNot, - Z3Expr::fromBinOp(LHS, BO_EQ, RHS, isSigned)); + return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned)); break; - // Bitwise operators + // Bitwise operators case BO_And: - AST = Z3_mk_bvand(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvand(Context.Context, LHS.AST, RHS.AST); break; case BO_Xor: - AST = Z3_mk_bvxor(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvxor(Context.Context, LHS.AST, RHS.AST); break; case BO_Or: - AST = Z3_mk_bvor(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_bvor(Context.Context, LHS.AST, RHS.AST); break; - // Logical operators + // Logical operators case BO_LAnd: case BO_LOr: { std::vector Args = {LHS.AST, RHS.AST}; - return Z3Expr::fromNBinOp(Op, Args); + return fromNBinOp(Op, Args); } } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a special floating-point binary operator, given /// a Z3_context. - static Z3Expr fromFloatSpecialBinOp(const Z3Expr &LHS, - const BinaryOperator::Opcode Op, - const llvm::APFloat::fltCategory &RHS) { + Z3Expr fromFloatSpecialBinOp(const Z3Expr &LHS, + const BinaryOperator::Opcode Op, + const llvm::APFloat::fltCategory &RHS) { Z3_ast AST; switch (Op) { @@ -428,40 +597,38 @@ public: llvm_unreachable("Unimplemented opcode"); break; - // Equality operators + // Equality operators case BO_EQ: switch (RHS) { case llvm::APFloat::fcInfinity: - AST = Z3_mk_fpa_is_infinite(Z3Context::ZC, LHS.AST); + AST = Z3_mk_fpa_is_infinite(Context.Context, LHS.AST); break; case llvm::APFloat::fcNaN: - AST = Z3_mk_fpa_is_nan(Z3Context::ZC, LHS.AST); + AST = Z3_mk_fpa_is_nan(Context.Context, LHS.AST); break; case llvm::APFloat::fcNormal: - AST = Z3_mk_fpa_is_normal(Z3Context::ZC, LHS.AST); + AST = Z3_mk_fpa_is_normal(Context.Context, LHS.AST); break; case llvm::APFloat::fcZero: - AST = Z3_mk_fpa_is_zero(Z3Context::ZC, LHS.AST); + AST = Z3_mk_fpa_is_zero(Context.Context, LHS.AST); break; } break; case BO_NE: - return Z3Expr::fromFloatUnOp( - UO_LNot, Z3Expr::fromFloatSpecialBinOp(LHS, BO_EQ, RHS)); + return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS)); break; } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a floating-point binary operator, given a /// Z3_context. - static Z3Expr fromFloatBinOp(const Z3Expr &LHS, - const BinaryOperator::Opcode Op, - const Z3Expr &RHS) { + Z3Expr fromFloatBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op, + const Z3Expr &RHS) { Z3_ast AST; - assert(Z3Sort::getSort(LHS.AST) == Z3Sort::getSort(RHS.AST) && + assert(getSort(LHS.AST) == getSort(RHS.AST) && "AST's must have the same sort!"); switch (Op) { @@ -469,86 +636,78 @@ public: llvm_unreachable("Unimplemented opcode"); break; - // Multiplicative operators + // Multiplicative operators case BO_Mul: { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - AST = Z3_mk_fpa_mul(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST); + Z3Expr RoundingMode = getFloatRoundingMode(); + AST = Z3_mk_fpa_mul(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); break; } case BO_Div: { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - AST = Z3_mk_fpa_div(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST); + Z3Expr RoundingMode = getFloatRoundingMode(); + AST = Z3_mk_fpa_div(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); break; } case BO_Rem: - AST = Z3_mk_fpa_rem(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_rem(Context.Context, LHS.AST, RHS.AST); break; - // Additive operators + // Additive operators case BO_Add: { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - AST = Z3_mk_fpa_add(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST); + Z3Expr RoundingMode = getFloatRoundingMode(); + AST = Z3_mk_fpa_add(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); break; } case BO_Sub: { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - AST = Z3_mk_fpa_sub(Z3Context::ZC, RoundingMode.AST, LHS.AST, RHS.AST); + Z3Expr RoundingMode = getFloatRoundingMode(); + AST = Z3_mk_fpa_sub(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); break; } - // Relational operators + // Relational operators case BO_LT: - AST = Z3_mk_fpa_lt(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_lt(Context.Context, LHS.AST, RHS.AST); break; case BO_GT: - AST = Z3_mk_fpa_gt(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_gt(Context.Context, LHS.AST, RHS.AST); break; case BO_LE: - AST = Z3_mk_fpa_leq(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_leq(Context.Context, LHS.AST, RHS.AST); break; case BO_GE: - AST = Z3_mk_fpa_geq(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_geq(Context.Context, LHS.AST, RHS.AST); break; - // Equality operators + // Equality operators case BO_EQ: - AST = Z3_mk_fpa_eq(Z3Context::ZC, LHS.AST, RHS.AST); + AST = Z3_mk_fpa_eq(Context.Context, LHS.AST, RHS.AST); break; case BO_NE: - return Z3Expr::fromFloatUnOp(UO_LNot, - Z3Expr::fromFloatBinOp(LHS, BO_EQ, RHS)); + return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS)); break; - // Logical operators + // Logical operators case BO_LAnd: case BO_LOr: - return Z3Expr::fromBinOp(LHS, Op, RHS, false); + return fromBinOp(LHS, Op, RHS, false); } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a SymbolData, given a Z3_context. - static Z3Expr fromData(const SymbolID ID, bool isBool, bool isFloat, - uint64_t BitWidth) { + Z3Expr fromData(const SymbolID ID, const QualType &Ty, uint64_t BitWidth) { llvm::Twine Name = "$" + llvm::Twine(ID); - Z3Sort Sort; - if (isBool) - Sort = Z3Sort::getBoolSort(); - else if (isFloat) - Sort = Z3Sort::getFloatSort(BitWidth); - else - Sort = Z3Sort::getBitvectorSort(BitWidth); + Z3Sort Sort = MkSort(Ty, BitWidth); - Z3_symbol Symbol = Z3_mk_string_symbol(Z3Context::ZC, Name.str().c_str()); - Z3_ast AST = Z3_mk_const(Z3Context::ZC, Symbol, Sort.Sort); - return Z3Expr(AST); + Z3_symbol Symbol = Z3_mk_string_symbol(Context.Context, Name.str().c_str()); + Z3_ast AST = Z3_mk_const(Context.Context, Symbol, Sort.Sort); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a SymbolCast, given a Z3_context. - static Z3Expr fromCast(const Z3Expr &Exp, QualType ToTy, uint64_t ToBitWidth, - QualType FromTy, uint64_t FromBitWidth) { + Z3Expr fromCast(const Z3Expr &Exp, QualType ToTy, uint64_t ToBitWidth, + QualType FromTy, uint64_t FromBitWidth) { Z3_ast AST; if ((FromTy->isIntegralOrEnumerationType() && @@ -560,99 +719,99 @@ public: // must use if-then-else expression instead of direct cast if (FromTy->isBooleanType()) { assert(ToBitWidth > 0 && "BitWidth must be positive!"); - Z3Expr Zero = Z3Expr::fromInt("0", ToBitWidth); - Z3Expr One = Z3Expr::fromInt("1", ToBitWidth); - AST = Z3_mk_ite(Z3Context::ZC, Exp.AST, One.AST, Zero.AST); + Z3Expr Zero = fromInt("0", ToBitWidth); + Z3Expr One = fromInt("1", ToBitWidth); + AST = Z3_mk_ite(Context.Context, Exp.AST, One.AST, Zero.AST); } else if (ToBitWidth > FromBitWidth) { AST = FromTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_sign_ext(Z3Context::ZC, ToBitWidth - FromBitWidth, + ? Z3_mk_sign_ext(Context.Context, ToBitWidth - FromBitWidth, Exp.AST) - : Z3_mk_zero_ext(Z3Context::ZC, ToBitWidth - FromBitWidth, + : Z3_mk_zero_ext(Context.Context, ToBitWidth - FromBitWidth, Exp.AST); } else if (ToBitWidth < FromBitWidth) { - AST = Z3_mk_extract(Z3Context::ZC, ToBitWidth - 1, 0, Exp.AST); + AST = Z3_mk_extract(Context.Context, ToBitWidth - 1, 0, Exp.AST); } else { // Both are bitvectors with the same width, ignore the type cast return Exp; } } else if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) { if (ToBitWidth != FromBitWidth) { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - Z3Sort Sort = Z3Sort::getFloatSort(ToBitWidth); - AST = Z3_mk_fpa_to_fp_float(Z3Context::ZC, RoundingMode.AST, Exp.AST, + Z3Expr RoundingMode = getFloatRoundingMode(); + Z3Sort Sort = getFloatSort(ToBitWidth); + AST = Z3_mk_fpa_to_fp_float(Context.Context, RoundingMode.AST, Exp.AST, Sort.Sort); } else { return Exp; } } else if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); - Z3Sort Sort = Z3Sort::getFloatSort(ToBitWidth); + Z3Expr RoundingMode = getFloatRoundingMode(); + Z3Sort Sort = getFloatSort(ToBitWidth); AST = FromTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_fpa_to_fp_signed(Z3Context::ZC, RoundingMode.AST, + ? Z3_mk_fpa_to_fp_signed(Context.Context, RoundingMode.AST, Exp.AST, Sort.Sort) - : Z3_mk_fpa_to_fp_unsigned(Z3Context::ZC, RoundingMode.AST, + : Z3_mk_fpa_to_fp_unsigned(Context.Context, RoundingMode.AST, Exp.AST, Sort.Sort); } else if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType()) { - Z3Expr RoundingMode = Z3Expr::getFloatRoundingMode(); + Z3Expr RoundingMode = getFloatRoundingMode(); AST = ToTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_fpa_to_sbv(Z3Context::ZC, RoundingMode.AST, Exp.AST, + ? Z3_mk_fpa_to_sbv(Context.Context, RoundingMode.AST, Exp.AST, ToBitWidth) - : Z3_mk_fpa_to_ubv(Z3Context::ZC, RoundingMode.AST, Exp.AST, + : Z3_mk_fpa_to_ubv(Context.Context, RoundingMode.AST, Exp.AST, ToBitWidth); } else { llvm_unreachable("Unsupported explicit type cast!"); } - return Z3Expr(AST); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a boolean, given a Z3_context. - static Z3Expr fromBoolean(const bool Bool) { - Z3_ast AST = Bool ? Z3_mk_true(Z3Context::ZC) : Z3_mk_false(Z3Context::ZC); - return Z3Expr(AST); + Z3Expr fromBoolean(const bool Bool) { + Z3_ast AST = + Bool ? Z3_mk_true(Context.Context) : Z3_mk_false(Context.Context); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from a finite APFloat, given a Z3_context. - static Z3Expr fromAPFloat(const llvm::APFloat &Float) { + Z3Expr fromAPFloat(const llvm::APFloat &Float) { Z3_ast AST; - Z3Sort Sort = Z3Sort::getFloatSort( - llvm::APFloat::semanticsSizeInBits(Float.getSemantics())); - - llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), true); - Z3Expr Z3Int = Z3Expr::fromAPSInt(Int); - AST = Z3_mk_fpa_to_fp_bv(Z3Context::ZC, Z3Int.AST, Sort.Sort); + Z3Sort Sort = + getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics())); - return Z3Expr(AST); + llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false); + Z3Expr Z3Int = fromAPSInt(Int); + AST = Z3_mk_fpa_to_fp_bv(Context.Context, Z3Int.AST, Sort.Sort); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from an APSInt, given a Z3_context. - static Z3Expr fromAPSInt(const llvm::APSInt &Int) { - Z3Sort Sort = Z3Sort::getBitvectorSort(Int.getBitWidth()); + Z3Expr fromAPSInt(const llvm::APSInt &Int) { + Z3Sort Sort = getBitvectorSort(Int.getBitWidth()); Z3_ast AST = - Z3_mk_numeral(Z3Context::ZC, Int.toString(10).c_str(), Sort.Sort); - return Z3Expr(AST); + Z3_mk_numeral(Context.Context, Int.toString(10).c_str(), Sort.Sort); + return Z3Expr(Context, AST); } /// Construct a Z3Expr from an integer, given a Z3_context. - static Z3Expr fromInt(const char *Int, uint64_t BitWidth) { - Z3Sort Sort = Z3Sort::getBitvectorSort(BitWidth); - Z3_ast AST = Z3_mk_numeral(Z3Context::ZC, Int, Sort.Sort); - return Z3Expr(AST); + Z3Expr fromInt(const char *Int, uint64_t BitWidth) { + Z3Sort Sort = getBitvectorSort(BitWidth); + Z3_ast AST = Z3_mk_numeral(Context.Context, Int, Sort.Sort); + return Z3Expr(Context, AST); } /// Construct an APFloat from a Z3Expr, given the AST representation - static bool toAPFloat(const Z3Sort &Sort, const Z3_ast &AST, - llvm::APFloat &Float, bool useSemantics = true) { + bool toAPFloat(const Z3Sort &Sort, const Z3_ast &AST, llvm::APFloat &Float, + bool useSemantics = true) { assert(Sort.getSortKind() == Z3_FLOATING_POINT_SORT && "Unsupported sort to floating-point!"); llvm::APSInt Int(Sort.getFloatSortSize(), true); const llvm::fltSemantics &Semantics = Z3Expr::getFloatSemantics(Sort.getFloatSortSize()); - Z3Sort BVSort = Z3Sort::getBitvectorSort(Sort.getFloatSortSize()); - if (!Z3Expr::toAPSInt(BVSort, AST, Int, true)) { + Z3Sort BVSort = getBitvectorSort(Sort.getFloatSortSize()); + if (!toAPSInt(BVSort, AST, Int, true)) { return false; } @@ -667,8 +826,8 @@ public: } /// Construct an APSInt from a Z3Expr, given the AST representation - static bool toAPSInt(const Z3Sort &Sort, const Z3_ast &AST, llvm::APSInt &Int, - bool useSemantics = true) { + bool toAPSInt(const Z3Sort &Sort, const Z3_ast &AST, llvm::APSInt &Int, + bool useSemantics = true) { switch (Sort.getSortKind()) { default: llvm_unreachable("Unsupported sort to integer!"); @@ -682,14 +841,15 @@ public: // Force cast because Z3 defines __uint64 to be a unsigned long long // type, which isn't compatible with a unsigned long type, even if they // are the same size. - Z3_get_numeral_uint64(Z3Context::ZC, AST, + Z3_get_numeral_uint64(Context.Context, AST, reinterpret_cast<__uint64 *>(&Value[0])); if (Sort.getBitvectorSortSize() <= 64) { Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), Int.isUnsigned()); } else if (Sort.getBitvectorSortSize() == 128) { - Z3Expr ASTHigh = Z3Expr(Z3_mk_extract(Z3Context::ZC, 127, 64, AST)); - Z3_get_numeral_uint64(Z3Context::ZC, AST, + Z3Expr ASTHigh = + Z3Expr(Context, Z3_mk_extract(Context.Context, 127, 64, AST)); + Z3_get_numeral_uint64(Context.Context, AST, reinterpret_cast<__uint64 *>(&Value[1])); Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), Int.isUnsigned()); @@ -706,209 +866,86 @@ public: } Int = llvm::APSInt( llvm::APInt(Int.getBitWidth(), - Z3_get_bool_value(Z3Context::ZC, AST) == Z3_L_TRUE ? 1 - : 0), + Z3_get_bool_value(Context.Context, AST) == Z3_L_TRUE ? 1 + : 0), Int.isUnsigned()); return true; } } - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddInteger(Z3_get_ast_hash(Z3Context::ZC, AST)); - } - - bool operator<(const Z3Expr &Other) const { - llvm::FoldingSetNodeID ID1, ID2; - Profile(ID1); - Other.Profile(ID2); - return ID1 < ID2; - } - - /// Comparison of AST equality, not model equivalence. - bool operator==(const Z3Expr &Other) const { - assert(Z3_is_eq_sort(Z3Context::ZC, Z3_get_sort(Z3Context::ZC, AST), - Z3_get_sort(Z3Context::ZC, Other.AST)) && - "AST's must have the same sort"); - return Z3_is_eq_ast(Z3Context::ZC, AST, Other.AST); - } - - /// Override implicit move constructor for correct reference counting. - Z3Expr &operator=(const Z3Expr &Move) { - Z3_inc_ref(Z3Context::ZC, Move.AST); - Z3_dec_ref(Z3Context::ZC, AST); - AST = Move.AST; - return *this; - } - - void print(raw_ostream &OS) const { - OS << Z3_ast_to_string(Z3Context::ZC, AST); - } - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } -}; // end class Z3Expr - -class Z3Model { - Z3_model Model; - -public: - Z3Model(Z3_model ZM) : Model(ZM) { Z3_model_inc_ref(Z3Context::ZC, Model); } - - /// Override implicit copy constructor for correct reference counting. - Z3Model(const Z3Model &Copy) : Model(Copy.Model) { - Z3_model_inc_ref(Z3Context::ZC, Model); - } - - /// Provide move constructor - Z3Model(Z3Model &&Move) : Model(nullptr) { *this = std::move(Move); } - - /// Provide move assignment constructor - Z3Model &operator=(Z3Model &&Move) { - if (this != &Move) { - if (Model) - Z3_model_dec_ref(Z3Context::ZC, Model); - Model = Move.Model; - Move.Model = nullptr; - } - return *this; - } - - ~Z3Model() { - if (Model) - Z3_model_dec_ref(Z3Context::ZC, Model); - } - - /// Given an expression, extract the value of this operand in the model. - bool getInterpretation(const Z3Expr &Exp, llvm::APSInt &Int) const { + /// Given an expression and a model, extract the value of this operand in + /// the model. + bool getInterpretation(const Z3Model Model, const Z3Expr &Exp, + llvm::APSInt &Int) { Z3_func_decl Func = - Z3_get_app_decl(Z3Context::ZC, Z3_to_app(Z3Context::ZC, Exp.AST)); - if (Z3_model_has_interp(Z3Context::ZC, Model, Func) != Z3_L_TRUE) + Z3_get_app_decl(Context.Context, Z3_to_app(Context.Context, Exp.AST)); + if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE) return false; - Z3_ast Assign = Z3_model_get_const_interp(Z3Context::ZC, Model, Func); - Z3Sort Sort = Z3Sort::getSort(Assign); - return Z3Expr::toAPSInt(Sort, Assign, Int, true); + Z3_ast Assign = + Z3_model_get_const_interp(Context.Context, Model.Model, Func); + Z3Sort Sort = getSort(Assign); + return toAPSInt(Sort, Assign, Int, true); } - /// Given an expression, extract the value of this operand in the model. - bool getInterpretation(const Z3Expr &Exp, llvm::APFloat &Float) const { + /// Given an expression and a model, extract the value of this operand in + /// the model. + bool getInterpretation(const Z3Model Model, const Z3Expr &Exp, + llvm::APFloat &Float) { Z3_func_decl Func = - Z3_get_app_decl(Z3Context::ZC, Z3_to_app(Z3Context::ZC, Exp.AST)); - if (Z3_model_has_interp(Z3Context::ZC, Model, Func) != Z3_L_TRUE) + Z3_get_app_decl(Context.Context, Z3_to_app(Context.Context, Exp.AST)); + if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE) return false; - Z3_ast Assign = Z3_model_get_const_interp(Z3Context::ZC, Model, Func); - Z3Sort Sort = Z3Sort::getSort(Assign); - return Z3Expr::toAPFloat(Sort, Assign, Float, true); - } - - void print(raw_ostream &OS) const { - OS << Z3_model_to_string(Z3Context::ZC, Model); - } - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } -}; // end class Z3Model - -class Z3Solver { - friend class Z3ConstraintManager; - - Z3_solver Solver; - - Z3Solver(Z3_solver ZS) : Solver(ZS) { - Z3_solver_inc_ref(Z3Context::ZC, Solver); - } - -public: - /// Override implicit copy constructor for correct reference counting. - Z3Solver(const Z3Solver &Copy) : Solver(Copy.Solver) { - Z3_solver_inc_ref(Z3Context::ZC, Solver); - } - - /// Provide move constructor - Z3Solver(Z3Solver &&Move) : Solver(nullptr) { *this = std::move(Move); } - - /// Provide move assignment constructor - Z3Solver &operator=(Z3Solver &&Move) { - if (this != &Move) { - if (Solver) - Z3_solver_dec_ref(Z3Context::ZC, Solver); - Solver = Move.Solver; - Move.Solver = nullptr; - } - return *this; + Z3_ast Assign = + Z3_model_get_const_interp(Context.Context, Model.Model, Func); + Z3Sort Sort = getSort(Assign); + return toAPFloat(Sort, Assign, Float, true); } - ~Z3Solver() { - if (Solver) - Z3_solver_dec_ref(Z3Context::ZC, Solver); - } - - /// Given a constraint, add it to the solver - void addConstraint(const Z3Expr &Exp) { - Z3_solver_assert(Z3Context::ZC, Solver, Exp.AST); - } - - /// Given a program state, construct the logical conjunction and add it to - /// the solver - void addStateConstraints(ProgramStateRef State) { - // TODO: Don't add all the constraints, only the relevant ones - ConstraintZ3Ty CZ = State->get(); - ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); - - // Construct the logical AND of all the constraints - if (I != IE) { - std::vector ASTs; - - while (I != IE) - ASTs.push_back(I++->second.AST); - - Z3Expr Conj = Z3Expr::fromNBinOp(BO_LAnd, ASTs); - addConstraint(Conj); - } + // Callback function for doCast parameter on APSInt type. + llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, + uint64_t ToWidth, QualType FromTy, + uint64_t FromWidth) { + APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType()); + return TargetType.convert(V); } /// Check if the constraints are satisfiable - Z3_lbool check() { return Z3_solver_check(Z3Context::ZC, Solver); } + Z3_lbool check() { return Z3_solver_check(Context.Context, Solver); } /// Push the current solver state - void push() { return Z3_solver_push(Z3Context::ZC, Solver); } + void push() { return Z3_solver_push(Context.Context, Solver); } /// Pop the previous solver state void pop(unsigned NumStates = 1) { - assert(Z3_solver_get_num_scopes(Z3Context::ZC, Solver) >= NumStates); - return Z3_solver_pop(Z3Context::ZC, Solver, NumStates); + assert(Z3_solver_get_num_scopes(Context.Context, Solver) >= NumStates); + return Z3_solver_pop(Context.Context, Solver, NumStates); } /// Get a model from the solver. Caller should check the model is /// satisfiable. Z3Model getModel() { - return Z3Model(Z3_solver_get_model(Z3Context::ZC, Solver)); + return Z3Model(Context, Z3_solver_get_model(Context.Context, Solver)); } /// Reset the solver and remove all constraints. - void reset() { Z3_solver_reset(Z3Context::ZC, Solver); } + void reset() { Z3_solver_reset(Context.Context, Solver); } void print(raw_ostream &OS) const { - OS << Z3_solver_to_string(Z3Context::ZC, Solver); + OS << Z3_solver_to_string(Context.Context, Solver); } LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Solver -void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) { - llvm::report_fatal_error("Z3 error: " + - llvm::Twine(Z3_get_error_msg_ex(Context, Error))); -} - class Z3ConstraintManager : public SMTConstraintManager { - Z3Context Context; mutable Z3Solver Solver; public: Z3ConstraintManager(SubEngine *SE, SValBuilder &SB) - : SMTConstraintManager(SE, SB), - Solver(Z3_mk_simple_solver(Z3Context::ZC)) { - Z3_set_error_handler(Z3Context::ZC, Z3ErrorHandler); - } + : SMTConstraintManager(SE, SB) {} + //===------------------------------------------------------------------===// // Implementation for Refutation. //===------------------------------------------------------------------===// @@ -1025,26 +1062,19 @@ private: // Perform implicit integer type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleIntegerConversion() - template + template void doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const; // Perform implicit floating-point type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleFloatConversion() - template + template void doFloatTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const; - - // Callback function for doCast parameter on APSInt type. - static llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, - uint64_t ToWidth, QualType FromTy, - uint64_t FromWidth); }; // end class Z3ConstraintManager -Z3_context Z3Context::ZC; - } // end anonymous namespace ProgramStateRef Z3ConstraintManager::assumeSym(ProgramStateRef State, @@ -1169,14 +1199,14 @@ const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, Z3Model Model = Solver.getModel(); // Model does not assign interpretation - if (!Model.getInterpretation(Exp, Value)) + if (!Solver.getInterpretation(Model, Exp, Value)) return nullptr; // A value has been obtained, check if it is the only value - Z3Expr NotExp = Z3Expr::fromBinOp( + Z3Expr NotExp = Solver.fromBinOp( Exp, BO_NE, - Ty->isBooleanType() ? Z3Expr::fromBoolean(Value.getBoolValue()) - : Z3Expr::fromAPSInt(Value), + Ty->isBooleanType() ? Solver.fromBoolean(Value.getBoolValue()) + : Solver.fromAPSInt(Value), false); Solver.addConstraint(NotExp); @@ -1219,8 +1249,8 @@ const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, QualType LTy, RTy; std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); - doIntTypeConversion( - ConvertedLHS, LTy, ConvertedRHS, RTy); + doIntTypeConversion(ConvertedLHS, LTy, + ConvertedRHS, RTy); return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); } @@ -1242,10 +1272,12 @@ Z3ConstraintManager::removeDeadBindings(ProgramStateRef State, } void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { + Solver.reset(); + for (const auto &I : CR) { SymbolRef Sym = I.first; - Z3Expr Constraints = Z3Expr::fromBoolean(false); + Z3Expr Constraints = Solver.fromBoolean(false); for (const auto &Range : I.second) { Z3Expr SymRange = getZ3RangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); @@ -1253,7 +1285,7 @@ void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { // FIXME: the last argument (isSigned) is not used when generating the // or expression, as both arguments are booleans Constraints = - Z3Expr::fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); + Solver.fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); } Solver.addConstraint(Constraints); } @@ -1266,10 +1298,7 @@ clang::ento::ConditionTruthVal Z3ConstraintManager::isModelFeasible() { return ConditionTruthVal(); } -LLVM_DUMP_METHOD void Z3ConstraintManager::dump() const -{ - Solver.dump(); -} +LLVM_DUMP_METHOD void Z3ConstraintManager::dump() const { Solver.dump(); } //===------------------------------------------------------------------===// // Internal implementation. @@ -1303,7 +1332,7 @@ Z3Expr Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy, } Z3Expr Z3ConstraintManager::getZ3NotExpr(const Z3Expr &Exp) const { - return Z3Expr::fromUnOp(UO_LNot, Exp); + return Solver.fromUnOp(UO_LNot, Exp); } Z3Expr Z3ConstraintManager::getZ3ZeroExpr(const Z3Expr &Exp, QualType Ty, @@ -1311,17 +1340,16 @@ Z3Expr Z3ConstraintManager::getZ3ZeroExpr(const Z3Expr &Exp, QualType Ty, ASTContext &Ctx = getBasicVals().getContext(); if (Ty->isRealFloatingType()) { llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); - return Z3Expr::fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Z3Expr::fromAPFloat(Zero)); + return Solver.fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, + Solver.fromAPFloat(Zero)); } else if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || Ty->isBlockPointerType() || Ty->isReferenceType()) { bool isSigned = Ty->isSignedIntegerOrEnumerationType(); // Skip explicit comparison for boolean types if (Ty->isBooleanType()) return Assumption ? getZ3NotExpr(Exp) : Exp; - return Z3Expr::fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Z3Expr::fromInt("0", Ctx.getTypeSize(Ty)), - isSigned); + return Solver.fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, + Solver.fromInt("0", Ctx.getTypeSize(Ty)), isSigned); } llvm_unreachable("Unsupported type for zero value!"); @@ -1360,15 +1388,14 @@ Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, Z3Expr Z3ConstraintManager::getZ3DataExpr(const SymbolID ID, QualType Ty) const { ASTContext &Ctx = getBasicVals().getContext(); - return Z3Expr::fromData(ID, Ty->isBooleanType(), Ty->isRealFloatingType(), - Ctx.getTypeSize(Ty)); + return Solver.fromData(ID, Ty, Ctx.getTypeSize(Ty)); } Z3Expr Z3ConstraintManager::getZ3CastExpr(const Z3Expr &Exp, QualType FromTy, QualType ToTy) const { ASTContext &Ctx = getBasicVals().getContext(); - return Z3Expr::fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, - Ctx.getTypeSize(FromTy)); + return Solver.fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, + Ctx.getTypeSize(FromTy)); } Z3Expr Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE, @@ -1381,12 +1408,12 @@ Z3Expr Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE, Z3Expr LHS = getZ3SymExpr(SIE->getLHS(), <y, hasComparison); llvm::APSInt NewRInt; std::tie(NewRInt, RTy) = fixAPSInt(SIE->getRHS()); - Z3Expr RHS = Z3Expr::fromAPSInt(NewRInt); + Z3Expr RHS = Solver.fromAPSInt(NewRInt); return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { llvm::APSInt NewLInt; std::tie(NewLInt, LTy) = fixAPSInt(ISE->getLHS()); - Z3Expr LHS = Z3Expr::fromAPSInt(NewLInt); + Z3Expr LHS = Solver.fromAPSInt(NewLInt); Z3Expr RHS = getZ3SymExpr(ISE->getRHS(), &RTy, hasComparison); return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { @@ -1425,9 +1452,9 @@ Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy, } return LTy->isRealFloatingType() - ? Z3Expr::fromFloatBinOp(NewLHS, Op, NewRHS) - : Z3Expr::fromBinOp(NewLHS, Op, NewRHS, - LTy->isSignedIntegerOrEnumerationType()); + ? Solver.fromFloatBinOp(NewLHS, Op, NewRHS) + : Solver.fromBinOp(NewLHS, Op, NewRHS, + LTy->isSignedIntegerOrEnumerationType()); } Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, @@ -1438,7 +1465,7 @@ Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, QualType FromTy; llvm::APSInt NewFromInt; std::tie(NewFromInt, FromTy) = fixAPSInt(From); - Z3Expr FromExp = Z3Expr::fromAPSInt(NewFromInt); + Z3Expr FromExp = Solver.fromAPSInt(NewFromInt); // Convert symbol QualType SymTy; @@ -1452,7 +1479,7 @@ Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, QualType ToTy; llvm::APSInt NewToInt; std::tie(NewToInt, ToTy) = fixAPSInt(To); - Z3Expr ToExp = Z3Expr::fromAPSInt(NewToInt); + Z3Expr ToExp = Solver.fromAPSInt(NewToInt); assert(FromTy == ToTy && "Range values have different types!"); // Construct two (in)equalities, and a logical and/or @@ -1461,8 +1488,8 @@ Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, Z3Expr RHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, /*RetTy=*/nullptr); - return Z3Expr::fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, - SymTy->isSignedIntegerOrEnumerationType()); + return Solver.fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, + SymTy->isSignedIntegerOrEnumerationType()); } //===------------------------------------------------------------------===// @@ -1499,9 +1526,11 @@ void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, if (LTy->isIntegralOrEnumerationType() && RTy->isIntegralOrEnumerationType()) { if (LTy->isArithmeticType() && RTy->isArithmeticType()) - return doIntTypeConversion(LHS, LTy, RHS, RTy); + return doIntTypeConversion(LHS, LTy, RHS, + RTy); } else if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { - return doFloatTypeConversion(LHS, LTy, RHS, RTy); + return doFloatTypeConversion(LHS, LTy, RHS, + RTy); } else if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || (LTy->isReferenceType() || RTy->isReferenceType())) { @@ -1518,10 +1547,10 @@ void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, (LTy->isReferenceType() ^ RTy->isReferenceType())) { if (LTy->isNullPtrType() || LTy->isBlockPointerType() || LTy->isReferenceType()) { - LHS = Z3Expr::fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = Solver.fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } else { - RHS = Z3Expr::fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = Solver.fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; } } @@ -1552,8 +1581,8 @@ void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, // TODO: Refine behavior for invalid type casts } -template +template void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { ASTContext &Ctx = getBasicVals().getContext(); @@ -1566,14 +1595,14 @@ void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, if (LTy->isPromotableIntegerType()) { QualType NewTy = Ctx.getPromotedIntegerType(LTy); uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - LHS = (*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); LTy = NewTy; LBitWidth = NewBitWidth; } if (RTy->isPromotableIntegerType()) { QualType NewTy = Ctx.getPromotedIntegerType(RTy); uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - RHS = (*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); RTy = NewTy; RBitWidth = NewBitWidth; } @@ -1590,20 +1619,20 @@ void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, if (isLSignedTy == isRSignedTy) { // Same signedness; use the higher-ranked type if (order == 1) { - RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; } else { - LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } } else if (order != (isLSignedTy ? 1 : -1)) { // The unsigned type has greater than or equal rank to the // signed type, so use the unsigned type if (isRSignedTy) { - RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; } else { - LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } } else if (LBitWidth != RBitWidth) { @@ -1611,10 +1640,10 @@ void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, // means the signed type is larger than the unsigned type, so // use the signed type. if (isLSignedTy) { - RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; } else { - LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } } else { @@ -1623,15 +1652,15 @@ void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, // on most 32-bit systems). Use the unsigned type corresponding // to the signed type. QualType NewTy = Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); - RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = NewTy; - LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = NewTy; } } -template +template void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { ASTContext &Ctx = getBasicVals().getContext(); @@ -1641,12 +1670,12 @@ void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType <y, T &RHS, // Perform float-point type promotion if (!LTy->isRealFloatingType()) { - LHS = (*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; LBitWidth = RBitWidth; } if (!RTy->isRealFloatingType()) { - RHS = (*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; RBitWidth = LBitWidth; } @@ -1659,24 +1688,16 @@ void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType <y, T &RHS, // Note: Safe to skip updating bitwidth because this must terminate int order = Ctx.getFloatingTypeOrder(LTy, RTy); if (order > 0) { - RHS = Z3Expr::fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); + RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; } else if (order == 0) { - LHS = Z3Expr::fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); + LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } else { llvm_unreachable("Unsupported floating-point type cast!"); } } -llvm::APSInt Z3ConstraintManager::castAPSInt(const llvm::APSInt &V, - QualType ToTy, uint64_t ToWidth, - QualType FromTy, - uint64_t FromWidth) { - APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType()); - return TargetType.convert(V); -} - //==------------------------------------------------------------------------==/ // Pretty-printing. //==------------------------------------------------------------------------==/ -- GitLab From 143e570b298eda45219fd0302d559235bf14143c Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:15 +0000 Subject: [PATCH 0712/1023] [analyzer] Create generic SMT Sort Class Summary: New base class for all future SMT sorts. The only change is that the class implements methods `isBooleanSort()`, `isBitvectorSort()` and `isFloatSort()` so it doesn't rely on `Z3`'s enum. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49550 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337916 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTSort.h | 71 +++++++++++++++++++ .../Core/Z3ConstraintManager.cpp | 54 +++++++------- 2 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h new file mode 100644 index 0000000000..6780dac751 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h @@ -0,0 +1,71 @@ +//== SMTSort.h --------------------------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a SMT generic Sort API, which will be the base class +// for every SMT solver sort specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H + +namespace clang { +namespace ento { + +class SMTSort { +public: + SMTSort() = default; + virtual ~SMTSort() = default; + + virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); } + virtual bool isFloatSort() const { return isFloatSortImpl(); } + virtual bool isBooleanSort() const { return isBooleanSortImpl(); } + + virtual unsigned getBitvectorSortSize() const { + assert(isBitvectorSort() && "Not a bitvector sort!"); + unsigned Size = getBitvectorSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + virtual unsigned getFloatSortSize() const { + assert(isFloatSort() && "Not a floating-point sort!"); + unsigned Size = getFloatSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + +protected: + virtual bool equal_to(SMTSort const &other) const = 0; + + virtual bool isBitvectorSortImpl() const = 0; + + virtual bool isFloatSortImpl() const = 0; + + virtual bool isBooleanSortImpl() const = 0; + + virtual unsigned getBitvectorSortSizeImpl() const = 0; + + virtual unsigned getFloatSortSizeImpl() const = 0; +}; + +using SMTSortRef = std::shared_ptr; + +} // namespace ento +} // namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 70b7c467cf..59107120ae 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -12,6 +12,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" #include "clang/Config/config.h" @@ -84,27 +85,26 @@ public: } }; // end class Z3Context -class Z3Sort { - friend class Z3Expr; +class Z3Sort : public SMTSort { friend class Z3Solver; Z3Context &Context; Z3_sort Sort; - Z3Sort(Z3Context &C, Z3_sort ZS) : Context(C), Sort(ZS) { - assert(C.Context != nullptr); + Z3Sort(Z3Context &C, Z3_sort ZS) : SMTSort(), Context(C), Sort(ZS) { Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } public: /// Override implicit copy constructor for correct reference counting. - Z3Sort(const Z3Sort &Copy) : Context(Copy.Context), Sort(Copy.Sort) { + Z3Sort(const Z3Sort &Copy) + : SMTSort(), Context(Copy.Context), Sort(Copy.Sort) { Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } /// Provide move constructor - Z3Sort(Z3Sort &&Move) : Context(Move.Context), Sort(nullptr) { + Z3Sort(Z3Sort &&Move) : SMTSort(), Context(Move.Context), Sort(nullptr) { *this = std::move(Move); } @@ -124,24 +124,30 @@ public: Z3_dec_ref(Context.Context, reinterpret_cast(Sort)); } - Z3_sort_kind getSortKind() const { - return Z3_get_sort_kind(Context.Context, Sort); + bool isBitvectorSortImpl() const override { + return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BV_SORT); + } + + bool isFloatSortImpl() const override { + return (Z3_get_sort_kind(Context.Context, Sort) == Z3_FLOATING_POINT_SORT); } - unsigned getBitvectorSortSize() const { - assert(getSortKind() == Z3_BV_SORT && "Not a bitvector sort!"); + bool isBooleanSortImpl() const override { + return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BOOL_SORT); + } + + unsigned getBitvectorSortSizeImpl() const override { return Z3_get_bv_sort_size(Context.Context, Sort); } - unsigned getFloatSortSize() const { - assert(getSortKind() == Z3_FLOATING_POINT_SORT && - "Not a floating-point sort!"); + unsigned getFloatSortSizeImpl() const override { return Z3_fpa_get_ebits(Context.Context, Sort) + Z3_fpa_get_sbits(Context.Context, Sort); } - bool operator==(const Z3Sort &Other) const { - return Z3_is_eq_sort(Context.Context, Sort, Other.Sort); + bool equal_to(SMTSort const &Other) const override { + return Z3_is_eq_sort(Context.Context, Sort, + static_cast(Other).Sort); } Z3Sort &operator=(const Z3Sort &Move) { @@ -151,11 +157,9 @@ public: return *this; } - void print(raw_ostream &OS) const { + void print(raw_ostream &OS) const override { OS << Z3_sort_to_string(Context.Context, Sort); } - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Sort class Z3Expr { @@ -804,8 +808,7 @@ public: /// Construct an APFloat from a Z3Expr, given the AST representation bool toAPFloat(const Z3Sort &Sort, const Z3_ast &AST, llvm::APFloat &Float, bool useSemantics = true) { - assert(Sort.getSortKind() == Z3_FLOATING_POINT_SORT && - "Unsupported sort to floating-point!"); + assert(Sort.isFloatSort() && "Unsupported sort to floating-point!"); llvm::APSInt Int(Sort.getFloatSortSize(), true); const llvm::fltSemantics &Semantics = @@ -828,10 +831,7 @@ public: /// Construct an APSInt from a Z3Expr, given the AST representation bool toAPSInt(const Z3Sort &Sort, const Z3_ast &AST, llvm::APSInt &Int, bool useSemantics = true) { - switch (Sort.getSortKind()) { - default: - llvm_unreachable("Unsupported sort to integer!"); - case Z3_BV_SORT: { + if (Sort.isBitvectorSort()) { if (useSemantics && Int.getBitWidth() != Sort.getBitvectorSortSize()) { assert(false && "Bitvector types don't match!"); return false; @@ -859,11 +859,13 @@ public: } return true; } - case Z3_BOOL_SORT: + + if (Sort.isBooleanSort()) { if (useSemantics && Int.getBitWidth() < 1) { assert(false && "Boolean type doesn't match!"); return false; } + Int = llvm::APSInt( llvm::APInt(Int.getBitWidth(), Z3_get_bool_value(Context.Context, AST) == Z3_L_TRUE ? 1 @@ -871,6 +873,8 @@ public: Int.isUnsigned()); return true; } + + llvm_unreachable("Unsupported sort to integer!"); } /// Given an expression and a model, extract the value of this operand in -- GitLab From 9a5865c57cafa814a1b7a142e67ac3a269c9445f Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:19 +0000 Subject: [PATCH 0713/1023] [analyzer] Create generic SMT Expr class Summary: New base class for all future SMT Exprs. No major changes except moving `areEquivalent` and `getFloatSemantics` outside of `Z3Expr` to keep the class minimal. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49551 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337917 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTExpr.h | 57 +++++++++++ .../Core/Z3ConstraintManager.cpp | 97 +++++++++---------- 2 files changed, 101 insertions(+), 53 deletions(-) create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h new file mode 100644 index 0000000000..f0591780b7 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h @@ -0,0 +1,57 @@ +//== SMTExpr.h --------------------------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a SMT generic Expr API, which will be the base class +// for every SMT solver expr specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" + +namespace clang { +namespace ento { + +class SMTExpr { +public: + SMTExpr() = default; + virtual ~SMTExpr() = default; + + bool operator<(const SMTExpr &Other) const { + llvm::FoldingSetNodeID ID1, ID2; + Profile(ID1); + Other.Profile(ID2); + return ID1 < ID2; + } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const { + static int Tag = 0; + ID.AddPointer(&Tag); + } + + friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + +protected: + virtual bool equal_to(SMTExpr const &other) const = 0; +}; + +using SMTExprRef = std::shared_ptr; + +} // namespace ento +} // namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 59107120ae..ff80e96f35 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -12,6 +12,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" #include "clang/Config/config.h" @@ -162,40 +163,25 @@ public: } }; // end class Z3Sort -class Z3Expr { - friend class Z3Model; +class Z3Expr : public SMTExpr { friend class Z3Solver; Z3Context &Context; Z3_ast AST; - Z3Expr(Z3Context &C, Z3_ast ZA) : Context(C), AST(ZA) { - assert(C.Context != nullptr); + Z3Expr(Z3Context &C, Z3_ast ZA) : SMTExpr(), Context(C), AST(ZA) { Z3_inc_ref(Context.Context, AST); } - // Determine whether two float semantics are equivalent - static bool areEquivalent(const llvm::fltSemantics &LHS, - const llvm::fltSemantics &RHS) { - return (llvm::APFloat::semanticsPrecision(LHS) == - llvm::APFloat::semanticsPrecision(RHS)) && - (llvm::APFloat::semanticsMinExponent(LHS) == - llvm::APFloat::semanticsMinExponent(RHS)) && - (llvm::APFloat::semanticsMaxExponent(LHS) == - llvm::APFloat::semanticsMaxExponent(RHS)) && - (llvm::APFloat::semanticsSizeInBits(LHS) == - llvm::APFloat::semanticsSizeInBits(RHS)); - } - public: /// Override implicit copy constructor for correct reference counting. - Z3Expr(const Z3Expr &Copy) : Context(Copy.Context), AST(Copy.AST) { + Z3Expr(const Z3Expr &Copy) : SMTExpr(), Context(Copy.Context), AST(Copy.AST) { Z3_inc_ref(Context.Context, AST); } /// Provide move constructor - Z3Expr(Z3Expr &&Move) : Context(Move.Context), AST(nullptr) { + Z3Expr(Z3Expr &&Move) : SMTExpr(), Context(Move.Context), AST(nullptr) { *this = std::move(Move); } @@ -215,40 +201,18 @@ public: Z3_dec_ref(Context.Context, AST); } - /// Get the corresponding IEEE floating-point type for a given bitwidth. - static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) { - switch (BitWidth) { - default: - llvm_unreachable("Unsupported floating-point semantics!"); - break; - case 16: - return llvm::APFloat::IEEEhalf(); - case 32: - return llvm::APFloat::IEEEsingle(); - case 64: - return llvm::APFloat::IEEEdouble(); - case 128: - return llvm::APFloat::IEEEquad(); - } - } - - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { ID.AddInteger(Z3_get_ast_hash(Context.Context, AST)); } - bool operator<(const Z3Expr &Other) const { - llvm::FoldingSetNodeID ID1, ID2; - Profile(ID1); - Other.Profile(ID2); - return ID1 < ID2; - } - /// Comparison of AST equality, not model equivalence. - bool operator==(const Z3Expr &Other) const { + bool equal_to(SMTExpr const &Other) const override { assert(Z3_is_eq_sort(Context.Context, Z3_get_sort(Context.Context, AST), - Z3_get_sort(Context.Context, Other.AST)) && + Z3_get_sort(Context.Context, + static_cast(Other).AST)) && "AST's must have the same sort"); - return Z3_is_eq_ast(Context.Context, AST, Other.AST); + return Z3_is_eq_ast(Context.Context, AST, + static_cast(Other).AST); } /// Override implicit move constructor for correct reference counting. @@ -259,11 +223,9 @@ public: return *this; } - void print(raw_ostream &OS) const { + void print(raw_ostream &OS) const override { OS << Z3_ast_to_string(Context.Context, AST); } - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Expr class Z3Model { @@ -312,6 +274,36 @@ public: LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Model +/// Get the corresponding IEEE floating-point type for a given bitwidth. +static const llvm::fltSemantics &getFloatSemantics(unsigned BitWidth) { + switch (BitWidth) { + default: + llvm_unreachable("Unsupported floating-point semantics!"); + break; + case 16: + return llvm::APFloat::IEEEhalf(); + case 32: + return llvm::APFloat::IEEEsingle(); + case 64: + return llvm::APFloat::IEEEdouble(); + case 128: + return llvm::APFloat::IEEEquad(); + } +} + +// Determine whether two float semantics are equivalent +static bool areEquivalent(const llvm::fltSemantics &LHS, + const llvm::fltSemantics &RHS) { + return (llvm::APFloat::semanticsPrecision(LHS) == + llvm::APFloat::semanticsPrecision(RHS)) && + (llvm::APFloat::semanticsMinExponent(LHS) == + llvm::APFloat::semanticsMinExponent(RHS)) && + (llvm::APFloat::semanticsMaxExponent(LHS) == + llvm::APFloat::semanticsMaxExponent(RHS)) && + (llvm::APFloat::semanticsSizeInBits(LHS) == + llvm::APFloat::semanticsSizeInBits(RHS)); +} + class Z3Solver { friend class Z3ConstraintManager; @@ -812,14 +804,13 @@ public: llvm::APSInt Int(Sort.getFloatSortSize(), true); const llvm::fltSemantics &Semantics = - Z3Expr::getFloatSemantics(Sort.getFloatSortSize()); + getFloatSemantics(Sort.getFloatSortSize()); Z3Sort BVSort = getBitvectorSort(Sort.getFloatSortSize()); if (!toAPSInt(BVSort, AST, Int, true)) { return false; } - if (useSemantics && - !Z3Expr::areEquivalent(Float.getSemantics(), Semantics)) { + if (useSemantics && !areEquivalent(Float.getSemantics(), Semantics)) { assert(false && "Floating-point types don't match!"); return false; } -- GitLab From c42f63716138de70bd17c7f4dc89a51025ffd994 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:23 +0000 Subject: [PATCH 0714/1023] [analyzer] Implemented SMT generic API Summary: Created new SMT generic API. Small changes to `Z3ConstraintManager` because of the new generic objects (`SMTSort` and `SMTExpr`) returned by `SMTSolver`. Reviewers: george.karpenkov, NoQ Reviewed By: george.karpenkov Subscribers: mgorny, xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49495 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337918 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTSolver.h | 546 ++++++++ .../Core/Z3ConstraintManager.cpp | 1114 +++++++++-------- 2 files changed, 1115 insertions(+), 545 deletions(-) create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h new file mode 100644 index 0000000000..15e646689c --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -0,0 +1,546 @@ +//== SMTSolver.h ------------------------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a SMT generic Solver API, which will be the base class +// for every SMT solver specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" + +namespace clang { +namespace ento { + +class SMTSolver { +public: + SMTSolver() = default; + virtual ~SMTSolver() = default; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + + // Return an appropriate floating-point sort for the given bitwidth. + SMTSortRef getFloatSort(unsigned BitWidth) { + switch (BitWidth) { + case 16: + return getFloat16Sort(); + case 32: + return getFloat32Sort(); + case 64: + return getFloat64Sort(); + case 128: + return getFloat128Sort(); + default:; + } + llvm_unreachable("Unsupported floating-point bitwidth!"); + } + + // Return an appropriate sort, given a QualType + SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth) { + if (Ty->isBooleanType()) + return getBoolSort(); + + if (Ty->isRealFloatingType()) + return getFloatSort(BitWidth); + + return getBitvectorSort(BitWidth); + } + + /// Construct a Z3Expr from a unary operator, given a Z3_context. + SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) { + switch (Op) { + case UO_Minus: + return mkBVNeg(Exp); + + case UO_Not: + return mkBVNot(Exp); + + case UO_LNot: + return mkNot(Exp); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct a Z3Expr from a floating-point unary operator, given a + /// Z3_context. + SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op, + const SMTExprRef &Exp) { + switch (Op) { + case UO_Minus: + return mkFPNeg(Exp); + + case UO_LNot: + return fromUnOp(Op, Exp); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct a Z3Expr from a n-ary binary operator. + SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op, + const std::vector &ASTs) { + assert(!ASTs.empty()); + + if (Op != BO_LAnd && Op != BO_LOr) + llvm_unreachable("Unimplemented opcode"); + + SMTExprRef res = ASTs.front(); + for (std::size_t i = 1; i < ASTs.size(); ++i) + res = (Op == BO_LAnd) ? mkAnd(res, ASTs[i]) : mkOr(res, ASTs[i]); + return res; + } + + /// Construct a Z3Expr from a binary operator, given a Z3_context. + SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, + const SMTExprRef &RHS, bool isSigned) { + assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!"); + + switch (Op) { + // Multiplicative operators + case BO_Mul: + return mkBVMul(LHS, RHS); + + case BO_Div: + return isSigned ? mkBVSDiv(LHS, RHS) : mkBVUDiv(LHS, RHS); + + case BO_Rem: + return isSigned ? mkBVSRem(LHS, RHS) : mkBVURem(LHS, RHS); + + // Additive operators + case BO_Add: + return mkBVAdd(LHS, RHS); + + case BO_Sub: + return mkBVSub(LHS, RHS); + + // Bitwise shift operators + case BO_Shl: + return mkBVShl(LHS, RHS); + + case BO_Shr: + return isSigned ? mkBVAshr(LHS, RHS) : mkBVLshr(LHS, RHS); + + // Relational operators + case BO_LT: + return isSigned ? mkBVSlt(LHS, RHS) : mkBVUlt(LHS, RHS); + + case BO_GT: + return isSigned ? mkBVSgt(LHS, RHS) : mkBVUgt(LHS, RHS); + + case BO_LE: + return isSigned ? mkBVSle(LHS, RHS) : mkBVUle(LHS, RHS); + + case BO_GE: + return isSigned ? mkBVSge(LHS, RHS) : mkBVUge(LHS, RHS); + + // Equality operators + case BO_EQ: + return mkEqual(LHS, RHS); + + case BO_NE: + return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned)); + + // Bitwise operators + case BO_And: + return mkBVAnd(LHS, RHS); + + case BO_Xor: + return mkBVXor(LHS, RHS); + + case BO_Or: + return mkBVOr(LHS, RHS); + + // Logical operators + case BO_LAnd: + return mkAnd(LHS, RHS); + + case BO_LOr: + return mkOr(LHS, RHS); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct a Z3Expr from a special floating-point binary operator, given + /// a Z3_context. + SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const llvm::APFloat::fltCategory &RHS) { + switch (Op) { + // Equality operators + case BO_EQ: + switch (RHS) { + case llvm::APFloat::fcInfinity: + return mkFPIsInfinite(LHS); + + case llvm::APFloat::fcNaN: + return mkFPIsNaN(LHS); + + case llvm::APFloat::fcNormal: + return mkFPIsNormal(LHS); + + case llvm::APFloat::fcZero: + return mkFPIsZero(LHS); + } + break; + + case BO_NE: + return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS)); + + default:; + } + + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct a Z3Expr from a floating-point binary operator, given a + /// Z3_context. + SMTExprRef fromFloatBinOp(const SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const SMTExprRef &RHS) { + assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!"); + + switch (Op) { + // Multiplicative operators + case BO_Mul: + return mkFPMul(LHS, RHS); + + case BO_Div: + return mkFPDiv(LHS, RHS); + + case BO_Rem: + return mkFPRem(LHS, RHS); + + // Additive operators + case BO_Add: + return mkFPAdd(LHS, RHS); + + case BO_Sub: + return mkFPSub(LHS, RHS); + + // Relational operators + case BO_LT: + return mkFPLt(LHS, RHS); + + case BO_GT: + return mkFPGt(LHS, RHS); + + case BO_LE: + return mkFPLe(LHS, RHS); + + case BO_GE: + return mkFPGe(LHS, RHS); + + // Equality operators + case BO_EQ: + return mkFPEqual(LHS, RHS); + + case BO_NE: + return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS)); + + // Logical operators + case BO_LAnd: + case BO_LOr: + return fromBinOp(LHS, Op, RHS, false); + + default:; + } + + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct a Z3Expr from a SymbolCast, given a Z3_context. + SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, + QualType FromTy, uint64_t FromBitWidth) { + if ((FromTy->isIntegralOrEnumerationType() && + ToTy->isIntegralOrEnumerationType()) || + (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) || + (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) || + (FromTy->isReferenceType() ^ ToTy->isReferenceType())) { + + if (FromTy->isBooleanType()) { + assert(ToBitWidth > 0 && "BitWidth must be positive!"); + return mkIte(Exp, mkBitvector(llvm::APSInt("1"), ToBitWidth), + mkBitvector(llvm::APSInt("0"), ToBitWidth)); + } + + if (ToBitWidth > FromBitWidth) + return FromTy->isSignedIntegerOrEnumerationType() + ? mkSignExt(ToBitWidth - FromBitWidth, Exp) + : mkZeroExt(ToBitWidth - FromBitWidth, Exp); + + if (ToBitWidth < FromBitWidth) + return mkExtract(ToBitWidth - 1, 0, Exp); + + // Both are bitvectors with the same width, ignore the type cast + return Exp; + } + + if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) { + if (ToBitWidth != FromBitWidth) + return mkFPtoFP(Exp, getFloatSort(ToBitWidth)); + + return Exp; + } + + if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) { + SMTSortRef Sort = getFloatSort(ToBitWidth); + return FromTy->isSignedIntegerOrEnumerationType() ? mkFPtoSBV(Exp, Sort) + : mkFPtoUBV(Exp, Sort); + } + + if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType()) + return ToTy->isSignedIntegerOrEnumerationType() + ? mkSBVtoFP(Exp, ToBitWidth) + : mkUBVtoFP(Exp, ToBitWidth); + + llvm_unreachable("Unsupported explicit type cast!"); + } + + // Callback function for doCast parameter on APSInt type. + llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, + uint64_t ToWidth, QualType FromTy, + uint64_t FromWidth) { + APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType()); + return TargetType.convert(V); + } + + // Return a boolean sort. + virtual SMTSortRef getBoolSort() = 0; + + // Return an appropriate bitvector sort for the given bitwidth. + virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0; + + // Return a floating-point sort of width 16 + virtual SMTSortRef getFloat16Sort() = 0; + + // Return a floating-point sort of width 32 + virtual SMTSortRef getFloat32Sort() = 0; + + // Return a floating-point sort of width 64 + virtual SMTSortRef getFloat64Sort() = 0; + + // Return a floating-point sort of width 128 + virtual SMTSortRef getFloat128Sort() = 0; + + // Return an appropriate sort for the given AST. + virtual SMTSortRef getSort(const SMTExprRef &AST) = 0; + + // Return a new SMTExprRef from an SMTExpr + virtual SMTExprRef newExprRef(const SMTExpr &E) const = 0; + + /// Given a constraint, add it to the solver + virtual void addConstraint(const SMTExprRef &Exp) const = 0; + + /// Create a bitvector addition operation + virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector subtraction operation + virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector multiplication operation + virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed modulus operation + virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned modulus operation + virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed division operation + virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned division operation + virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector logical shift left operation + virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector arithmetic shift right operation + virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector logical shift right operation + virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector negation operation + virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0; + + /// Create a bitvector not operation + virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0; + + /// Create a bitvector xor operation + virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector or operation + virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector and operation + virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned less-than operation + virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed less-than operation + virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned greater-than operation + virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed greater-than operation + virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned less-equal-than operation + virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed less-equal-than operation + virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector unsigned greater-equal-than operation + virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a bitvector signed greater-equal-than operation + virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Create a boolean not operation + virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0; + + /// Create a bitvector equality operation + virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, + const SMTExprRef &F) = 0; + + virtual SMTExprRef mkSignExt(unsigned i, const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkZeroExt(unsigned i, const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0; + + virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0; + + virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + + virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + + virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0; + + // Return an appropriate floating-point rounding mode. + virtual SMTExprRef getFloatRoundingMode() = 0; + + virtual const llvm::APSInt getBitvector(const SMTExprRef &Exp) = 0; + + virtual bool getBoolean(const SMTExprRef &Exp) = 0; + + /// Construct a const SMTExprRef &From a boolean. + virtual SMTExprRef mkBoolean(const bool b) = 0; + + /// Construct a const SMTExprRef &From a finite APFloat. + virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0; + + /// Construct a const SMTExprRef &From an APSInt. + virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0; + + SMTExprRef mkBitvector(const llvm::APSInt Int) { + return mkBitvector(Int, Int.getBitWidth()); + } + + /// Given an expression, extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0; + + /// Given an expression extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, + llvm::APFloat &Float) = 0; + + /// Construct a Z3Expr from a boolean, given a Z3_context. + virtual SMTExprRef fromBoolean(const bool Bool) = 0; + /// Construct a Z3Expr from a finite APFloat, given a Z3_context. + virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0; + + /// Construct a Z3Expr from an APSInt, given a Z3_context. + virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0; + + /// Construct a Z3Expr from an integer, given a Z3_context. + virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0; + + /// Construct a const SMTExprRef &From a SymbolData, given a SMT_context. + virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty, + uint64_t BitWidth) = 0; + + /// Check if the constraints are satisfiable + virtual ConditionTruthVal check() const = 0; + + /// Push the current solver state + virtual void push() = 0; + + /// Pop the previous solver state + virtual void pop(unsigned NumStates = 1) = 0; + + /// Reset the solver and remove all constraints. + virtual void reset() const = 0; + + virtual void print(raw_ostream &OS) const = 0; +}; + +using SMTSolverRef = std::shared_ptr; + +} // namespace ento +} // namespace clang + +#endif diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index ff80e96f35..1f033d06e8 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -13,6 +13,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" #include "clang/Config/config.h" @@ -93,11 +94,11 @@ class Z3Sort : public SMTSort { Z3_sort Sort; +public: Z3Sort(Z3Context &C, Z3_sort ZS) : SMTSort(), Context(C), Sort(ZS) { Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } -public: /// Override implicit copy constructor for correct reference counting. Z3Sort(const Z3Sort &Copy) : SMTSort(), Context(Copy.Context), Sort(Copy.Sort) { @@ -163,6 +164,10 @@ public: } }; // end class Z3Sort +static const Z3Sort &toZ3Sort(const SMTSort &S) { + return static_cast(S); +} + class Z3Expr : public SMTExpr { friend class Z3Solver; @@ -170,11 +175,11 @@ class Z3Expr : public SMTExpr { Z3_ast AST; +public: Z3Expr(Z3Context &C, Z3_ast ZA) : SMTExpr(), Context(C), AST(ZA) { Z3_inc_ref(Context.Context, AST); } -public: /// Override implicit copy constructor for correct reference counting. Z3Expr(const Z3Expr &Copy) : SMTExpr(), Context(Copy.Context), AST(Copy.AST) { Z3_inc_ref(Context.Context, AST); @@ -228,6 +233,10 @@ public: } }; // end class Z3Expr +static const Z3Expr &toZ3Expr(const SMTExpr &E) { + return static_cast(E); +} + class Z3Model { friend class Z3Solver; @@ -304,25 +313,27 @@ static bool areEquivalent(const llvm::fltSemantics &LHS, llvm::APFloat::semanticsSizeInBits(RHS)); } -class Z3Solver { +class Z3Solver : public SMTSolver { friend class Z3ConstraintManager; Z3Context Context; Z3_solver Solver; - Z3Solver() : Solver(Z3_mk_simple_solver(Context.Context)) { + Z3Solver() : SMTSolver(), Solver(Z3_mk_simple_solver(Context.Context)) { Z3_solver_inc_ref(Context.Context, Solver); } public: /// Override implicit copy constructor for correct reference counting. - Z3Solver(const Z3Solver &Copy) : Context(Copy.Context), Solver(Copy.Solver) { + Z3Solver(const Z3Solver &Copy) + : SMTSolver(), Context(Copy.Context), Solver(Copy.Solver) { Z3_solver_inc_ref(Context.Context, Solver); } /// Provide move constructor - Z3Solver(Z3Solver &&Move) : Context(Move.Context), Solver(nullptr) { + Z3Solver(Z3Solver &&Move) + : SMTSolver(), Context(Move.Context), Solver(nullptr) { *this = std::move(Move); } @@ -342,470 +353,460 @@ public: Z3_solver_dec_ref(Context.Context, Solver); } - /// Given a constraint, add it to the solver - void addConstraint(const Z3Expr &Exp) { - Z3_solver_assert(Context.Context, Solver, Exp.AST); + void addConstraint(const SMTExprRef &Exp) const override { + Z3_solver_assert(Context.Context, Solver, toZ3Expr(*Exp).AST); } - // Return a boolean sort. - Z3Sort getBoolSort() { - return Z3Sort(Context, Z3_mk_bool_sort(Context.Context)); + SMTSortRef getBoolSort() override { + return std::make_shared(Context, Z3_mk_bool_sort(Context.Context)); } - // Return an appropriate bitvector sort for the given bitwidth. - Z3Sort getBitvectorSort(unsigned BitWidth) { - return Z3Sort(Context, Z3_mk_bv_sort(Context.Context, BitWidth)); + SMTSortRef getBitvectorSort(unsigned BitWidth) override { + return std::make_shared(Context, + Z3_mk_bv_sort(Context.Context, BitWidth)); } - // Return an appropriate floating-point sort for the given bitwidth. - Z3Sort getFloatSort(unsigned BitWidth) { - Z3_sort Sort; + SMTSortRef getSort(const SMTExprRef &Exp) override { + return std::make_shared( + Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST)); + } - switch (BitWidth) { - default: - llvm_unreachable("Unsupported floating-point bitwidth!"); - break; - case 16: - Sort = Z3_mk_fpa_sort_16(Context.Context); - break; - case 32: - Sort = Z3_mk_fpa_sort_32(Context.Context); - break; - case 64: - Sort = Z3_mk_fpa_sort_64(Context.Context); - break; - case 128: - Sort = Z3_mk_fpa_sort_128(Context.Context); - break; - } - return Z3Sort(Context, Sort); + SMTSortRef getFloat16Sort() override { + return std::make_shared(Context, + Z3_mk_fpa_sort_16(Context.Context)); } - // Return an appropriate sort, given a QualType - Z3Sort MkSort(const QualType &Ty, unsigned BitWidth) { - if (Ty->isBooleanType()) - return getBoolSort(); + SMTSortRef getFloat32Sort() override { + return std::make_shared(Context, + Z3_mk_fpa_sort_32(Context.Context)); + } - if (Ty->isRealFloatingType()) - return getFloatSort(BitWidth); + SMTSortRef getFloat64Sort() override { + return std::make_shared(Context, + Z3_mk_fpa_sort_64(Context.Context)); + } - return getBitvectorSort(BitWidth); + SMTSortRef getFloat128Sort() override { + return std::make_shared(Context, + Z3_mk_fpa_sort_128(Context.Context)); } - // Return an appropriate sort for the given AST. - Z3Sort getSort(Z3_ast AST) { - return Z3Sort(Context, Z3_get_sort(Context.Context, AST)); + SMTExprRef newExprRef(const SMTExpr &E) const override { + return std::make_shared(toZ3Expr(E)); } - /// Given a program state, construct the logical conjunction and add it to - /// the solver - void addStateConstraints(ProgramStateRef State) { - // TODO: Don't add all the constraints, only the relevant ones - ConstraintZ3Ty CZ = State->get(); - ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); + SMTExprRef mkBVNeg(const SMTExprRef &Exp) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvneg(Context.Context, toZ3Expr(*Exp).AST))); + } - // Construct the logical AND of all the constraints - if (I != IE) { - std::vector ASTs; + SMTExprRef mkBVNot(const SMTExprRef &Exp) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvnot(Context.Context, toZ3Expr(*Exp).AST))); + } - while (I != IE) - ASTs.push_back(I++->second.AST); + SMTExprRef mkNot(const SMTExprRef &Exp) override { + return newExprRef( + Z3Expr(Context, Z3_mk_not(Context.Context, toZ3Expr(*Exp).AST))); + } - Z3Expr Conj = fromNBinOp(BO_LAnd, ASTs); - addConstraint(Conj); - } + SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvadd(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); } - // Return an appropriate floating-point rounding mode. - Z3Expr getFloatRoundingMode() { - // TODO: Don't assume nearest ties to even rounding mode - return Z3Expr(Context, Z3_mk_fpa_rne(Context.Context)); + SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsub(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); } - /// Construct a Z3Expr from a unary operator, given a Z3_context. - Z3Expr fromUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) { - Z3_ast AST; + SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvmul(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; + SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsrem(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case UO_Minus: - AST = Z3_mk_bvneg(Context.Context, Exp.AST); - break; + SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvurem(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case UO_Not: - AST = Z3_mk_bvnot(Context.Context, Exp.AST); - break; + SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsdiv(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case UO_LNot: - AST = Z3_mk_not(Context.Context, Exp.AST); - break; - } + SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvudiv(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); + SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvshl(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); } - /// Construct a Z3Expr from a floating-point unary operator, given a - /// Z3_context. - Z3Expr fromFloatUnOp(const UnaryOperator::Opcode Op, const Z3Expr &Exp) { - Z3_ast AST; + SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvashr(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; + SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvlshr(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case UO_Minus: - AST = Z3_mk_fpa_neg(Context.Context, Exp.AST); - break; + SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvxor(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case UO_LNot: - return fromUnOp(Op, Exp); - } + SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvor(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); + SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvand(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); } - /// Construct a Z3Expr from a n-ary binary operator. - Z3Expr fromNBinOp(const BinaryOperator::Opcode Op, - const std::vector &ASTs) { - Z3_ast AST; + SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvult(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; + SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvslt(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case BO_LAnd: - AST = Z3_mk_and(Context.Context, ASTs.size(), ASTs.data()); - break; + SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvugt(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - case BO_LOr: - AST = Z3_mk_or(Context.Context, ASTs.size(), ASTs.data()); - break; - } + SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsgt(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); - } - - /// Construct a Z3Expr from a binary operator, given a Z3_context. - Z3Expr fromBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op, - const Z3Expr &RHS, bool isSigned) { - Z3_ast AST; - - assert(getSort(LHS.AST) == getSort(RHS.AST) && - "AST's must have the same sort!"); - - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; - - // Multiplicative operators - case BO_Mul: - AST = Z3_mk_bvmul(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Div: - AST = isSigned ? Z3_mk_bvsdiv(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvudiv(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Rem: - AST = isSigned ? Z3_mk_bvsrem(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvurem(Context.Context, LHS.AST, RHS.AST); - break; - - // Additive operators - case BO_Add: - AST = Z3_mk_bvadd(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Sub: - AST = Z3_mk_bvsub(Context.Context, LHS.AST, RHS.AST); - break; - - // Bitwise shift operators - case BO_Shl: - AST = Z3_mk_bvshl(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Shr: - AST = isSigned ? Z3_mk_bvashr(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvlshr(Context.Context, LHS.AST, RHS.AST); - break; - - // Relational operators - case BO_LT: - AST = isSigned ? Z3_mk_bvslt(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvult(Context.Context, LHS.AST, RHS.AST); - break; - case BO_GT: - AST = isSigned ? Z3_mk_bvsgt(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvugt(Context.Context, LHS.AST, RHS.AST); - break; - case BO_LE: - AST = isSigned ? Z3_mk_bvsle(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvule(Context.Context, LHS.AST, RHS.AST); - break; - case BO_GE: - AST = isSigned ? Z3_mk_bvsge(Context.Context, LHS.AST, RHS.AST) - : Z3_mk_bvuge(Context.Context, LHS.AST, RHS.AST); - break; - - // Equality operators - case BO_EQ: - AST = Z3_mk_eq(Context.Context, LHS.AST, RHS.AST); - break; - case BO_NE: - return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned)); - break; - - // Bitwise operators - case BO_And: - AST = Z3_mk_bvand(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Xor: - AST = Z3_mk_bvxor(Context.Context, LHS.AST, RHS.AST); - break; - case BO_Or: - AST = Z3_mk_bvor(Context.Context, LHS.AST, RHS.AST); - break; - - // Logical operators - case BO_LAnd: - case BO_LOr: { - std::vector Args = {LHS.AST, RHS.AST}; - return fromNBinOp(Op, Args); - } - } + SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvule(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); - } - - /// Construct a Z3Expr from a special floating-point binary operator, given - /// a Z3_context. - Z3Expr fromFloatSpecialBinOp(const Z3Expr &LHS, - const BinaryOperator::Opcode Op, - const llvm::APFloat::fltCategory &RHS) { - Z3_ast AST; - - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; - - // Equality operators - case BO_EQ: - switch (RHS) { - case llvm::APFloat::fcInfinity: - AST = Z3_mk_fpa_is_infinite(Context.Context, LHS.AST); - break; - case llvm::APFloat::fcNaN: - AST = Z3_mk_fpa_is_nan(Context.Context, LHS.AST); - break; - case llvm::APFloat::fcNormal: - AST = Z3_mk_fpa_is_normal(Context.Context, LHS.AST); - break; - case llvm::APFloat::fcZero: - AST = Z3_mk_fpa_is_zero(Context.Context, LHS.AST); - break; - } - break; - case BO_NE: - return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS)); - break; - } + SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsle(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); + SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvuge(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); } - /// Construct a Z3Expr from a floating-point binary operator, given a - /// Z3_context. - Z3Expr fromFloatBinOp(const Z3Expr &LHS, const BinaryOperator::Opcode Op, - const Z3Expr &RHS) { - Z3_ast AST; + SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_bvsge(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - assert(getSort(LHS.AST) == getSort(RHS.AST) && - "AST's must have the same sort!"); + SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST}; + return newExprRef(Z3Expr(Context, Z3_mk_and(Context.Context, 2, Args))); + } - switch (Op) { - default: - llvm_unreachable("Unimplemented opcode"); - break; + SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + Z3_ast Args[2] = {toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST}; + return newExprRef(Z3Expr(Context, Z3_mk_or(Context.Context, 2, Args))); + } - // Multiplicative operators - case BO_Mul: { - Z3Expr RoundingMode = getFloatRoundingMode(); - AST = Z3_mk_fpa_mul(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); - break; - } - case BO_Div: { - Z3Expr RoundingMode = getFloatRoundingMode(); - AST = Z3_mk_fpa_div(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); - break; - } - case BO_Rem: - AST = Z3_mk_fpa_rem(Context.Context, LHS.AST, RHS.AST); - break; - - // Additive operators - case BO_Add: { - Z3Expr RoundingMode = getFloatRoundingMode(); - AST = Z3_mk_fpa_add(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); - break; - } - case BO_Sub: { - Z3Expr RoundingMode = getFloatRoundingMode(); - AST = Z3_mk_fpa_sub(Context.Context, RoundingMode.AST, LHS.AST, RHS.AST); - break; - } + SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_eq(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - // Relational operators - case BO_LT: - AST = Z3_mk_fpa_lt(Context.Context, LHS.AST, RHS.AST); - break; - case BO_GT: - AST = Z3_mk_fpa_gt(Context.Context, LHS.AST, RHS.AST); - break; - case BO_LE: - AST = Z3_mk_fpa_leq(Context.Context, LHS.AST, RHS.AST); - break; - case BO_GE: - AST = Z3_mk_fpa_geq(Context.Context, LHS.AST, RHS.AST); - break; - - // Equality operators - case BO_EQ: - AST = Z3_mk_fpa_eq(Context.Context, LHS.AST, RHS.AST); - break; - case BO_NE: - return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS)); - break; - - // Logical operators - case BO_LAnd: - case BO_LOr: - return fromBinOp(LHS, Op, RHS, false); - } + SMTExprRef mkFPNeg(const SMTExprRef &Exp) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_neg(Context.Context, toZ3Expr(*Exp).AST))); + } - return Z3Expr(Context, AST); + SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) override { + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_is_infinite(Context.Context, toZ3Expr(*Exp).AST))); } - /// Construct a Z3Expr from a SymbolData, given a Z3_context. - Z3Expr fromData(const SymbolID ID, const QualType &Ty, uint64_t BitWidth) { - llvm::Twine Name = "$" + llvm::Twine(ID); + SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_is_nan(Context.Context, toZ3Expr(*Exp).AST))); + } - Z3Sort Sort = MkSort(Ty, BitWidth); - - Z3_symbol Symbol = Z3_mk_string_symbol(Context.Context, Name.str().c_str()); - Z3_ast AST = Z3_mk_const(Context.Context, Symbol, Sort.Sort); - return Z3Expr(Context, AST); - } - - /// Construct a Z3Expr from a SymbolCast, given a Z3_context. - Z3Expr fromCast(const Z3Expr &Exp, QualType ToTy, uint64_t ToBitWidth, - QualType FromTy, uint64_t FromBitWidth) { - Z3_ast AST; - - if ((FromTy->isIntegralOrEnumerationType() && - ToTy->isIntegralOrEnumerationType()) || - (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) || - (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) || - (FromTy->isReferenceType() ^ ToTy->isReferenceType())) { - // Special case: Z3 boolean type is distinct from bitvector type, so - // must use if-then-else expression instead of direct cast - if (FromTy->isBooleanType()) { - assert(ToBitWidth > 0 && "BitWidth must be positive!"); - Z3Expr Zero = fromInt("0", ToBitWidth); - Z3Expr One = fromInt("1", ToBitWidth); - AST = Z3_mk_ite(Context.Context, Exp.AST, One.AST, Zero.AST); - } else if (ToBitWidth > FromBitWidth) { - AST = FromTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_sign_ext(Context.Context, ToBitWidth - FromBitWidth, - Exp.AST) - : Z3_mk_zero_ext(Context.Context, ToBitWidth - FromBitWidth, - Exp.AST); - } else if (ToBitWidth < FromBitWidth) { - AST = Z3_mk_extract(Context.Context, ToBitWidth - 1, 0, Exp.AST); - } else { - // Both are bitvectors with the same width, ignore the type cast - return Exp; - } - } else if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) { - if (ToBitWidth != FromBitWidth) { - Z3Expr RoundingMode = getFloatRoundingMode(); - Z3Sort Sort = getFloatSort(ToBitWidth); - AST = Z3_mk_fpa_to_fp_float(Context.Context, RoundingMode.AST, Exp.AST, - Sort.Sort); - } else { - return Exp; - } - } else if (FromTy->isIntegralOrEnumerationType() && - ToTy->isRealFloatingType()) { - Z3Expr RoundingMode = getFloatRoundingMode(); - Z3Sort Sort = getFloatSort(ToBitWidth); - AST = FromTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_fpa_to_fp_signed(Context.Context, RoundingMode.AST, - Exp.AST, Sort.Sort) - : Z3_mk_fpa_to_fp_unsigned(Context.Context, RoundingMode.AST, - Exp.AST, Sort.Sort); - } else if (FromTy->isRealFloatingType() && - ToTy->isIntegralOrEnumerationType()) { - Z3Expr RoundingMode = getFloatRoundingMode(); - AST = ToTy->isSignedIntegerOrEnumerationType() - ? Z3_mk_fpa_to_sbv(Context.Context, RoundingMode.AST, Exp.AST, - ToBitWidth) - : Z3_mk_fpa_to_ubv(Context.Context, RoundingMode.AST, Exp.AST, - ToBitWidth); - } else { - llvm_unreachable("Unsupported explicit type cast!"); - } + SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) override { + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_is_normal(Context.Context, toZ3Expr(*Exp).AST))); + } + + SMTExprRef mkFPIsZero(const SMTExprRef &Exp) override { + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_is_zero(Context.Context, toZ3Expr(*Exp).AST))); + } + + SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef( + Z3Expr(Context, + Z3_mk_fpa_mul(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST))); + } + + SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef( + Z3Expr(Context, + Z3_mk_fpa_div(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST))); + } + + SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_rem(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef( + Z3Expr(Context, + Z3_mk_fpa_add(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST))); + } + + SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef( + Z3Expr(Context, + Z3_mk_fpa_sub(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST, toZ3Expr(*RoundingMode).AST))); + } + + SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_lt(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_gt(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } - return Z3Expr(Context, AST); + SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_leq(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_geq(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_fpa_eq(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, + const SMTExprRef &F) override { + return newExprRef( + Z3Expr(Context, Z3_mk_ite(Context.Context, toZ3Expr(*Cond).AST, + toZ3Expr(*T).AST, toZ3Expr(*F).AST))); + } + + SMTExprRef mkSignExt(unsigned i, const SMTExprRef &Exp) override { + return newExprRef(Z3Expr( + Context, Z3_mk_sign_ext(Context.Context, i, toZ3Expr(*Exp).AST))); + } + + SMTExprRef mkZeroExt(unsigned i, const SMTExprRef &Exp) override { + return newExprRef(Z3Expr( + Context, Z3_mk_zero_ext(Context.Context, i, toZ3Expr(*Exp).AST))); + } + + SMTExprRef mkExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) override { + return newExprRef(Z3Expr(Context, Z3_mk_extract(Context.Context, High, Low, + toZ3Expr(*Exp).AST))); + } + + SMTExprRef mkConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + return newExprRef( + Z3Expr(Context, Z3_mk_concat(Context.Context, toZ3Expr(*LHS).AST, + toZ3Expr(*RHS).AST))); + } + + SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef(Z3Expr( + Context, + Z3_mk_fpa_to_fp_float(Context.Context, toZ3Expr(*RoundingMode).AST, + toZ3Expr(*From).AST, toZ3Sort(*To).Sort))); + } + + SMTExprRef mkFPtoSBV(const SMTExprRef &From, const SMTSortRef &To) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef(Z3Expr( + Context, + Z3_mk_fpa_to_fp_signed(Context.Context, toZ3Expr(*RoundingMode).AST, + toZ3Expr(*From).AST, toZ3Sort(*To).Sort))); + } + + SMTExprRef mkFPtoUBV(const SMTExprRef &From, const SMTSortRef &To) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef(Z3Expr( + Context, + Z3_mk_fpa_to_fp_unsigned(Context.Context, toZ3Expr(*RoundingMode).AST, + toZ3Expr(*From).AST, toZ3Sort(*To).Sort))); + } + + SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_to_sbv(Context.Context, toZ3Expr(*RoundingMode).AST, + toZ3Expr(*From).AST, ToWidth))); + } + + SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) override { + SMTExprRef RoundingMode = getFloatRoundingMode(); + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_to_ubv(Context.Context, toZ3Expr(*RoundingMode).AST, + toZ3Expr(*From).AST, ToWidth))); + } + + SMTExprRef mkBoolean(const bool b) override { + return newExprRef(Z3Expr(Context, b ? Z3_mk_true(Context.Context) + : Z3_mk_false(Context.Context))); + } + + SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) override { + const SMTSortRef Sort = getBitvectorSort(BitWidth); + return newExprRef( + Z3Expr(Context, Z3_mk_numeral(Context.Context, Int.toString(10).c_str(), + toZ3Sort(*Sort).Sort))); + } + + SMTExprRef mkFloat(const llvm::APFloat Float) override { + SMTSortRef Sort = + getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics())); + + llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false); + SMTExprRef Z3Int = mkBitvector(Int, Int.getBitWidth()); + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST, + toZ3Sort(*Sort).Sort))); + } + + SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) override { + return newExprRef( + Z3Expr(Context, Z3_mk_const(Context.Context, + Z3_mk_string_symbol(Context.Context, Name), + toZ3Sort(*Sort).Sort))); + } + + const llvm::APSInt getBitvector(const SMTExprRef &Exp) override { + // FIXME: this returns a string and the bitWidth is overridden + return llvm::APSInt( + Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST)); + } + + bool getBoolean(const SMTExprRef &Exp) override { + return Z3_get_bool_value(Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE; + } + + // Return an appropriate floating-point rounding mode. + SMTExprRef getFloatRoundingMode() override { + // TODO: Don't assume nearest ties to even rounding mode + return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context))); + } + + /// Construct a Z3Expr from a SymbolData, given a Z3_context. + SMTExprRef fromData(const SymbolID ID, const QualType &Ty, + uint64_t BitWidth) override { + llvm::Twine Name = "$" + llvm::Twine(ID); + return mkSymbol(Name.str().c_str(), mkSort(Ty, BitWidth)); } /// Construct a Z3Expr from a boolean, given a Z3_context. - Z3Expr fromBoolean(const bool Bool) { + SMTExprRef fromBoolean(const bool Bool) override { Z3_ast AST = Bool ? Z3_mk_true(Context.Context) : Z3_mk_false(Context.Context); - return Z3Expr(Context, AST); + return newExprRef(Z3Expr(Context, AST)); } /// Construct a Z3Expr from a finite APFloat, given a Z3_context. - Z3Expr fromAPFloat(const llvm::APFloat &Float) { - Z3_ast AST; - Z3Sort Sort = + SMTExprRef fromAPFloat(const llvm::APFloat &Float) override { + SMTSortRef Sort = getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics())); llvm::APSInt Int = llvm::APSInt(Float.bitcastToAPInt(), false); - Z3Expr Z3Int = fromAPSInt(Int); - AST = Z3_mk_fpa_to_fp_bv(Context.Context, Z3Int.AST, Sort.Sort); - return Z3Expr(Context, AST); + SMTExprRef Z3Int = fromAPSInt(Int); + return newExprRef(Z3Expr( + Context, Z3_mk_fpa_to_fp_bv(Context.Context, toZ3Expr(*Z3Int).AST, + toZ3Sort(*Sort).Sort))); } /// Construct a Z3Expr from an APSInt, given a Z3_context. - Z3Expr fromAPSInt(const llvm::APSInt &Int) { - Z3Sort Sort = getBitvectorSort(Int.getBitWidth()); - Z3_ast AST = - Z3_mk_numeral(Context.Context, Int.toString(10).c_str(), Sort.Sort); - return Z3Expr(Context, AST); + SMTExprRef fromAPSInt(const llvm::APSInt &Int) override { + SMTSortRef Sort = getBitvectorSort(Int.getBitWidth()); + Z3_ast AST = Z3_mk_numeral(Context.Context, Int.toString(10).c_str(), + toZ3Sort(*Sort).Sort); + return newExprRef(Z3Expr(Context, AST)); } /// Construct a Z3Expr from an integer, given a Z3_context. - Z3Expr fromInt(const char *Int, uint64_t BitWidth) { - Z3Sort Sort = getBitvectorSort(BitWidth); - Z3_ast AST = Z3_mk_numeral(Context.Context, Int, Sort.Sort); - return Z3Expr(Context, AST); + SMTExprRef fromInt(const char *Int, uint64_t BitWidth) override { + SMTSortRef Sort = getBitvectorSort(BitWidth); + Z3_ast AST = Z3_mk_numeral(Context.Context, Int, toZ3Sort(*Sort).Sort); + return newExprRef(Z3Expr(Context, AST)); } - /// Construct an APFloat from a Z3Expr, given the AST representation - bool toAPFloat(const Z3Sort &Sort, const Z3_ast &AST, llvm::APFloat &Float, - bool useSemantics = true) { - assert(Sort.isFloatSort() && "Unsupported sort to floating-point!"); + bool toAPFloat(const SMTSortRef &Sort, const SMTExprRef &AST, + llvm::APFloat &Float, bool useSemantics) { + assert(Sort->isFloatSort() && "Unsupported sort to floating-point!"); - llvm::APSInt Int(Sort.getFloatSortSize(), true); + llvm::APSInt Int(Sort->getFloatSortSize(), true); const llvm::fltSemantics &Semantics = - getFloatSemantics(Sort.getFloatSortSize()); - Z3Sort BVSort = getBitvectorSort(Sort.getFloatSortSize()); + getFloatSemantics(Sort->getFloatSortSize()); + SMTSortRef BVSort = getBitvectorSort(Sort->getFloatSortSize()); if (!toAPSInt(BVSort, AST, Int, true)) { return false; } @@ -819,11 +820,10 @@ public: return true; } - /// Construct an APSInt from a Z3Expr, given the AST representation - bool toAPSInt(const Z3Sort &Sort, const Z3_ast &AST, llvm::APSInt &Int, - bool useSemantics = true) { - if (Sort.isBitvectorSort()) { - if (useSemantics && Int.getBitWidth() != Sort.getBitvectorSortSize()) { + bool toAPSInt(const SMTSortRef &Sort, const SMTExprRef &AST, + llvm::APSInt &Int, bool useSemantics) { + if (Sort->isBitvectorSort()) { + if (useSemantics && Int.getBitWidth() != Sort->getBitvectorSortSize()) { assert(false && "Bitvector types don't match!"); return false; } @@ -832,15 +832,14 @@ public: // Force cast because Z3 defines __uint64 to be a unsigned long long // type, which isn't compatible with a unsigned long type, even if they // are the same size. - Z3_get_numeral_uint64(Context.Context, AST, + Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, reinterpret_cast<__uint64 *>(&Value[0])); - if (Sort.getBitvectorSortSize() <= 64) { + if (Sort->getBitvectorSortSize() <= 64) { Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), Int.isUnsigned()); - } else if (Sort.getBitvectorSortSize() == 128) { - Z3Expr ASTHigh = - Z3Expr(Context, Z3_mk_extract(Context.Context, 127, 64, AST)); - Z3_get_numeral_uint64(Context.Context, AST, + } else if (Sort->getBitvectorSortSize() == 128) { + SMTExprRef ASTHigh = mkExtract(127, 64, AST); + Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, reinterpret_cast<__uint64 *>(&Value[1])); Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), Int.isUnsigned()); @@ -851,17 +850,14 @@ public: return true; } - if (Sort.isBooleanSort()) { + if (Sort->isBooleanSort()) { if (useSemantics && Int.getBitWidth() < 1) { assert(false && "Boolean type doesn't match!"); return false; } - Int = llvm::APSInt( - llvm::APInt(Int.getBitWidth(), - Z3_get_bool_value(Context.Context, AST) == Z3_L_TRUE ? 1 - : 0), - Int.isUnsigned()); + Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), getBoolean(AST)), + Int.isUnsigned()); return true; } @@ -870,50 +866,53 @@ public: /// Given an expression and a model, extract the value of this operand in /// the model. - bool getInterpretation(const Z3Model Model, const Z3Expr &Exp, - llvm::APSInt &Int) { - Z3_func_decl Func = - Z3_get_app_decl(Context.Context, Z3_to_app(Context.Context, Exp.AST)); + bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override { + Z3Model Model = getModel(); + Z3_func_decl Func = Z3_get_app_decl( + Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST)); if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE) return false; - Z3_ast Assign = - Z3_model_get_const_interp(Context.Context, Model.Model, Func); - Z3Sort Sort = getSort(Assign); + SMTExprRef Assign = newExprRef( + Z3Expr(Context, + Z3_model_get_const_interp(Context.Context, Model.Model, Func))); + SMTSortRef Sort = getSort(Assign); return toAPSInt(Sort, Assign, Int, true); } /// Given an expression and a model, extract the value of this operand in /// the model. - bool getInterpretation(const Z3Model Model, const Z3Expr &Exp, - llvm::APFloat &Float) { - Z3_func_decl Func = - Z3_get_app_decl(Context.Context, Z3_to_app(Context.Context, Exp.AST)); + bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override { + Z3Model Model = getModel(); + Z3_func_decl Func = Z3_get_app_decl( + Context.Context, Z3_to_app(Context.Context, toZ3Expr(*Exp).AST)); if (Z3_model_has_interp(Context.Context, Model.Model, Func) != Z3_L_TRUE) return false; - Z3_ast Assign = - Z3_model_get_const_interp(Context.Context, Model.Model, Func); - Z3Sort Sort = getSort(Assign); + SMTExprRef Assign = newExprRef( + Z3Expr(Context, + Z3_model_get_const_interp(Context.Context, Model.Model, Func))); + SMTSortRef Sort = getSort(Assign); return toAPFloat(Sort, Assign, Float, true); } - // Callback function for doCast parameter on APSInt type. - llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, - uint64_t ToWidth, QualType FromTy, - uint64_t FromWidth) { - APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType()); - return TargetType.convert(V); - } - /// Check if the constraints are satisfiable - Z3_lbool check() { return Z3_solver_check(Context.Context, Solver); } + ConditionTruthVal check() const override { + Z3_lbool res = Z3_solver_check(Context.Context, Solver); + if (res == Z3_L_TRUE) + return true; + + if (res == Z3_L_FALSE) + return false; + + return ConditionTruthVal(); + } /// Push the current solver state - void push() { return Z3_solver_push(Context.Context, Solver); } + void push() override { return Z3_solver_push(Context.Context, Solver); } /// Pop the previous solver state - void pop(unsigned NumStates = 1) { + void pop(unsigned NumStates = 1) override { assert(Z3_solver_get_num_scopes(Context.Context, Solver) >= NumStates); return Z3_solver_pop(Context.Context, Solver, NumStates); } @@ -925,13 +924,11 @@ public: } /// Reset the solver and remove all constraints. - void reset() { Z3_solver_reset(Context.Context, Solver); } + void reset() const override { Z3_solver_reset(Context.Context, Solver); } - void print(raw_ostream &OS) const { + void print(raw_ostream &OS) const override { OS << Z3_solver_to_string(Context.Context, Solver); } - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } }; // end class Z3Solver class Z3ConstraintManager : public SMTConstraintManager { @@ -988,54 +985,60 @@ private: // Internal implementation. //===------------------------------------------------------------------===// + /// Given a program state, construct the logical conjunction and add it to + /// the solver + void addStateConstraints(ProgramStateRef State) const; + // Check whether a new model is satisfiable, and update the program state. ProgramStateRef assumeZ3Expr(ProgramStateRef State, SymbolRef Sym, - const Z3Expr &Exp); + const SMTExprRef &Exp); // Generate and check a Z3 model, using the given constraint. - Z3_lbool checkZ3Model(ProgramStateRef State, const Z3Expr &Exp) const; + ConditionTruthVal checkZ3Model(ProgramStateRef State, + const SMTExprRef &Exp) const; // Generate a Z3Expr that represents the given symbolic expression. // Sets the hasComparison parameter if the expression has a comparison // operator. // Sets the RetTy parameter to the final return type after promotions and // casts. - Z3Expr getZ3Expr(SymbolRef Sym, QualType *RetTy = nullptr, - bool *hasComparison = nullptr) const; + SMTExprRef getZ3Expr(SymbolRef Sym, QualType *RetTy = nullptr, + bool *hasComparison = nullptr) const; // Generate a Z3Expr that takes the logical not of an expression. - Z3Expr getZ3NotExpr(const Z3Expr &Exp) const; + SMTExprRef getZ3NotExpr(const SMTExprRef &Exp) const; // Generate a Z3Expr that compares the expression to zero. - Z3Expr getZ3ZeroExpr(const Z3Expr &Exp, QualType RetTy, - bool Assumption) const; + SMTExprRef getZ3ZeroExpr(const SMTExprRef &Exp, QualType RetTy, + bool Assumption) const; // Recursive implementation to unpack and generate symbolic expression. // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - Z3Expr getZ3SymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const; + SMTExprRef getZ3SymExpr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const; // Wrapper to generate Z3Expr from SymbolData. - Z3Expr getZ3DataExpr(const SymbolID ID, QualType Ty) const; + SMTExprRef getZ3DataExpr(const SymbolID ID, QualType Ty) const; // Wrapper to generate Z3Expr from SymbolCast. - Z3Expr getZ3CastExpr(const Z3Expr &Exp, QualType FromTy, QualType Ty) const; + SMTExprRef getZ3CastExpr(const SMTExprRef &Exp, QualType FromTy, + QualType Ty) const; // Wrapper to generate Z3Expr from BinarySymExpr. // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - Z3Expr getZ3SymBinExpr(const BinarySymExpr *BSE, bool *hasComparison, - QualType *RetTy) const; + SMTExprRef getZ3SymBinExpr(const BinarySymExpr *BSE, bool *hasComparison, + QualType *RetTy) const; // Wrapper to generate Z3Expr from unpacked binary symbolic expression. // Sets the RetTy parameter. See getZ3Expr(). - Z3Expr getZ3BinExpr(const Z3Expr &LHS, QualType LTy, - BinaryOperator::Opcode Op, const Z3Expr &RHS, - QualType RTy, QualType *RetTy) const; + SMTExprRef getZ3BinExpr(const SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, const SMTExprRef &RHS, + QualType RTy, QualType *RetTy) const; // Wrapper to generate Z3Expr from a range. If From == To, an equality will // be created instead. - Z3Expr getZ3RangeExpr(SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, bool InRange); + SMTExprRef getZ3RangeExpr(SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, bool InRange); //===------------------------------------------------------------------===// // Helper functions. @@ -1051,33 +1054,49 @@ private: // Perform implicit type conversion on binary symbolic expressions. // May modify all input parameters. // TODO: Refactor to use built-in conversion functions - void doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, QualType <y, + void doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, QualType &RTy) const; // Perform implicit integer type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleIntegerConversion() - template + template void doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const; // Perform implicit floating-point type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleFloatConversion() - template + template void doFloatTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const; }; // end class Z3ConstraintManager } // end anonymous namespace +void Z3ConstraintManager::addStateConstraints(ProgramStateRef State) const { + // TODO: Don't add all the constraints, only the relevant ones + ConstraintZ3Ty CZ = State->get(); + ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); + + // Construct the logical AND of all the constraints + if (I != IE) { + std::vector ASTs; + + while (I != IE) + ASTs.push_back(Solver.newExprRef(Z3Expr(I++->second))); + + Solver.addConstraint(Solver.fromNBinOp(BO_LAnd, ASTs)); + } +} + ProgramStateRef Z3ConstraintManager::assumeSym(ProgramStateRef State, SymbolRef Sym, bool Assumption) { QualType RetTy; bool hasComparison; - Z3Expr Exp = getZ3Expr(Sym, &RetTy, &hasComparison); + SMTExprRef Exp = getZ3Expr(Sym, &RetTy, &hasComparison); // Create zero comparison for implicit boolean cast, with reversed assumption if (!hasComparison && !RetTy->isBooleanType()) return assumeZ3Expr(State, Sym, getZ3ZeroExpr(Exp, RetTy, !Assumption)); @@ -1145,27 +1164,29 @@ ConditionTruthVal Z3ConstraintManager::checkNull(ProgramStateRef State, SymbolRef Sym) { QualType RetTy; // The expression may be casted, so we cannot call getZ3DataExpr() directly - Z3Expr VarExp = getZ3Expr(Sym, &RetTy); - Z3Expr Exp = getZ3ZeroExpr(VarExp, RetTy, true); + SMTExprRef VarExp = getZ3Expr(Sym, &RetTy); + SMTExprRef Exp = getZ3ZeroExpr(VarExp, RetTy, true); + // Negate the constraint - Z3Expr NotExp = getZ3ZeroExpr(VarExp, RetTy, false); + SMTExprRef NotExp = getZ3ZeroExpr(VarExp, RetTy, false); Solver.reset(); - Solver.addStateConstraints(State); + addStateConstraints(State); Solver.push(); Solver.addConstraint(Exp); - Z3_lbool isSat = Solver.check(); + ConditionTruthVal isSat = Solver.check(); Solver.pop(); Solver.addConstraint(NotExp); - Z3_lbool isNotSat = Solver.check(); + ConditionTruthVal isNotSat = Solver.check(); // Zero is the only possible solution - if (isSat == Z3_L_TRUE && isNotSat == Z3_L_FALSE) + if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse()) return true; + // Zero is not a solution - else if (isSat == Z3_L_FALSE && isNotSat == Z3_L_TRUE) + if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue()) return false; // Zero may be a solution @@ -1183,29 +1204,31 @@ const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, llvm::APSInt Value(Ctx.getTypeSize(Ty), !Ty->isSignedIntegerOrEnumerationType()); - Z3Expr Exp = getZ3DataExpr(SD->getSymbolID(), Ty); + SMTExprRef Exp = getZ3DataExpr(SD->getSymbolID(), Ty); Solver.reset(); - Solver.addStateConstraints(State); + addStateConstraints(State); // Constraints are unsatisfiable - if (Solver.check() != Z3_L_TRUE) + ConditionTruthVal isSat = Solver.check(); + if (!isSat.isConstrainedTrue()) return nullptr; - Z3Model Model = Solver.getModel(); // Model does not assign interpretation - if (!Solver.getInterpretation(Model, Exp, Value)) + if (!Solver.getInterpretation(Exp, Value)) return nullptr; // A value has been obtained, check if it is the only value - Z3Expr NotExp = Solver.fromBinOp( + SMTExprRef NotExp = Solver.fromBinOp( Exp, BO_NE, Ty->isBooleanType() ? Solver.fromBoolean(Value.getBoolValue()) : Solver.fromAPSInt(Value), false); Solver.addConstraint(NotExp); - if (Solver.check() == Z3_L_TRUE) + + ConditionTruthVal isNotSat = Solver.check(); + if (isNotSat.isConstrainedTrue()) return nullptr; // This is the only solution, store it @@ -1244,8 +1267,8 @@ const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, QualType LTy, RTy; std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); - doIntTypeConversion(ConvertedLHS, LTy, - ConvertedRHS, RTy); + doIntTypeConversion( + ConvertedLHS, LTy, ConvertedRHS, RTy); return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); } @@ -1272,9 +1295,9 @@ void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { for (const auto &I : CR) { SymbolRef Sym = I.first; - Z3Expr Constraints = Solver.fromBoolean(false); + SMTExprRef Constraints = Solver.fromBoolean(false); for (const auto &Range : I.second) { - Z3Expr SymRange = + SMTExprRef SymRange = getZ3RangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); // FIXME: the last argument (isSigned) is not used when generating the @@ -1287,10 +1310,7 @@ void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { } clang::ento::ConditionTruthVal Z3ConstraintManager::isModelFeasible() { - if (Solver.check() == Z3_L_FALSE) - return false; - - return ConditionTruthVal(); + return Solver.check(); } LLVM_DUMP_METHOD void Z3ConstraintManager::dump() const { Solver.dump(); } @@ -1301,24 +1321,25 @@ LLVM_DUMP_METHOD void Z3ConstraintManager::dump() const { Solver.dump(); } ProgramStateRef Z3ConstraintManager::assumeZ3Expr(ProgramStateRef State, SymbolRef Sym, - const Z3Expr &Exp) { + const SMTExprRef &Exp) { // Check the model, avoid simplifying AST to save time - if (checkZ3Model(State, Exp) == Z3_L_TRUE) - return State->add(std::make_pair(Sym, Exp)); + if (checkZ3Model(State, Exp).isConstrainedTrue()) + return State->add(std::make_pair(Sym, toZ3Expr(*Exp))); return nullptr; } -Z3_lbool Z3ConstraintManager::checkZ3Model(ProgramStateRef State, - const Z3Expr &Exp) const { +ConditionTruthVal +Z3ConstraintManager::checkZ3Model(ProgramStateRef State, + const SMTExprRef &Exp) const { Solver.reset(); Solver.addConstraint(Exp); - Solver.addStateConstraints(State); + addStateConstraints(State); return Solver.check(); } -Z3Expr Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { +SMTExprRef Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const { if (hasComparison) { *hasComparison = false; } @@ -1326,12 +1347,13 @@ Z3Expr Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy, return getZ3SymExpr(Sym, RetTy, hasComparison); } -Z3Expr Z3ConstraintManager::getZ3NotExpr(const Z3Expr &Exp) const { +SMTExprRef Z3ConstraintManager::getZ3NotExpr(const SMTExprRef &Exp) const { return Solver.fromUnOp(UO_LNot, Exp); } -Z3Expr Z3ConstraintManager::getZ3ZeroExpr(const Z3Expr &Exp, QualType Ty, - bool Assumption) const { +SMTExprRef Z3ConstraintManager::getZ3ZeroExpr(const SMTExprRef &Exp, + QualType Ty, + bool Assumption) const { ASTContext &Ctx = getBasicVals().getContext(); if (Ty->isRealFloatingType()) { llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); @@ -1350,8 +1372,8 @@ Z3Expr Z3ConstraintManager::getZ3ZeroExpr(const Z3Expr &Exp, QualType Ty, llvm_unreachable("Unsupported type for zero value!"); } -Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { +SMTExprRef Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const { if (const SymbolData *SD = dyn_cast(Sym)) { if (RetTy) *RetTy = Sym->getType(); @@ -1362,7 +1384,7 @@ Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, *RetTy = Sym->getType(); QualType FromTy; - Z3Expr Exp = getZ3SymExpr(SC->getOperand(), &FromTy, hasComparison); + SMTExprRef Exp = getZ3SymExpr(SC->getOperand(), &FromTy, hasComparison); // Casting an expression with a comparison invalidates it. Note that this // must occur after the recursive call above. // e.g. (signed char) (x > 0) @@ -1370,7 +1392,7 @@ Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, *hasComparison = false; return getZ3CastExpr(Exp, FromTy, Sym->getType()); } else if (const BinarySymExpr *BSE = dyn_cast(Sym)) { - Z3Expr Exp = getZ3SymBinExpr(BSE, hasComparison, RetTy); + SMTExprRef Exp = getZ3SymBinExpr(BSE, hasComparison, RetTy); // Set the hasComparison parameter, in post-order traversal order. if (hasComparison) *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); @@ -1380,52 +1402,52 @@ Z3Expr Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, llvm_unreachable("Unsupported SymbolRef type!"); } -Z3Expr Z3ConstraintManager::getZ3DataExpr(const SymbolID ID, - QualType Ty) const { +SMTExprRef Z3ConstraintManager::getZ3DataExpr(const SymbolID ID, + QualType Ty) const { ASTContext &Ctx = getBasicVals().getContext(); return Solver.fromData(ID, Ty, Ctx.getTypeSize(Ty)); } -Z3Expr Z3ConstraintManager::getZ3CastExpr(const Z3Expr &Exp, QualType FromTy, - QualType ToTy) const { +SMTExprRef Z3ConstraintManager::getZ3CastExpr(const SMTExprRef &Exp, + QualType FromTy, + QualType ToTy) const { ASTContext &Ctx = getBasicVals().getContext(); return Solver.fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, Ctx.getTypeSize(FromTy)); } -Z3Expr Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE, - bool *hasComparison, - QualType *RetTy) const { +SMTExprRef Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE, + bool *hasComparison, + QualType *RetTy) const { QualType LTy, RTy; BinaryOperator::Opcode Op = BSE->getOpcode(); if (const SymIntExpr *SIE = dyn_cast(BSE)) { - Z3Expr LHS = getZ3SymExpr(SIE->getLHS(), <y, hasComparison); + SMTExprRef LHS = getZ3SymExpr(SIE->getLHS(), <y, hasComparison); llvm::APSInt NewRInt; std::tie(NewRInt, RTy) = fixAPSInt(SIE->getRHS()); - Z3Expr RHS = Solver.fromAPSInt(NewRInt); + SMTExprRef RHS = Solver.fromAPSInt(NewRInt); return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { llvm::APSInt NewLInt; std::tie(NewLInt, LTy) = fixAPSInt(ISE->getLHS()); - Z3Expr LHS = Solver.fromAPSInt(NewLInt); - Z3Expr RHS = getZ3SymExpr(ISE->getRHS(), &RTy, hasComparison); + SMTExprRef LHS = Solver.fromAPSInt(NewLInt); + SMTExprRef RHS = getZ3SymExpr(ISE->getRHS(), &RTy, hasComparison); return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { - Z3Expr LHS = getZ3SymExpr(SSM->getLHS(), <y, hasComparison); - Z3Expr RHS = getZ3SymExpr(SSM->getRHS(), &RTy, hasComparison); + SMTExprRef LHS = getZ3SymExpr(SSM->getLHS(), <y, hasComparison); + SMTExprRef RHS = getZ3SymExpr(SSM->getRHS(), &RTy, hasComparison); return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); } else { llvm_unreachable("Unsupported BinarySymExpr type!"); } } -Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy, - BinaryOperator::Opcode Op, - const Z3Expr &RHS, QualType RTy, - QualType *RetTy) const { - Z3Expr NewLHS = LHS; - Z3Expr NewRHS = RHS; +SMTExprRef Z3ConstraintManager::getZ3BinExpr( + const SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, + const SMTExprRef &RHS, QualType RTy, QualType *RetTy) const { + SMTExprRef NewLHS = LHS; + SMTExprRef NewRHS = RHS; doTypeConversion(NewLHS, NewRHS, LTy, RTy); // Update the return type parameter if the output type has changed. if (RetTy) { @@ -1452,19 +1474,19 @@ Z3Expr Z3ConstraintManager::getZ3BinExpr(const Z3Expr &LHS, QualType LTy, LTy->isSignedIntegerOrEnumerationType()); } -Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool InRange) { +SMTExprRef Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) { // Convert lower bound QualType FromTy; llvm::APSInt NewFromInt; std::tie(NewFromInt, FromTy) = fixAPSInt(From); - Z3Expr FromExp = Solver.fromAPSInt(NewFromInt); + SMTExprRef FromExp = Solver.fromAPSInt(NewFromInt); // Convert symbol QualType SymTy; - Z3Expr Exp = getZ3Expr(Sym, &SymTy); + SMTExprRef Exp = getZ3Expr(Sym, &SymTy); // Construct single (in)equality if (From == To) @@ -1474,14 +1496,15 @@ Z3Expr Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, QualType ToTy; llvm::APSInt NewToInt; std::tie(NewToInt, ToTy) = fixAPSInt(To); - Z3Expr ToExp = Solver.fromAPSInt(NewToInt); + SMTExprRef ToExp = Solver.fromAPSInt(NewToInt); assert(FromTy == ToTy && "Range values have different types!"); // Construct two (in)equalities, and a logical and/or - Z3Expr LHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, - FromTy, /*RetTy=*/nullptr); - Z3Expr RHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, - /*RetTy=*/nullptr); + SMTExprRef LHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, + FromTy, /*RetTy=*/nullptr); + SMTExprRef RHS = + getZ3BinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); return Solver.fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, SymTy->isSignedIntegerOrEnumerationType()); @@ -1512,7 +1535,7 @@ Z3ConstraintManager::fixAPSInt(const llvm::APSInt &Int) const { return std::make_pair(NewInt, getAPSIntType(NewInt)); } -void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, +void Z3ConstraintManager::doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, QualType &RTy) const { ASTContext &Ctx = getBasicVals().getContext(); @@ -1520,12 +1543,13 @@ void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, // Perform type conversion if (LTy->isIntegralOrEnumerationType() && RTy->isIntegralOrEnumerationType()) { - if (LTy->isArithmeticType() && RTy->isArithmeticType()) - return doIntTypeConversion(LHS, LTy, RHS, - RTy); + if (LTy->isArithmeticType() && RTy->isArithmeticType()) { + doIntTypeConversion(LHS, LTy, RHS, RTy); + return; + } } else if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { - return doFloatTypeConversion(LHS, LTy, RHS, - RTy); + doFloatTypeConversion(LHS, LTy, RHS, RTy); + return; } else if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || (LTy->isReferenceType() || RTy->isReferenceType())) { @@ -1576,8 +1600,8 @@ void Z3ConstraintManager::doTypeConversion(Z3Expr &LHS, Z3Expr &RHS, // TODO: Refine behavior for invalid type casts } -template +template void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { ASTContext &Ctx = getBasicVals().getContext(); @@ -1654,8 +1678,8 @@ void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, } } -template +template void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { ASTContext &Ctx = getBasicVals().getContext(); -- GitLab From 45c38892c8add9247ad37a0b39ec935f364e4f30 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:29 +0000 Subject: [PATCH 0715/1023] [analyzer] Moved non solver specific code from Z3ConstraintManager to SMTConstraintManager Summary: This patch moves a lot of code from `Z3ConstraintManager` to `SMTConstraintManager`, leaving only the necessary: * `canReasonAbout` which returns if a Solver can handle a given `SVal` (should be moved to `SMTSolver` in the future). * `removeDeadBindings`, `assumeExpr` and `print`: methods that need to use `ConstraintZ3Ty`, can probably be moved to `SMTConstraintManager` in the future. The patch creates a new file, `SMTConstraintManager.cpp` with the moved code. Conceptually, this is move in the right direction and needs further improvements: `SMTConstraintManager` still does a lot of things that are not required by a `ConstraintManager`. We ought to move the unrelated to `SMTSolver` and remove everything that's not related to a `ConstraintManager`. In particular, we could remove `addRangeConstraints` and `isModelFeasible`, and make the refutation manager create an Z3Solver directly. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: mgorny, xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49668 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337919 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTConstraintManager.h | 237 ++++- lib/StaticAnalyzer/Core/CMakeLists.txt | 1 + .../Core/SMTConstraintManager.cpp | 479 ++++++++++ .../Core/Z3ConstraintManager.cpp | 837 ++---------------- 4 files changed, 784 insertions(+), 770 deletions(-) create mode 100644 lib/StaticAnalyzer/Core/SMTConstraintManager.cpp diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 28e31896a7..9871091209 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -16,27 +16,254 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h" namespace clang { namespace ento { class SMTConstraintManager : public clang::ento::SimpleConstraintManager { + SMTSolverRef &Solver; public: - SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB) - : SimpleConstraintManager(SE, SB) {} + SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB, + SMTSolverRef &S) + : SimpleConstraintManager(SE, SB), Solver(S) {} virtual ~SMTConstraintManager() = default; + //===------------------------------------------------------------------===// + // Implementation for interface from SimpleConstraintManager. + //===------------------------------------------------------------------===// + + ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym, + bool Assumption) override; + + ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) override; + + ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, + bool Assumption) override; + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; + + const llvm::APSInt *getSymVal(ProgramStateRef State, + SymbolRef Sym) const override; + /// Converts the ranged constraints of a set of symbols to SMT /// /// \param CR The set of constraints. - virtual void addRangeConstraints(clang::ento::ConstraintRangeTy CR) = 0; + void addRangeConstraints(clang::ento::ConstraintRangeTy CR); /// Checks if the added constraints are satisfiable - virtual clang::ento::ConditionTruthVal isModelFeasible() = 0; + clang::ento::ConditionTruthVal isModelFeasible(); /// Dumps SMT formula - LLVM_DUMP_METHOD virtual void dump() const = 0; + LLVM_DUMP_METHOD void dump() const { Solver->dump(); } + +protected: + //===------------------------------------------------------------------===// + // Internal implementation. + //===------------------------------------------------------------------===// + + // Check whether a new model is satisfiable, and update the program state. + virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, + const SMTExprRef &Exp) = 0; + + /// Given a program state, construct the logical conjunction and add it to + /// the solver + virtual void addStateConstraints(ProgramStateRef State) const = 0; + + // Generate and check a Z3 model, using the given constraint. + ConditionTruthVal checkModel(ProgramStateRef State, + const SMTExprRef &Exp) const; + + // Generate a Z3Expr that represents the given symbolic expression. + // Sets the hasComparison parameter if the expression has a comparison + // operator. + // Sets the RetTy parameter to the final return type after promotions and + // casts. + SMTExprRef getExpr(SymbolRef Sym, QualType *RetTy = nullptr, + bool *hasComparison = nullptr) const; + + // Generate a Z3Expr that takes the logical not of an expression. + SMTExprRef getNotExpr(const SMTExprRef &Exp) const; + + // Generate a Z3Expr that compares the expression to zero. + SMTExprRef getZeroExpr(const SMTExprRef &Exp, QualType RetTy, + bool Assumption) const; + + // Recursive implementation to unpack and generate symbolic expression. + // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + SMTExprRef getSymExpr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const; + + // Wrapper to generate Z3Expr from SymbolData. + SMTExprRef getDataExpr(const SymbolID ID, QualType Ty) const; + + // Wrapper to generate Z3Expr from SymbolCast. + SMTExprRef getCastExpr(const SMTExprRef &Exp, QualType FromTy, + QualType Ty) const; + + // Wrapper to generate Z3Expr from BinarySymExpr. + // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + SMTExprRef getSymBinExpr(const BinarySymExpr *BSE, bool *hasComparison, + QualType *RetTy) const; + + // Wrapper to generate Z3Expr from unpacked binary symbolic expression. + // Sets the RetTy parameter. See getZ3Expr(). + SMTExprRef getBinExpr(const SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, const SMTExprRef &RHS, + QualType RTy, QualType *RetTy) const; + + // Wrapper to generate Z3Expr from a range. If From == To, an equality will + // be created instead. + SMTExprRef getRangeExpr(SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, bool InRange); + + //===------------------------------------------------------------------===// + // Helper functions. + //===------------------------------------------------------------------===// + + // Recover the QualType of an APSInt. + // TODO: Refactor to put elsewhere + QualType getAPSIntType(const llvm::APSInt &Int) const; + + // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1. + std::pair fixAPSInt(const llvm::APSInt &Int) const; + + // Perform implicit type conversion on binary symbolic expressions. + // May modify all input parameters. + // TODO: Refactor to use built-in conversion functions + void doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, + QualType &RTy) const; + + // Perform implicit integer type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleIntegerConversion() + template + void doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { + ASTContext &Ctx = getBasicVals().getContext(); + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + // Always perform integer promotion before checking type equality. + // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion + if (LTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(LTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + LHS = ((*Solver).*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); + LTy = NewTy; + LBitWidth = NewBitWidth; + } + if (RTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(RTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + RHS = ((*Solver).*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); + RTy = NewTy; + RBitWidth = NewBitWidth; + } + + if (LTy == RTy) + return; + + // Perform integer type conversion + // Note: Safe to skip updating bitwidth because this must terminate + bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType(); + bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType(); + + int order = Ctx.getIntegerTypeOrder(LTy, RTy); + if (isLSignedTy == isRSignedTy) { + // Same signedness; use the higher-ranked type + if (order == 1) { + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (order != (isLSignedTy ? 1 : -1)) { + // The unsigned type has greater than or equal rank to the + // signed type, so use the unsigned type + if (isRSignedTy) { + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (LBitWidth != RBitWidth) { + // The two types are different widths; if we are here, that + // means the signed type is larger than the unsigned type, so + // use the signed type. + if (isLSignedTy) { + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else { + // The signed type is higher-ranked than the unsigned type, + // but isn't actually any bigger (like unsigned int and long + // on most 32-bit systems). Use the unsigned type corresponding + // to the signed type. + QualType NewTy = + Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = NewTy; + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = NewTy; + } + } + + // Perform implicit floating-point type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleFloatConversion() + template + void doFloatTypeConversion(T &LHS, QualType <y, T &RHS, + QualType &RTy) const { + ASTContext &Ctx = getBasicVals().getContext(); + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Perform float-point type promotion + if (!LTy->isRealFloatingType()) { + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + LBitWidth = RBitWidth; + } + if (!RTy->isRealFloatingType()) { + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + RBitWidth = LBitWidth; + } + + if (LTy == RTy) + return; + + // If we have two real floating types, convert the smaller operand to the + // bigger result + // Note: Safe to skip updating bitwidth because this must terminate + int order = Ctx.getFloatingTypeOrder(LTy, RTy); + if (order > 0) { + RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else if (order == 0) { + LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + llvm_unreachable("Unsupported floating-point type cast!"); + } + } }; // end class SMTConstraintManager } // namespace ento diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt index 8e1da211cd..de994b598e 100644 --- a/lib/StaticAnalyzer/Core/CMakeLists.txt +++ b/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -48,6 +48,7 @@ add_clang_library(clangStaticAnalyzerCore SVals.cpp SimpleConstraintManager.cpp SimpleSValBuilder.cpp + SMTConstraintManager.cpp Store.cpp SubEngine.cpp SymbolManager.cpp diff --git a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp new file mode 100644 index 0000000000..d70e040183 --- /dev/null +++ b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp @@ -0,0 +1,479 @@ +//== SMTConstraintManager.cpp -----------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" + +using namespace clang; +using namespace ento; + +void SMTConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { + Solver->reset(); + + for (const auto &I : CR) { + SymbolRef Sym = I.first; + + SMTExprRef Constraints = Solver->fromBoolean(false); + for (const auto &Range : I.second) { + SMTExprRef SymRange = + getRangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); + + // FIXME: the last argument (isSigned) is not used when generating the + // or expression, as both arguments are booleans + Constraints = + Solver->fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); + } + Solver->addConstraint(Constraints); + } +} + +clang::ento::ConditionTruthVal SMTConstraintManager::isModelFeasible() { + return Solver->check(); +} + +ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State, + SymbolRef Sym, + bool Assumption) { + QualType RetTy; + bool hasComparison; + + SMTExprRef Exp = getExpr(Sym, &RetTy, &hasComparison); + // Create zero comparison for implicit boolean cast, with reversed assumption + if (!hasComparison && !RetTy->isBooleanType()) + return assumeExpr(State, Sym, getZeroExpr(Exp, RetTy, !Assumption)); + + return assumeExpr(State, Sym, Assumption ? Exp : getNotExpr(Exp)); +} + +ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, bool InRange) { + return assumeExpr(State, Sym, getRangeExpr(Sym, From, To, InRange)); +} + +ProgramStateRef +SMTConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, + bool Assumption) { + // Skip anything that is unsupported + return State; +} + +ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State, + SymbolRef Sym) { + QualType RetTy; + // The expression may be casted, so we cannot call getZ3DataExpr() directly + SMTExprRef VarExp = getExpr(Sym, &RetTy); + SMTExprRef Exp = getZeroExpr(VarExp, RetTy, true); + + // Negate the constraint + SMTExprRef NotExp = getZeroExpr(VarExp, RetTy, false); + + Solver->reset(); + addStateConstraints(State); + + Solver->push(); + Solver->addConstraint(Exp); + ConditionTruthVal isSat = Solver->check(); + + Solver->pop(); + Solver->addConstraint(NotExp); + ConditionTruthVal isNotSat = Solver->check(); + + // Zero is the only possible solution + if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse()) + return true; + + // Zero is not a solution + if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue()) + return false; + + // Zero may be a solution + return ConditionTruthVal(); +} + +const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State, + SymbolRef Sym) const { + BasicValueFactory &BVF = getBasicVals(); + ASTContext &Ctx = BVF.getContext(); + + if (const SymbolData *SD = dyn_cast(Sym)) { + QualType Ty = Sym->getType(); + assert(!Ty->isRealFloatingType()); + llvm::APSInt Value(Ctx.getTypeSize(Ty), + !Ty->isSignedIntegerOrEnumerationType()); + + SMTExprRef Exp = getDataExpr(SD->getSymbolID(), Ty); + + Solver->reset(); + addStateConstraints(State); + + // Constraints are unsatisfiable + ConditionTruthVal isSat = Solver->check(); + if (!isSat.isConstrainedTrue()) + return nullptr; + + // Model does not assign interpretation + if (!Solver->getInterpretation(Exp, Value)) + return nullptr; + + // A value has been obtained, check if it is the only value + SMTExprRef NotExp = Solver->fromBinOp( + Exp, BO_NE, + Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue()) + : Solver->fromAPSInt(Value), + false); + + Solver->addConstraint(NotExp); + + ConditionTruthVal isNotSat = Solver->check(); + if (isNotSat.isConstrainedTrue()) + return nullptr; + + // This is the only solution, store it + return &BVF.getValue(Value); + } + + if (const SymbolCast *SC = dyn_cast(Sym)) { + SymbolRef CastSym = SC->getOperand(); + QualType CastTy = SC->getType(); + // Skip the void type + if (CastTy->isVoidType()) + return nullptr; + + const llvm::APSInt *Value; + if (!(Value = getSymVal(State, CastSym))) + return nullptr; + return &BVF.Convert(SC->getType(), *Value); + } + + if (const BinarySymExpr *BSE = dyn_cast(Sym)) { + const llvm::APSInt *LHS, *RHS; + if (const SymIntExpr *SIE = dyn_cast(BSE)) { + LHS = getSymVal(State, SIE->getLHS()); + RHS = &SIE->getRHS(); + } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { + LHS = &ISE->getLHS(); + RHS = getSymVal(State, ISE->getRHS()); + } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { + // Early termination to avoid expensive call + LHS = getSymVal(State, SSM->getLHS()); + RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr; + } else { + llvm_unreachable("Unsupported binary expression to get symbol value!"); + } + + if (!LHS || !RHS) + return nullptr; + + llvm::APSInt ConvertedLHS, ConvertedRHS; + QualType LTy, RTy; + std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); + std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); + doIntTypeConversion( + ConvertedLHS, LTy, ConvertedRHS, RTy); + return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); + } + + llvm_unreachable("Unsupported expression to get symbol value!"); +} + +//===------------------------------------------------------------------===// +// Internal implementation. +//===------------------------------------------------------------------===// + +ConditionTruthVal +SMTConstraintManager::checkModel(ProgramStateRef State, + const SMTExprRef &Exp) const { + Solver->reset(); + Solver->addConstraint(Exp); + addStateConstraints(State); + return Solver->check(); +} + +SMTExprRef SMTConstraintManager::getExpr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const { + if (hasComparison) { + *hasComparison = false; + } + + return getSymExpr(Sym, RetTy, hasComparison); +} + +SMTExprRef SMTConstraintManager::getNotExpr(const SMTExprRef &Exp) const { + return Solver->fromUnOp(UO_LNot, Exp); +} + +SMTExprRef SMTConstraintManager::getZeroExpr(const SMTExprRef &Exp, QualType Ty, + bool Assumption) const { + ASTContext &Ctx = getBasicVals().getContext(); + if (Ty->isRealFloatingType()) { + llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); + return Solver->fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, + Solver->fromAPFloat(Zero)); + } + + if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || + Ty->isBlockPointerType() || Ty->isReferenceType()) { + + // Skip explicit comparison for boolean types + bool isSigned = Ty->isSignedIntegerOrEnumerationType(); + if (Ty->isBooleanType()) + return Assumption ? getNotExpr(Exp) : Exp; + + return Solver->fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, + Solver->fromInt("0", Ctx.getTypeSize(Ty)), + isSigned); + } + + llvm_unreachable("Unsupported type for zero value!"); +} + +SMTExprRef SMTConstraintManager::getSymExpr(SymbolRef Sym, QualType *RetTy, + bool *hasComparison) const { + if (const SymbolData *SD = dyn_cast(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + return getDataExpr(SD->getSymbolID(), Sym->getType()); + } + + if (const SymbolCast *SC = dyn_cast(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + QualType FromTy; + SMTExprRef Exp = getSymExpr(SC->getOperand(), &FromTy, hasComparison); + // Casting an expression with a comparison invalidates it. Note that this + // must occur after the recursive call above. + // e.g. (signed char) (x > 0) + if (hasComparison) + *hasComparison = false; + return getCastExpr(Exp, FromTy, Sym->getType()); + } + + if (const BinarySymExpr *BSE = dyn_cast(Sym)) { + SMTExprRef Exp = getSymBinExpr(BSE, hasComparison, RetTy); + // Set the hasComparison parameter, in post-order traversal order. + if (hasComparison) + *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); + return Exp; + } + + llvm_unreachable("Unsupported SymbolRef type!"); +} + +SMTExprRef SMTConstraintManager::getDataExpr(const SymbolID ID, + QualType Ty) const { + ASTContext &Ctx = getBasicVals().getContext(); + return Solver->fromData(ID, Ty, Ctx.getTypeSize(Ty)); +} + +SMTExprRef SMTConstraintManager::getCastExpr(const SMTExprRef &Exp, + QualType FromTy, + QualType ToTy) const { + ASTContext &Ctx = getBasicVals().getContext(); + return Solver->fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, + Ctx.getTypeSize(FromTy)); +} + +SMTExprRef SMTConstraintManager::getSymBinExpr(const BinarySymExpr *BSE, + bool *hasComparison, + QualType *RetTy) const { + QualType LTy, RTy; + BinaryOperator::Opcode Op = BSE->getOpcode(); + + if (const SymIntExpr *SIE = dyn_cast(BSE)) { + SMTExprRef LHS = getSymExpr(SIE->getLHS(), <y, hasComparison); + llvm::APSInt NewRInt; + std::tie(NewRInt, RTy) = fixAPSInt(SIE->getRHS()); + SMTExprRef RHS = Solver->fromAPSInt(NewRInt); + return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const IntSymExpr *ISE = dyn_cast(BSE)) { + llvm::APSInt NewLInt; + std::tie(NewLInt, LTy) = fixAPSInt(ISE->getLHS()); + SMTExprRef LHS = Solver->fromAPSInt(NewLInt); + SMTExprRef RHS = getSymExpr(ISE->getRHS(), &RTy, hasComparison); + return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const SymSymExpr *SSM = dyn_cast(BSE)) { + SMTExprRef LHS = getSymExpr(SSM->getLHS(), <y, hasComparison); + SMTExprRef RHS = getSymExpr(SSM->getRHS(), &RTy, hasComparison); + return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); + } + + llvm_unreachable("Unsupported BinarySymExpr type!"); +} + +SMTExprRef SMTConstraintManager::getBinExpr(const SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, + const SMTExprRef &RHS, QualType RTy, + QualType *RetTy) const { + SMTExprRef NewLHS = LHS; + SMTExprRef NewRHS = RHS; + doTypeConversion(NewLHS, NewRHS, LTy, RTy); + + // Update the return type parameter if the output type has changed. + if (RetTy) { + // A boolean result can be represented as an integer type in C/C++, but at + // this point we only care about the Z3 type. Set it as a boolean type to + // avoid subsequent Z3 errors. + if (BinaryOperator::isComparisonOp(Op) || BinaryOperator::isLogicalOp(Op)) { + ASTContext &Ctx = getBasicVals().getContext(); + *RetTy = Ctx.BoolTy; + } else { + *RetTy = LTy; + } + + // If the two operands are pointers and the operation is a subtraction, the + // result is of type ptrdiff_t, which is signed + if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { + *RetTy = getBasicVals().getContext().getPointerDiffType(); + } + } + + return LTy->isRealFloatingType() + ? Solver->fromFloatBinOp(NewLHS, Op, NewRHS) + : Solver->fromBinOp(NewLHS, Op, NewRHS, + LTy->isSignedIntegerOrEnumerationType()); +} + +SMTExprRef SMTConstraintManager::getRangeExpr(SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) { + // Convert lower bound + QualType FromTy; + llvm::APSInt NewFromInt; + std::tie(NewFromInt, FromTy) = fixAPSInt(From); + SMTExprRef FromExp = Solver->fromAPSInt(NewFromInt); + + // Convert symbol + QualType SymTy; + SMTExprRef Exp = getExpr(Sym, &SymTy); + + // Construct single (in)equality + if (From == To) + return getBinExpr(Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, FromTy, + /*RetTy=*/nullptr); + + QualType ToTy; + llvm::APSInt NewToInt; + std::tie(NewToInt, ToTy) = fixAPSInt(To); + SMTExprRef ToExp = Solver->fromAPSInt(NewToInt); + assert(FromTy == ToTy && "Range values have different types!"); + + // Construct two (in)equalities, and a logical and/or + SMTExprRef LHS = getBinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, + FromTy, /*RetTy=*/nullptr); + SMTExprRef RHS = getBinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); + + return Solver->fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, + SymTy->isSignedIntegerOrEnumerationType()); +} + +//===------------------------------------------------------------------===// +// Helper functions. +//===------------------------------------------------------------------===// + +QualType SMTConstraintManager::getAPSIntType(const llvm::APSInt &Int) const { + ASTContext &Ctx = getBasicVals().getContext(); + return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); +} + +std::pair +SMTConstraintManager::fixAPSInt(const llvm::APSInt &Int) const { + llvm::APSInt NewInt; + + // FIXME: This should be a cast from a 1-bit integer type to a boolean type, + // but the former is not available in Clang. Instead, extend the APSInt + // directly. + if (Int.getBitWidth() == 1 && getAPSIntType(Int).isNull()) { + ASTContext &Ctx = getBasicVals().getContext(); + NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); + } else + NewInt = Int; + + return std::make_pair(NewInt, getAPSIntType(NewInt)); +} + +void SMTConstraintManager::doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, + QualType <y, + QualType &RTy) const { + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + + ASTContext &Ctx = getBasicVals().getContext(); + + // Perform type conversion + if ((LTy->isIntegralOrEnumerationType() && + RTy->isIntegralOrEnumerationType()) && + (LTy->isArithmeticType() && RTy->isArithmeticType())) { + doIntTypeConversion(LHS, LTy, RHS, RTy); + return; + } + + if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { + doFloatTypeConversion(LHS, LTy, RHS, RTy); + return; + } + + if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || + (LTy->isReferenceType() || RTy->isReferenceType())) { + // TODO: Refactor to Sema::FindCompositePointerType(), and + // Sema::CheckCompareOperands(). + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Cast the non-pointer type to the pointer type. + // TODO: Be more strict about this. + if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) || + (LTy->isReferenceType() ^ RTy->isReferenceType())) { + if (LTy->isNullPtrType() || LTy->isBlockPointerType() || + LTy->isReferenceType()) { + LHS = Solver->fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + RHS = Solver->fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } + } + + // Cast the void pointer type to the non-void pointer type. + // For void types, this assumes that the casted value is equal to the value + // of the original pointer, and does not account for alignment requirements. + if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) { + assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) && + "Pointer types have different bitwidths!"); + if (RTy->isVoidPointerType()) + RTy = LTy; + else + LTy = RTy; + } + + if (LTy == RTy) + return; + } + + // Fallback: for the solver, assume that these types don't really matter + if ((LTy.getCanonicalType() == RTy.getCanonicalType()) || + (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) { + LTy = RTy; + return; + } + + // TODO: Refine behavior for invalid type casts +} diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 1f033d06e8..1051493279 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -320,11 +320,11 @@ class Z3Solver : public SMTSolver { Z3_solver Solver; +public: Z3Solver() : SMTSolver(), Solver(Z3_mk_simple_solver(Context.Context)) { Z3_solver_inc_ref(Context.Context, Solver); } -public: /// Override implicit copy constructor for correct reference counting. Z3Solver(const Z3Solver &Copy) : SMTSolver(), Context(Copy.Context), Solver(Copy.Solver) { @@ -932,807 +932,114 @@ public: }; // end class Z3Solver class Z3ConstraintManager : public SMTConstraintManager { - mutable Z3Solver Solver; + SMTSolverRef Solver = std::make_shared(); public: Z3ConstraintManager(SubEngine *SE, SValBuilder &SB) - : SMTConstraintManager(SE, SB) {} - - //===------------------------------------------------------------------===// - // Implementation for Refutation. - //===------------------------------------------------------------------===// - - void addRangeConstraints(clang::ento::ConstraintRangeTy CR) override; - - ConditionTruthVal isModelFeasible() override; - - LLVM_DUMP_METHOD void dump() const override; - - //===------------------------------------------------------------------===// - // Implementation for interface from ConstraintManager. - //===------------------------------------------------------------------===// - - bool canReasonAbout(SVal X) const override; - - ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; - - const llvm::APSInt *getSymVal(ProgramStateRef State, - SymbolRef Sym) const override; - - ProgramStateRef removeDeadBindings(ProgramStateRef St, - SymbolReaper &SymReaper) override; - - void print(ProgramStateRef St, raw_ostream &Out, const char *nl, - const char *sep) override; - - //===------------------------------------------------------------------===// - // Implementation for interface from SimpleConstraintManager. - //===------------------------------------------------------------------===// - - ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym, - bool Assumption) override; - - ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool InRange) override; - - ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, - bool Assumption) override; - -private: - //===------------------------------------------------------------------===// - // Internal implementation. - //===------------------------------------------------------------------===// - - /// Given a program state, construct the logical conjunction and add it to - /// the solver - void addStateConstraints(ProgramStateRef State) const; - - // Check whether a new model is satisfiable, and update the program state. - ProgramStateRef assumeZ3Expr(ProgramStateRef State, SymbolRef Sym, - const SMTExprRef &Exp); - - // Generate and check a Z3 model, using the given constraint. - ConditionTruthVal checkZ3Model(ProgramStateRef State, - const SMTExprRef &Exp) const; - - // Generate a Z3Expr that represents the given symbolic expression. - // Sets the hasComparison parameter if the expression has a comparison - // operator. - // Sets the RetTy parameter to the final return type after promotions and - // casts. - SMTExprRef getZ3Expr(SymbolRef Sym, QualType *RetTy = nullptr, - bool *hasComparison = nullptr) const; - - // Generate a Z3Expr that takes the logical not of an expression. - SMTExprRef getZ3NotExpr(const SMTExprRef &Exp) const; - - // Generate a Z3Expr that compares the expression to zero. - SMTExprRef getZ3ZeroExpr(const SMTExprRef &Exp, QualType RetTy, - bool Assumption) const; - - // Recursive implementation to unpack and generate symbolic expression. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - SMTExprRef getZ3SymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const; - - // Wrapper to generate Z3Expr from SymbolData. - SMTExprRef getZ3DataExpr(const SymbolID ID, QualType Ty) const; - - // Wrapper to generate Z3Expr from SymbolCast. - SMTExprRef getZ3CastExpr(const SMTExprRef &Exp, QualType FromTy, - QualType Ty) const; - - // Wrapper to generate Z3Expr from BinarySymExpr. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - SMTExprRef getZ3SymBinExpr(const BinarySymExpr *BSE, bool *hasComparison, - QualType *RetTy) const; - - // Wrapper to generate Z3Expr from unpacked binary symbolic expression. - // Sets the RetTy parameter. See getZ3Expr(). - SMTExprRef getZ3BinExpr(const SMTExprRef &LHS, QualType LTy, - BinaryOperator::Opcode Op, const SMTExprRef &RHS, - QualType RTy, QualType *RetTy) const; - - // Wrapper to generate Z3Expr from a range. If From == To, an equality will - // be created instead. - SMTExprRef getZ3RangeExpr(SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, bool InRange); - - //===------------------------------------------------------------------===// - // Helper functions. - //===------------------------------------------------------------------===// - - // Recover the QualType of an APSInt. - // TODO: Refactor to put elsewhere - QualType getAPSIntType(const llvm::APSInt &Int) const; - - // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1. - std::pair fixAPSInt(const llvm::APSInt &Int) const; - - // Perform implicit type conversion on binary symbolic expressions. - // May modify all input parameters. - // TODO: Refactor to use built-in conversion functions - void doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, - QualType &RTy) const; - - // Perform implicit integer type conversion. - // May modify all input parameters. - // TODO: Refactor to use Sema::handleIntegerConversion() - template - void doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const; - - // Perform implicit floating-point type conversion. - // May modify all input parameters. - // TODO: Refactor to use Sema::handleFloatConversion() - template - void doFloatTypeConversion(T &LHS, QualType <y, T &RHS, - QualType &RTy) const; -}; // end class Z3ConstraintManager - -} // end anonymous namespace - -void Z3ConstraintManager::addStateConstraints(ProgramStateRef State) const { - // TODO: Don't add all the constraints, only the relevant ones - ConstraintZ3Ty CZ = State->get(); - ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); - - // Construct the logical AND of all the constraints - if (I != IE) { - std::vector ASTs; - - while (I != IE) - ASTs.push_back(Solver.newExprRef(Z3Expr(I++->second))); + : SMTConstraintManager(SE, SB, Solver) {} - Solver.addConstraint(Solver.fromNBinOp(BO_LAnd, ASTs)); - } -} - -ProgramStateRef Z3ConstraintManager::assumeSym(ProgramStateRef State, - SymbolRef Sym, bool Assumption) { - QualType RetTy; - bool hasComparison; - - SMTExprRef Exp = getZ3Expr(Sym, &RetTy, &hasComparison); - // Create zero comparison for implicit boolean cast, with reversed assumption - if (!hasComparison && !RetTy->isBooleanType()) - return assumeZ3Expr(State, Sym, getZ3ZeroExpr(Exp, RetTy, !Assumption)); - - return assumeZ3Expr(State, Sym, Assumption ? Exp : getZ3NotExpr(Exp)); -} - -ProgramStateRef Z3ConstraintManager::assumeSymInclusiveRange( - ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, bool InRange) { - return assumeZ3Expr(State, Sym, getZ3RangeExpr(Sym, From, To, InRange)); -} - -ProgramStateRef Z3ConstraintManager::assumeSymUnsupported(ProgramStateRef State, - SymbolRef Sym, - bool Assumption) { - // Skip anything that is unsupported - return State; -} - -bool Z3ConstraintManager::canReasonAbout(SVal X) const { - const TargetInfo &TI = getBasicVals().getContext().getTargetInfo(); - - Optional SymVal = X.getAs(); - if (!SymVal) - return true; - - const SymExpr *Sym = SymVal->getSymbol(); - QualType Ty = Sym->getType(); - - // Complex types are not modeled - if (Ty->isComplexType() || Ty->isComplexIntegerType()) - return false; - - // Non-IEEE 754 floating-point types are not modeled - if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) && - (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() || - &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble()))) - return false; - - if (isa(Sym)) - return true; + void addStateConstraints(ProgramStateRef State) const override { + // TODO: Don't add all the constraints, only the relevant ones + ConstraintZ3Ty CZ = State->get(); + ConstraintZ3Ty::iterator I = CZ.begin(), IE = CZ.end(); - SValBuilder &SVB = getSValBuilder(); + // Construct the logical AND of all the constraints + if (I != IE) { + std::vector ASTs; - if (const SymbolCast *SC = dyn_cast(Sym)) - return canReasonAbout(SVB.makeSymbolVal(SC->getOperand())); - - if (const BinarySymExpr *BSE = dyn_cast(Sym)) { - if (const SymIntExpr *SIE = dyn_cast(BSE)) - return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS())); - - if (const IntSymExpr *ISE = dyn_cast(BSE)) - return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS())); + SMTExprRef Constraint = Solver->newExprRef(I++->second); + while (I != IE) { + Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second)); + } - if (const SymSymExpr *SSE = dyn_cast(BSE)) - return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) && - canReasonAbout(SVB.makeSymbolVal(SSE->getRHS())); + Solver->addConstraint(Constraint); + } } - llvm_unreachable("Unsupported expression to reason about!"); -} - -ConditionTruthVal Z3ConstraintManager::checkNull(ProgramStateRef State, - SymbolRef Sym) { - QualType RetTy; - // The expression may be casted, so we cannot call getZ3DataExpr() directly - SMTExprRef VarExp = getZ3Expr(Sym, &RetTy); - SMTExprRef Exp = getZ3ZeroExpr(VarExp, RetTy, true); - - // Negate the constraint - SMTExprRef NotExp = getZ3ZeroExpr(VarExp, RetTy, false); - - Solver.reset(); - addStateConstraints(State); - - Solver.push(); - Solver.addConstraint(Exp); - ConditionTruthVal isSat = Solver.check(); + bool canReasonAbout(SVal X) const override { + const TargetInfo &TI = getBasicVals().getContext().getTargetInfo(); - Solver.pop(); - Solver.addConstraint(NotExp); - ConditionTruthVal isNotSat = Solver.check(); - - // Zero is the only possible solution - if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse()) - return true; - - // Zero is not a solution - if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue()) - return false; - - // Zero may be a solution - return ConditionTruthVal(); -} - -const llvm::APSInt *Z3ConstraintManager::getSymVal(ProgramStateRef State, - SymbolRef Sym) const { - BasicValueFactory &BVF = getBasicVals(); - ASTContext &Ctx = BVF.getContext(); + Optional SymVal = X.getAs(); + if (!SymVal) + return true; - if (const SymbolData *SD = dyn_cast(Sym)) { + const SymExpr *Sym = SymVal->getSymbol(); QualType Ty = Sym->getType(); - assert(!Ty->isRealFloatingType()); - llvm::APSInt Value(Ctx.getTypeSize(Ty), - !Ty->isSignedIntegerOrEnumerationType()); - - SMTExprRef Exp = getZ3DataExpr(SD->getSymbolID(), Ty); - - Solver.reset(); - addStateConstraints(State); - - // Constraints are unsatisfiable - ConditionTruthVal isSat = Solver.check(); - if (!isSat.isConstrainedTrue()) - return nullptr; - - // Model does not assign interpretation - if (!Solver.getInterpretation(Exp, Value)) - return nullptr; - - // A value has been obtained, check if it is the only value - SMTExprRef NotExp = Solver.fromBinOp( - Exp, BO_NE, - Ty->isBooleanType() ? Solver.fromBoolean(Value.getBoolValue()) - : Solver.fromAPSInt(Value), - false); - - Solver.addConstraint(NotExp); - - ConditionTruthVal isNotSat = Solver.check(); - if (isNotSat.isConstrainedTrue()) - return nullptr; - - // This is the only solution, store it - return &BVF.getValue(Value); - } else if (const SymbolCast *SC = dyn_cast(Sym)) { - SymbolRef CastSym = SC->getOperand(); - QualType CastTy = SC->getType(); - // Skip the void type - if (CastTy->isVoidType()) - return nullptr; - - const llvm::APSInt *Value; - if (!(Value = getSymVal(State, CastSym))) - return nullptr; - return &BVF.Convert(SC->getType(), *Value); - } else if (const BinarySymExpr *BSE = dyn_cast(Sym)) { - const llvm::APSInt *LHS, *RHS; - if (const SymIntExpr *SIE = dyn_cast(BSE)) { - LHS = getSymVal(State, SIE->getLHS()); - RHS = &SIE->getRHS(); - } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { - LHS = &ISE->getLHS(); - RHS = getSymVal(State, ISE->getRHS()); - } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { - // Early termination to avoid expensive call - LHS = getSymVal(State, SSM->getLHS()); - RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr; - } else { - llvm_unreachable("Unsupported binary expression to get symbol value!"); - } - if (!LHS || !RHS) - return nullptr; - - llvm::APSInt ConvertedLHS, ConvertedRHS; - QualType LTy, RTy; - std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); - std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); - doIntTypeConversion( - ConvertedLHS, LTy, ConvertedRHS, RTy); - return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); - } - - llvm_unreachable("Unsupported expression to get symbol value!"); -} + // Complex types are not modeled + if (Ty->isComplexType() || Ty->isComplexIntegerType()) + return false; -ProgramStateRef -Z3ConstraintManager::removeDeadBindings(ProgramStateRef State, - SymbolReaper &SymReaper) { - ConstraintZ3Ty CZ = State->get(); - ConstraintZ3Ty::Factory &CZFactory = State->get_context(); + // Non-IEEE 754 floating-point types are not modeled + if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) && + (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() || + &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble()))) + return false; - for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) { - if (SymReaper.maybeDead(I->first)) - CZ = CZFactory.remove(CZ, *I); - } + if (isa(Sym)) + return true; - return State->set(CZ); -} + SValBuilder &SVB = getSValBuilder(); -void Z3ConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { - Solver.reset(); + if (const SymbolCast *SC = dyn_cast(Sym)) + return canReasonAbout(SVB.makeSymbolVal(SC->getOperand())); - for (const auto &I : CR) { - SymbolRef Sym = I.first; + if (const BinarySymExpr *BSE = dyn_cast(Sym)) { + if (const SymIntExpr *SIE = dyn_cast(BSE)) + return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS())); - SMTExprRef Constraints = Solver.fromBoolean(false); - for (const auto &Range : I.second) { - SMTExprRef SymRange = - getZ3RangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); + if (const IntSymExpr *ISE = dyn_cast(BSE)) + return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS())); - // FIXME: the last argument (isSigned) is not used when generating the - // or expression, as both arguments are booleans - Constraints = - Solver.fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); + if (const SymSymExpr *SSE = dyn_cast(BSE)) + return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) && + canReasonAbout(SVB.makeSymbolVal(SSE->getRHS())); } - Solver.addConstraint(Constraints); - } -} - -clang::ento::ConditionTruthVal Z3ConstraintManager::isModelFeasible() { - return Solver.check(); -} - -LLVM_DUMP_METHOD void Z3ConstraintManager::dump() const { Solver.dump(); } -//===------------------------------------------------------------------===// -// Internal implementation. -//===------------------------------------------------------------------===// - -ProgramStateRef Z3ConstraintManager::assumeZ3Expr(ProgramStateRef State, - SymbolRef Sym, - const SMTExprRef &Exp) { - // Check the model, avoid simplifying AST to save time - if (checkZ3Model(State, Exp).isConstrainedTrue()) - return State->add(std::make_pair(Sym, toZ3Expr(*Exp))); - - return nullptr; -} - -ConditionTruthVal -Z3ConstraintManager::checkZ3Model(ProgramStateRef State, - const SMTExprRef &Exp) const { - Solver.reset(); - Solver.addConstraint(Exp); - addStateConstraints(State); - return Solver.check(); -} - -SMTExprRef Z3ConstraintManager::getZ3Expr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { - if (hasComparison) { - *hasComparison = false; + llvm_unreachable("Unsupported expression to reason about!"); } - return getZ3SymExpr(Sym, RetTy, hasComparison); -} - -SMTExprRef Z3ConstraintManager::getZ3NotExpr(const SMTExprRef &Exp) const { - return Solver.fromUnOp(UO_LNot, Exp); -} - -SMTExprRef Z3ConstraintManager::getZ3ZeroExpr(const SMTExprRef &Exp, - QualType Ty, - bool Assumption) const { - ASTContext &Ctx = getBasicVals().getContext(); - if (Ty->isRealFloatingType()) { - llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); - return Solver.fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Solver.fromAPFloat(Zero)); - } else if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || - Ty->isBlockPointerType() || Ty->isReferenceType()) { - bool isSigned = Ty->isSignedIntegerOrEnumerationType(); - // Skip explicit comparison for boolean types - if (Ty->isBooleanType()) - return Assumption ? getZ3NotExpr(Exp) : Exp; - return Solver.fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Solver.fromInt("0", Ctx.getTypeSize(Ty)), isSigned); - } - - llvm_unreachable("Unsupported type for zero value!"); -} - -SMTExprRef Z3ConstraintManager::getZ3SymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { - if (const SymbolData *SD = dyn_cast(Sym)) { - if (RetTy) - *RetTy = Sym->getType(); - - return getZ3DataExpr(SD->getSymbolID(), Sym->getType()); - } else if (const SymbolCast *SC = dyn_cast(Sym)) { - if (RetTy) - *RetTy = Sym->getType(); - - QualType FromTy; - SMTExprRef Exp = getZ3SymExpr(SC->getOperand(), &FromTy, hasComparison); - // Casting an expression with a comparison invalidates it. Note that this - // must occur after the recursive call above. - // e.g. (signed char) (x > 0) - if (hasComparison) - *hasComparison = false; - return getZ3CastExpr(Exp, FromTy, Sym->getType()); - } else if (const BinarySymExpr *BSE = dyn_cast(Sym)) { - SMTExprRef Exp = getZ3SymBinExpr(BSE, hasComparison, RetTy); - // Set the hasComparison parameter, in post-order traversal order. - if (hasComparison) - *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); - return Exp; - } - - llvm_unreachable("Unsupported SymbolRef type!"); -} - -SMTExprRef Z3ConstraintManager::getZ3DataExpr(const SymbolID ID, - QualType Ty) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Solver.fromData(ID, Ty, Ctx.getTypeSize(Ty)); -} - -SMTExprRef Z3ConstraintManager::getZ3CastExpr(const SMTExprRef &Exp, - QualType FromTy, - QualType ToTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Solver.fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, - Ctx.getTypeSize(FromTy)); -} - -SMTExprRef Z3ConstraintManager::getZ3SymBinExpr(const BinarySymExpr *BSE, - bool *hasComparison, - QualType *RetTy) const { - QualType LTy, RTy; - BinaryOperator::Opcode Op = BSE->getOpcode(); - - if (const SymIntExpr *SIE = dyn_cast(BSE)) { - SMTExprRef LHS = getZ3SymExpr(SIE->getLHS(), <y, hasComparison); - llvm::APSInt NewRInt; - std::tie(NewRInt, RTy) = fixAPSInt(SIE->getRHS()); - SMTExprRef RHS = Solver.fromAPSInt(NewRInt); - return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { - llvm::APSInt NewLInt; - std::tie(NewLInt, LTy) = fixAPSInt(ISE->getLHS()); - SMTExprRef LHS = Solver.fromAPSInt(NewLInt); - SMTExprRef RHS = getZ3SymExpr(ISE->getRHS(), &RTy, hasComparison); - return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { - SMTExprRef LHS = getZ3SymExpr(SSM->getLHS(), <y, hasComparison); - SMTExprRef RHS = getZ3SymExpr(SSM->getRHS(), &RTy, hasComparison); - return getZ3BinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } else { - llvm_unreachable("Unsupported BinarySymExpr type!"); - } -} + ProgramStateRef removeDeadBindings(ProgramStateRef State, + SymbolReaper &SymReaper) override { + ConstraintZ3Ty CZ = State->get(); + ConstraintZ3Ty::Factory &CZFactory = State->get_context(); -SMTExprRef Z3ConstraintManager::getZ3BinExpr( - const SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, - const SMTExprRef &RHS, QualType RTy, QualType *RetTy) const { - SMTExprRef NewLHS = LHS; - SMTExprRef NewRHS = RHS; - doTypeConversion(NewLHS, NewRHS, LTy, RTy); - // Update the return type parameter if the output type has changed. - if (RetTy) { - // A boolean result can be represented as an integer type in C/C++, but at - // this point we only care about the Z3 type. Set it as a boolean type to - // avoid subsequent Z3 errors. - if (BinaryOperator::isComparisonOp(Op) || BinaryOperator::isLogicalOp(Op)) { - ASTContext &Ctx = getBasicVals().getContext(); - *RetTy = Ctx.BoolTy; - } else { - *RetTy = LTy; + for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) { + if (SymReaper.maybeDead(I->first)) + CZ = CZFactory.remove(CZ, *I); } - // If the two operands are pointers and the operation is a subtraction, the - // result is of type ptrdiff_t, which is signed - if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { - *RetTy = getBasicVals().getContext().getPointerDiffType(); - } + return State->set(CZ); } - return LTy->isRealFloatingType() - ? Solver.fromFloatBinOp(NewLHS, Op, NewRHS) - : Solver.fromBinOp(NewLHS, Op, NewRHS, - LTy->isSignedIntegerOrEnumerationType()); -} - -SMTExprRef Z3ConstraintManager::getZ3RangeExpr(SymbolRef Sym, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool InRange) { - // Convert lower bound - QualType FromTy; - llvm::APSInt NewFromInt; - std::tie(NewFromInt, FromTy) = fixAPSInt(From); - SMTExprRef FromExp = Solver.fromAPSInt(NewFromInt); - - // Convert symbol - QualType SymTy; - SMTExprRef Exp = getZ3Expr(Sym, &SymTy); - - // Construct single (in)equality - if (From == To) - return getZ3BinExpr(Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, FromTy, - /*RetTy=*/nullptr); - - QualType ToTy; - llvm::APSInt NewToInt; - std::tie(NewToInt, ToTy) = fixAPSInt(To); - SMTExprRef ToExp = Solver.fromAPSInt(NewToInt); - assert(FromTy == ToTy && "Range values have different types!"); - - // Construct two (in)equalities, and a logical and/or - SMTExprRef LHS = getZ3BinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, - FromTy, /*RetTy=*/nullptr); - SMTExprRef RHS = - getZ3BinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, - /*RetTy=*/nullptr); - - return Solver.fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, - SymTy->isSignedIntegerOrEnumerationType()); -} - -//===------------------------------------------------------------------===// -// Helper functions. -//===------------------------------------------------------------------===// - -QualType Z3ConstraintManager::getAPSIntType(const llvm::APSInt &Int) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); -} - -std::pair -Z3ConstraintManager::fixAPSInt(const llvm::APSInt &Int) const { - llvm::APSInt NewInt; - - // FIXME: This should be a cast from a 1-bit integer type to a boolean type, - // but the former is not available in Clang. Instead, extend the APSInt - // directly. - if (Int.getBitWidth() == 1 && getAPSIntType(Int).isNull()) { - ASTContext &Ctx = getBasicVals().getContext(); - NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); - } else - NewInt = Int; - - return std::make_pair(NewInt, getAPSIntType(NewInt)); -} - -void Z3ConstraintManager::doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, - QualType <y, QualType &RTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - - assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); - // Perform type conversion - if (LTy->isIntegralOrEnumerationType() && - RTy->isIntegralOrEnumerationType()) { - if (LTy->isArithmeticType() && RTy->isArithmeticType()) { - doIntTypeConversion(LHS, LTy, RHS, RTy); - return; - } - } else if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { - doFloatTypeConversion(LHS, LTy, RHS, RTy); - return; - } else if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || - (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || - (LTy->isReferenceType() || RTy->isReferenceType())) { - // TODO: Refactor to Sema::FindCompositePointerType(), and - // Sema::CheckCompareOperands(). - - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - // Cast the non-pointer type to the pointer type. - // TODO: Be more strict about this. - if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) || - (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) || - (LTy->isReferenceType() ^ RTy->isReferenceType())) { - if (LTy->isNullPtrType() || LTy->isBlockPointerType() || - LTy->isReferenceType()) { - LHS = Solver.fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } else { - RHS = Solver.fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } - } - - // Cast the void pointer type to the non-void pointer type. - // For void types, this assumes that the casted value is equal to the value - // of the original pointer, and does not account for alignment requirements. - if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) { - assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) && - "Pointer types have different bitwidths!"); - if (RTy->isVoidPointerType()) - RTy = LTy; - else - LTy = RTy; - } + ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, + const SMTExprRef &Exp) override { + // Check the model, avoid simplifying AST to save time + if (checkModel(State, Exp).isConstrainedTrue()) + return State->add(std::make_pair(Sym, toZ3Expr(*Exp))); - if (LTy == RTy) - return; + return nullptr; } - // Fallback: for the solver, assume that these types don't really matter - if ((LTy.getCanonicalType() == RTy.getCanonicalType()) || - (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) { - LTy = RTy; - return; - } + //==------------------------------------------------------------------------==/ + // Pretty-printing. + //==------------------------------------------------------------------------==/ - // TODO: Refine behavior for invalid type casts -} + void print(ProgramStateRef St, raw_ostream &OS, const char *nl, + const char *sep) override { -template -void Z3ConstraintManager::doIntTypeConversion(T &LHS, QualType <y, T &RHS, - QualType &RTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); - // Always perform integer promotion before checking type equality. - // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion - if (LTy->isPromotableIntegerType()) { - QualType NewTy = Ctx.getPromotedIntegerType(LTy); - uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - LHS = (Solver.*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); - LTy = NewTy; - LBitWidth = NewBitWidth; - } - if (RTy->isPromotableIntegerType()) { - QualType NewTy = Ctx.getPromotedIntegerType(RTy); - uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - RHS = (Solver.*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); - RTy = NewTy; - RBitWidth = NewBitWidth; - } - - if (LTy == RTy) - return; - - // Perform integer type conversion - // Note: Safe to skip updating bitwidth because this must terminate - bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType(); - bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType(); - - int order = Ctx.getIntegerTypeOrder(LTy, RTy); - if (isLSignedTy == isRSignedTy) { - // Same signedness; use the higher-ranked type - if (order == 1) { - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else if (order != (isLSignedTy ? 1 : -1)) { - // The unsigned type has greater than or equal rank to the - // signed type, so use the unsigned type - if (isRSignedTy) { - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else if (LBitWidth != RBitWidth) { - // The two types are different widths; if we are here, that - // means the signed type is larger than the unsigned type, so - // use the signed type. - if (isLSignedTy) { - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else { - // The signed type is higher-ranked than the unsigned type, - // but isn't actually any bigger (like unsigned int and long - // on most 32-bit systems). Use the unsigned type corresponding - // to the signed type. - QualType NewTy = Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = NewTy; - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = NewTy; - } -} + ConstraintZ3Ty CZ = St->get(); -template -void Z3ConstraintManager::doFloatTypeConversion(T &LHS, QualType <y, T &RHS, - QualType &RTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - // Perform float-point type promotion - if (!LTy->isRealFloatingType()) { - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - LBitWidth = RBitWidth; - } - if (!RTy->isRealFloatingType()) { - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - RBitWidth = LBitWidth; - } - - if (LTy == RTy) - return; - - // If we have two real floating types, convert the smaller operand to the - // bigger result - // Note: Safe to skip updating bitwidth because this must terminate - int order = Ctx.getFloatingTypeOrder(LTy, RTy); - if (order > 0) { - RHS = (Solver.*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else if (order == 0) { - LHS = (Solver.*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } else { - llvm_unreachable("Unsupported floating-point type cast!"); + OS << nl << sep << "Constraints:"; + for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) { + OS << nl << ' ' << I->first << " : "; + I->second.print(OS); + } + OS << nl; } -} - -//==------------------------------------------------------------------------==/ -// Pretty-printing. -//==------------------------------------------------------------------------==/ - -void Z3ConstraintManager::print(ProgramStateRef St, raw_ostream &OS, - const char *nl, const char *sep) { - - ConstraintZ3Ty CZ = St->get(); +}; // end class Z3ConstraintManager - OS << nl << sep << "Constraints:"; - for (ConstraintZ3Ty::iterator I = CZ.begin(), E = CZ.end(); I != E; ++I) { - OS << nl << ' ' << I->first << " : "; - I->second.print(OS); - } - OS << nl; -} +} // end anonymous namespace #endif -- GitLab From 877e8da78a09adb546b6e332fae8059ff2f81342 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:32 +0000 Subject: [PATCH 0716/1023] [analyzer] Try to minimize the number of equivalent bug reports evaluated by the refutation manager Summary: This patch changes how the SMT bug refutation runs in an equivalent bug report class. Now, all other visitor are executed until they find a valid bug or mark all bugs as invalid. When the one valid bug is found (and crosscheck is enabled), the SMT refutation checks the satisfiability of this single bug. If the bug is still valid after checking with Z3, it is returned and a bug report is created. If the bug is found to be invalid, the next bug report in the equivalent class goes through the same process, until we find a valid bug or all bugs are marked as invalid. Massive speedups when verifying redis/src/rax.c, from 1500s to 10s. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49693 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337920 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporter.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 096c8e7356..f990eb6a05 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2605,8 +2605,6 @@ std::pair> findValidReport( // Register refutation visitors first, if they mark the bug invalid no // further analysis is required R->addVisitor(llvm::make_unique()); - if (Opts.shouldCrosscheckWithZ3()) - R->addVisitor(llvm::make_unique()); // Register additional node visitors. R->addVisitor(llvm::make_unique()); @@ -2619,9 +2617,24 @@ std::pair> findValidReport( std::unique_ptr visitorNotes = generateVisitorsDiagnostics(R, ErrorNode, BRC); - if (R->isValid()) - return std::make_pair(R, std::move(visitorNotes)); + if (R->isValid()) { + if (Opts.shouldCrosscheckWithZ3()) { + // If crosscheck is enabled, remove all visitors, add the refutation + // visitor and check again + R->clearVisitors(); + R->addVisitor(llvm::make_unique()); + + // We don't overrite the notes inserted by other visitors because the + // refutation manager does not add any new note to the path + generateVisitorsDiagnostics(R, ErrorGraph.ErrorNode, BRC); + } + + // Check if the bug is still valid + if (R->isValid()) + return std::make_pair(R, std::move(visitorNotes)); + } } + return std::make_pair(nullptr, llvm::make_unique()); } -- GitLab From 375087785c80101af6a2c57f4dab1319d07b25ad Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:37 +0000 Subject: [PATCH 0717/1023] [analyzer] Moved code from SMTConstraintManager to SMTSolver Summary: This is the second part of D49668, and moves all the code that's not specific to a ConstraintManager to SMTSolver. No functional change intended. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49767 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337921 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTConstraintManager.h | 183 -------- .../Core/PathSensitive/SMTSolver.h | 414 ++++++++++++++++++ .../Core/SMTConstraintManager.cpp | 322 +------------- 3 files changed, 438 insertions(+), 481 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 9871091209..6b44e02b3e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -81,189 +81,6 @@ protected: // Generate and check a Z3 model, using the given constraint. ConditionTruthVal checkModel(ProgramStateRef State, const SMTExprRef &Exp) const; - - // Generate a Z3Expr that represents the given symbolic expression. - // Sets the hasComparison parameter if the expression has a comparison - // operator. - // Sets the RetTy parameter to the final return type after promotions and - // casts. - SMTExprRef getExpr(SymbolRef Sym, QualType *RetTy = nullptr, - bool *hasComparison = nullptr) const; - - // Generate a Z3Expr that takes the logical not of an expression. - SMTExprRef getNotExpr(const SMTExprRef &Exp) const; - - // Generate a Z3Expr that compares the expression to zero. - SMTExprRef getZeroExpr(const SMTExprRef &Exp, QualType RetTy, - bool Assumption) const; - - // Recursive implementation to unpack and generate symbolic expression. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - SMTExprRef getSymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const; - - // Wrapper to generate Z3Expr from SymbolData. - SMTExprRef getDataExpr(const SymbolID ID, QualType Ty) const; - - // Wrapper to generate Z3Expr from SymbolCast. - SMTExprRef getCastExpr(const SMTExprRef &Exp, QualType FromTy, - QualType Ty) const; - - // Wrapper to generate Z3Expr from BinarySymExpr. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). - SMTExprRef getSymBinExpr(const BinarySymExpr *BSE, bool *hasComparison, - QualType *RetTy) const; - - // Wrapper to generate Z3Expr from unpacked binary symbolic expression. - // Sets the RetTy parameter. See getZ3Expr(). - SMTExprRef getBinExpr(const SMTExprRef &LHS, QualType LTy, - BinaryOperator::Opcode Op, const SMTExprRef &RHS, - QualType RTy, QualType *RetTy) const; - - // Wrapper to generate Z3Expr from a range. If From == To, an equality will - // be created instead. - SMTExprRef getRangeExpr(SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, bool InRange); - - //===------------------------------------------------------------------===// - // Helper functions. - //===------------------------------------------------------------------===// - - // Recover the QualType of an APSInt. - // TODO: Refactor to put elsewhere - QualType getAPSIntType(const llvm::APSInt &Int) const; - - // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1. - std::pair fixAPSInt(const llvm::APSInt &Int) const; - - // Perform implicit type conversion on binary symbolic expressions. - // May modify all input parameters. - // TODO: Refactor to use built-in conversion functions - void doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, - QualType &RTy) const; - - // Perform implicit integer type conversion. - // May modify all input parameters. - // TODO: Refactor to use Sema::handleIntegerConversion() - template - void doIntTypeConversion(T &LHS, QualType <y, T &RHS, QualType &RTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); - // Always perform integer promotion before checking type equality. - // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion - if (LTy->isPromotableIntegerType()) { - QualType NewTy = Ctx.getPromotedIntegerType(LTy); - uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - LHS = ((*Solver).*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); - LTy = NewTy; - LBitWidth = NewBitWidth; - } - if (RTy->isPromotableIntegerType()) { - QualType NewTy = Ctx.getPromotedIntegerType(RTy); - uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); - RHS = ((*Solver).*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); - RTy = NewTy; - RBitWidth = NewBitWidth; - } - - if (LTy == RTy) - return; - - // Perform integer type conversion - // Note: Safe to skip updating bitwidth because this must terminate - bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType(); - bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType(); - - int order = Ctx.getIntegerTypeOrder(LTy, RTy); - if (isLSignedTy == isRSignedTy) { - // Same signedness; use the higher-ranked type - if (order == 1) { - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else if (order != (isLSignedTy ? 1 : -1)) { - // The unsigned type has greater than or equal rank to the - // signed type, so use the unsigned type - if (isRSignedTy) { - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else if (LBitWidth != RBitWidth) { - // The two types are different widths; if we are here, that - // means the signed type is larger than the unsigned type, so - // use the signed type. - if (isLSignedTy) { - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else { - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } - } else { - // The signed type is higher-ranked than the unsigned type, - // but isn't actually any bigger (like unsigned int and long - // on most 32-bit systems). Use the unsigned type corresponding - // to the signed type. - QualType NewTy = - Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = NewTy; - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = NewTy; - } - } - - // Perform implicit floating-point type conversion. - // May modify all input parameters. - // TODO: Refactor to use Sema::handleFloatConversion() - template - void doFloatTypeConversion(T &LHS, QualType <y, T &RHS, - QualType &RTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - // Perform float-point type promotion - if (!LTy->isRealFloatingType()) { - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - LBitWidth = RBitWidth; - } - if (!RTy->isRealFloatingType()) { - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - RBitWidth = LBitWidth; - } - - if (LTy == RTy) - return; - - // If we have two real floating types, convert the smaller operand to the - // bigger result - // Note: Safe to skip updating bitwidth because this must terminate - int order = Ctx.getFloatingTypeOrder(LTy, RTy); - if (order > 0) { - RHS = ((*Solver).*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } else if (order == 0) { - LHS = ((*Solver).*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } else { - llvm_unreachable("Unsupported floating-point type cast!"); - } - } }; // end class SMTConstraintManager } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index 15e646689c..3a3adc044a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -318,6 +318,420 @@ public: return TargetType.convert(V); } + // Generate a Z3Expr that represents the given symbolic expression. + // Sets the hasComparison parameter if the expression has a comparison + // operator. + // Sets the RetTy parameter to the final return type after promotions and + // casts. + SMTExprRef getExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy = nullptr, + bool *hasComparison = nullptr) { + if (hasComparison) { + *hasComparison = false; + } + + return getSymExpr(Ctx, Sym, RetTy, hasComparison); + } + + // Generate a Z3Expr that compares the expression to zero. + SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty, + bool Assumption) { + + if (Ty->isRealFloatingType()) { + llvm::APFloat Zero = + llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); + return fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, fromAPFloat(Zero)); + } + + if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || + Ty->isBlockPointerType() || Ty->isReferenceType()) { + + // Skip explicit comparison for boolean types + bool isSigned = Ty->isSignedIntegerOrEnumerationType(); + if (Ty->isBooleanType()) + return Assumption ? fromUnOp(UO_LNot, Exp) : Exp; + + return fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, + fromInt("0", Ctx.getTypeSize(Ty)), isSigned); + } + + llvm_unreachable("Unsupported type for zero value!"); + } + + // Recursive implementation to unpack and generate symbolic expression. + // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, + bool *hasComparison) { + if (const SymbolData *SD = dyn_cast(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + return getDataExpr(Ctx, SD->getSymbolID(), Sym->getType()); + } + + if (const SymbolCast *SC = dyn_cast(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + QualType FromTy; + SMTExprRef Exp = + getSymExpr(Ctx, SC->getOperand(), &FromTy, hasComparison); + // Casting an expression with a comparison invalidates it. Note that this + // must occur after the recursive call above. + // e.g. (signed char) (x > 0) + if (hasComparison) + *hasComparison = false; + return getCastExpr(Ctx, Exp, FromTy, Sym->getType()); + } + + if (const BinarySymExpr *BSE = dyn_cast(Sym)) { + SMTExprRef Exp = getSymBinExpr(Ctx, BSE, hasComparison, RetTy); + // Set the hasComparison parameter, in post-order traversal order. + if (hasComparison) + *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); + return Exp; + } + + llvm_unreachable("Unsupported SymbolRef type!"); + } + + // Wrapper to generate Z3Expr from SymbolData. + SMTExprRef getDataExpr(ASTContext &Ctx, const SymbolID ID, QualType Ty) { + return fromData(ID, Ty, Ctx.getTypeSize(Ty)); + } + + // Wrapper to generate Z3Expr from SymbolCast. + SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp, + QualType FromTy, QualType ToTy) { + + return fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, + Ctx.getTypeSize(FromTy)); + } + + // Wrapper to generate Z3Expr from BinarySymExpr. + // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE, + bool *hasComparison, QualType *RetTy) { + QualType LTy, RTy; + BinaryOperator::Opcode Op = BSE->getOpcode(); + + if (const SymIntExpr *SIE = dyn_cast(BSE)) { + SMTExprRef LHS = getSymExpr(Ctx, SIE->getLHS(), <y, hasComparison); + llvm::APSInt NewRInt; + std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS()); + SMTExprRef RHS = fromAPSInt(NewRInt); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const IntSymExpr *ISE = dyn_cast(BSE)) { + llvm::APSInt NewLInt; + std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS()); + SMTExprRef LHS = fromAPSInt(NewLInt); + SMTExprRef RHS = getSymExpr(Ctx, ISE->getRHS(), &RTy, hasComparison); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const SymSymExpr *SSM = dyn_cast(BSE)) { + SMTExprRef LHS = getSymExpr(Ctx, SSM->getLHS(), <y, hasComparison); + SMTExprRef RHS = getSymExpr(Ctx, SSM->getRHS(), &RTy, hasComparison); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + llvm_unreachable("Unsupported BinarySymExpr type!"); + } + + // Wrapper to generate Z3Expr from unpacked binary symbolic expression. + // Sets the RetTy parameter. See getZ3Expr(). + SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, const SMTExprRef &RHS, + QualType RTy, QualType *RetTy) { + SMTExprRef NewLHS = LHS; + SMTExprRef NewRHS = RHS; + doTypeConversion(Ctx, NewLHS, NewRHS, LTy, RTy); + + // Update the return type parameter if the output type has changed. + if (RetTy) { + // A boolean result can be represented as an integer type in C/C++, but at + // this point we only care about the Z3 type. Set it as a boolean type to + // avoid subsequent Z3 errors. + if (BinaryOperator::isComparisonOp(Op) || + BinaryOperator::isLogicalOp(Op)) { + + *RetTy = Ctx.BoolTy; + } else { + *RetTy = LTy; + } + + // If the two operands are pointers and the operation is a subtraction, + // the result is of type ptrdiff_t, which is signed + if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { + *RetTy = Ctx.getPointerDiffType(); + } + } + + return LTy->isRealFloatingType() + ? fromFloatBinOp(NewLHS, Op, NewRHS) + : fromBinOp(NewLHS, Op, NewRHS, + LTy->isSignedIntegerOrEnumerationType()); + } + + // Wrapper to generate Z3Expr from a range. If From == To, an equality will + // be created instead. + SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym, + const llvm::APSInt &From, const llvm::APSInt &To, + bool InRange) { + // Convert lower bound + QualType FromTy; + llvm::APSInt NewFromInt; + std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From); + SMTExprRef FromExp = fromAPSInt(NewFromInt); + + // Convert symbol + QualType SymTy; + SMTExprRef Exp = getExpr(Ctx, Sym, &SymTy); + + // Construct single (in)equality + if (From == To) + return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, + FromTy, + /*RetTy=*/nullptr); + + QualType ToTy; + llvm::APSInt NewToInt; + std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To); + SMTExprRef ToExp = fromAPSInt(NewToInt); + assert(FromTy == ToTy && "Range values have different types!"); + + // Construct two (in)equalities, and a logical and/or + SMTExprRef LHS = getBinExpr(Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, + FromExp, FromTy, /*RetTy=*/nullptr); + SMTExprRef RHS = + getBinExpr(Ctx, Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); + + return fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, + SymTy->isSignedIntegerOrEnumerationType()); + } + + // Recover the QualType of an APSInt. + // TODO: Refactor to put elsewhere + QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int) { + + return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); + } + + // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1. + std::pair fixAPSInt(ASTContext &Ctx, + const llvm::APSInt &Int) { + llvm::APSInt NewInt; + + // FIXME: This should be a cast from a 1-bit integer type to a boolean type, + // but the former is not available in Clang. Instead, extend the APSInt + // directly. + if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) { + + NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); + } else + NewInt = Int; + + return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt)); + } + + // Perform implicit type conversion on binary symbolic expressions. + // May modify all input parameters. + // TODO: Refactor to use built-in conversion functions + void doTypeConversion(ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS, + QualType <y, QualType &RTy) { + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + + // Perform type conversion + if ((LTy->isIntegralOrEnumerationType() && + RTy->isIntegralOrEnumerationType()) && + (LTy->isArithmeticType() && RTy->isArithmeticType())) { + doIntTypeConversion(Ctx, LHS, LTy, RHS, + RTy); + return; + } + + if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { + doFloatTypeConversion(Ctx, LHS, LTy, + RHS, RTy); + return; + } + + if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || + (LTy->isReferenceType() || RTy->isReferenceType())) { + // TODO: Refactor to Sema::FindCompositePointerType(), and + // Sema::CheckCompareOperands(). + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Cast the non-pointer type to the pointer type. + // TODO: Be more strict about this. + if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) || + (LTy->isReferenceType() ^ RTy->isReferenceType())) { + if (LTy->isNullPtrType() || LTy->isBlockPointerType() || + LTy->isReferenceType()) { + LHS = fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + RHS = fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } + } + + // Cast the void pointer type to the non-void pointer type. + // For void types, this assumes that the casted value is equal to the + // value of the original pointer, and does not account for alignment + // requirements. + if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) { + assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) && + "Pointer types have different bitwidths!"); + if (RTy->isVoidPointerType()) + RTy = LTy; + else + LTy = RTy; + } + + if (LTy == RTy) + return; + } + + // Fallback: for the solver, assume that these types don't really matter + if ((LTy.getCanonicalType() == RTy.getCanonicalType()) || + (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) { + LTy = RTy; + return; + } + + // TODO: Refine behavior for invalid type casts + } + + // Perform implicit integer type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleIntegerConversion() + template + void doIntTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, + QualType &RTy) { + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + // Always perform integer promotion before checking type equality. + // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion + if (LTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(LTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + LHS = (this->*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); + LTy = NewTy; + LBitWidth = NewBitWidth; + } + if (RTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(RTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + RHS = (this->*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); + RTy = NewTy; + RBitWidth = NewBitWidth; + } + + if (LTy == RTy) + return; + + // Perform integer type conversion + // Note: Safe to skip updating bitwidth because this must terminate + bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType(); + bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType(); + + int order = Ctx.getIntegerTypeOrder(LTy, RTy); + if (isLSignedTy == isRSignedTy) { + // Same signedness; use the higher-ranked type + if (order == 1) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (order != (isLSignedTy ? 1 : -1)) { + // The unsigned type has greater than or equal rank to the + // signed type, so use the unsigned type + if (isRSignedTy) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (LBitWidth != RBitWidth) { + // The two types are different widths; if we are here, that + // means the signed type is larger than the unsigned type, so + // use the signed type. + if (isLSignedTy) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else { + // The signed type is higher-ranked than the unsigned type, + // but isn't actually any bigger (like unsigned int and long + // on most 32-bit systems). Use the unsigned type corresponding + // to the signed type. + QualType NewTy = + Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = NewTy; + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = NewTy; + } + } + + // Perform implicit floating-point type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleFloatConversion() + template + void doFloatTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, + QualType &RTy) { + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Perform float-point type promotion + if (!LTy->isRealFloatingType()) { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + LBitWidth = RBitWidth; + } + if (!RTy->isRealFloatingType()) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + RBitWidth = LBitWidth; + } + + if (LTy == RTy) + return; + + // If we have two real floating types, convert the smaller operand to the + // bigger result + // Note: Safe to skip updating bitwidth because this must terminate + int order = Ctx.getFloatingTypeOrder(LTy, RTy); + if (order > 0) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else if (order == 0) { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + llvm_unreachable("Unsupported floating-point type cast!"); + } + } + // Return a boolean sort. virtual SMTSortRef getBoolSort() = 0; diff --git a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp index d70e040183..542b3741be 100644 --- a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp @@ -16,6 +16,7 @@ using namespace clang; using namespace ento; void SMTConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { + ASTContext &Ctx = getBasicVals().getContext(); Solver->reset(); for (const auto &I : CR) { @@ -23,8 +24,8 @@ void SMTConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { SMTExprRef Constraints = Solver->fromBoolean(false); for (const auto &Range : I.second) { - SMTExprRef SymRange = - getRangeExpr(Sym, Range.From(), Range.To(), /*InRange=*/true); + SMTExprRef SymRange = Solver->getRangeExpr(Ctx, Sym, Range.From(), + Range.To(), /*InRange=*/true); // FIXME: the last argument (isSigned) is not used when generating the // or expression, as both arguments are booleans @@ -42,21 +43,28 @@ clang::ento::ConditionTruthVal SMTConstraintManager::isModelFeasible() { ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State, SymbolRef Sym, bool Assumption) { + ASTContext &Ctx = getBasicVals().getContext(); + QualType RetTy; bool hasComparison; - SMTExprRef Exp = getExpr(Sym, &RetTy, &hasComparison); + SMTExprRef Exp = Solver->getExpr(Ctx, Sym, &RetTy, &hasComparison); + // Create zero comparison for implicit boolean cast, with reversed assumption if (!hasComparison && !RetTy->isBooleanType()) - return assumeExpr(State, Sym, getZeroExpr(Exp, RetTy, !Assumption)); + return assumeExpr(State, Sym, + Solver->getZeroExpr(Ctx, Exp, RetTy, !Assumption)); - return assumeExpr(State, Sym, Assumption ? Exp : getNotExpr(Exp)); + return assumeExpr(State, Sym, + Assumption ? Exp : Solver->fromUnOp(UO_LNot, Exp)); } ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange( ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { - return assumeExpr(State, Sym, getRangeExpr(Sym, From, To, InRange)); + ASTContext &Ctx = getBasicVals().getContext(); + return assumeExpr(State, Sym, + Solver->getRangeExpr(Ctx, Sym, From, To, InRange)); } ProgramStateRef @@ -68,13 +76,15 @@ SMTConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State, SymbolRef Sym) { + ASTContext &Ctx = getBasicVals().getContext(); + QualType RetTy; // The expression may be casted, so we cannot call getZ3DataExpr() directly - SMTExprRef VarExp = getExpr(Sym, &RetTy); - SMTExprRef Exp = getZeroExpr(VarExp, RetTy, true); + SMTExprRef VarExp = Solver->getExpr(Ctx, Sym, &RetTy); + SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, true); // Negate the constraint - SMTExprRef NotExp = getZeroExpr(VarExp, RetTy, false); + SMTExprRef NotExp = Solver->getZeroExpr(Ctx, VarExp, RetTy, false); Solver->reset(); addStateConstraints(State); @@ -110,7 +120,7 @@ const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State, llvm::APSInt Value(Ctx.getTypeSize(Ty), !Ty->isSignedIntegerOrEnumerationType()); - SMTExprRef Exp = getDataExpr(SD->getSymbolID(), Ty); + SMTExprRef Exp = Solver->getDataExpr(Ctx, SD->getSymbolID(), Ty); Solver->reset(); addStateConstraints(State); @@ -175,20 +185,16 @@ const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State, llvm::APSInt ConvertedLHS, ConvertedRHS; QualType LTy, RTy; - std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS); - std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS); - doIntTypeConversion( - ConvertedLHS, LTy, ConvertedRHS, RTy); + std::tie(ConvertedLHS, LTy) = Solver->fixAPSInt(Ctx, *LHS); + std::tie(ConvertedRHS, RTy) = Solver->fixAPSInt(Ctx, *RHS); + Solver->doIntTypeConversion( + Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy); return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); } llvm_unreachable("Unsupported expression to get symbol value!"); } -//===------------------------------------------------------------------===// -// Internal implementation. -//===------------------------------------------------------------------===// - ConditionTruthVal SMTConstraintManager::checkModel(ProgramStateRef State, const SMTExprRef &Exp) const { @@ -197,283 +203,3 @@ SMTConstraintManager::checkModel(ProgramStateRef State, addStateConstraints(State); return Solver->check(); } - -SMTExprRef SMTConstraintManager::getExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { - if (hasComparison) { - *hasComparison = false; - } - - return getSymExpr(Sym, RetTy, hasComparison); -} - -SMTExprRef SMTConstraintManager::getNotExpr(const SMTExprRef &Exp) const { - return Solver->fromUnOp(UO_LNot, Exp); -} - -SMTExprRef SMTConstraintManager::getZeroExpr(const SMTExprRef &Exp, QualType Ty, - bool Assumption) const { - ASTContext &Ctx = getBasicVals().getContext(); - if (Ty->isRealFloatingType()) { - llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); - return Solver->fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Solver->fromAPFloat(Zero)); - } - - if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || - Ty->isBlockPointerType() || Ty->isReferenceType()) { - - // Skip explicit comparison for boolean types - bool isSigned = Ty->isSignedIntegerOrEnumerationType(); - if (Ty->isBooleanType()) - return Assumption ? getNotExpr(Exp) : Exp; - - return Solver->fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, - Solver->fromInt("0", Ctx.getTypeSize(Ty)), - isSigned); - } - - llvm_unreachable("Unsupported type for zero value!"); -} - -SMTExprRef SMTConstraintManager::getSymExpr(SymbolRef Sym, QualType *RetTy, - bool *hasComparison) const { - if (const SymbolData *SD = dyn_cast(Sym)) { - if (RetTy) - *RetTy = Sym->getType(); - - return getDataExpr(SD->getSymbolID(), Sym->getType()); - } - - if (const SymbolCast *SC = dyn_cast(Sym)) { - if (RetTy) - *RetTy = Sym->getType(); - - QualType FromTy; - SMTExprRef Exp = getSymExpr(SC->getOperand(), &FromTy, hasComparison); - // Casting an expression with a comparison invalidates it. Note that this - // must occur after the recursive call above. - // e.g. (signed char) (x > 0) - if (hasComparison) - *hasComparison = false; - return getCastExpr(Exp, FromTy, Sym->getType()); - } - - if (const BinarySymExpr *BSE = dyn_cast(Sym)) { - SMTExprRef Exp = getSymBinExpr(BSE, hasComparison, RetTy); - // Set the hasComparison parameter, in post-order traversal order. - if (hasComparison) - *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); - return Exp; - } - - llvm_unreachable("Unsupported SymbolRef type!"); -} - -SMTExprRef SMTConstraintManager::getDataExpr(const SymbolID ID, - QualType Ty) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Solver->fromData(ID, Ty, Ctx.getTypeSize(Ty)); -} - -SMTExprRef SMTConstraintManager::getCastExpr(const SMTExprRef &Exp, - QualType FromTy, - QualType ToTy) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Solver->fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, - Ctx.getTypeSize(FromTy)); -} - -SMTExprRef SMTConstraintManager::getSymBinExpr(const BinarySymExpr *BSE, - bool *hasComparison, - QualType *RetTy) const { - QualType LTy, RTy; - BinaryOperator::Opcode Op = BSE->getOpcode(); - - if (const SymIntExpr *SIE = dyn_cast(BSE)) { - SMTExprRef LHS = getSymExpr(SIE->getLHS(), <y, hasComparison); - llvm::APSInt NewRInt; - std::tie(NewRInt, RTy) = fixAPSInt(SIE->getRHS()); - SMTExprRef RHS = Solver->fromAPSInt(NewRInt); - return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } - - if (const IntSymExpr *ISE = dyn_cast(BSE)) { - llvm::APSInt NewLInt; - std::tie(NewLInt, LTy) = fixAPSInt(ISE->getLHS()); - SMTExprRef LHS = Solver->fromAPSInt(NewLInt); - SMTExprRef RHS = getSymExpr(ISE->getRHS(), &RTy, hasComparison); - return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } - - if (const SymSymExpr *SSM = dyn_cast(BSE)) { - SMTExprRef LHS = getSymExpr(SSM->getLHS(), <y, hasComparison); - SMTExprRef RHS = getSymExpr(SSM->getRHS(), &RTy, hasComparison); - return getBinExpr(LHS, LTy, Op, RHS, RTy, RetTy); - } - - llvm_unreachable("Unsupported BinarySymExpr type!"); -} - -SMTExprRef SMTConstraintManager::getBinExpr(const SMTExprRef &LHS, QualType LTy, - BinaryOperator::Opcode Op, - const SMTExprRef &RHS, QualType RTy, - QualType *RetTy) const { - SMTExprRef NewLHS = LHS; - SMTExprRef NewRHS = RHS; - doTypeConversion(NewLHS, NewRHS, LTy, RTy); - - // Update the return type parameter if the output type has changed. - if (RetTy) { - // A boolean result can be represented as an integer type in C/C++, but at - // this point we only care about the Z3 type. Set it as a boolean type to - // avoid subsequent Z3 errors. - if (BinaryOperator::isComparisonOp(Op) || BinaryOperator::isLogicalOp(Op)) { - ASTContext &Ctx = getBasicVals().getContext(); - *RetTy = Ctx.BoolTy; - } else { - *RetTy = LTy; - } - - // If the two operands are pointers and the operation is a subtraction, the - // result is of type ptrdiff_t, which is signed - if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { - *RetTy = getBasicVals().getContext().getPointerDiffType(); - } - } - - return LTy->isRealFloatingType() - ? Solver->fromFloatBinOp(NewLHS, Op, NewRHS) - : Solver->fromBinOp(NewLHS, Op, NewRHS, - LTy->isSignedIntegerOrEnumerationType()); -} - -SMTExprRef SMTConstraintManager::getRangeExpr(SymbolRef Sym, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool InRange) { - // Convert lower bound - QualType FromTy; - llvm::APSInt NewFromInt; - std::tie(NewFromInt, FromTy) = fixAPSInt(From); - SMTExprRef FromExp = Solver->fromAPSInt(NewFromInt); - - // Convert symbol - QualType SymTy; - SMTExprRef Exp = getExpr(Sym, &SymTy); - - // Construct single (in)equality - if (From == To) - return getBinExpr(Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, FromTy, - /*RetTy=*/nullptr); - - QualType ToTy; - llvm::APSInt NewToInt; - std::tie(NewToInt, ToTy) = fixAPSInt(To); - SMTExprRef ToExp = Solver->fromAPSInt(NewToInt); - assert(FromTy == ToTy && "Range values have different types!"); - - // Construct two (in)equalities, and a logical and/or - SMTExprRef LHS = getBinExpr(Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, - FromTy, /*RetTy=*/nullptr); - SMTExprRef RHS = getBinExpr(Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, - /*RetTy=*/nullptr); - - return Solver->fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, - SymTy->isSignedIntegerOrEnumerationType()); -} - -//===------------------------------------------------------------------===// -// Helper functions. -//===------------------------------------------------------------------===// - -QualType SMTConstraintManager::getAPSIntType(const llvm::APSInt &Int) const { - ASTContext &Ctx = getBasicVals().getContext(); - return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); -} - -std::pair -SMTConstraintManager::fixAPSInt(const llvm::APSInt &Int) const { - llvm::APSInt NewInt; - - // FIXME: This should be a cast from a 1-bit integer type to a boolean type, - // but the former is not available in Clang. Instead, extend the APSInt - // directly. - if (Int.getBitWidth() == 1 && getAPSIntType(Int).isNull()) { - ASTContext &Ctx = getBasicVals().getContext(); - NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); - } else - NewInt = Int; - - return std::make_pair(NewInt, getAPSIntType(NewInt)); -} - -void SMTConstraintManager::doTypeConversion(SMTExprRef &LHS, SMTExprRef &RHS, - QualType <y, - QualType &RTy) const { - assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); - - ASTContext &Ctx = getBasicVals().getContext(); - - // Perform type conversion - if ((LTy->isIntegralOrEnumerationType() && - RTy->isIntegralOrEnumerationType()) && - (LTy->isArithmeticType() && RTy->isArithmeticType())) { - doIntTypeConversion(LHS, LTy, RHS, RTy); - return; - } - - if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { - doFloatTypeConversion(LHS, LTy, RHS, RTy); - return; - } - - if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || - (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || - (LTy->isReferenceType() || RTy->isReferenceType())) { - // TODO: Refactor to Sema::FindCompositePointerType(), and - // Sema::CheckCompareOperands(). - - uint64_t LBitWidth = Ctx.getTypeSize(LTy); - uint64_t RBitWidth = Ctx.getTypeSize(RTy); - - // Cast the non-pointer type to the pointer type. - // TODO: Be more strict about this. - if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) || - (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) || - (LTy->isReferenceType() ^ RTy->isReferenceType())) { - if (LTy->isNullPtrType() || LTy->isBlockPointerType() || - LTy->isReferenceType()) { - LHS = Solver->fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); - LTy = RTy; - } else { - RHS = Solver->fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); - RTy = LTy; - } - } - - // Cast the void pointer type to the non-void pointer type. - // For void types, this assumes that the casted value is equal to the value - // of the original pointer, and does not account for alignment requirements. - if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) { - assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) && - "Pointer types have different bitwidths!"); - if (RTy->isVoidPointerType()) - RTy = LTy; - else - LTy = RTy; - } - - if (LTy == RTy) - return; - } - - // Fallback: for the solver, assume that these types don't really matter - if ((LTy.getCanonicalType() == RTy.getCanonicalType()) || - (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) { - LTy = RTy; - return; - } - - // TODO: Refine behavior for invalid type casts -} -- GitLab From 7179078a7a3501a27cc18d911079025a3865e134 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:43 +0000 Subject: [PATCH 0718/1023] [analyzer] Removed API used by the Refutation Manager from SMTConstraintManager and replace by proper calls to SMTSolver Summary: Third patch in the refactoring series, to decouple the SMT Solver from the Refutation Manager (1st: D49668, 2nd: D49767). The refutation API in the `SMTConstraintManager` was a hack to allow us to create an SMT solver and verify the constraints; it was conceptually wrong from the start. Now, we don't actually need to use the `SMTConstraintManager` and can create an SMT object directly, add the constraints and check them. While updating the Falsification visitor, I inlined the two functions that were used to collect the constraints and add them to the solver. As a result of this patch, we could move the SMT API elsewhere and as it's not really dependent on the CSA anymore. Maybe we can create a new dir (utils/smt) for Z3 and future solvers? Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49768 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337922 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTConstraintManager.h | 8 --- .../Core/PathSensitive/SMTSolver.h | 2 + .../Core/BugReporterVisitors.cpp | 63 +++++++++---------- .../Core/SMTConstraintManager.cpp | 25 -------- .../Core/Z3ConstraintManager.cpp | 13 +++- 5 files changed, 45 insertions(+), 66 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 6b44e02b3e..f593fcc393 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -54,14 +54,6 @@ public: const llvm::APSInt *getSymVal(ProgramStateRef State, SymbolRef Sym) const override; - /// Converts the ranged constraints of a set of symbols to SMT - /// - /// \param CR The set of constraints. - void addRangeConstraints(clang::ento::ConstraintRangeTy CR); - - /// Checks if the added constraints are satisfiable - clang::ento::ConditionTruthVal isModelFeasible(); - /// Dumps SMT formula LLVM_DUMP_METHOD void dump() const { Solver->dump(); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index 3a3adc044a..bdd3505d62 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -954,6 +954,8 @@ public: using SMTSolverRef = std::shared_ptr; +std::unique_ptr CreateZ3Solver(); + } // namespace ento } // namespace clang diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index f17f41a7ac..6213fc0598 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -2370,34 +2370,6 @@ TaintBugVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, return std::make_shared(L, "Taint originated here"); } -static bool areConstraintsUnfeasible(BugReporterContext &BRC, - const ConstraintRangeTy &Cs) { - // Create a refutation manager - std::unique_ptr RefutationMgr = CreateZ3ConstraintManager( - BRC.getStateManager(), BRC.getStateManager().getOwningEngine()); - - SMTConstraintManager *SMTRefutationMgr = - static_cast(RefutationMgr.get()); - - // Add constraints to the solver - SMTRefutationMgr->addRangeConstraints(Cs); - - // And check for satisfiability - return SMTRefutationMgr->isModelFeasible().isConstrainedFalse(); -} - -static void addNewConstraints(ConstraintRangeTy &Cs, - const ConstraintRangeTy &NewCs, - ConstraintRangeTy::Factory &CF) { - // Add constraints if we don't have them yet - for (auto const &C : NewCs) { - const SymbolRef &Sym = C.first; - if (!Cs.contains(Sym)) { - Cs = CF.add(Cs, Sym, C.second); - } - } -} - FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor() : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {} @@ -2406,8 +2378,26 @@ void FalsePositiveRefutationBRVisitor::finalizeVisitor( // Collect new constraints VisitNode(EndPathNode, nullptr, BRC, BR); - // Create a new refutation manager and check feasibility - if (areConstraintsUnfeasible(BRC, Constraints)) + // Create a refutation manager + std::unique_ptr RefutationSolver = CreateZ3Solver(); + ASTContext &Ctx = BRC.getASTContext(); + + // Add constraints to the solver + for (const auto &I : Constraints) { + SymbolRef Sym = I.first; + + SMTExprRef Constraints = RefutationSolver->fromBoolean(false); + for (const auto &Range : I.second) { + Constraints = RefutationSolver->mkOr( + Constraints, + RefutationSolver->getRangeExpr(Ctx, Sym, Range.From(), Range.To(), + /*InRange=*/true)); + } + RefutationSolver->addConstraint(Constraints); + } + + // And check for satisfiability + if (RefutationSolver->check().isConstrainedFalse()) BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext()); } @@ -2417,8 +2407,17 @@ FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { // Collect new constraints - addNewConstraints(Constraints, N->getState()->get(), - N->getState()->get_context()); + const ConstraintRangeTy &NewCs = N->getState()->get(); + ConstraintRangeTy::Factory &CF = + N->getState()->get_context(); + + // Add constraints if we don't have them yet + for (auto const &C : NewCs) { + const SymbolRef &Sym = C.first; + if (!Constraints.contains(Sym)) { + Constraints = CF.add(Constraints, Sym, C.second); + } + } return nullptr; } diff --git a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp index 542b3741be..8e31635dc9 100644 --- a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp @@ -15,31 +15,6 @@ using namespace clang; using namespace ento; -void SMTConstraintManager::addRangeConstraints(ConstraintRangeTy CR) { - ASTContext &Ctx = getBasicVals().getContext(); - Solver->reset(); - - for (const auto &I : CR) { - SymbolRef Sym = I.first; - - SMTExprRef Constraints = Solver->fromBoolean(false); - for (const auto &Range : I.second) { - SMTExprRef SymRange = Solver->getRangeExpr(Ctx, Sym, Range.From(), - Range.To(), /*InRange=*/true); - - // FIXME: the last argument (isSigned) is not used when generating the - // or expression, as both arguments are booleans - Constraints = - Solver->fromBinOp(Constraints, BO_LOr, SymRange, /*IsSigned=*/true); - } - Solver->addConstraint(Constraints); - } -} - -clang::ento::ConditionTruthVal SMTConstraintManager::isModelFeasible() { - return Solver->check(); -} - ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State, SymbolRef Sym, bool Assumption) { diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 1051493279..f15737bed4 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -932,7 +932,7 @@ public: }; // end class Z3Solver class Z3ConstraintManager : public SMTConstraintManager { - SMTSolverRef Solver = std::make_shared(); + SMTSolverRef Solver = CreateZ3Solver(); public: Z3ConstraintManager(SubEngine *SE, SValBuilder &SB) @@ -1043,6 +1043,17 @@ public: #endif +std::unique_ptr clang::ento::CreateZ3Solver() { +#if CLANG_ANALYZER_WITH_Z3 + return llvm::make_unique(); +#else + llvm::report_fatal_error("Clang was not compiled with Z3 support, rebuild " + "with -DCLANG_ANALYZER_BUILD_Z3=ON", + false); + return nullptr; +#endif +} + std::unique_ptr ento::CreateZ3ConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { #if CLANG_ANALYZER_WITH_Z3 -- GitLab From 18b6344a9de24b645d295cf7bc2dd2f58a7733ac Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 12:49:47 +0000 Subject: [PATCH 0719/1023] [analyzer] Use the macro REGISTER_TRAIT_WITH_PROGRAMSTATE in the Z3 backend Summary: The macro was manually expanded in the Z3 backend and this patch adds it back. Adding the expanded code is dangerous as the macro may change in the future and the expanded code might be left outdated. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49769 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337923 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/Z3ConstraintManager.cpp | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index f15737bed4..536de5d037 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -25,28 +25,6 @@ using namespace ento; #include -// Forward declarations -namespace { -class Z3Expr; -class ConstraintZ3 {}; -} // end anonymous namespace - -typedef llvm::ImmutableSet> ConstraintZ3Ty; - -// Expansion of REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintZ3, Z3SetPair) -namespace clang { -namespace ento { -template <> -struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { - static int Index; - return &Index; - } -}; -} // end namespace ento -} // end namespace clang - namespace { class Z3Config { @@ -313,6 +291,13 @@ static bool areEquivalent(const llvm::fltSemantics &LHS, llvm::APFloat::semanticsSizeInBits(RHS)); } +} // end anonymous namespace + +typedef llvm::ImmutableSet> ConstraintZ3Ty; +REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintZ3, ConstraintZ3Ty) + +namespace { + class Z3Solver : public SMTSolver { friend class Z3ConstraintManager; -- GitLab From 9fdbc7af5ebeede70f7c193da62182c558beb693 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 25 Jul 2018 13:55:06 +0000 Subject: [PATCH 0720/1023] [Docs] Update supported oses for safestack, ubsan, asan, tsan and msan Adding oses others than Linux. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337926 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/AddressSanitizer.rst | 1 + docs/MemorySanitizer.rst | 6 +++++- docs/SafeStack.rst | 2 +- docs/ThreadSanitizer.rst | 6 +++++- docs/UndefinedBehaviorSanitizer.rst | 10 ++-------- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst index 20cf699ac0..7549159a39 100644 --- a/docs/AddressSanitizer.rst +++ b/docs/AddressSanitizer.rst @@ -276,6 +276,7 @@ AddressSanitizer is supported on: * OS X 10.7 - 10.11 (i386/x86\_64) * iOS Simulator * Android ARM +* NetBSD i386/x86\_64 * FreeBSD i386/x86\_64 (tested on FreeBSD 11-current) Ports to various other platforms are in progress. diff --git a/docs/MemorySanitizer.rst b/docs/MemorySanitizer.rst index 5bb19ed8a5..4e033fa194 100644 --- a/docs/MemorySanitizer.rst +++ b/docs/MemorySanitizer.rst @@ -185,7 +185,11 @@ self-built instrumented libc++ (as a replacement for libstdc++). Supported Platforms =================== -MemorySanitizer is supported on Linux x86\_64/MIPS64/AArch64. +MemorySanitizer is supported on the following OS: + +* Linux +* NetBSD +* FreeBSD Limitations =========== diff --git a/docs/SafeStack.rst b/docs/SafeStack.rst index 866a8060aa..b046aa6168 100644 --- a/docs/SafeStack.rst +++ b/docs/SafeStack.rst @@ -126,7 +126,7 @@ and link command lines. Supported Platforms ------------------- -SafeStack was tested on Linux, FreeBSD and MacOSX. +SafeStack was tested on Linux, NetBSD, FreeBSD and MacOSX. Low-level API ------------- diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst index cfbaa63d64..4a8db9154e 100644 --- a/docs/ThreadSanitizer.rst +++ b/docs/ThreadSanitizer.rst @@ -17,7 +17,11 @@ Build LLVM/Clang with `CMake `_. Supported Platforms ------------------- -ThreadSanitizer is supported on Linux x86_64 (tested on Ubuntu 12.04). +ThreadSanitizer is supported on the following OS: + +* Linux +* NetBSD +* FreeBSD Support for other 64-bit architectures is possible, contributions are welcome. Support for 32-bit platforms is problematic and is not planned. diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst index 8dd9157e81..71a8ebd4bc 100644 --- a/docs/UndefinedBehaviorSanitizer.rst +++ b/docs/UndefinedBehaviorSanitizer.rst @@ -252,17 +252,11 @@ UndefinedBehaviorSanitizer is supported on the following OS: * Android * Linux +* NetBSD * FreeBSD +* OpenBSD * OS X 10.6 onwards -and for the following architectures: - -* i386/x86\_64 -* ARM -* AArch64 -* PowerPC64 -* MIPS/MIPS64 - Current Status ============== -- GitLab From 80911293a8a04489b48df2cb2758d0803cec7dde Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 25 Jul 2018 14:27:14 +0000 Subject: [PATCH 0721/1023] Fix tsan doc git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337927 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ThreadSanitizer.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst index 4a8db9154e..d1e2c65ec5 100644 --- a/docs/ThreadSanitizer.rst +++ b/docs/ThreadSanitizer.rst @@ -22,6 +22,7 @@ ThreadSanitizer is supported on the following OS: * Linux * NetBSD * FreeBSD + Support for other 64-bit architectures is possible, contributions are welcome. Support for 32-bit platforms is problematic and is not planned. -- GitLab From 3334e9178a3382da8d7ba92c462d4be410772fe0 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 25 Jul 2018 14:40:26 +0000 Subject: [PATCH 0722/1023] [OPENMP] Fix PR38256: Fix locations of the artificial conditional op. Fixed the source locations of the conditional op so that they don'r crash coverage pass. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337928 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 3 ++- test/CoverageMapping/openmp.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/CoverageMapping/openmp.c diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index f5a1d0b222..e1a4c420d4 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -4909,7 +4909,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT, UB.get(), LastIteration.get()); ExprResult CondOp = SemaRef.ActOnConditionalOp( - InitLoc, InitLoc, IsUBGreater.get(), LastIteration.get(), UB.get()); + LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(), + LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); diff --git a/test/CoverageMapping/openmp.c b/test/CoverageMapping/openmp.c new file mode 100644 index 0000000000..1ac12624e0 --- /dev/null +++ b/test/CoverageMapping/openmp.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fopenmp -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name openmp.c %s | FileCheck %s + +// CHECK: openmp.c:{{.+}}omp_outlined{{.+}}: +// CHECK: File 0, 10:3 -> 10:31 +// CHECK: File 0, 10:19 -> 10:24 +// CHECK: File 0, 10:26 -> 10:29 +// CHECK: File 0, 10:30 -> 10:31 +int foo(int time, int n) { +#pragma omp parallel for default(shared) schedule(dynamic, 1) reduction(+ : time) + for (int i = 1; i < n; ++i); + return 0; +} -- GitLab From 9280a04746a98ebc1d45917ae030be9c06fa4f15 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 25 Jul 2018 17:27:45 +0000 Subject: [PATCH 0723/1023] [OPENMP] Exclude service expressions/statements from the list of the children. Special internal helper expressions/statements for the OpenMP directives should not be exposed as children, only the main substatement must be represented as the child. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337941 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/StmtOpenMP.h | 4 +++- test/OpenMP/dump.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 963c3f5fef..84a35db938 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -252,7 +252,9 @@ public: if (!hasAssociatedStmt()) return child_range(child_iterator(), child_iterator()); Stmt **ChildStorage = reinterpret_cast(getClauses().end()); - return child_range(ChildStorage, ChildStorage + NumChildren); + /// Do not mark all the special expression/statements as children, except + /// for the associated statement. + return child_range(ChildStorage, ChildStorage + 1); } ArrayRef clauses() { return getClauses(); } diff --git a/test/OpenMP/dump.cpp b/test/OpenMP/dump.cpp index 28da82b3b8..812afb72f6 100644 --- a/test/OpenMP/dump.cpp +++ b/test/OpenMP/dump.cpp @@ -53,11 +53,11 @@ struct S { // CHECK-NEXT: | |-OMPScheduleClause {{.+}} // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'int' // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int' -// CHECK-NEXT: | |-CapturedStmt {{.+}} -// CHECK-NEXT: | | |-CapturedDecl {{.+}} <> -// CHECK-NEXT: | | | |-ForStmt {{.+}} -// CHECK: | | | | `-UnaryOperator {{.+}} 'int' lvalue prefix '++' -// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &' +// CHECK-NEXT: | `-CapturedStmt {{.+}} +// CHECK-NEXT: | |-CapturedDecl {{.+}} <> +// CHECK-NEXT: | | |-ForStmt {{.+}} +// CHECK: | | | `-UnaryOperator {{.+}} 'int' lvalue prefix '++' +// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &' #pragma omp declare simd #pragma omp declare simd inbranch -- GitLab From 9d271415afbba1a47a2a0b81b4d7af05c9f158fa Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 25 Jul 2018 18:11:01 +0000 Subject: [PATCH 0724/1023] [clang:sema] de-duplicate getDepthAndIndex helpers Summary: Continuing off of: https://reviews.llvm.org/D38382 Fixes: https://bugs.llvm.org/show_bug.cgi?id=12176 Reviewers: srhines, pirama, vsk Reviewed By: vsk Subscribers: cfe-commits, vsk, maitesin Differential Revision: https://reviews.llvm.org/D49760 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337944 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/SemaInternal.h | 21 +++++++++++++++++++++ lib/Sema/SemaTemplateDeduction.cpp | 23 ----------------------- lib/Sema/SemaTemplateInstantiate.cpp | 13 ------------- lib/Sema/SemaTemplateVariadic.cpp | 13 ------------- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index 153270f3d0..86ab703a5b 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -101,6 +101,27 @@ inline InheritableAttr *getDLLAttr(Decl *D) { return nullptr; } +/// Retrieve the depth and index of a template parameter. +inline std::pair getDepthAndIndex(NamedDecl *ND) { + if (const auto *TTP = dyn_cast(ND)) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + if (const auto *NTTP = dyn_cast(ND)) + return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); + + const auto *TTP = cast(ND); + return std::make_pair(TTP->getDepth(), TTP->getIndex()); +} + +/// Retrieve the depth and index of an unexpanded parameter pack. +inline std::pair +getDepthAndIndex(UnexpandedParameterPack UPP) { + if (const auto *TTP = UPP.first.dyn_cast()) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + return getDepthAndIndex(UPP.first.get()); +} + class TypoCorrectionConsumer : public VisibleDeclConsumer { typedef SmallVector TypoResultList; typedef llvm::StringMap TypoResultsMap; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 0b41a515d9..633b2837e1 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -628,29 +628,6 @@ static bool IsPossiblyOpaquelyQualifiedType(QualType T) { } } -/// Retrieve the depth and index of a template parameter. -static std::pair -getDepthAndIndex(NamedDecl *ND) { - if (TemplateTypeParmDecl *TTP = dyn_cast(ND)) - return std::make_pair(TTP->getDepth(), TTP->getIndex()); - - if (NonTypeTemplateParmDecl *NTTP = dyn_cast(ND)) - return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); - - TemplateTemplateParmDecl *TTP = cast(ND); - return std::make_pair(TTP->getDepth(), TTP->getIndex()); -} - -/// Retrieve the depth and index of an unexpanded parameter pack. -static std::pair -getDepthAndIndex(UnexpandedParameterPack UPP) { - if (const TemplateTypeParmType *TTP - = UPP.first.dyn_cast()) - return std::make_pair(TTP->getDepth(), TTP->getIndex()); - - return getDepthAndIndex(UPP.first.get()); -} - /// Helper function to build a TemplateParameter when we don't /// know its type statically. static TemplateParameter makeTemplateParameter(Decl *D) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3cf584344c..bc2ee42400 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -708,19 +708,6 @@ Optional Sema::isSFINAEContext() const { return None; } -/// Retrieve the depth and index of a parameter pack. -static std::pair -getDepthAndIndex(NamedDecl *ND) { - if (TemplateTypeParmDecl *TTP = dyn_cast(ND)) - return std::make_pair(TTP->getDepth(), TTP->getIndex()); - - if (NonTypeTemplateParmDecl *NTTP = dyn_cast(ND)) - return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); - - TemplateTemplateParmDecl *TTP = cast(ND); - return std::make_pair(TTP->getDepth(), TTP->getIndex()); -} - //===----------------------------------------------------------------------===/ // Template Instantiation for Types //===----------------------------------------------------------------------===/ diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 8f7a75a165..fc16413342 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -26,19 +26,6 @@ using namespace clang; // Visitor that collects unexpanded parameter packs //---------------------------------------------------------------------------- -/// Retrieve the depth and index of a parameter pack. -static std::pair -getDepthAndIndex(NamedDecl *ND) { - if (TemplateTypeParmDecl *TTP = dyn_cast(ND)) - return std::make_pair(TTP->getDepth(), TTP->getIndex()); - - if (NonTypeTemplateParmDecl *NTTP = dyn_cast(ND)) - return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); - - TemplateTemplateParmDecl *TTP = cast(ND); - return std::make_pair(TTP->getDepth(), TTP->getIndex()); -} - namespace { /// A class that collects unexpanded parameter packs. class CollectUnexpandedParameterPacksVisitor : -- GitLab From b4e6971ad794232deb402af54d49e215f5bab364 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 18:26:50 +0000 Subject: [PATCH 0725/1023] [analyzer] Fix compilation when LLVM_ENABLE_MODULES=ON git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337948 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h | 3 ++- include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h | 4 ++++ include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h index f0591780b7..c34056c955 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h @@ -15,7 +15,8 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/FoldingSet.h" namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index bdd3505d62..f01c5b9284 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -15,8 +15,12 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H +#include "clang/AST/Expr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h index 6780dac751..e5e3844e88 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H +#include "clang/Basic/TargetInfo.h" + namespace clang { namespace ento { -- GitLab From cb27abbb2b60f0f3c40844e81f1d1a378a05e360 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Wed, 25 Jul 2018 19:16:26 +0000 Subject: [PATCH 0726/1023] [Preprocessor] Stop entering included files after hitting a fatal error. Fixes a problem when we have multiple inclusion cycles and try to enumerate all possible ways to reach the max inclusion depth. rdar://problem/38871876 Reviewers: bruno, rsmith, jkorous, aaron.ballman Reviewed By: bruno, jkorous, aaron.ballman Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D48786 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337953 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/PPDirectives.cpp | 6 ++++++ test/Preprocessor/Inputs/cycle/a.h | 8 ++++++++ test/Preprocessor/Inputs/cycle/b.h | 1 + test/Preprocessor/Inputs/cycle/c.h | 1 + test/Preprocessor/include-cycle.c | 5 +++++ 5 files changed, 21 insertions(+) create mode 100644 test/Preprocessor/Inputs/cycle/a.h create mode 100644 test/Preprocessor/Inputs/cycle/b.h create mode 100644 test/Preprocessor/Inputs/cycle/c.h create mode 100644 test/Preprocessor/include-cycle.c diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 4ea0f485d3..d8dae73037 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1896,6 +1896,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (PPOpts->SingleFileParseMode) ShouldEnter = false; + // Any diagnostics after the fatal error will not be visible. As the + // compilation failed already and errors in subsequently included files won't + // be visible, avoid preprocessing those files. + if (ShouldEnter && Diags->hasFatalErrorOccurred()) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). diff --git a/test/Preprocessor/Inputs/cycle/a.h b/test/Preprocessor/Inputs/cycle/a.h new file mode 100644 index 0000000000..dd3ef35d61 --- /dev/null +++ b/test/Preprocessor/Inputs/cycle/a.h @@ -0,0 +1,8 @@ +// Presence of 2 inclusion cycles +// b.h -> a.h -> b.h -> ... +// c.h -> a.h -> c.h -> ... +// makes it unfeasible to reach max inclusion depth in all possible ways. Need +// to stop earlier. + +#include "b.h" +#include "c.h" diff --git a/test/Preprocessor/Inputs/cycle/b.h b/test/Preprocessor/Inputs/cycle/b.h new file mode 100644 index 0000000000..2243de1baf --- /dev/null +++ b/test/Preprocessor/Inputs/cycle/b.h @@ -0,0 +1 @@ +#include "a.h" diff --git a/test/Preprocessor/Inputs/cycle/c.h b/test/Preprocessor/Inputs/cycle/c.h new file mode 100644 index 0000000000..2243de1baf --- /dev/null +++ b/test/Preprocessor/Inputs/cycle/c.h @@ -0,0 +1 @@ +#include "a.h" diff --git a/test/Preprocessor/include-cycle.c b/test/Preprocessor/include-cycle.c new file mode 100644 index 0000000000..52fcfbd27a --- /dev/null +++ b/test/Preprocessor/include-cycle.c @@ -0,0 +1,5 @@ +// RUN: not %clang_cc1 -E -I%S/Inputs -ferror-limit 20 %s + +// Test that preprocessing terminates even if we have inclusion cycles. + +#include "cycle/a.h" -- GitLab From 21c05575c39fe139269c24eb56a0b4549f698a3a Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 25 Jul 2018 19:34:48 +0000 Subject: [PATCH 0727/1023] [analyzer] Update SMT API documentation and methods Summary: Update the documentation of all the classes introduced with the new generic SMT API, most of them were referencing Z3 and how previous operations were being done (like including the context as parameter in a few methods). Renamed the following methods, so it's clear that the operate on bitvectors: *`mkSignExt` -> `mkBVSignExt` *`mkZeroExt` -> `mkBVZeroExt` *`mkExtract` -> `mkBVExtract` *`mkConcat` -> `mkBVConcat` Removed the unecessary methods: * `getDataExpr`: it was an one line method that called `fromData` * `mkBitvector(const llvm::APSInt Int)`: it was not being used anywhere Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49799 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337954 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTConstraintManager.h | 4 - .../Core/PathSensitive/SMTContext.h | 1 + .../Core/PathSensitive/SMTExpr.h | 4 + .../Core/PathSensitive/SMTSolver.h | 223 ++++++++++-------- .../Core/PathSensitive/SMTSort.h | 18 ++ .../Core/SMTConstraintManager.cpp | 11 +- .../Core/Z3ConstraintManager.cpp | 32 +-- 7 files changed, 168 insertions(+), 125 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index f593fcc393..19d3d5973e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -58,10 +58,6 @@ public: LLVM_DUMP_METHOD void dump() const { Solver->dump(); } protected: - //===------------------------------------------------------------------===// - // Internal implementation. - //===------------------------------------------------------------------===// - // Check whether a new model is satisfiable, and update the program state. virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, const SMTExprRef &Exp) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h index 01aa1c8b6d..45c9df4ef4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h @@ -18,6 +18,7 @@ namespace clang { namespace ento { +/// Generic base class for SMT contexts class SMTContext { public: SMTContext() = default; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h index c34056c955..9dedf96cfa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h @@ -21,6 +21,7 @@ namespace clang { namespace ento { +/// Generic base class for SMT exprs class SMTExpr { public: SMTExpr() = default; @@ -47,9 +48,12 @@ public: LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. virtual bool equal_to(SMTExpr const &other) const = 0; }; +/// Shared pointer for SMTExprs, used by SMTSolver API. using SMTExprRef = std::shared_ptr; } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index f01c5b9284..d10e69788c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -25,6 +25,11 @@ namespace clang { namespace ento { +/// Generic base class for SMT Solvers +/// +/// This class is responsible for wrapping all sorts and expression generation, +/// through the mk* methods. It also provides methods to create SMT expressions +/// straight from clang's AST, through the from* methods. class SMTSolver { public: SMTSolver() = default; @@ -32,7 +37,7 @@ public: LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } - // Return an appropriate floating-point sort for the given bitwidth. + // Returns an appropriate floating-point sort for the given bitwidth. SMTSortRef getFloatSort(unsigned BitWidth) { switch (BitWidth) { case 16: @@ -48,7 +53,7 @@ public: llvm_unreachable("Unsupported floating-point bitwidth!"); } - // Return an appropriate sort, given a QualType + // Returns an appropriate sort, given a QualType and it's bit width. SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth) { if (Ty->isBooleanType()) return getBoolSort(); @@ -59,7 +64,7 @@ public: return getBitvectorSort(BitWidth); } - /// Construct a Z3Expr from a unary operator, given a Z3_context. + /// Constructs an SMTExprRef from an unary operator. SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) { switch (Op) { case UO_Minus: @@ -76,8 +81,7 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct a Z3Expr from a floating-point unary operator, given a - /// Z3_context. + /// Constructs an SMTExprRef from a floating-point unary operator. SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) { switch (Op) { @@ -92,7 +96,7 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct a Z3Expr from a n-ary binary operator. + /// Construct an SMTExprRef from a n-ary binary operator. SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op, const std::vector &ASTs) { assert(!ASTs.empty()); @@ -106,7 +110,7 @@ public: return res; } - /// Construct a Z3Expr from a binary operator, given a Z3_context. + /// Construct an SMTExprRef from a binary operator. SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS, bool isSigned) { assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!"); @@ -122,21 +126,21 @@ public: case BO_Rem: return isSigned ? mkBVSRem(LHS, RHS) : mkBVURem(LHS, RHS); - // Additive operators + // Additive operators case BO_Add: return mkBVAdd(LHS, RHS); case BO_Sub: return mkBVSub(LHS, RHS); - // Bitwise shift operators + // Bitwise shift operators case BO_Shl: return mkBVShl(LHS, RHS); case BO_Shr: return isSigned ? mkBVAshr(LHS, RHS) : mkBVLshr(LHS, RHS); - // Relational operators + // Relational operators case BO_LT: return isSigned ? mkBVSlt(LHS, RHS) : mkBVUlt(LHS, RHS); @@ -149,14 +153,14 @@ public: case BO_GE: return isSigned ? mkBVSge(LHS, RHS) : mkBVUge(LHS, RHS); - // Equality operators + // Equality operators case BO_EQ: return mkEqual(LHS, RHS); case BO_NE: return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned)); - // Bitwise operators + // Bitwise operators case BO_And: return mkBVAnd(LHS, RHS); @@ -166,7 +170,7 @@ public: case BO_Or: return mkBVOr(LHS, RHS); - // Logical operators + // Logical operators case BO_LAnd: return mkAnd(LHS, RHS); @@ -178,8 +182,7 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct a Z3Expr from a special floating-point binary operator, given - /// a Z3_context. + /// Construct an SMTExprRef from a special floating-point binary operator. SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS) { @@ -210,8 +213,7 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct a Z3Expr from a floating-point binary operator, given a - /// Z3_context. + /// Construct an SMTExprRef from a floating-point binary operator. SMTExprRef fromFloatBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS) { @@ -266,7 +268,8 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct a Z3Expr from a SymbolCast, given a Z3_context. + /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and + /// their bit widths. SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, QualType FromTy, uint64_t FromBitWidth) { if ((FromTy->isIntegralOrEnumerationType() && @@ -283,11 +286,11 @@ public: if (ToBitWidth > FromBitWidth) return FromTy->isSignedIntegerOrEnumerationType() - ? mkSignExt(ToBitWidth - FromBitWidth, Exp) - : mkZeroExt(ToBitWidth - FromBitWidth, Exp); + ? mkBVSignExt(ToBitWidth - FromBitWidth, Exp) + : mkBVZeroExt(ToBitWidth - FromBitWidth, Exp); if (ToBitWidth < FromBitWidth) - return mkExtract(ToBitWidth - 1, 0, Exp); + return mkBVExtract(ToBitWidth - 1, 0, Exp); // Both are bitvectors with the same width, ignore the type cast return Exp; @@ -322,7 +325,7 @@ public: return TargetType.convert(V); } - // Generate a Z3Expr that represents the given symbolic expression. + // Generate an SMTExprRef that represents the given symbolic expression. // Sets the hasComparison parameter if the expression has a comparison // operator. // Sets the RetTy parameter to the final return type after promotions and @@ -336,7 +339,7 @@ public: return getSymExpr(Ctx, Sym, RetTy, hasComparison); } - // Generate a Z3Expr that compares the expression to zero. + // Generate an SMTExprRef that compares the expression to zero. SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty, bool Assumption) { @@ -362,14 +365,15 @@ public: } // Recursive implementation to unpack and generate symbolic expression. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + // Sets the hasComparison and RetTy parameters. See getExpr(). SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, bool *hasComparison) { if (const SymbolData *SD = dyn_cast(Sym)) { if (RetTy) *RetTy = Sym->getType(); - return getDataExpr(Ctx, SD->getSymbolID(), Sym->getType()); + return fromData(SD->getSymbolID(), Sym->getType(), + Ctx.getTypeSize(Sym->getType())); } if (const SymbolCast *SC = dyn_cast(Sym)) { @@ -398,21 +402,15 @@ public: llvm_unreachable("Unsupported SymbolRef type!"); } - // Wrapper to generate Z3Expr from SymbolData. - SMTExprRef getDataExpr(ASTContext &Ctx, const SymbolID ID, QualType Ty) { - return fromData(ID, Ty, Ctx.getTypeSize(Ty)); - } - - // Wrapper to generate Z3Expr from SymbolCast. + // Wrapper to generate SMTExprRef from SymbolCast data. SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType FromTy, QualType ToTy) { - return fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, Ctx.getTypeSize(FromTy)); } - // Wrapper to generate Z3Expr from BinarySymExpr. - // Sets the hasComparison and RetTy parameters. See getZ3Expr(). + // Wrapper to generate SMTExprRef from BinarySymExpr. + // Sets the hasComparison and RetTy parameters. See getSMTExprRef(). SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE, bool *hasComparison, QualType *RetTy) { QualType LTy, RTy; @@ -443,8 +441,8 @@ public: llvm_unreachable("Unsupported BinarySymExpr type!"); } - // Wrapper to generate Z3Expr from unpacked binary symbolic expression. - // Sets the RetTy parameter. See getZ3Expr(). + // Wrapper to generate SMTExprRef from unpacked binary symbolic expression. + // Sets the RetTy parameter. See getSMTExprRef(). SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, const SMTExprRef &RHS, QualType RTy, QualType *RetTy) { @@ -455,11 +453,10 @@ public: // Update the return type parameter if the output type has changed. if (RetTy) { // A boolean result can be represented as an integer type in C/C++, but at - // this point we only care about the Z3 type. Set it as a boolean type to - // avoid subsequent Z3 errors. + // this point we only care about the SMT sorts. Set it as a boolean type + // to avoid subsequent SMT errors. if (BinaryOperator::isComparisonOp(Op) || BinaryOperator::isLogicalOp(Op)) { - *RetTy = Ctx.BoolTy; } else { *RetTy = LTy; @@ -478,8 +475,8 @@ public: LTy->isSignedIntegerOrEnumerationType()); } - // Wrapper to generate Z3Expr from a range. If From == To, an equality will - // be created instead. + // Wrapper to generate SMTExprRef from a range. If From == To, an equality + // will be created instead. SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { @@ -496,8 +493,7 @@ public: // Construct single (in)equality if (From == To) return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, - FromTy, - /*RetTy=*/nullptr); + FromTy, /*RetTy=*/nullptr); QualType ToTy; llvm::APSInt NewToInt; @@ -519,7 +515,6 @@ public: // Recover the QualType of an APSInt. // TODO: Refactor to put elsewhere QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int) { - return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); } @@ -532,7 +527,6 @@ public: // but the former is not available in Clang. Instead, extend the APSInt // directly. if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) { - NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); } else NewInt = Int; @@ -736,189 +730,221 @@ public: } } - // Return a boolean sort. + // Returns a boolean sort. virtual SMTSortRef getBoolSort() = 0; - // Return an appropriate bitvector sort for the given bitwidth. + // Returns an appropriate bitvector sort for the given bitwidth. virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0; - // Return a floating-point sort of width 16 + // Returns a floating-point sort of width 16 virtual SMTSortRef getFloat16Sort() = 0; - // Return a floating-point sort of width 32 + // Returns a floating-point sort of width 32 virtual SMTSortRef getFloat32Sort() = 0; - // Return a floating-point sort of width 64 + // Returns a floating-point sort of width 64 virtual SMTSortRef getFloat64Sort() = 0; - // Return a floating-point sort of width 128 + // Returns a floating-point sort of width 128 virtual SMTSortRef getFloat128Sort() = 0; - // Return an appropriate sort for the given AST. + // Returns an appropriate sort for the given AST. virtual SMTSortRef getSort(const SMTExprRef &AST) = 0; - // Return a new SMTExprRef from an SMTExpr + // Returns a new SMTExprRef from an SMTExpr virtual SMTExprRef newExprRef(const SMTExpr &E) const = 0; - /// Given a constraint, add it to the solver + /// Given a constraint, adds it to the solver virtual void addConstraint(const SMTExprRef &Exp) const = 0; - /// Create a bitvector addition operation + /// Creates a bitvector addition operation virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector subtraction operation + /// Creates a bitvector subtraction operation virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector multiplication operation + /// Creates a bitvector multiplication operation virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed modulus operation + /// Creates a bitvector signed modulus operation virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned modulus operation + /// Creates a bitvector unsigned modulus operation virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed division operation + /// Creates a bitvector signed division operation virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned division operation + /// Creates a bitvector unsigned division operation virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector logical shift left operation + /// Creates a bitvector logical shift left operation virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector arithmetic shift right operation + /// Creates a bitvector arithmetic shift right operation virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector logical shift right operation + /// Creates a bitvector logical shift right operation virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector negation operation + /// Creates a bitvector negation operation virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0; - /// Create a bitvector not operation + /// Creates a bitvector not operation virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0; - /// Create a bitvector xor operation + /// Creates a bitvector xor operation virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector or operation + /// Creates a bitvector or operation virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector and operation + /// Creates a bitvector and operation virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned less-than operation + /// Creates a bitvector unsigned less-than operation virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed less-than operation + /// Creates a bitvector signed less-than operation virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned greater-than operation + /// Creates a bitvector unsigned greater-than operation virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed greater-than operation + /// Creates a bitvector signed greater-than operation virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned less-equal-than operation + /// Creates a bitvector unsigned less-equal-than operation virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed less-equal-than operation + /// Creates a bitvector signed less-equal-than operation virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector unsigned greater-equal-than operation + /// Creates a bitvector unsigned greater-equal-than operation virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a bitvector signed greater-equal-than operation + /// Creates a bitvector signed greater-equal-than operation virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - /// Create a boolean not operation + /// Creates a boolean not operation virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0; - /// Create a bitvector equality operation + /// Creates a boolean equality operation virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a boolean and operation virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a boolean or operation virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a boolean ite operation virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, const SMTExprRef &F) = 0; - virtual SMTExprRef mkSignExt(unsigned i, const SMTExprRef &Exp) = 0; + /// Creates a bitvector sign extension operation + virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0; - virtual SMTExprRef mkZeroExt(unsigned i, const SMTExprRef &Exp) = 0; + /// Creates a bitvector zero extension operation + virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0; - virtual SMTExprRef mkExtract(unsigned High, unsigned Low, - const SMTExprRef &Exp) = 0; + /// Creates a bitvector extract operation + virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) = 0; - virtual SMTExprRef mkConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a bitvector concat operation + virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + /// Creates a floating-point negation operation virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0; + /// Creates a floating-point isInfinite operation virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0; + /// Creates a floating-point isNaN operation virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0; + /// Creates a floating-point isNormal operation virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0; + /// Creates a floating-point isZero operation virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0; + /// Creates a floating-point multiplication operation virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point division operation virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point remainder operation virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point addition operation virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point subtraction operation virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point less-than operation virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point greater-than operation virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point less-than-or-equal operation virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point greater-than-or-equal operation virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point equality operation virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + /// Creates a floating-point conversion from floatint-point to floating-point + /// operation virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0; + /// Creates a floating-point conversion from floatint-point to signed + /// bitvector operation virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, const SMTSortRef &To) = 0; + /// Creates a floating-point conversion from floatint-point to unsigned + /// bitvector operation virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, const SMTSortRef &To) = 0; + /// Creates a floating-point conversion from signed bitvector to + /// floatint-point operation virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + /// Creates a floating-point conversion from unsigned bitvector to + /// floatint-point operation virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + /// Creates a new symbol, given a name and a sort virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0; - // Return an appropriate floating-point rounding mode. + // Returns an appropriate floating-point rounding mode. virtual SMTExprRef getFloatRoundingMode() = 0; + // If the a model is available, returns the value of a given bitvector symbol virtual const llvm::APSInt getBitvector(const SMTExprRef &Exp) = 0; + // If the a model is available, returns the value of a given boolean symbol virtual bool getBoolean(const SMTExprRef &Exp) = 0; - /// Construct a const SMTExprRef &From a boolean. + /// Constructs an SMTExprRef from a boolean. virtual SMTExprRef mkBoolean(const bool b) = 0; - /// Construct a const SMTExprRef &From a finite APFloat. + /// Constructs an SMTExprRef from a finite APFloat. virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0; - /// Construct a const SMTExprRef &From an APSInt. + /// Constructs an SMTExprRef from an APSInt and its bit width virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0; - SMTExprRef mkBitvector(const llvm::APSInt Int) { - return mkBitvector(Int, Int.getBitWidth()); - } - /// Given an expression, extract the value of this operand in the model. virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0; @@ -926,18 +952,19 @@ public: virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) = 0; - /// Construct a Z3Expr from a boolean, given a Z3_context. + /// Construct an SMTExprRef value from a boolean. virtual SMTExprRef fromBoolean(const bool Bool) = 0; - /// Construct a Z3Expr from a finite APFloat, given a Z3_context. + + /// Construct an SMTExprRef value from a finite APFloat. virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0; - /// Construct a Z3Expr from an APSInt, given a Z3_context. + /// Construct an SMTExprRef value from an APSInt. virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0; - /// Construct a Z3Expr from an integer, given a Z3_context. + /// Construct an SMTExprRef value from an integer. virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0; - /// Construct a const SMTExprRef &From a SymbolData, given a SMT_context. + /// Construct an SMTExprRef from a SymbolData. virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty, uint64_t BitWidth) = 0; @@ -956,8 +983,10 @@ public: virtual void print(raw_ostream &OS) const = 0; }; +/// Shared pointer for SMTSolvers. using SMTSolverRef = std::shared_ptr; +/// Convenience method to create and Z3Solver object std::unique_ptr CreateZ3Solver(); } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h index e5e3844e88..41ef573f0c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h @@ -20,15 +20,23 @@ namespace clang { namespace ento { +/// Generic base class for SMT sorts class SMTSort { public: SMTSort() = default; virtual ~SMTSort() = default; + /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl(). virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); } + + /// Returns true if the sort is a floating-point, calls isFloatSortImpl(). virtual bool isFloatSort() const { return isFloatSortImpl(); } + + /// Returns true if the sort is a boolean, calls isBooleanSortImpl(). virtual bool isBooleanSort() const { return isBooleanSortImpl(); } + /// Returns the bitvector size, fails if the sort is not a bitvector + /// Calls getBitvectorSortSizeImpl(). virtual unsigned getBitvectorSortSize() const { assert(isBitvectorSort() && "Not a bitvector sort!"); unsigned Size = getBitvectorSortSizeImpl(); @@ -36,6 +44,8 @@ public: return Size; }; + /// Returns the floating-point size, fails if the sort is not a floating-point + /// Calls getFloatSortSizeImpl(). virtual unsigned getFloatSortSize() const { assert(isFloatSort() && "Not a floating-point sort!"); unsigned Size = getFloatSortSizeImpl(); @@ -52,19 +62,27 @@ public: LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. virtual bool equal_to(SMTSort const &other) const = 0; + /// Query the SMT solver and checks if a sort is bitvector. virtual bool isBitvectorSortImpl() const = 0; + /// Query the SMT solver and checks if a sort is floating-point. virtual bool isFloatSortImpl() const = 0; + /// Query the SMT solver and checks if a sort is boolean. virtual bool isBooleanSortImpl() const = 0; + /// Query the SMT solver and returns the sort bit width. virtual unsigned getBitvectorSortSizeImpl() const = 0; + /// Query the SMT solver and returns the sort bit width. virtual unsigned getFloatSortSizeImpl() const = 0; }; +/// Shared pointer for SMTSorts, used by SMTSolver API. using SMTSortRef = std::shared_ptr; } // namespace ento diff --git a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp index 8e31635dc9..d379562bf3 100644 --- a/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/SMTConstraintManager.cpp @@ -30,8 +30,7 @@ ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State, return assumeExpr(State, Sym, Solver->getZeroExpr(Ctx, Exp, RetTy, !Assumption)); - return assumeExpr(State, Sym, - Assumption ? Exp : Solver->fromUnOp(UO_LNot, Exp)); + return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp)); } ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange( @@ -56,10 +55,11 @@ ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State, QualType RetTy; // The expression may be casted, so we cannot call getZ3DataExpr() directly SMTExprRef VarExp = Solver->getExpr(Ctx, Sym, &RetTy); - SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, true); + SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/true); // Negate the constraint - SMTExprRef NotExp = Solver->getZeroExpr(Ctx, VarExp, RetTy, false); + SMTExprRef NotExp = + Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/false); Solver->reset(); addStateConstraints(State); @@ -95,7 +95,8 @@ const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State, llvm::APSInt Value(Ctx.getTypeSize(Ty), !Ty->isSignedIntegerOrEnumerationType()); - SMTExprRef Exp = Solver->getDataExpr(Ctx, SD->getSymbolID(), Ty); + SMTExprRef Exp = + Solver->fromData(SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty)); Solver->reset(); addStateConstraints(State); diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 536de5d037..4613ae7614 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -27,6 +27,7 @@ using namespace ento; namespace { +/// Configuration class for Z3 class Z3Config { friend class Z3Context; @@ -45,17 +46,21 @@ public: ~Z3Config() { Z3_del_config(Config); } }; // end class Z3Config +// Function used to report errors void Z3ErrorHandler(Z3_context Context, Z3_error_code Error) { llvm::report_fatal_error("Z3 error: " + llvm::Twine(Z3_get_error_msg_ex(Context, Error))); } +/// Wrapper for Z3 context class Z3Context : public SMTContext { public: Z3_context Context; Z3Context() : SMTContext() { Context = Z3_mk_context_rc(Z3Config().Config); + // The error function is set here because the context is the first object + // created by the backend Z3_set_error_handler(Context, Z3ErrorHandler); } @@ -65,6 +70,7 @@ public: } }; // end class Z3Context +/// Wrapper for Z3 Sort class Z3Sort : public SMTSort { friend class Z3Solver; @@ -73,6 +79,7 @@ class Z3Sort : public SMTSort { Z3_sort Sort; public: + /// Default constructor, mainly used by make_shared Z3Sort(Z3Context &C, Z3_sort ZS) : SMTSort(), Context(C), Sort(ZS) { Z3_inc_ref(Context.Context, reinterpret_cast(Sort)); } @@ -637,23 +644,23 @@ public: toZ3Expr(*T).AST, toZ3Expr(*F).AST))); } - SMTExprRef mkSignExt(unsigned i, const SMTExprRef &Exp) override { + SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) override { return newExprRef(Z3Expr( Context, Z3_mk_sign_ext(Context.Context, i, toZ3Expr(*Exp).AST))); } - SMTExprRef mkZeroExt(unsigned i, const SMTExprRef &Exp) override { + SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) override { return newExprRef(Z3Expr( Context, Z3_mk_zero_ext(Context.Context, i, toZ3Expr(*Exp).AST))); } - SMTExprRef mkExtract(unsigned High, unsigned Low, - const SMTExprRef &Exp) override { + SMTExprRef mkBVExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) override { return newExprRef(Z3Expr(Context, Z3_mk_extract(Context.Context, High, Low, toZ3Expr(*Exp).AST))); } - SMTExprRef mkConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override { + SMTExprRef mkBVConcat(const SMTExprRef &LHS, const SMTExprRef &RHS) override { return newExprRef( Z3Expr(Context, Z3_mk_concat(Context.Context, toZ3Expr(*LHS).AST, toZ3Expr(*RHS).AST))); @@ -737,27 +744,23 @@ public: return Z3_get_bool_value(Context.Context, toZ3Expr(*Exp).AST) == Z3_L_TRUE; } - // Return an appropriate floating-point rounding mode. SMTExprRef getFloatRoundingMode() override { // TODO: Don't assume nearest ties to even rounding mode return newExprRef(Z3Expr(Context, Z3_mk_fpa_rne(Context.Context))); } - /// Construct a Z3Expr from a SymbolData, given a Z3_context. SMTExprRef fromData(const SymbolID ID, const QualType &Ty, uint64_t BitWidth) override { llvm::Twine Name = "$" + llvm::Twine(ID); return mkSymbol(Name.str().c_str(), mkSort(Ty, BitWidth)); } - /// Construct a Z3Expr from a boolean, given a Z3_context. SMTExprRef fromBoolean(const bool Bool) override { Z3_ast AST = Bool ? Z3_mk_true(Context.Context) : Z3_mk_false(Context.Context); return newExprRef(Z3Expr(Context, AST)); } - /// Construct a Z3Expr from a finite APFloat, given a Z3_context. SMTExprRef fromAPFloat(const llvm::APFloat &Float) override { SMTSortRef Sort = getFloatSort(llvm::APFloat::semanticsSizeInBits(Float.getSemantics())); @@ -769,7 +772,6 @@ public: toZ3Sort(*Sort).Sort))); } - /// Construct a Z3Expr from an APSInt, given a Z3_context. SMTExprRef fromAPSInt(const llvm::APSInt &Int) override { SMTSortRef Sort = getBitvectorSort(Int.getBitWidth()); Z3_ast AST = Z3_mk_numeral(Context.Context, Int.toString(10).c_str(), @@ -777,7 +779,6 @@ public: return newExprRef(Z3Expr(Context, AST)); } - /// Construct a Z3Expr from an integer, given a Z3_context. SMTExprRef fromInt(const char *Int, uint64_t BitWidth) override { SMTSortRef Sort = getBitvectorSort(BitWidth); Z3_ast AST = Z3_mk_numeral(Context.Context, Int, toZ3Sort(*Sort).Sort); @@ -823,7 +824,7 @@ public: Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), Int.isUnsigned()); } else if (Sort->getBitvectorSortSize() == 128) { - SMTExprRef ASTHigh = mkExtract(127, 64, AST); + SMTExprRef ASTHigh = mkBVExtract(127, 64, AST); Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, reinterpret_cast<__uint64 *>(&Value[1])); Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), @@ -849,8 +850,6 @@ public: llvm_unreachable("Unsupported sort to integer!"); } - /// Given an expression and a model, extract the value of this operand in - /// the model. bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) override { Z3Model Model = getModel(); Z3_func_decl Func = Z3_get_app_decl( @@ -865,8 +864,6 @@ public: return toAPSInt(Sort, Assign, Int, true); } - /// Given an expression and a model, extract the value of this operand in - /// the model. bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) override { Z3Model Model = getModel(); Z3_func_decl Func = Z3_get_app_decl( @@ -881,7 +878,6 @@ public: return toAPFloat(Sort, Assign, Float, true); } - /// Check if the constraints are satisfiable ConditionTruthVal check() const override { Z3_lbool res = Z3_solver_check(Context.Context, Solver); if (res == Z3_L_TRUE) @@ -893,10 +889,8 @@ public: return ConditionTruthVal(); } - /// Push the current solver state void push() override { return Z3_solver_push(Context.Context, Solver); } - /// Pop the previous solver state void pop(unsigned NumStates = 1) override { assert(Z3_solver_get_num_scopes(Context.Context, Solver) >= NumStates); return Z3_solver_pop(Context.Context, Solver, NumStates); -- GitLab From a465f7c8c4f2c7c23099ea45caba0744a4be7c8a Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 25 Jul 2018 20:03:01 +0000 Subject: [PATCH 0728/1023] [OPENMP] ThreadId in serialized parallel regions is 0. The first argument for the parallel outlined functions, called as serialized parallel regions, should be a pointer to the global thread id that always is 0. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337957 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 4 ++-- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 21 ++++++++++++++------- test/OpenMP/nvptx_target_codegen.cpp | 4 ++-- test/OpenMP/parallel_if_codegen.cpp | 20 ++++++++++---------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 478fda7d91..3730b9af12 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2839,12 +2839,12 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); // OutlinedFn(>id, &zero, CapturedStruct); - Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name*/ ".zero.addr"); CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); llvm::SmallVector OutlinedFnArgs; - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); + // ThreadId for serialized parallels is 0. + OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 5aaebff8f7..036b5371fe 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -1784,8 +1784,9 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( /*DestWidth=*/32, /*Signed=*/1), ".zero.addr"); CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - Address ThreadIDAddr = emitThreadIDAddress(CGF, Loc); - auto &&CodeGen = [this, Fn, CapturedVars, Loc, ZeroAddr, ThreadIDAddr]( + // ThreadId for serialized parallels is 0. + Address ThreadIDAddr = ZeroAddr; + auto &&CodeGen = [this, Fn, CapturedVars, Loc, ZeroAddr, &ThreadIDAddr]( CodeGenFunction &CGF, PrePostActionTy &Action) { Action.Enter(CGF); @@ -1883,8 +1884,9 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( Work.emplace_back(WFn); }; - auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen, &CodeGen]( - CodeGenFunction &CGF, PrePostActionTy &Action) { + auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen, &CodeGen, + &ThreadIDAddr](CodeGenFunction &CGF, + PrePostActionTy &Action) { RegionCodeGenTy RCG(CodeGen); if (IsInParallelRegion) { SeqGen(CGF, Action); @@ -1936,6 +1938,8 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( // There is no need to emit line number for unconditional branch. (void)ApplyDebugLocation::CreateEmpty(CGF); CGF.EmitBlock(ElseBlock); + // In the worker need to use the real thread id. + ThreadIDAddr = emitThreadIDAddress(CGF, Loc); RCG(CGF); // There is no need to emit line number for unconditional branch. (void)ApplyDebugLocation::CreateEmpty(CGF); @@ -1965,10 +1969,11 @@ void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall( /*DestWidth=*/32, /*Signed=*/1), ".zero.addr"); CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); - Address ThreadIDAddr = emitThreadIDAddress(CGF, Loc); + // ThreadId for serialized parallels is 0. + Address ThreadIDAddr = ZeroAddr; auto &&CodeGen = [this, OutlinedFn, CapturedVars, Loc, ZeroAddr, - ThreadIDAddr](CodeGenFunction &CGF, - PrePostActionTy &Action) { + &ThreadIDAddr](CodeGenFunction &CGF, + PrePostActionTy &Action) { Action.Enter(CGF); llvm::SmallVector OutlinedFnArgs; @@ -1995,6 +2000,8 @@ void CGOpenMPRuntimeNVPTX::emitSPMDParallelCall( }; if (IsInTargetMasterThreadRegion) { + // In the worker need to use the real thread id. + ThreadIDAddr = emitThreadIDAddress(CGF, Loc); RegionCodeGenTy RCG(CodeGen); RCG(CGF); } else { diff --git a/test/OpenMP/nvptx_target_codegen.cpp b/test/OpenMP/nvptx_target_codegen.cpp index d4d9941bc4..5f9b3bd328 100644 --- a/test/OpenMP/nvptx_target_codegen.cpp +++ b/test/OpenMP/nvptx_target_codegen.cpp @@ -562,7 +562,6 @@ int baz(int f, double &a) { // CHECK: [[REC_ADDR:%.+]] = bitcast i8* [[PTR]] to %struct._globalized_locals_ty* // CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0 // CHECK: store i32 %{{.+}}, i32* [[F_PTR]], - // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]], // CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode() // CHECK: icmp ne i8 [[RES]], 0 @@ -573,7 +572,7 @@ int baz(int f, double &a) { // CHECK: br i1 // CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]]) - // CHECK: call void [[OUTLINED:@.+]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}}) + // CHECK: call void [[OUTLINED:@.+]](i32* [[ZERO_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}}) // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]]) // CHECK: br label @@ -591,6 +590,7 @@ int baz(int f, double &a) { // CHECK: call void @__kmpc_end_sharing_variables() // CHECK: br label + // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]], // CHECK: call void [[OUTLINED]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}}) // CHECK: br label diff --git a/test/OpenMP/parallel_if_codegen.cpp b/test/OpenMP/parallel_if_codegen.cpp index e59415a9d2..49e4bd402c 100644 --- a/test/OpenMP/parallel_if_codegen.cpp +++ b/test/OpenMP/parallel_if_codegen.cpp @@ -29,12 +29,12 @@ void gtid_test() { } // CHECK: define internal {{.*}}void [[GTID_TEST_REGION1]](i{{.+}}* noalias [[GTID_PARAM:%.+]], i32* noalias +// CHECK: store i32 0, i32* [[ZERO_ADDR:%.+]], // CHECK: store i{{[0-9]+}}* [[GTID_PARAM]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]], // CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]] // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_ADDR]] // CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]]) -// CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]] -// CHECK: call void [[GTID_TEST_REGION2:@.+]](i{{[0-9]+}}* [[GTID_ADDR]] +// CHECK: call void [[GTID_TEST_REGION2:@.+]](i{{[0-9]+}}* [[ZERO_ADDR]] // CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]]) // CHECK: ret void @@ -56,12 +56,13 @@ int tmain(T Arg) { // CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main() int main() { // CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num( +// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]], +// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]], // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN4:@.+]] to void #pragma omp parallel if (true) fn4(); // CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) -// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]], -// CHECK: call void [[CAP_FN5:@.+]](i32* [[GTID_ADDR]], +// CHECK: call void [[CAP_FN5:@.+]](i32* [[ZERO_ADDR1]], i32* [[ZERO_ADDR1]]) // CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) #pragma omp parallel if (false) fn5(); @@ -72,8 +73,7 @@ int main() { // CHECK: br label %[[OMP_END:.+]] // CHECK: [[OMP_ELSE]] // CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) -// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]], -// CHECK: call void [[CAP_FN6]](i32* [[GTID_ADDR]], +// CHECK: call void [[CAP_FN6]](i32* [[ZERO_ADDR2]], i32* [[ZERO_ADDR2]]) // CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) // CHECK: br label %[[OMP_END]] // CHECK: [[OMP_END]] @@ -97,10 +97,11 @@ int main() { // CHECK-LABEL: define {{.+}} @{{.+}}tmain // CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num( +// CHECK: store i32 0, i32* [[ZERO_ADDR2:%.+]], +// CHECK: store i32 0, i32* [[ZERO_ADDR1:%.+]], // CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN1:@.+]] to void // CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) -// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]], -// CHECK: call void [[CAP_FN2:@.+]](i32* [[GTID_ADDR]], +// CHECK: call void [[CAP_FN2:@.+]](i32* [[ZERO_ADDR1]], i32* [[ZERO_ADDR1]]) // CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) // CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]] // CHECK: [[OMP_THEN]] @@ -108,8 +109,7 @@ int main() { // CHECK: br label %[[OMP_END:.+]] // CHECK: [[OMP_ELSE]] // CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) -// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]], -// CHECK: call void [[CAP_FN3]](i32* [[GTID_ADDR]], +// CHECK: call void [[CAP_FN3]](i32* [[ZERO_ADDR2]], i32* [[ZERO_ADDR2]]) // CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]]) // CHECK: br label %[[OMP_END]] // CHECK: [[OMP_END]] -- GitLab From c78e9948f0c4544e0f6d28180d8c37f09d55d013 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 25 Jul 2018 22:52:05 +0000 Subject: [PATCH 0729/1023] [ODRHash] Support hashing enums. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337978 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 8 + include/clang/AST/ODRHash.h | 6 +- .../Basic/DiagnosticSerializationKinds.td | 27 +++ include/clang/Serialization/ASTReader.h | 4 + lib/AST/Decl.cpp | 11 + lib/AST/ODRHash.cpp | 36 +++- lib/Serialization/ASTReader.cpp | 204 +++++++++++++++++- lib/Serialization/ASTReaderDecl.cpp | 5 + lib/Serialization/ASTWriterDecl.cpp | 3 + test/Modules/odr_hash.cpp | 171 +++++++++++++++ 10 files changed, 471 insertions(+), 4 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 4e19434b16..dde9459963 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -3335,6 +3335,10 @@ class EnumDecl : public TagDecl { /// information. MemberSpecializationInfo *SpecializationInfo = nullptr; + /// Store the ODRHash after first calculation. + unsigned HasODRHash : 1; + unsigned ODRHash; + EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) @@ -3346,6 +3350,8 @@ class EnumDecl : public TagDecl { IsScoped = Scoped; IsScopedUsingClassTag = ScopedUsingClassTag; IsFixed = Fixed; + HasODRHash = false; + ODRHash = 0; } void anchor() override; @@ -3496,6 +3502,8 @@ public: return IsFixed; } + unsigned getODRHash(); + /// Returns true if this can be considered a complete type. bool isComplete() const { // IntegerType is set for fixed type enums and non-fixed but implicitly diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h index 6a66ba1dad..75b3617892 100644 --- a/include/clang/AST/ODRHash.h +++ b/include/clang/AST/ODRHash.h @@ -58,6 +58,10 @@ public: // hash as if the function has no body. void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody = false); + // Use this for ODR checking enums between modules. This method compares + // more information than the AddDecl class. + void AddEnumDecl(const EnumDecl *Enum); + // Process SubDecls of the main Decl. This method calls the DeclVisitor // while AddDecl does not. void AddSubDecl(const Decl *D); @@ -83,7 +87,7 @@ public: // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - static bool isWhitelistedDecl(const Decl* D, const CXXRecordDecl *Record); + static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent); }; } // end namespace clang diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index a70e48a788..3a552e2f3d 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -341,6 +341,33 @@ def note_module_odr_violation_function : Note<"but in '%0' found " "a different body" "}1">; +def err_module_odr_violation_enum : Error< + "%q0 has different definitions in different modules; " + "%select{definition in module '%2'|defined here}1 " + "first difference is " + "%select{" + "enum that is %select{not scoped|scoped}4|" + "enum scoped with keyword %select{struct|class}4|" + "enum %select{without|with}4 specified type|" + "enum with specified type %4|" + "enum with %4 element%s4|" + "%ordinal4 element has name %5|" + "%ordinal4 element %5 %select{has|does not have}6 an initilizer|" + "%ordinal4 element %5 has an initializer|" + "}3">; + +def note_module_odr_violation_enum : Note<"but in '%0' found " + "%select{" + "enum that is %select{not scoped|scoped}2|" + "enum scoped with keyword %select{struct|class}2|" + "enum %select{without|with}2 specified type|" + "enum with specified type %2|" + "enum with %2 element%s2|" + "%ordinal2 element has name %3|" + "%ordinal2 element %3 %select{has|does not have}4 an initializer|" + "%ordinal2 element %3 has different initializer|" + "}1">; + def err_module_odr_violation_mismatch_decl_unknown : Error< "%q0 %select{with definition in module '%2'|defined here}1 has different " "definitions in different modules; first difference is this " diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index b33f317765..82a74a6444 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1099,6 +1099,10 @@ private: llvm::SmallDenseMap, 2> PendingFunctionOdrMergeFailures; + /// Enum definitions in which we found an ODR violation. + llvm::SmallDenseMap, 2> + PendingEnumOdrMergeFailures; + /// DeclContexts in which we have diagnosed an ODR violation. llvm::SmallPtrSet DiagnosedOdrMergeFailures; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a23499f3fe..3b9b85a20a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3973,6 +3973,17 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK); } +unsigned EnumDecl::getODRHash() { + if (HasODRHash) + return ODRHash; + + class ODRHash Hash; + Hash.AddEnumDecl(this); + HasODRHash = true; + ODRHash = Hash.CalculateHash(); + return ODRHash; +} + //===----------------------------------------------------------------------===// // RecordDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 45b8ee61ad..e710d37803 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -407,12 +407,17 @@ public: AddDecl(D->getTemplatedDecl()); Inherited::VisitFunctionTemplateDecl(D); } + + void VisitEnumConstantDecl(const EnumConstantDecl *D) { + AddStmt(D->getInitExpr()); + Inherited::VisitEnumConstantDecl(D); + } }; } // namespace // Only allow a small portion of Decl's to be processed. Remove this once // all Decl's can be handled. -bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { +bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) { if (D->isImplicit()) return false; if (D->getDeclContext() != Parent) return false; @@ -423,6 +428,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXMethod: + case Decl::EnumConstant: // Only found in EnumDecl's. case Decl::Field: case Decl::Friend: case Decl::FunctionTemplate: @@ -554,6 +560,34 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function, } } +void ODRHash::AddEnumDecl(const EnumDecl *Enum) { + assert(Enum); + AddDeclarationName(Enum->getDeclName()); + + AddBoolean(Enum->isScoped()); + if (Enum->isScoped()) + AddBoolean(Enum->isScopedUsingClassTag()); + + if (Enum->getIntegerTypeSourceInfo()) + AddQualType(Enum->getIntegerType()); + + // Filter out sub-Decls which will not be processed in order to get an + // accurate count of Decl's. + llvm::SmallVector Decls; + for (Decl *SubDecl : Enum->decls()) { + if (isWhitelistedDecl(SubDecl, Enum)) { + assert(isa(SubDecl) && "Unexpected Decl"); + Decls.push_back(SubDecl); + } + } + + ID.AddInteger(Decls.size()); + for (auto SubDecl : Decls) { + AddSubDecl(SubDecl); + } + +} + void ODRHash::AddDecl(const Decl *D) { assert(D && "Expecting non-null pointer."); D = D->getCanonicalDecl(); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4167e86880..9a3b9e1da3 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9443,7 +9443,8 @@ void ASTReader::finishPendingActions() { void ASTReader::diagnoseOdrViolations() { if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && - PendingFunctionOdrMergeFailures.empty()) + PendingFunctionOdrMergeFailures.empty() && + PendingEnumOdrMergeFailures.empty()) return; // Trigger the import of the full definition of each class that had any @@ -9479,6 +9480,16 @@ void ASTReader::diagnoseOdrViolations() { } } + // Trigger the import of enums. + auto EnumOdrMergeFailures = std::move(PendingEnumOdrMergeFailures); + PendingEnumOdrMergeFailures.clear(); + for (auto &Merge : EnumOdrMergeFailures) { + Merge.first->decls_begin(); + for (auto &Enum : Merge.second) { + Enum->decls_begin(); + } + } + // For each declaration from a merged context, check that the canonical // definition of that context also contains a declaration of the same // entity. @@ -9561,7 +9572,8 @@ void ASTReader::diagnoseOdrViolations() { } } - if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty()) + if (OdrMergeFailures.empty() && FunctionOdrMergeFailures.empty() && + EnumOdrMergeFailures.empty()) return; // Ensure we don't accidentally recursively enter deserialization while @@ -11308,6 +11320,194 @@ void ASTReader::diagnoseOdrViolations() { (void)Diagnosed; assert(Diagnosed && "Unable to emit ODR diagnostic."); } + + // Issue ODR failures diagnostics for enums. + for (auto &Merge : EnumOdrMergeFailures) { + enum ODREnumDifference { + SingleScopedEnum, + EnumTagKeywordMismatch, + SingleSpecifiedType, + DifferentSpecifiedTypes, + DifferentNumberEnumConstants, + EnumConstantName, + EnumConstantSingleInitilizer, + EnumConstantDifferentInitilizer, + }; + + // If we've already pointed out a specific problem with this enum, don't + // bother issuing a general "something's different" diagnostic. + if (!DiagnosedOdrMergeFailures.insert(Merge.first).second) + continue; + + EnumDecl *FirstEnum = Merge.first; + std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum); + + using DeclHashes = + llvm::SmallVector, 4>; + auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum]( + DeclHashes &Hashes, EnumDecl *Enum) { + for (auto *D : Enum->decls()) { + // Due to decl merging, the first EnumDecl is the parent of + // Decls in both records. + if (!ODRHash::isWhitelistedDecl(D, FirstEnum)) + continue; + assert(isa(D) && "Unexpected Decl kind"); + Hashes.emplace_back(cast(D), + ComputeSubDeclODRHash(D)); + } + }; + DeclHashes FirstHashes; + PopulateHashes(FirstHashes, FirstEnum); + bool Diagnosed = false; + for (auto &SecondEnum : Merge.second) { + + if (FirstEnum == SecondEnum) + continue; + + std::string SecondModule = + getOwningModuleNameForDiagnostic(SecondEnum); + + auto ODRDiagError = [FirstEnum, &FirstModule, + this](SourceLocation Loc, SourceRange Range, + ODREnumDifference DiffType) { + return Diag(Loc, diag::err_module_odr_violation_enum) + << FirstEnum << FirstModule.empty() << FirstModule << Range + << DiffType; + }; + auto ODRDiagNote = [&SecondModule, this](SourceLocation Loc, + SourceRange Range, + ODREnumDifference DiffType) { + return Diag(Loc, diag::note_module_odr_violation_enum) + << SecondModule << Range << DiffType; + }; + + if (FirstEnum->isScoped() != SecondEnum->isScoped()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + SingleScopedEnum) + << FirstEnum->isScoped(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + SingleScopedEnum) + << SecondEnum->isScoped(); + Diagnosed = true; + continue; + } + + if (FirstEnum->isScoped() && SecondEnum->isScoped()) { + if (FirstEnum->isScopedUsingClassTag() != + SecondEnum->isScopedUsingClassTag()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + EnumTagKeywordMismatch) + << FirstEnum->isScopedUsingClassTag(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + EnumTagKeywordMismatch) + << SecondEnum->isScopedUsingClassTag(); + Diagnosed = true; + continue; + } + } + + QualType FirstUnderlyingType = + FirstEnum->getIntegerTypeSourceInfo() + ? FirstEnum->getIntegerTypeSourceInfo()->getType() + : QualType(); + QualType SecondUnderlyingType = + SecondEnum->getIntegerTypeSourceInfo() + ? SecondEnum->getIntegerTypeSourceInfo()->getType() + : QualType(); + if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + SingleSpecifiedType) + << !FirstUnderlyingType.isNull(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + SingleSpecifiedType) + << !SecondUnderlyingType.isNull(); + Diagnosed = true; + continue; + } + + if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) { + if (ComputeQualTypeODRHash(FirstUnderlyingType) != + ComputeQualTypeODRHash(SecondUnderlyingType)) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + DifferentSpecifiedTypes) + << FirstUnderlyingType; + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + DifferentSpecifiedTypes) + << SecondUnderlyingType; + Diagnosed = true; + continue; + } + } + + DeclHashes SecondHashes; + PopulateHashes(SecondHashes, SecondEnum); + + if (FirstHashes.size() != SecondHashes.size()) { + ODRDiagError(FirstEnum->getLocation(), FirstEnum->getSourceRange(), + DifferentNumberEnumConstants) + << (int)FirstHashes.size(); + ODRDiagNote(SecondEnum->getLocation(), SecondEnum->getSourceRange(), + DifferentNumberEnumConstants) + << (int)SecondHashes.size(); + Diagnosed = true; + continue; + } + + for (unsigned I = 0; I < FirstHashes.size(); ++I) { + if (FirstHashes[I].second == SecondHashes[I].second) + continue; + const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first; + const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first; + + if (FirstEnumConstant->getDeclName() != + SecondEnumConstant->getDeclName()) { + + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), EnumConstantName) + << I + 1 << FirstEnumConstant; + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), EnumConstantName) + << I + 1 << SecondEnumConstant; + Diagnosed = true; + break; + } + + const Expr *FirstInit = FirstEnumConstant->getInitExpr(); + const Expr *SecondInit = SecondEnumConstant->getInitExpr(); + if (!FirstInit && !SecondInit) + continue; + + if (!FirstInit || !SecondInit) { + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), + EnumConstantSingleInitilizer) + << I + 1 << FirstEnumConstant << (FirstInit != nullptr); + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), + EnumConstantSingleInitilizer) + << I + 1 << SecondEnumConstant << (SecondInit != nullptr); + Diagnosed = true; + break; + } + + if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { + ODRDiagError(FirstEnumConstant->getLocation(), + FirstEnumConstant->getSourceRange(), + EnumConstantDifferentInitilizer) + << I + 1 << FirstEnumConstant; + ODRDiagNote(SecondEnumConstant->getLocation(), + SecondEnumConstant->getSourceRange(), + EnumConstantDifferentInitilizer) + << I + 1 << SecondEnumConstant; + Diagnosed = true; + break; + } + } + } + + (void)Diagnosed; + assert(Diagnosed && "Unable to emit ODR diagnostic."); + } } void ASTReader::StartedDeserializing() { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index b33b88c271..7e2c4829b1 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -746,6 +746,9 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->IsScopedUsingClassTag = Record.readInt(); ED->IsFixed = Record.readInt(); + ED->HasODRHash = true; + ED->ODRHash = Record.readInt(); + // If this is a definition subject to the ODR, and we already have a // definition, merge this one into it. if (ED->IsCompleteDefinition && @@ -766,6 +769,8 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); ED->IsCompleteDefinition = false; Reader.mergeDefinitionVisibility(OldDef, ED); + if (OldDef->getODRHash() != ED->getODRHash()) + Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); } else { OldDef = ED; } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 61d9fed480..77e578f6bc 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -431,6 +431,8 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { Record.push_back(D->isScoped()); Record.push_back(D->isScopedUsingClassTag()); Record.push_back(D->isFixed()); + Record.push_back(D->getODRHash()); + if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); Record.push_back(MemberInfo->getTemplateSpecializationKind()); @@ -1865,6 +1867,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedMembEnum // DC Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 28ee423c74..16ddfefa53 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -3146,6 +3146,177 @@ Invalid1 i1; #undef DECLS } +namespace Enums { +#if defined(FIRST) +enum E1 { x11 }; +#elif defined(SECOND) +enum E1 {}; +#else +E1 e1; +// expected-error@first.h:* {{'Enums::x11' from module 'FirstModule' is not present in definition of 'Enums::E1' in module 'SecondModule'}} +// expected-note@second.h:* {{definition has no member 'x11'}} +#endif + +#if defined(FIRST) +enum E2 {}; +#elif defined(SECOND) +enum E2 { x21 }; +#else +E2 e2; +// expected-error@second.h:* {{'Enums::E2' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 1 element}} +// expected-note@first.h:* {{but in 'FirstModule' found enum with 0 elements}} +#endif + +#if defined(FIRST) +enum E3 { x31 }; +#elif defined(SECOND) +enum E3 { x32 }; +#else +E3 e3; +// expected-error@first.h:* {{'Enums::x31' from module 'FirstModule' is not present in definition of 'Enums::E3' in module 'SecondModule'}} +// expected-note@second.h:* {{definition has no member 'x31'}} +#endif + +#if defined(FIRST) +enum E4 { x41 }; +#elif defined(SECOND) +enum E4 { x41, x42 }; +#else +E4 e4; +// expected-error@second.h:* {{'Enums::E4' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 2 elements}} +// expected-note@first.h:* {{but in 'FirstModule' found enum with 1 element}} +#endif + +#if defined(FIRST) +enum E5 { x51, x52 }; +#elif defined(SECOND) +enum E5 { x51 }; +#else +E5 e5; +// expected-error@first.h:* {{'Enums::x52' from module 'FirstModule' is not present in definition of 'Enums::E5' in module 'SecondModule'}} +// expected-note@second.h:* {{definition has no member 'x52'}} +#endif + +#if defined(FIRST) +enum E6 { x61, x62 }; +#elif defined(SECOND) +enum E6 { x62, x61 }; +#else +E6 e6; +// expected-error@second.h:* {{'Enums::E6' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element has name 'x62'}} +// expected-note@first.h:* {{but in 'FirstModule' found 1st element has name 'x61'}} +#endif + +#if defined(FIRST) +enum E7 { x71 = 0 }; +#elif defined(SECOND) +enum E7 { x71 }; +#else +E7 e7; +// expected-error@second.h:* {{'Enums::E7' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x71' has an initilizer}} +// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x71' does not have an initializer}} +#endif + +#if defined(FIRST) +enum E8 { x81 }; +#elif defined(SECOND) +enum E8 { x81 = 0 }; +#else +E8 e8; +// expected-error@second.h:* {{'Enums::E8' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x81' does not have an initilizer}} +// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x81' has an initializer}} +#endif + +#if defined(FIRST) +enum E9 { x91 = 0, x92 = 1 }; +#elif defined(SECOND) +enum E9 { x91 = 0, x92 = 2 - 1 }; +#else +E9 e9; +// expected-error@second.h:* {{'Enums::E9' has different definitions in different modules; definition in module 'SecondModule' first difference is 2nd element 'x92' has an initializer}} +// expected-note@first.h:* {{but in 'FirstModule' found 2nd element 'x92' has different initializer}} +#endif + +#if defined(FIRST) +enum class E10 : int {}; +#elif defined(SECOND) +enum class E10 {}; +#else +E10 e10; +// expected-error@second.h:* {{'Enums::E10' has different definitions in different modules; definition in module 'SecondModule' first difference is enum without specified type}} +// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type}} +#endif + +#if defined(FIRST) +enum E11 {}; +#elif defined(SECOND) +enum E11 : int {}; +#else +E11 e11; +// expected-error@second.h:* {{'Enums::E11' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type}} +// expected-note@first.h:* {{but in 'FirstModule' found enum without specified type}} +#endif + +#if defined(FIRST) +enum struct E12 : long {}; +#elif defined(SECOND) +enum struct E12 : int {}; +#else +E12 e12; +// expected-error@second.h:* {{'Enums::E12' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type 'int'}} +// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type 'long'}} +#endif + +#if defined(FIRST) +enum struct E13 {}; +#elif defined(SECOND) +enum E13 {}; +#else +E13 e13; +// expected-error@second.h:* {{'Enums::E13' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is not scoped}} +// expected-note@first.h:* {{but in 'FirstModule' found enum that is scoped}} +#endif + +#if defined(FIRST) +enum E14 {}; +#elif defined(SECOND) +enum struct E14 {}; +#else +E14 e14; +// expected-error@second.h:* {{'Enums::E14' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is scoped}} +// expected-note@first.h:* {{but in 'FirstModule' found enum that is not scoped}} +#endif + +#if defined(FIRST) +enum class E15 {}; +#elif defined(SECOND) +enum struct E15 {}; +#else +E15 e15; +// expected-error@second.h:* {{'Enums::E15' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword struct}} +// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword class}} +#endif + +#if defined(FIRST) +enum struct E16 {}; +#elif defined(SECOND) +enum class E16 {}; +#else +E16 e16; +// expected-error@second.h:* {{'Enums::E16' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword class}} +// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword struct}} +#endif + +#if defined(FIRST) +enum Valid { v1 = (struct S*)0 == (struct S*)0 }; +#elif defined(SECOND) +struct S {}; +enum Valid { v1 = (struct S*)0 == (struct S*)0 }; +#else +Valid V; +#endif +} // namespace Enums + // Collection of interesting cases below. // Naive parsing of AST can lead to cycles in processing. Ensure -- GitLab From c0a52144170c7bfb6cb0313da17bcb488ae9b6f9 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 26 Jul 2018 11:17:13 +0000 Subject: [PATCH 0730/1023] [analyzer] Fixed method to get APSInt model Summary: This patch replaces the current method of getting an `APSInt` from Z3's model by calling generic API method `getBitvector` instead of `Z3_get_numeral_uint64`. By calling `getBitvector`, there's no need to handle bitvectors with bit width == 128 separately. And, as a bonus, clang now compiles correctly with Z3 4.7.1. Reviewers: NoQ, george.karpenkov Reviewed By: george.karpenkov Subscribers: xazax.hun, szepet, a.sidorin Differential Revision: https://reviews.llvm.org/D49818 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338020 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/SMTSolver.h | 3 +- .../Core/Z3ConstraintManager.cpp | 41 ++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index d10e69788c..a43ca48690 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -931,7 +931,8 @@ public: virtual SMTExprRef getFloatRoundingMode() = 0; // If the a model is available, returns the value of a given bitvector symbol - virtual const llvm::APSInt getBitvector(const SMTExprRef &Exp) = 0; + virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, + bool isUnsigned) = 0; // If the a model is available, returns the value of a given boolean symbol virtual bool getBoolean(const SMTExprRef &Exp) = 0; diff --git a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp index 4613ae7614..7379ded49c 100644 --- a/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp @@ -734,10 +734,11 @@ public: toZ3Sort(*Sort).Sort))); } - const llvm::APSInt getBitvector(const SMTExprRef &Exp) override { - // FIXME: this returns a string and the bitWidth is overridden - return llvm::APSInt( - Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST)); + llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, + bool isUnsigned) override { + return llvm::APSInt(llvm::APInt( + BitWidth, Z3_get_numeral_string(Context.Context, toZ3Expr(*Exp).AST), + 10)); } bool getBoolean(const SMTExprRef &Exp) override { @@ -814,26 +815,20 @@ public: return false; } - uint64_t Value[2]; - // Force cast because Z3 defines __uint64 to be a unsigned long long - // type, which isn't compatible with a unsigned long type, even if they - // are the same size. - Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, - reinterpret_cast<__uint64 *>(&Value[0])); - if (Sort->getBitvectorSortSize() <= 64) { - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value[0]), - Int.isUnsigned()); - } else if (Sort->getBitvectorSortSize() == 128) { - SMTExprRef ASTHigh = mkBVExtract(127, 64, AST); - Z3_get_numeral_uint64(Context.Context, toZ3Expr(*AST).AST, - reinterpret_cast<__uint64 *>(&Value[1])); - Int = llvm::APSInt(llvm::APInt(Int.getBitWidth(), Value), - Int.isUnsigned()); - } else { - assert(false && "Bitwidth not supported!"); - return false; + // FIXME: This function is also used to retrieve floating-point values, + // which can be 16, 32, 64 or 128 bits long. Bitvectors can be anything + // between 1 and 64 bits long, which is the reason we have this weird + // guard. In the future, we need proper calls in the backend to retrieve + // floating-points and its special values (NaN, +/-infinity, +/-zero), + // then we can drop this weird condition. + if (Sort->getBitvectorSortSize() <= 64 || + Sort->getBitvectorSortSize() == 128) { + Int = getBitvector(AST, Int.getBitWidth(), Int.isUnsigned()); + return true; } - return true; + + assert(false && "Bitwidth not supported!"); + return false; } if (Sort->isBooleanSort()) { -- GitLab From 6d3287506dedaf6f013372fffa206141bed2e89a Mon Sep 17 00:00:00 2001 From: Jonas Toth Date: Thu, 26 Jul 2018 13:02:05 +0000 Subject: [PATCH 0731/1023] [ASTMatchers] fix the missing documentation for new decltypeType matcher Summary: Regenerate the Matchers documentation, forgotten in the original patch. Reviewers: alexfh, aaron.ballman Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49850 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338022 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 49899c3086..e8335d95e1 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1577,6 +1577,18 @@ Example matches i[1].
+Matcher<Type>decltypeTypeMatcher<DecltypeType>... +
Matches types nodes representing C++11 decltype(<expr>) types.
+
+Given:
+  short i = 1;
+  int j = 42;
+  decltype(i + j) result = i + j;
+decltypeType() 
+  matches "decltype(i + j)"
+
+ + Matcher<Type>dependentSizedArrayTypeMatcher<DependentSizedArrayType>...
Matches C++ arrays whose size is a value-dependent expression.
 
@@ -5156,6 +5168,19 @@ declaration of class D.
 
+Matcher<DecltypeType>hasUnderlyingTypeMatcher<Type> +
Matches DecltypeType nodes to find out the underlying type.
+
+Given
+  decltype(1) a = 1;
+  decltype(2.0) b = 2.0;
+decltypeType(hasUnderlyingType(isInteger()))
+  matches "auto a"
+
+Usable as: Matcher<DecltypeType>
+
+ + Matcher<DoStmt>hasBodyMatcher<Stmt> InnerMatcher
Matches a 'for', 'while', 'do while' statement or a function
 definition that has a given body.
-- 
GitLab


From 6e40d5198855cd06852e8f3b955a662a9cf97bb4 Mon Sep 17 00:00:00 2001
From: Aaron Ballman 
Date: Thu, 26 Jul 2018 13:03:16 +0000
Subject: [PATCH 0732/1023] Allow thread safety annotation lock upgrading and
 downgrading.

Patch thanks to Aaron Puchert!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338024 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Analysis/ThreadSafety.cpp                | 27 +++++-----
 test/SemaCXX/warn-thread-safety-analysis.cpp | 57 ++++++++++++++++++--
 2 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 8895dec02b..03cc234dce 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -109,9 +109,7 @@ class FactSet;
 /// along with additional information, such as where it was acquired, whether
 /// it is exclusive or shared, etc.
 ///
-/// FIXME: this analysis does not currently support either re-entrant
-/// locking or lock "upgrading" and "downgrading" between exclusive and
-/// shared.
+/// FIXME: this analysis does not currently support re-entrant locking.
 class FactEntry : public CapabilityExpr {
 private:
   /// Exclusive or shared.
@@ -1737,8 +1735,7 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
     }
   }
 
-  for(Attr *Atconst : D->attrs()) {
-    auto *At = const_cast(Atconst);
+  for(const Attr *At : D->attrs()) {
     switch (At->getKind()) {
       // When we encounter a lock function, we need to add the lock to our
       // lockset.
@@ -1838,6 +1835,16 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
     }
   }
 
+  // Remove locks first to allow lock upgrading/downgrading.
+  // FIXME -- should only fully remove if the attribute refers to 'this'.
+  bool Dtor = isa(D);
+  for (const auto &M : ExclusiveLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
+  for (const auto &M : SharedLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
+  for (const auto &M : GenericLocksToRemove)
+    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
+
   // Add locks.
   for (const auto &M : ExclusiveLocksToAdd)
     Analyzer->addLock(FSet, llvm::make_unique(
@@ -1864,16 +1871,6 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
                           Scp, MLoc, ExclusiveLocksToAdd, SharedLocksToAdd),
                       CapDiagKind);
   }
-
-  // Remove locks.
-  // FIXME -- should only fully remove if the attribute refers to 'this'.
-  bool Dtor = isa(D);
-  for (const auto &M : ExclusiveLocksToRemove)
-    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
-  for (const auto &M : SharedLocksToRemove)
-    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
-  for (const auto &M : GenericLocksToRemove)
-    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
 }
 
 /// For unary operations which read and write a variable, we need to
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 2c59a518c4..51535be97d 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -22,8 +22,6 @@
 #define SHARED_LOCK_FUNCTION(...)       __attribute__((acquire_shared_capability(__VA_ARGS__)))
 #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
 #define SHARED_TRYLOCK_FUNCTION(...)    __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
-#define EXCLUSIVE_UNLOCK_FUNCTION(...)  __attribute__((release_capability(__VA_ARGS__)))
-#define SHARED_UNLOCK_FUNCTION(...)     __attribute__((release_shared_capability(__VA_ARGS__)))
 #define EXCLUSIVE_LOCKS_REQUIRED(...)   __attribute__((requires_capability(__VA_ARGS__)))
 #define SHARED_LOCKS_REQUIRED(...)      __attribute__((requires_shared_capability(__VA_ARGS__)))
 #else
@@ -34,11 +32,11 @@
 #define SHARED_LOCK_FUNCTION(...)       __attribute__((shared_lock_function(__VA_ARGS__)))
 #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
 #define SHARED_TRYLOCK_FUNCTION(...)    __attribute__((shared_trylock_function(__VA_ARGS__)))
-#define EXCLUSIVE_UNLOCK_FUNCTION(...)  __attribute__((unlock_function(__VA_ARGS__)))
-#define SHARED_UNLOCK_FUNCTION(...)     __attribute__((unlock_function(__VA_ARGS__)))
 #define EXCLUSIVE_LOCKS_REQUIRED(...)   __attribute__((exclusive_locks_required(__VA_ARGS__)))
 #define SHARED_LOCKS_REQUIRED(...)      __attribute__((shared_locks_required(__VA_ARGS__)))
 #endif
+#define EXCLUSIVE_UNLOCK_FUNCTION(...)  __attribute__((release_capability(__VA_ARGS__)))
+#define SHARED_UNLOCK_FUNCTION(...)     __attribute__((release_shared_capability(__VA_ARGS__)))
 #define UNLOCK_FUNCTION(...)            __attribute__((unlock_function(__VA_ARGS__)))
 #define LOCK_RETURNED(x)                __attribute__((lock_returned(x)))
 #define LOCKS_EXCLUDED(...)             __attribute__((locks_excluded(__VA_ARGS__)))
@@ -50,10 +48,15 @@ class LOCKABLE Mutex {
   void Lock() EXCLUSIVE_LOCK_FUNCTION();
   void ReaderLock() SHARED_LOCK_FUNCTION();
   void Unlock() UNLOCK_FUNCTION();
+  void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION();
+  void ReaderUnlock() SHARED_UNLOCK_FUNCTION();
   bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
   bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
   void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION();
 
+  void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION();
+  void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION();
+
   // for negative capabilities
   const Mutex& operator!() const { return *this; }
 
@@ -704,6 +707,26 @@ void shared_fun_8() {
   sls_mu.Unlock();
 }
 
+void shared_fun_9() {
+  sls_mu.Lock();
+  sls_mu.ExclusiveUnlock();
+
+  sls_mu.ReaderLock();
+  sls_mu.ReaderUnlock();
+}
+
+void shared_fun_10() {
+  sls_mu.Lock();
+  sls_mu.DemoteExclusive();
+  sls_mu.ReaderUnlock();
+}
+
+void shared_fun_11() {
+  sls_mu.ReaderLock();
+  sls_mu.PromoteShared();
+  sls_mu.Unlock();
+}
+
 void shared_bad_0() {
   sls_mu.Lock();  // \
     // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
@@ -737,6 +760,32 @@ void shared_bad_2() {
   sls_mu.Unlock();
 }
 
+void shared_bad_3() {
+  sls_mu.Lock();
+  sls_mu.ReaderUnlock(); // \
+    // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
+}
+
+void shared_bad_4() {
+  sls_mu.ReaderLock();
+  sls_mu.ExclusiveUnlock(); // \
+    // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
+}
+
+void shared_bad_5() {
+  sls_mu.Lock();
+  sls_mu.PromoteShared(); // \
+    // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}}
+  sls_mu.ExclusiveUnlock();
+}
+
+void shared_bad_6() {
+  sls_mu.ReaderLock();
+  sls_mu.DemoteExclusive(); // \
+    // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}}
+  sls_mu.ReaderUnlock();
+}
+
 // FIXME: Add support for functions (not only methods)
 class LRBar {
  public:
-- 
GitLab


From 8441afe6e6e4748a86a7ed717942e9556eb5cc4b Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Thu, 26 Jul 2018 15:17:38 +0000
Subject: [PATCH 0733/1023] [OPENMP] Force OpenMP 4.5 when compiling for
 offloading.

If the user requested compilation for OpenMP with the offloading
support, force the version of the OpenMP standard to 4.5 by default.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338032 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Driver/ToolChains/Clang.cpp     |  2 +-
 lib/Frontend/CompilerInvocation.cpp | 10 ++++++----
 test/OpenMP/driver.c                |  3 +++
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index a95080bbec..eaff940a1c 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -4698,7 +4698,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   // For all the host OpenMP offloading compile jobs we need to pass the targets
   // information using -fopenmp-targets= option.
-  if (isa(JA) && JA.isHostOffloading(Action::OFK_OpenMP)) {
+  if (JA.isHostOffloading(Action::OFK_OpenMP)) {
     SmallString<128> TargetInfo("-fopenmp-targets=");
 
     Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 5878cce772..78e6babd02 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -2594,13 +2594,15 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
       Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
   Opts.OpenMPIsDevice =
       Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
+  bool IsTargetSpecified =
+      Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);
 
   if (Opts.OpenMP || Opts.OpenMPSimd) {
-    if (int Version =
-            getLastArgIntValue(Args, OPT_fopenmp_version_EQ,
-                               IsSimdSpecified ? 45 : Opts.OpenMP, Diags))
+    if (int Version = getLastArgIntValue(
+            Args, OPT_fopenmp_version_EQ,
+            (IsSimdSpecified || IsTargetSpecified) ? 45 : Opts.OpenMP, Diags))
       Opts.OpenMP = Version;
-    else if (IsSimdSpecified)
+    else if (IsSimdSpecified || IsTargetSpecified)
       Opts.OpenMP = 45;
     // Provide diagnostic when a given target is not expected to be an OpenMP
     // device or host.
diff --git a/test/OpenMP/driver.c b/test/OpenMP/driver.c
index 9e6ecfbe27..4c8b1df538 100644
--- a/test/OpenMP/driver.c
+++ b/test/OpenMP/driver.c
@@ -1,3 +1,4 @@
+// REQUIRES: x86-registered-target
 // Test that by default -fnoopenmp-use-tls is passed to frontend.
 //
 // RUN: %clang %s -### -o %t.o 2>&1 -fopenmp=libomp | FileCheck --check-prefix=CHECK-DEFAULT %s
@@ -23,7 +24,9 @@
 
 // RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-version=45 | FileCheck --check-prefix=CHECK-45-VERSION %s
 // RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-simd | FileCheck --check-prefix=CHECK-45-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp=libomp -fopenmp-targets=x86_64-unknown-unknown -o - | FileCheck --check-prefix=CHECK-45-VERSION --check-prefix=CHECK-45-VERSION2 %s
 // CHECK-45-VERSION: #define _OPENMP 201511
+// CHECK-45-VERSION2: #define _OPENMP 201511
 
 // RUN: %clang %s -c -E -dM -fopenmp-version=1 | FileCheck --check-prefix=CHECK-VERSION %s
 // RUN: %clang %s -c -E -dM -fopenmp-version=31 | FileCheck --check-prefix=CHECK-VERSION %s
-- 
GitLab


From 95dc1a4cb76bf7a95a660382154bdaeea0b2d137 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka 
Date: Thu, 26 Jul 2018 16:51:21 +0000
Subject: [PATCH 0734/1023] [CodeGen][ObjC] Make block copy/dispose helper
 functions exception-safe.

When an exception is thrown in a block copy helper function, captured
objects that have previously been copied should be destructed or
released. Similarly, captured objects that are yet to be released should
be released when an exception is thrown in a dispose helper function.

rdar://problem/42410255

Differential Revision: https://reviews.llvm.org/D49718

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338041 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/CGBlocks.cpp         | 132 +++++++++++++++++-------------
 lib/CodeGen/CGDecl.cpp           |  12 ++-
 lib/CodeGen/CodeGenFunction.h    |  20 ++++-
 test/CodeGenObjC/blocks.m        |   5 +-
 test/CodeGenObjCXX/arc-blocks.mm | 135 ++++++++++++++++++++++++++++++-
 5 files changed, 239 insertions(+), 65 deletions(-)

diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 352a02db2b..617856a7b4 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -1585,6 +1585,64 @@ static void findBlockCapturedManagedEntities(
   }
 }
 
+namespace {
+/// Release a __block variable.
+struct CallBlockRelease final : EHScopeStack::Cleanup {
+  Address Addr;
+  BlockFieldFlags FieldFlags;
+  bool LoadBlockVarAddr;
+
+  CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue)
+      : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue) {}
+
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+    llvm::Value *BlockVarAddr;
+    if (LoadBlockVarAddr) {
+      BlockVarAddr = CGF.Builder.CreateLoad(Addr);
+      BlockVarAddr = CGF.Builder.CreateBitCast(BlockVarAddr, CGF.VoidPtrTy);
+    } else {
+      BlockVarAddr = Addr.getPointer();
+    }
+
+    CGF.BuildBlockRelease(BlockVarAddr, FieldFlags);
+  }
+};
+} // end anonymous namespace
+
+static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
+                               Address Field, QualType CaptureType,
+                               BlockFieldFlags Flags, bool EHOnly,
+                               CodeGenFunction &CGF) {
+  switch (CaptureKind) {
+  case BlockCaptureEntityKind::CXXRecord:
+  case BlockCaptureEntityKind::ARCWeak:
+  case BlockCaptureEntityKind::NonTrivialCStruct:
+  case BlockCaptureEntityKind::ARCStrong: {
+    if (CaptureType.isDestructedType() &&
+        (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) {
+      CodeGenFunction::Destroyer *Destroyer =
+          CaptureKind == BlockCaptureEntityKind::ARCStrong
+              ? CodeGenFunction::destroyARCStrongImprecise
+              : CGF.getDestroyer(CaptureType.isDestructedType());
+      CleanupKind Kind =
+          EHOnly ? EHCleanup
+                 : CGF.getCleanupKind(CaptureType.isDestructedType());
+      CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup);
+    }
+    break;
+  }
+  case BlockCaptureEntityKind::BlockObject: {
+    if (!EHOnly || CGF.getLangOpts().Exceptions) {
+      CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup;
+      CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true);
+    }
+    break;
+  }
+  case BlockCaptureEntityKind::None:
+    llvm_unreachable("unexpected BlockCaptureEntityKind");
+  }
+}
+
 /// Generate the copy-helper function for a block closure object:
 ///   static void block_copy_helper(block_t *dst, block_t *src);
 /// The runtime will have previously initialized 'dst' by doing a
@@ -1648,6 +1706,7 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
   for (const auto &CopiedCapture : CopiedCaptures) {
     const BlockDecl::Capture &CI = CopiedCapture.CI;
     const CGBlockInfo::Capture &capture = CopiedCapture.Capture;
+    QualType captureType = CI.getVariable()->getType();
     BlockFieldFlags flags = CopiedCapture.Flags;
 
     unsigned index = capture.getIndex();
@@ -1685,9 +1744,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
         } else {
           EmitARCRetainNonBlock(srcValue);
 
-          // We don't need this anymore, so kill it.  It's not quite
-          // worth the annoyance to avoid creating it in the first place.
-          cast(dstField.getPointer())->eraseFromParent();
+          // Unless EH cleanup is required, we don't need this anymore, so kill
+          // it. It's not quite worth the annoyance to avoid creating it in the
+          // first place.
+          if (!needsEHCleanup(captureType.isDestructedType()))
+            cast(dstField.getPointer())->eraseFromParent();
         }
       } else {
         assert(CopiedCapture.Kind == BlockCaptureEntityKind::BlockObject);
@@ -1715,6 +1776,11 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
         }
       }
     }
+
+    // Ensure that we destroy the copied object if an exception is thrown later
+    // in the helper function.
+    pushCaptureCleanup(CopiedCapture.Kind, dstField, captureType, flags, /*EHOnly*/ true,
+                       *this);
   }
 
   FinishFunction();
@@ -1830,36 +1896,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
     Address srcField =
       Builder.CreateStructGEP(src, capture.getIndex(), capture.getOffset());
 
-    // If the captured record has a destructor then call it.
-    if (DestroyedCapture.Kind == BlockCaptureEntityKind::CXXRecord) {
-      const auto *Dtor =
-          CI.getVariable()->getType()->getAsCXXRecordDecl()->getDestructor();
-      PushDestructorCleanup(Dtor, srcField);
-
-      // If this is a __weak capture, emit the release directly.
-    } else if (DestroyedCapture.Kind == BlockCaptureEntityKind::ARCWeak) {
-      EmitARCDestroyWeak(srcField);
-
-    // Destroy strong objects with a call if requested.
-    } else if (DestroyedCapture.Kind == BlockCaptureEntityKind::ARCStrong) {
-      EmitARCDestroyStrong(srcField, ARCImpreciseLifetime);
-
-    // If this is a C struct that requires non-trivial destruction, emit a call
-    // to its destructor.
-    } else if (DestroyedCapture.Kind ==
-               BlockCaptureEntityKind::NonTrivialCStruct) {
-      QualType varType = CI.getVariable()->getType();
-      pushDestroy(varType.isDestructedType(), srcField, varType);
-
-    // Otherwise we call _Block_object_dispose.  It wouldn't be too
-    // hard to just emit this as a cleanup if we wanted to make sure
-    // that things were done in reverse.
-    } else {
-      assert(DestroyedCapture.Kind == BlockCaptureEntityKind::BlockObject);
-      llvm::Value *value = Builder.CreateLoad(srcField);
-      value = Builder.CreateBitCast(value, VoidPtrTy);
-      BuildBlockRelease(value, flags);
-    }
+    pushCaptureCleanup(DestroyedCapture.Kind, srcField,
+                       CI.getVariable()->getType(), flags, /*EHOnly*/ false, *this);
   }
 
   cleanups.ForceCleanup();
@@ -2538,30 +2576,10 @@ void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
   EmitNounwindRuntimeCall(F, args); // FIXME: throwing destructors?
 }
 
-namespace {
-  /// Release a __block variable.
-  struct CallBlockRelease final : EHScopeStack::Cleanup {
-    llvm::Value *Addr;
-    CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
-
-    void Emit(CodeGenFunction &CGF, Flags flags) override {
-      // Should we be passing FIELD_IS_WEAK here?
-      CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
-    }
-  };
-} // end anonymous namespace
-
-/// Enter a cleanup to destroy a __block variable.  Note that this
-/// cleanup should be a no-op if the variable hasn't left the stack
-/// yet; if a cleanup is required for the variable itself, that needs
-/// to be done externally.
-void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
-  // We don't enter this cleanup if we're in pure-GC mode.
-  if (CGM.getLangOpts().getGC() == LangOptions::GCOnly)
-    return;
-
-  EHStack.pushCleanup(NormalAndEHCleanup,
-                                        emission.Addr.getPointer());
+void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
+                                        BlockFieldFlags Flags,
+                                        bool LoadBlockVarAddr) {
+  EHStack.pushCleanup(Kind, Addr, Flags, LoadBlockVarAddr);
 }
 
 /// Adjust the declaration of something from the blocks API.
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index d1df5b33b6..57b2fbadbe 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1710,9 +1710,15 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
   }
 
   // If this is a block variable, call _Block_object_destroy
-  // (on the unforwarded address).
-  if (emission.IsByRef)
-    enterByrefCleanup(emission);
+  // (on the unforwarded address). Don't enter this cleanup if we're in pure-GC
+  // mode.
+  if (emission.IsByRef && CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
+    BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
+    if (emission.Variable->getType().isObjCGCWeak())
+      Flags |= BLOCK_FIELD_IS_WEAK;
+    enterByrefCleanup(NormalAndEHCleanup, emission.Addr, Flags,
+                      /*LoadBlockVarAddr*/ false);
+  }
 }
 
 CodeGenFunction::Destroyer *
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 752d670a5f..79870ed59c 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1758,7 +1758,25 @@ public:
   class AutoVarEmission;
 
   void emitByrefStructureInit(const AutoVarEmission &emission);
-  void enterByrefCleanup(const AutoVarEmission &emission);
+
+  /// Enter a cleanup to destroy a __block variable.  Note that this
+  /// cleanup should be a no-op if the variable hasn't left the stack
+  /// yet; if a cleanup is required for the variable itself, that needs
+  /// to be done externally.
+  ///
+  /// \param Kind Cleanup kind.
+  ///
+  /// \param Addr When \p LoadBlockVarAddr is false, the address of the __block
+  /// structure that will be passed to _Block_object_dispose. When
+  /// \p LoadBlockVarAddr is true, the address of the field of the block
+  /// structure that holds the address of the __block structure.
+  ///
+  /// \param Flags The flag that will be passed to _Block_object_dispose.
+  ///
+  /// \param LoadBlockVarAddr Indicates whether we need to emit a load from
+  /// \p Addr to get the address of the __block structure.
+  void enterByrefCleanup(CleanupKind Kind, Address Addr, BlockFieldFlags Flags,
+                         bool LoadBlockVarAddr);
 
   void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum,
                                 llvm::Value *ptr);
diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m
index d485bb4053..05880dea79 100644
--- a/test/CodeGenObjC/blocks.m
+++ b/test/CodeGenObjC/blocks.m
@@ -79,10 +79,9 @@ void test2(Test2 *x) {
   // Then we initialize the block, blah blah blah.
   // CHECK:      call void @test2_helper(
 
-  // Finally, kill the variable with BLOCK_FIELD_IS_BYREF.  We're not
-  // supposed to pass BLOCK_FIELD_IS_WEAK here.
+  // Finally, kill the variable with BLOCK_FIELD_IS_BYREF.
   // CHECK:      [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8*
-  // CHECK:      call void @_Block_object_dispose(i8* [[T0]], i32 8)
+  // CHECK:      call void @_Block_object_dispose(i8* [[T0]], i32 24)
 
   __attribute__((objc_gc(weak))) __block Test2 *weakX = x;
   test2_helper(^{ [weakX destroy]; });
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm
index 1e439578e8..3a75576681 100644
--- a/test/CodeGenObjCXX/arc-blocks.mm
+++ b/test/CodeGenObjCXX/arc-blocks.mm
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -o - %s | FileCheck -check-prefix CHECK %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -fexceptions -fobjc-arc-exceptions -O1 -o - %s | FileCheck -check-prefix CHECK-O1 %s
 
 // CHECK: [[A:.*]] = type { i64, [10 x i8*] }
+// CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 }
+// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
 
 // CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00"
 
@@ -47,3 +50,133 @@ namespace test0 {
   // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T1]])
   // CHECK-NEXT: ret void
 }
+
+namespace test1 {
+
+// Check that copy/dispose helper functions are exception safe.
+
+// CHECK-LABEL: define internal void @__copy_helper_block_(
+// CHECK: %[[BLOCK_SOURCE:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+// CHECK: %[[BLOCK_DEST:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 6
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 6
+// CHECK: %[[BLOCKCOPY_SRC:.*]] = load i8*, i8** %[[V4]], align 8
+// CHECK: %[[V6:.*]] = bitcast i8** %[[V5]] to i8*
+// CHECK: call void @_Block_object_assign(i8* %[[V6]], i8* %[[BLOCKCOPY_SRC]], i32 8)
+
+// CHECK: %[[V7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 7
+// CHECK: %[[V8:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 7
+// CHECK: call void @objc_copyWeak(i8** %[[V8]], i8** %[[V7]])
+
+// CHECK: %[[V9:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 5
+// CHECK: %[[V10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 5
+// CHECK: %[[BLOCKCOPY_SRC2:.*]] = load i8*, i8** %[[V9]], align 8
+// CHECK: store i8* null, i8** %[[V10]], align 8
+// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* %[[BLOCKCOPY_SRC2]])
+
+// CHECK: %[[V11:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 8
+// CHECK: %[[V12:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 8
+// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V12]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V11]])
+// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT]]:
+// CHECK: %[[V13:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_SOURCE]], i32 0, i32 9
+// CHECK: %[[V14:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK_DEST]], i32 0, i32 9
+// CHECK: invoke void @_ZN5test12S0C1ERKS0_(%[[STRUCT_TEST1_S0]]* %[[V14]], %[[STRUCT_TEST1_S0]]* dereferenceable(4) %[[V13]])
+// CHECK: to label %[[INVOKE_CONT4:.*]] unwind label %[[LPAD3:.*]]
+
+// CHECK: [[INVOKE_CONT4]]:
+// CHECK: ret void
+
+// CHECK: [[LPAD]]:
+// CHECK: br label %[[EHCLEANUP:.*]]
+
+// CHECK: [[LPAD3]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V12]])
+// CHECK: to label %[[INVOKE_CONT5:.*]] unwind label %[[TERMINATE_LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT5]]:
+// CHECK: br label %[[EHCLEANUP]]
+
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V10]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V8]])
+// CHECK: %[[V21:.*]] = load i8*, i8** %[[V5]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V21]], i32 8)
+// CHECK: br label %[[EH_RESUME:.*]]
+
+// CHECK: [[EH_RESUME]]:
+// CHECK: resume { i8*, i32 }
+
+// CHECK: [[TERMINATE_LPAD]]:
+// CHECK: call void @__clang_call_terminate(
+
+// CHECK-O1-LABEL: define internal void @__copy_helper_block_(
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+
+// CHECK: define internal void @__destroy_helper_block_(
+// CHECK: %[[BLOCK:.*]] = bitcast i8* %{{.*}} to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>*
+// CHECK: %[[V2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 7
+// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 5
+// CHECK: %[[V5:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 8
+// CHECK: %[[V6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8*, %[[STRUCT_TEST1_S0]], %[[STRUCT_TEST1_S0]] }>* %[[BLOCK]], i32 0, i32 9
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V6]])
+// CHECK: to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+
+// CHECK: [[INVOKE_CONT]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V5]])
+// CHECK: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD1:.*]]
+
+// CHECK: [[INVOKE_CONT2]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: %[[V7:.*]] = load i8*, i8** %[[V2]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V7]], i32 8)
+// CHECK: ret void
+
+// CHECK: [[LPAD]]:
+// CHECK: invoke void @_ZN5test12S0D1Ev(%[[STRUCT_TEST1_S0]]* %[[V5]])
+// CHECK: to label %[[INVOKE_CONT3:.*]] unwind label %[[TERMINATE_LPAD]]
+
+// CHECK: [[LPAD1]]
+// CHECK: br label %[[EHCLEANUP:.*]]
+
+// CHECK: [[INVOKE_CONT3]]:
+// CHECK: br label %[[EHCLEANUP]]
+
+// CHECK: [[EHCLEANUP]]:
+// CHECK: call void @objc_storeStrong(i8** %[[V4]], i8* null)
+// CHECK: call void @objc_destroyWeak(i8** %[[V3]])
+// CHECK: %[[V14:.*]] = load i8*, i8** %[[V2]], align 8
+// CHECK: call void @_Block_object_dispose(i8* %[[V14]], i32 8)
+// CHECK: br label %[[EH_RESUME]]
+
+// CHECK: [[EH_RESUME]]:
+// CHECK: resume { i8*, i32 }
+
+// CHECK: [[TERMINATE_LPAD]]:
+// CHECK: call void @__clang_call_terminate(
+
+// CHECK-O1-LABEL: define internal void @__destroy_helper_block_(
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+// CHECK-O1: tail call void @objc_release({{.*}}) {{.*}} !clang.imprecise_release
+
+struct S0 {
+  S0();
+  S0(const S0 &);
+  ~S0();
+  int f0;
+};
+
+id getObj();
+
+void foo1() {
+  __block id t0 = getObj();
+  __weak id t1 = getObj();
+  id t2 = getObj();
+  S0 t3, t4;
+  ^{ (void)t0; (void)t1; (void)t2; (void)t3; (void)t4; };
+}
+}
-- 
GitLab


From a37cc0790f54b6fa8fdbe1a337ea6324d99cf8fd Mon Sep 17 00:00:00 2001
From: Ana Pazos 
Date: Thu, 26 Jul 2018 17:37:45 +0000
Subject: [PATCH 0735/1023]  [RISCV] Add support for interrupt attribute

Summary:
Clang supports the GNU style ``__attribute__((interrupt))`` attribute  on RISCV targets.
Permissible values for this parameter are user, supervisor, and machine.
If there is no parameter, then it defaults to machine.
Reference: https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
Based on initial patch by Zhaoshi Zheng.

Reviewers: asb, aaron.ballman

Reviewed By: asb, aaron.ballman

Subscribers: rkruppe, the_o, aaron.ballman, MartinMosbeck, brucehoult, rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, zzheng, edward-jones, mgrang, rogfer01, cfe-commits

Differential Revision: https://reviews.llvm.org/D48412

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338045 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/Attr.td                | 12 +++++
 include/clang/Basic/AttrDocs.td            | 23 ++++++++
 include/clang/Basic/DiagnosticSemaKinds.td | 10 +++-
 lib/CodeGen/TargetInfo.cpp                 | 21 ++++++++
 lib/Sema/SemaDeclAttr.cpp                  | 62 ++++++++++++++++++++++
 test/Sema/riscv-interrupt-attr.c           | 62 ++++++++++++++++++++++
 test/Sema/riscv-interrupt-attr.cpp         | 16 ++++++
 7 files changed, 205 insertions(+), 1 deletion(-)
 create mode 100644 test/Sema/riscv-interrupt-attr.c
 create mode 100644 test/Sema/riscv-interrupt-attr.cpp

diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 47da0896ce..0bbe52bf5f 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -308,6 +308,7 @@ def TargetAVR : TargetArch<["avr"]>;
 def TargetMips32 : TargetArch<["mips", "mipsel"]>;
 def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>;
 def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
 def TargetX86 : TargetArch<["x86"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
 def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
@@ -1374,6 +1375,17 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr {
   let Documentation = [MicroMipsDocs];
 }
 
+def RISCVInterrupt : InheritableAttr, TargetSpecificAttr {
+  let Spellings = [GCC<"interrupt">];
+  let Subjects = SubjectList<[Function]>;
+  let Args = [EnumArgument<"Interrupt", "InterruptType",
+                           ["user", "supervisor", "machine"],
+                           ["user", "supervisor", "machine"],
+                           1>];
+  let ParseKind = "Interrupt";
+  let Documentation = [RISCVInterruptDocs];
+}
+
 // This is not a TargetSpecificAttr so that is silently accepted and
 // ignored on other targets as encouraged by the OpenCL spec.
 //
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index 61e7682059..5a5ab78b49 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -1501,6 +1501,29 @@ as ``-mlong-calls`` and ``-mno-long-calls``.
   }];
 }
 
+def RISCVInterruptDocs : Documentation {
+  let Category = DocCatFunction;
+  let Heading = "interrupt (RISCV)";
+  let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV
+targets. This attribute may be attached to a function definition and instructs
+the backend to generate appropriate function entry/exit code so that it can be
+used directly as an interrupt service routine.
+
+Permissible values for this parameter are ``user``, ``supervisor``,
+and ``machine``. If there is no parameter, then it defaults to machine.
+
+Repeated interrupt attribute on the same declaration will cause a warning
+to be emitted. In case of repeated declarations, the last one prevails.
+
+Refer to:
+https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
+https://riscv.org/specifications/privileged-isa/
+The RISC-V Instruction Set Manual Volume II: Privileged Architecture
+Version 1.10.
+  }];
+}
+
 def AVRInterruptDocs : Documentation {
   let Category = DocCatFunction;
   let Heading = "interrupt (AVR)";
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 33634c8c8b..d0a2bec780 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -274,6 +274,14 @@ def warn_mips_interrupt_attribute : Warning<
    "MIPS 'interrupt' attribute only applies to functions that have "
    "%select{no parameters|a 'void' return type}0">,
    InGroup;
+def warn_riscv_repeated_interrupt_attribute : Warning<
+  "repeated RISC-V 'interrupt' attribute">, InGroup;
+def note_riscv_repeated_interrupt_attribute : Note<
+  "repeated RISC-V 'interrupt' attribute is here">;
+def warn_riscv_interrupt_attribute : Warning<
+   "RISC-V 'interrupt' attribute only applies to functions that have "
+   "%select{no parameters|a 'void' return type}0">,
+   InGroup;
 def warn_unused_parameter : Warning<"unused parameter %0">,
   InGroup, DefaultIgnore;
 def warn_unused_variable : Warning<"unused variable %0">,
@@ -281,7 +289,7 @@ def warn_unused_variable : Warning<"unused variable %0">,
 def warn_unused_local_typedef : Warning<
   "unused %select{typedef|type alias}0 %1">,
   InGroup, DefaultIgnore;
-def warn_unused_property_backing_ivar : 
+def warn_unused_property_backing_ivar :
   Warning<"ivar %0 which backs the property is not "
   "referenced in this property's accessor">,
   InGroup, DefaultIgnore;
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 2078ea1fea..fa9b0a27af 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -8971,6 +8971,27 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen)
       : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen)) {}
+
+  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                           CodeGen::CodeGenModule &CGM) const override {
+    const auto *FD = dyn_cast_or_null(D);
+    if (!FD) return;
+
+    const auto *Attr = FD->getAttr();
+    if (!Attr)
+      return;
+
+    const char *Kind;
+    switch (Attr->getInterrupt()) {
+    case RISCVInterruptAttr::user: Kind = "user"; break;
+    case RISCVInterruptAttr::supervisor: Kind = "supervisor"; break;
+    case RISCVInterruptAttr::machine: Kind = "machine"; break;
+    }
+
+    auto *Fn = cast(GV);
+
+    Fn->addFnAttr("interrupt", Kind);
+  }
 };
 } // namespace
 
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index d1786f7682..320eabd5ec 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -5372,6 +5372,64 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   handleSimpleAttribute(S, D, AL);
 }
 
+
+static void handleRISCVInterruptAttr(Sema &S, Decl *D,
+                                     const ParsedAttr &AL) {
+  // Warn about repeated attributes.
+  if (const auto *A = D->getAttr()) {
+    S.Diag(AL.getRange().getBegin(),
+      diag::warn_riscv_repeated_interrupt_attribute);
+    S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
+    return;
+  }
+
+  // Check the attribute argument. Argument is optional.
+  if (!checkAttributeAtMostNumArgs(S, AL, 1))
+    return;
+
+  StringRef Str;
+  SourceLocation ArgLoc;
+
+  // 'machine'is the default interrupt mode.
+  if (AL.getNumArgs() == 0)
+    Str = "machine";
+  else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
+    return;
+
+  // Semantic checks for a function with the 'interrupt' attribute:
+  // - Must be a function.
+  // - Must have no parameters.
+  // - Must have the 'void' return type.
+  // - The attribute itself must either have no argument or one of the
+  //   valid interrupt types, see [RISCVInterruptDocs].
+
+  if (D->getFunctionType() == nullptr) {
+    S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+      << "'interrupt'" << ExpectedFunction;
+    return;
+  }
+
+  if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+    S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 0;
+    return;
+  }
+
+  if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+    S.Diag(D->getLocation(), diag::warn_riscv_interrupt_attribute) << 1;
+    return;
+  }
+
+  RISCVInterruptAttr::InterruptType Kind;
+  if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+    S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+      << AL.getName() << Str << ArgLoc;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) RISCVInterruptAttr(
+    AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
+}
+
 static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // Dispatch the interrupt attribute based on the current target.
   switch (S.Context.getTargetInfo().getTriple().getArch()) {
@@ -5389,6 +5447,10 @@ static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   case llvm::Triple::avr:
     handleAVRInterruptAttr(S, D, AL);
     break;
+  case llvm::Triple::riscv32:
+  case llvm::Triple::riscv64:
+    handleRISCVInterruptAttr(S, D, AL);
+    break;
   default:
     handleARMInterruptAttr(S, D, AL);
     break;
diff --git a/test/Sema/riscv-interrupt-attr.c b/test/Sema/riscv-interrupt-attr.c
new file mode 100644
index 0000000000..55f0863c1f
--- /dev/null
+++ b/test/Sema/riscv-interrupt-attr.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple riscv32-unknown-elf -emit-llvm -DCHECK_IR < %s| FileCheck %s
+// RUN: %clang_cc1 -triple riscv64-unknown-elf -emit-llvm -DCHECK_IR < %s| FileCheck %s
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only
+
+#if defined(CHECK_IR)
+// CHECK-LABEL:  @foo_user() #0
+// CHECK: ret void
+__attribute__((interrupt("user"))) void foo_user(void) {}
+// CHECK-LABEL:  @foo_supervisor() #1
+// CHECK: ret void
+__attribute__((interrupt("supervisor"))) void foo_supervisor(void) {}
+// CHECK-LABEL:  @foo_machine() #2
+// CHECK: ret void
+__attribute__((interrupt("machine"))) void foo_machine(void) {}
+// CHECK-LABEL:  @foo_default() #2
+// CHECK: ret void
+__attribute__((interrupt())) void foo_default(void) {}
+// CHECK-LABEL:  @foo_default2() #2
+// CHECK: ret void
+__attribute__((interrupt())) void foo_default2(void) {}
+// CHECK: attributes #0
+// CHECK: "interrupt"="user"
+// CHECK: attributes #1
+// CHECK: "interrupt"="supervisor"
+// CHECK: attributes #2
+// CHECK: "interrupt"="machine"
+#else
+struct a { int b; };
+
+struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attribute only applies to functions}}
+
+__attribute__((interrupt("USER"))) void foo1(void) {} // expected-warning {{'interrupt' attribute argument not supported: USER}}
+
+__attribute__((interrupt("user", 1))) void foo2(void) {} // expected-error {{'interrupt' attribute takes no more than 1 argument}}
+
+__attribute__((interrupt)) int foo3(void) {return 0;} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have a 'void' return type}}
+
+__attribute__((interrupt())) void foo4();
+__attribute__((interrupt())) void foo4() {};
+
+__attribute__((interrupt())) void foo5(int a) {} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have no parameters}}
+
+__attribute__((interrupt("user"), interrupt("supervisor"))) void foo6(void) {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+  // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+
+__attribute__((interrupt, interrupt)) void foo7(void) {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+                                                     // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+
+__attribute__((interrupt(""))) void foo8(void) {} // expected-warning {{'interrupt' attribute argument not supported}}
+
+__attribute__((interrupt("user"))) void foo9(void);
+__attribute__((interrupt("supervisor"))) void foo9(void);
+__attribute__((interrupt("machine"))) void foo9(void);
+
+__attribute__((interrupt("user"))) void foo10(void) {}
+__attribute__((interrupt("supervisor"))) void foo11(void) {}
+__attribute__((interrupt("machine"))) void foo12(void) {}
+__attribute__((interrupt())) void foo13(void) {}
+__attribute__((interrupt)) void foo14(void) {}
+#endif
+
diff --git a/test/Sema/riscv-interrupt-attr.cpp b/test/Sema/riscv-interrupt-attr.cpp
new file mode 100644
index 0000000000..a01999b3a1
--- /dev/null
+++ b/test/Sema/riscv-interrupt-attr.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -x c++ -triple riscv32-unknown-elf -emit-llvm  -DCHECK_IR < %s | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple riscv64-unknown-elf -emit-llvm  -DCHECK_IR < %s | FileCheck %s
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only
+
+#if defined(CHECK_IR)
+// CHECK-LABEL: @_Z11foo_defaultv() #0
+// CHECK: ret void
+[[gnu::interrupt]] void foo_default() {}
+// CHECK: attributes #0
+// CHECK: "interrupt"="machine"
+#else
+[[gnu::interrupt]] [[gnu::interrupt]] void foo1() {} // expected-warning {{repeated RISC-V 'interrupt' attribute}} \
+                                                     // expected-note {{repeated RISC-V 'interrupt' attribute is here}}
+[[gnu::interrupt]] void foo2() {}
+#endif
-- 
GitLab


From dcd0309c08ba6c3c39bb75ed975fcf95ca63ad7f Mon Sep 17 00:00:00 2001
From: Akira Hatanaka 
Date: Thu, 26 Jul 2018 17:51:13 +0000
Subject: [PATCH 0736/1023] [Sema][ObjC] Do not propagate the nullability
 specifier on the receiver to the result type of a message send if the result
 type cannot have a nullability specifier.

Previously, clang would print the following message when the code in
nullability.m was compiled:

"incompatible integer to pointer conversion initializing 'int *' with
an expression of type 'int _Nullable'"

This is wrong as 'int' isn't supposed to have any nullability
specifiers.

rdar://problem/40830514

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338048 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaExprObjC.cpp   |  5 +++++
 test/SemaObjC/nullability.m | 11 +++++++++++
 2 files changed, 16 insertions(+)

diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index bf9d081bb9..bf0ffeba06 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1357,6 +1357,11 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
   if (isClassMessage)
     return resultType;
 
+  // There is nothing left to do if the result type cannot have a nullability
+  // specifier.
+  if (!resultType->canHaveNullability())
+    return resultType;
+
   // Map the nullability of the result into a table index.
   unsigned receiverNullabilityIdx = 0;
   if (auto nullability = ReceiverType->getNullability(Context))
diff --git a/test/SemaObjC/nullability.m b/test/SemaObjC/nullability.m
index cbfe132d14..93f4d1d499 100644
--- a/test/SemaObjC/nullability.m
+++ b/test/SemaObjC/nullability.m
@@ -279,3 +279,14 @@ void test(ArraysInMethods *obj) {
   [obj simpleSugar:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
   [obj sugarWithTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
 }
+
+// Check that we don't propagate the nullability specifier on the receiver to
+// the result type of a message send if the result type cannot have a
+// nullability specifier.
+@interface C0
+-(int) count;
+@end
+
+void testMessageSendResultType(C0 * _Nullable c0) {
+  int *p = [c0 count]; // expected-warning {{incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int'}}
+}
-- 
GitLab


From 0e0e209a78f3e2e66a5ac7207be53147f4143347 Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Thu, 26 Jul 2018 17:53:45 +0000
Subject: [PATCH 0737/1023] [OPENMP] What's new for OpenMP in clang.

Updated ReleaseNotes + Status of the OpenMP support in clang.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338049 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/OpenMPSupport.rst | 75 ++++++++++++++++++++++++++++++++++++++----
 docs/ReleaseNotes.rst  | 16 ++++++++-
 2 files changed, 84 insertions(+), 7 deletions(-)

diff --git a/docs/OpenMPSupport.rst b/docs/OpenMPSupport.rst
index f34049473f..e8ec1e371b 100644
--- a/docs/OpenMPSupport.rst
+++ b/docs/OpenMPSupport.rst
@@ -10,13 +10,15 @@
 .. role:: partial
 .. role:: good
 
+.. contents::
+   :local:
+
 ==================
 OpenMP Support
 ==================
 
-Clang fully supports OpenMP 3.1 + some elements of OpenMP 4.5. Clang supports offloading to X86_64, AArch64 and PPC64[LE] devices.
-Support for Cuda devices is not ready yet.
-The status of major OpenMP 4.5 features support in Clang.
+Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64,
+PPC64[LE] and has `basic support for Cuda devices`_.
 
 Standalone directives
 =====================
@@ -35,7 +37,7 @@ Standalone directives
 
 * #pragma omp target: :good:`Complete`.
 
-* #pragma omp declare target: :partial:`Partial`.  No full codegen support.
+* #pragma omp declare target: :good:`Complete`.
 
 * #pragma omp teams: :good:`Complete`.
 
@@ -64,5 +66,66 @@ Combined directives
 
 * #pragma omp target teams distribute parallel for [simd]: :good:`Complete`.
 
-Clang does not support any constructs/updates from upcoming OpenMP 5.0 except for `reduction`-based clauses in the `task` and `target`-based directives.
-In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
+Clang does not support any constructs/updates from upcoming OpenMP 5.0 except
+for `reduction`-based clauses in the `task` and `target`-based directives.
+
+In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
+Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
+ows, and mac OS.
+
+.. _basic support for Cuda devices:
+
+Cuda devices support
+====================
+
+Directives execution modes
+--------------------------
+
+Clang code generation for target regions supports two modes: the SPMD and
+non-SPMD modes. Clang chooses one of these two modes automatically based on the
+way directives and clauses on those directives are used. The SPMD mode uses a
+simplified set of runtime functions thus increasing performance at the cost of
+supporting some OpenMP features. The non-SPMD mode is the most generic mode and
+supports all currently available OpenMP features. The compiler will always
+attempt to use the SPMD mode wherever possible. SPMD mode will not be used if:
+
+   - The target region contains an `if()` clause that refers to a `parallel`
+     directive.
+
+   - The target region contains a `parallel` directive with a `num_threads()`
+     clause.
+
+   - The target region contains user code (other than OpenMP-specific
+     directives) in between the `target` and the `parallel` directives.
+
+Data-sharing modes
+------------------
+
+Clang supports two data-sharing models for Cuda devices: `Generic` and `Cuda`
+modes. The default mode is `Generic`. `Cuda` mode can give an additional
+performance and can be activated using the `-fopenmp-cuda-mode` flag. In
+`Generic` mode all local variables that can be shared in the parallel regions
+are stored in the global memory. In `Cuda` mode local variables are not shared
+between the threads and it is user responsibility to share the required data
+between the threads in the parallel regions.
+
+Features not supported or with limited support for Cuda devices
+---------------------------------------------------------------
+
+- Reductions across the teams are not supported yet.
+
+- Cancellation constructs are not supported.
+
+- Doacross loop nest is not supported.
+
+- User-defined reductions are supported only for trivial types.
+
+- Nested parallelism: inner parallel regions are executed sequentially.
+
+- Static linking of libraries containing device code is not supported yet.
+
+- Automatic translation of math functions in target regions to device-specific
+  math functions is not implemented yet.
+
+- Debug information for OpenMP target regions is not supported yet.
+
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index dab70f1bca..24f182b824 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -216,7 +216,21 @@ OpenCL C Language Changes in Clang
 OpenMP Support in Clang
 ----------------------------------
 
-- ...
+- Clang gained basic support for OpenMP 4.5 offloading for NVPTX target.
+   To compile your program for NVPTX target use the following options:
+   `-fopenmp -fopenmp-targets=nvptx64-nvidia-cuda` for 64 bit platforms or
+   `-fopenmp -fopenmp-targets=nvptx-nvidia-cuda` for 32 bit platform.
+
+- Passing options to the OpenMP device offloading toolchain can be done using
+  the `-Xopenmp-target= -opt=val` flag. In this way the `-opt=val`
+  option will be forwarded to the respective OpenMP device offloading toolchain
+  described by the triple. For example passing the compute capability to
+  the OpenMP NVPTX offloading toolchain can be done as follows:
+  `-Xopenmp-target=nvptx62-nvidia-cuda -march=sm_60`. For the case when only one
+  target offload toolchain is specified under the `-fopenmp-targets=`
+  option, then the triple can be skipped: `-Xopenmp-target -march=sm_60`.
+
+- Other bugfixes.
 
 CUDA Support in Clang
 ---------------------
-- 
GitLab


From 681015848a6aee4b21acc13664ce830e5001afb7 Mon Sep 17 00:00:00 2001
From: Mandeep Singh Grang 
Date: Thu, 26 Jul 2018 18:07:59 +0000
Subject: [PATCH 0738/1023] [COFF, ARM64] Decide when to mark struct returns as
 SRet

Summary:
Refer the MS ARM64 ABI Convention for the behavior for struct returns:
https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions#return-values

Reviewers: mstorsjo, compnerd, rnk, javed.absar, yinma, efriedma

Reviewed By: rnk, efriedma

Subscribers: haripul, TomTan, yinma, efriedma, kristof.beyls, chrib, llvm-commits

Differential Revision: https://reviews.llvm.org/D49464

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338050 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/CodeGen/CGFunctionInfo.h     | 16 ++++++++++++--
 lib/CodeGen/CGCall.cpp                     |  3 ++-
 lib/CodeGen/MicrosoftCXXABI.cpp            | 12 +++++++++++
 test/CodeGen/arm64-microsoft-arguments.cpp | 25 ++++++++++++++++++++++
 4 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 test/CodeGen/arm64-microsoft-arguments.cpp

diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index 5ea655cb2a..cf64e9f3ee 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -96,6 +96,7 @@ private:
   bool InReg : 1;           // isDirect() || isExtend() || isIndirect()
   bool CanBeFlattened: 1;   // isDirect()
   bool SignExt : 1;         // isExtend()
+  bool SuppressSRet : 1;    // isIndirect()
 
   bool canHavePaddingType() const {
     return isDirect() || isExtend() || isIndirect() || isExpand();
@@ -111,13 +112,14 @@ private:
   }
 
   ABIArgInfo(Kind K)
-      : TheKind(K), PaddingInReg(false), InReg(false) {
+      : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
   }
 
 public:
   ABIArgInfo()
       : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
-        TheKind(Direct), PaddingInReg(false), InReg(false) {}
+        TheKind(Direct), PaddingInReg(false), InReg(false),
+        SuppressSRet(false) {}
 
   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
                               llvm::Type *Padding = nullptr,
@@ -406,6 +408,16 @@ public:
     CanBeFlattened = Flatten;
   }
 
+  bool getSuppressSRet() const {
+    assert(isIndirect() && "Invalid kind!");
+    return SuppressSRet;
+  }
+
+  void setSuppressSRet(bool Suppress) {
+    assert(isIndirect() && "Invalid kind!");
+    SuppressSRet = Suppress;
+  }
+
   void dump() const;
 };
 
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index f60136c2f1..f066ce1685 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1988,7 +1988,8 @@ void CodeGenModule::ConstructAttributeList(
   // Attach attributes to sret.
   if (IRFunctionArgs.hasSRetArg()) {
     llvm::AttrBuilder SRETAttrs;
-    SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+    if (!RetAI.getSuppressSRet())
+      SRETAttrs.addAttribute(llvm::Attribute::StructRet);
     hasUsedSRet = true;
     if (RetAI.getInReg())
       SRETAttrs.addAttribute(llvm::Attribute::InReg);
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index e5e9cf67fd..a1122dc80a 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1060,10 +1060,22 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
     // the second parameter.
     FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
     FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+
+    // aarch64-windows requires that instance methods use X1 for the return
+    // address. So for aarch64-windows we do not mark the
+    // return as SRet.
+    FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
+                                       llvm::Triple::aarch64);
     return true;
   } else if (!RD->isPOD()) {
     // If it's a free function, non-POD types are returned indirectly.
     FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+
+    // aarch64-windows requires that non-POD, non-instance returns use X0 for
+    // the return address. So for aarch64-windows we do not mark the return as
+    // SRet.
+    FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
+                                       llvm::Triple::aarch64);
     return true;
   }
 
diff --git a/test/CodeGen/arm64-microsoft-arguments.cpp b/test/CodeGen/arm64-microsoft-arguments.cpp
new file mode 100644
index 0000000000..3ef468880a
--- /dev/null
+++ b/test/CodeGen/arm64-microsoft-arguments.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
+// RUN: -x c++ -o - %s | FileCheck %s
+
+struct pod { int a, b, c, d, e; };
+
+struct non_pod {
+  int a;
+  non_pod() {}
+};
+
+struct pod s;
+struct non_pod t;
+
+struct pod bar() { return s; }
+struct non_pod foo() { return t; }
+// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
+// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+
+
+// Check instance methods.
+struct pod2 { int x; };
+struct Baz { pod2 baz(); };
+
+int qux() { return Baz().baz().x; }
+// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
-- 
GitLab


From 172cbdc41f25ea610a15bb7f071a973751d57b6e Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Thu, 26 Jul 2018 18:40:41 +0000
Subject: [PATCH 0739/1023] [OPENMP, DOCS] Fixed typo, NFC.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338055 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 24f182b824..342fed3393 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -226,7 +226,7 @@ OpenMP Support in Clang
   option will be forwarded to the respective OpenMP device offloading toolchain
   described by the triple. For example passing the compute capability to
   the OpenMP NVPTX offloading toolchain can be done as follows:
-  `-Xopenmp-target=nvptx62-nvidia-cuda -march=sm_60`. For the case when only one
+  `-Xopenmp-target=nvptx64-nvidia-cuda -march=sm_60`. For the case when only one
   target offload toolchain is specified under the `-fopenmp-targets=`
   option, then the triple can be skipped: `-Xopenmp-target -march=sm_60`.
 
-- 
GitLab


From 51cfee88b37794cb98ee948c142884044a74e1fb Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Thu, 26 Jul 2018 18:41:30 +0000
Subject: [PATCH 0740/1023] Refactor checking of switch conditions and case
 values.

Check each case value in turn while parsing it, performing the
conversion to the switch type within the context of the expression
itself. This will become necessary in order to properly handle cleanups
for temporaries created as part of the case label (in an upcoming
patch). For now it's just good hygiene.

This necessitates moving the checking for the switch condition itself to
earlier, so that the destination type is available when checking the
case labels.

As a nice side-effect, we get slightly improved diagnostic quality and
error recovery by separating the case expression checking from the case
statement checking and from tracking whether there are discarded case
labels.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338056 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Parse/Parser.h     |   1 +
 include/clang/Sema/ScopeInfo.h   |   6 +-
 include/clang/Sema/Sema.h        |   7 +-
 lib/Parse/ParseExpr.cpp          |   8 +
 lib/Parse/ParseStmt.cpp          |  26 +---
 lib/Sema/SemaCodeComplete.cpp    |   2 +-
 lib/Sema/SemaStmt.cpp            | 247 +++++++++++++++----------------
 lib/Sema/TreeTransform.h         |   4 +-
 test/Parser/switch-recovery.cpp  |   8 +-
 test/Sema/complex-int.c          |   4 +
 test/Sema/switch.c               |   2 +-
 test/SemaCXX/i-c-e-cxx.cpp       |   6 +-
 test/SemaCXX/scope-check.cpp     |   3 +-
 test/SemaCXX/typo-correction.cpp |   2 +-
 14 files changed, 162 insertions(+), 164 deletions(-)

diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index c6ffcde5a1..d7b83803af 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1578,6 +1578,7 @@ public:
   ExprResult ParseConstantExpressionInExprEvalContext(
       TypeCastState isTypeCast = NotTypeCast);
   ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
+  ExprResult ParseCaseExpression(SourceLocation CaseLoc);
   ExprResult ParseConstraintExpression();
   // Expr that doesn't include commas.
   ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast);
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 1074074c60..5eac2845fd 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -175,9 +175,13 @@ public:
   /// Used to determine if errors occurred in this function or block.
   DiagnosticErrorTrap ErrorTrap;
 
+  /// A SwitchStmt, along with a flag indicating if its list of case statements
+  /// is incomplete (because we dropped an invalid one while parsing).
+  using SwitchInfo = llvm::PointerIntPair;
+
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
-  SmallVector SwitchStack;
+  SmallVector SwitchStack;
 
   /// The list of return statements that occur within the function or
   /// block, if there is any chance of applying the named return value
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index ab934223b8..b1077c620f 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3727,9 +3727,10 @@ public:
                                    SourceLocation EndLoc);
   void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
   StmtResult ActOnForEachLValueExpr(Expr *E);
-  StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
-                                   SourceLocation DotDotDotLoc, Expr *RHSVal,
-                                   SourceLocation ColonLoc);
+  ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
+  StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
+                           SourceLocation DotDotDotLoc, ExprResult RHS,
+                           SourceLocation ColonLoc);
   void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
 
   StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d96dc5b362..6904906403 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -217,6 +217,14 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
   return ParseConstantExpressionInExprEvalContext(isTypeCast);
 }
 
+ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
+  EnterExpressionEvaluationContext ConstantEvaluated(
+      Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+  ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+  return Actions.ActOnCaseExpr(CaseLoc, Res);
+}
+
 /// Parse a constraint-expression.
 ///
 /// \verbatim
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index b16ce4fde3..deb10af4b1 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -685,20 +685,12 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
 
     ExprResult LHS;
     if (!MissingCase) {
-      LHS = ParseConstantExpression();
-      if (!getLangOpts().CPlusPlus11) {
-        LHS = Actions.CorrectDelayedTyposInExpr(LHS, [this](class Expr *E) {
-          return Actions.VerifyIntegerConstantExpression(E);
-        });
-      }
+      LHS = ParseCaseExpression(CaseLoc);
       if (LHS.isInvalid()) {
         // If constant-expression is parsed unsuccessfully, recover by skipping
         // current case statement (moving to the colon that ends it).
-        if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
-          TryConsumeToken(tok::colon, ColonLoc);
-          continue;
-        }
-        return StmtError();
+        if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
+          return StmtError();
       }
     } else {
       LHS = Expr;
@@ -710,13 +702,10 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
     ExprResult RHS;
     if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
       Diag(DotDotDotLoc, diag::ext_gnu_case_range);
-      RHS = ParseConstantExpression();
+      RHS = ParseCaseExpression(CaseLoc);
       if (RHS.isInvalid()) {
-        if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) {
-          TryConsumeToken(tok::colon, ColonLoc);
-          continue;
-        }
-        return StmtError();
+        if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
+          return StmtError();
       }
     }
 
@@ -738,8 +727,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
     }
 
     StmtResult Case =
-      Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc,
-                            RHS.get(), ColonLoc);
+        Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
 
     // If we had a sema error parsing this case, then just ignore it and
     // continue parsing the sub-stmt.
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index ae5183408f..4e571eba17 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4316,7 +4316,7 @@ void Sema::CodeCompleteCase(Scope *S) {
   if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
     return;
 
-  SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+  SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
   QualType type = Switch->getCond()->IgnoreImplicit()->getType();
   if (!type->isEnumeralType()) {
     CodeCompleteExpressionData Data(type);
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 058a2cd4f2..b2f9783d44 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -392,65 +392,79 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
   return CompoundStmt::Create(Context, Elts, L, R);
 }
 
+ExprResult
+Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
+  if (!Val.get())
+    return Val;
+
+  if (DiagnoseUnexpandedParameterPack(Val.get()))
+    return ExprError();
+
+  // If we're not inside a switch, let the 'case' statement handling diagnose
+  // this. Just clean up after the expression as best we can.
+  if (!getCurFunction()->SwitchStack.empty()) {
+    Expr *CondExpr =
+        getCurFunction()->SwitchStack.back().getPointer()->getCond();
+    if (!CondExpr)
+      return ExprError();
+    QualType CondType = CondExpr->getType();
+
+    auto CheckAndFinish = [&](Expr *E) {
+      if (CondType->isDependentType() || E->isTypeDependent())
+        return ExprResult(E);
+
+      if (getLangOpts().CPlusPlus11) {
+        // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+        // constant expression of the promoted type of the switch condition.
+        llvm::APSInt TempVal;
+        return CheckConvertedConstantExpression(E, CondType, TempVal,
+                                                CCEK_CaseValue);
+      }
+
+      ExprResult ER = E;
+      if (!E->isValueDependent())
+        ER = VerifyIntegerConstantExpression(E);
+      if (!ER.isInvalid())
+        ER = DefaultLvalueConversion(ER.get());
+      if (!ER.isInvalid())
+        ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
+      return ER;
+    };
+
+    ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+    if (Converted.get() == Val.get())
+      Converted = CheckAndFinish(Val.get());
+    if (Converted.isInvalid())
+      return ExprError();
+    Val = Converted;
+  }
+
+  return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
+                             getLangOpts().CPlusPlus11);
+}
+
 StmtResult
-Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
-                    SourceLocation DotDotDotLoc, Expr *RHSVal,
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
+                    SourceLocation DotDotDotLoc, ExprResult RHSVal,
                     SourceLocation ColonLoc) {
-  assert(LHSVal && "missing expression in case statement");
+  assert((LHSVal.isInvalid() || LHSVal.get()) && "missing LHS value");
+  assert((DotDotDotLoc.isInvalid() ? RHSVal.isUnset()
+                                   : RHSVal.isInvalid() || RHSVal.get()) &&
+         "missing RHS value");
 
   if (getCurFunction()->SwitchStack.empty()) {
     Diag(CaseLoc, diag::err_case_not_in_switch);
     return StmtError();
   }
 
-  ExprResult LHS =
-      CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) {
-        if (!getLangOpts().CPlusPlus11)
-          return VerifyIntegerConstantExpression(E);
-        if (Expr *CondExpr =
-                getCurFunction()->SwitchStack.back()->getCond()) {
-          QualType CondType = CondExpr->getType();
-          llvm::APSInt TempVal;
-          return CheckConvertedConstantExpression(E, CondType, TempVal,
-                                                        CCEK_CaseValue);
-        }
-        return ExprError();
-      });
-  if (LHS.isInvalid())
+  if (LHSVal.isInvalid() || RHSVal.isInvalid()) {
+    getCurFunction()->SwitchStack.back().setInt(true);
     return StmtError();
-  LHSVal = LHS.get();
-
-  if (!getLangOpts().CPlusPlus11) {
-    // C99 6.8.4.2p3: The expression shall be an integer constant.
-    // However, GCC allows any evaluatable integer expression.
-    if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) {
-      LHSVal = VerifyIntegerConstantExpression(LHSVal).get();
-      if (!LHSVal)
-        return StmtError();
-    }
-
-    // GCC extension: The expression shall be an integer constant.
-
-    if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) {
-      RHSVal = VerifyIntegerConstantExpression(RHSVal).get();
-      // Recover from an error by just forgetting about it.
-    }
   }
 
-  LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
-                                 getLangOpts().CPlusPlus11);
-  if (LHS.isInvalid())
-    return StmtError();
-
-  auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
-                                          getLangOpts().CPlusPlus11)
-                    : ExprResult();
-  if (RHS.isInvalid())
-    return StmtError();
-
   CaseStmt *CS = new (Context)
-      CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc);
-  getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
+      CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc);
+  getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
   return CS;
 }
 
@@ -473,7 +487,7 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
   }
 
   DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
-  getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
+  getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS);
   return DS;
 }
 
@@ -679,20 +693,44 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
   if (CondResult.isInvalid())
     return ExprError();
 
+  // FIXME: PerformContextualImplicitConversion doesn't always tell us if it
+  // failed and produced a diagnostic.
+  Cond = CondResult.get();
+  if (!Cond->isTypeDependent() &&
+      !Cond->getType()->isIntegralOrEnumerationType())
+    return ExprError();
+
   // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
-  return UsualUnaryConversions(CondResult.get());
+  return UsualUnaryConversions(Cond);
 }
 
 StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
                                         Stmt *InitStmt, ConditionResult Cond) {
-  if (Cond.isInvalid())
-    return StmtError();
+  Expr *CondExpr = Cond.get().second;
+  assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
+
+  if (CondExpr && !CondExpr->isTypeDependent()) {
+    // We have already converted the expression to an integral or enumeration
+    // type, when we parsed the switch condition. If we don't have an
+    // appropriate type now, enter the switch scope but remember that it's
+    // invalid.
+    assert(CondExpr->getType()->isIntegralOrEnumerationType() &&
+           "invalid condition type");
+    if (CondExpr->isKnownToHaveBooleanValue()) {
+      // switch(bool_expr) {...} is often a programmer error, e.g.
+      //   switch(n && mask) { ... }  // Doh - should be "n & mask".
+      // One can always use an if statement instead of switch(bool_expr).
+      Diag(SwitchLoc, diag::warn_bool_switch_condition)
+          << CondExpr->getSourceRange();
+    }
+  }
 
   setFunctionHasBranchIntoScope();
 
   SwitchStmt *SS = new (Context)
-      SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second);
-  getCurFunction()->SwitchStack.push_back(SS);
+      SwitchStmt(Context, InitStmt, Cond.get().first, CondExpr);
+  getCurFunction()->SwitchStack.push_back(
+      FunctionScopeInfo::SwitchInfo(SS, false));
   return SS;
 }
 
@@ -705,6 +743,10 @@ static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
 /// type.
 static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
                            unsigned UnpromotedWidth, bool UnpromotedSign) {
+  // In C++11 onwards, this is checked by the language rules.
+  if (S.getLangOpts().CPlusPlus11)
+    return;
+
   // If the case value was signed and negative and the switch expression is
   // unsigned, don't bother to warn: this is implementation-defined behavior.
   // FIXME: Introduce a second, default-ignored warning for this case?
@@ -759,7 +801,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
 
 static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
                                        const Expr *Case) {
-  QualType CondType = GetTypeBeforeIntegralPromotion(Cond);
+  QualType CondType = Cond->getType();
   QualType CaseType = Case->getType();
 
   const EnumType *CondEnumType = CondType->getAs();
@@ -787,7 +829,8 @@ StmtResult
 Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
                             Stmt *BodyStmt) {
   SwitchStmt *SS = cast(Switch);
-  assert(SS == getCurFunction()->SwitchStack.back() &&
+  bool CaseListIsIncomplete = getCurFunction()->SwitchStack.back().getInt();
+  assert(SS == getCurFunction()->SwitchStack.back().getPointer() &&
          "switch stack missing push/pop!");
 
   getCurFunction()->SwitchStack.pop_back();
@@ -800,10 +843,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
 
   QualType CondType = CondExpr->getType();
 
-  const Expr *CondExprBeforePromotion = CondExpr;
-  QualType CondTypeBeforePromotion =
-      GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
-
   // C++ 6.4.2.p2:
   // Integral promotions are performed (on the switch condition).
   //
@@ -811,21 +850,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
   // type (before the promotion) doesn't make sense, even when it can
   // be represented by the promoted type.  Therefore we need to find
   // the pre-promotion type of the switch condition.
-  if (!CondExpr->isTypeDependent()) {
-    // We have already converted the expression to an integral or enumeration
-    // type, when we started the switch statement. If we don't have an
-    // appropriate type now, just return an error.
-    if (!CondType->isIntegralOrEnumerationType())
-      return StmtError();
-
-    if (CondExpr->isKnownToHaveBooleanValue()) {
-      // switch(bool_expr) {...} is often a programmer error, e.g.
-      //   switch(n && mask) { ... }  // Doh - should be "n & mask".
-      // One can always use an if statement instead of switch(bool_expr).
-      Diag(SwitchLoc, diag::warn_bool_switch_condition)
-          << CondExpr->getSourceRange();
-    }
-  }
+  const Expr *CondExprBeforePromotion = CondExpr;
+  QualType CondTypeBeforePromotion =
+      GetTypeBeforeIntegralPromotion(CondExprBeforePromotion);
 
   // Get the bitwidth of the switched-on value after promotions. We must
   // convert the integer case values to this width before comparison.
@@ -878,50 +905,32 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
 
       Expr *Lo = CS->getLHS();
 
-      if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+      if (Lo->isValueDependent()) {
         HasDependentValue = true;
         break;
       }
 
-      checkEnumTypesInSwitchStmt(*this, CondExpr, Lo);
-
-      llvm::APSInt LoVal;
-
-      if (getLangOpts().CPlusPlus11) {
-        // C++11 [stmt.switch]p2: the constant-expression shall be a converted
-        // constant expression of the promoted type of the switch condition.
-        ExprResult ConvLo =
-          CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue);
-        if (ConvLo.isInvalid()) {
-          CaseListIsErroneous = true;
-          continue;
-        }
-        Lo = ConvLo.get();
-      } else {
-        // We already verified that the expression has a i-c-e value (C99
-        // 6.8.4.2p3) - get that value now.
-        LoVal = Lo->EvaluateKnownConstInt(Context);
-
-        // If the LHS is not the same type as the condition, insert an implicit
-        // cast.
-        Lo = DefaultLvalueConversion(Lo).get();
-        Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get();
-      }
+      // We already verified that the expression has a constant value;
+      // get that value (prior to conversions).
+      const Expr *LoBeforePromotion = Lo;
+      GetTypeBeforeIntegralPromotion(LoBeforePromotion);
+      llvm::APSInt LoVal = LoBeforePromotion->EvaluateKnownConstInt(Context);
 
       // Check the unconverted value is within the range of possible values of
       // the switch expression.
       checkCaseValue(*this, Lo->getLocStart(), LoVal,
                      CondWidthBeforePromotion, CondIsSignedBeforePromotion);
 
+      // FIXME: This duplicates the check performed for warn_not_in_enum below.
+      checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
+                                 LoBeforePromotion);
+
       // Convert the value to the same width/sign as the condition.
       AdjustAPSInt(LoVal, CondWidth, CondIsSigned);
 
-      CS->setLHS(Lo);
-
       // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
       if (CS->getRHS()) {
-        if (CS->getRHS()->isTypeDependent() ||
-            CS->getRHS()->isValueDependent()) {
+        if (CS->getRHS()->isValueDependent()) {
           HasDependentValue = true;
           break;
         }
@@ -1002,27 +1011,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
         llvm::APSInt &LoVal = CaseRanges[i].first;
         CaseStmt *CR = CaseRanges[i].second;
         Expr *Hi = CR->getRHS();
-        llvm::APSInt HiVal;
-
-        if (getLangOpts().CPlusPlus11) {
-          // C++11 [stmt.switch]p2: the constant-expression shall be a converted
-          // constant expression of the promoted type of the switch condition.
-          ExprResult ConvHi =
-            CheckConvertedConstantExpression(Hi, CondType, HiVal,
-                                             CCEK_CaseValue);
-          if (ConvHi.isInvalid()) {
-            CaseListIsErroneous = true;
-            continue;
-          }
-          Hi = ConvHi.get();
-        } else {
-          HiVal = Hi->EvaluateKnownConstInt(Context);
 
-          // If the RHS is not the same type as the condition, insert an
-          // implicit cast.
-          Hi = DefaultLvalueConversion(Hi).get();
-          Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get();
-        }
+        const Expr *HiBeforePromotion = Hi;
+        GetTypeBeforeIntegralPromotion(HiBeforePromotion);
+        llvm::APSInt HiVal = HiBeforePromotion->EvaluateKnownConstInt(Context);
 
         // Check the unconverted value is within the range of possible values of
         // the switch expression.
@@ -1032,8 +1024,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
         // Convert the value to the same width/sign as the condition.
         AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
 
-        CR->setRHS(Hi);
-
         // If the low value is bigger than the high value, the case is empty.
         if (LoVal > HiVal) {
           Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
@@ -1104,7 +1094,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
     }
 
     // Complain if we have a constant condition and we didn't find a match.
-    if (!CaseListIsErroneous && ShouldCheckConstantCond) {
+    if (!CaseListIsErroneous && !CaseListIsIncomplete &&
+        ShouldCheckConstantCond) {
       // TODO: it would be nice if we printed enums as enums, chars as
       // chars, etc.
       Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
@@ -1120,8 +1111,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
     const EnumType *ET = CondTypeBeforePromotion->getAs();
 
     // If switch has default case, then ignore it.
-    if (!CaseListIsErroneous && !HasConstantCond && ET &&
-        ET->getDecl()->isCompleteDefinition()) {
+    if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&
+        ET && ET->getDecl()->isCompleteDefinition()) {
       const EnumDecl *ED = ET->getDecl();
       EnumValsTy EnumVals;
 
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 1956739711..3b39539910 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6525,13 +6525,13 @@ TreeTransform::TransformCaseStmt(CaseStmt *S) {
 
     // Transform the left-hand case value.
     LHS = getDerived().TransformExpr(S->getLHS());
-    LHS = SemaRef.ActOnConstantExpression(LHS);
+    LHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), LHS);
     if (LHS.isInvalid())
       return StmtError();
 
     // Transform the right-hand case value (for the GNU case-range extension).
     RHS = getDerived().TransformExpr(S->getRHS());
-    RHS = SemaRef.ActOnConstantExpression(RHS);
+    RHS = SemaRef.ActOnCaseExpr(S->getCaseLoc(), RHS);
     if (RHS.isInvalid())
       return StmtError();
   }
diff --git a/test/Parser/switch-recovery.cpp b/test/Parser/switch-recovery.cpp
index 4b06d55ba5..a3a0178cd1 100644
--- a/test/Parser/switch-recovery.cpp
+++ b/test/Parser/switch-recovery.cpp
@@ -185,8 +185,9 @@ void pr19022_1a(int x) {
 
 void pr19022_1b(int x) {
   switch(x) {
-  case v  // expected-error{{use of undeclared identifier 'v'}}
-  }
+  case v  // expected-error{{use of undeclared identifier 'v'}} \
+          // expected-error{{expected ':' after 'case'}}
+  } // expected-error{{expected statement}}
  }
 
 void pr19022_2() {
@@ -209,7 +210,8 @@ int pr19022_4(int x) {
 
 void pr19022_5(int x) {
   switch(x) {
-  case 1: case
+  case 1: case // expected-error{{expected ':' after 'case'}} \
+               // expected-error{{expected statement}}
   }  // expected-error{{expected expression}}
 }
 
diff --git a/test/Sema/complex-int.c b/test/Sema/complex-int.c
index 2b797e5a14..52ea44dd77 100644
--- a/test/Sema/complex-int.c
+++ b/test/Sema/complex-int.c
@@ -18,6 +18,10 @@ result = arr*brr;
 result = xx*yy;
 
 switch (arr) { // expected-error{{statement requires expression of integer type ('_Complex int' invalid)}}
+  case brr: ;
+  case xx: ;
+}
+switch (ii) {
   case brr: ; // expected-error{{expression is not an integer constant expression}}
   case xx: ; // expected-error{{expression is not an integer constant expression}}
 }
diff --git a/test/Sema/switch.c b/test/Sema/switch.c
index a33300b41f..638fd99767 100644
--- a/test/Sema/switch.c
+++ b/test/Sema/switch.c
@@ -372,7 +372,7 @@ void switch_on_ExtendedEnum1(enum ExtendedEnum1 e) {
   case EE1_b: break;
   case EE1_c: break; // no-warning
   case EE1_d: break; // expected-warning {{case value not in enumerated type 'enum ExtendedEnum1'}}
-  // expected-warning@-1 {{comparison of two values with different enumeration types in switch statement ('enum ExtendedEnum1' and 'const enum ExtendedEnum1_unrelated')}}
+  // expected-warning@-1 {{comparison of two values with different enumeration types in switch statement ('enum ExtendedEnum1' and 'enum ExtendedEnum1_unrelated')}}
   }
 }
 
diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp
index 9e01ccb6b3..2bfb67ffdf 100644
--- a/test/SemaCXX/i-c-e-cxx.cpp
+++ b/test/SemaCXX/i-c-e-cxx.cpp
@@ -23,10 +23,8 @@ int a() {
   // expected-note@-2 {{read of object outside its lifetime}}
 #endif
 
-  switch(1) {
-#if __cplusplus <= 199711L
-  // expected-warning@-2 {{no case matching constant switch condition '1'}}
-#endif
+  switch(1) { // do not warn that 1 is not a case value;
+              // 't' might have been expected to evalaute to 1
     case t:; // expected-note {{initializer of 't' is not a constant expression}}
 #if __cplusplus <= 199711L
     // expected-error@-2 {{not an integral constant expression}}
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index 9e00332985..518a1e9f26 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -193,7 +193,8 @@ namespace PR10462 {
 
   bool recurse() {
     MyEnum K;
-    switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}}
+    switch (K) { // do not warn that 'something_invalid' is not listed;
+                 // 'what_am_i_thinking' might have been intended to be that case.
     case something_valid:
     case what_am_i_thinking: // expected-error {{use of undeclared identifier}}
       int *X = 0;
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index ed845c3e83..0b520e0af1 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -411,7 +411,7 @@ public:
 
 void testAccess() {
   Figure obj;
-  switch (obj.type()) {  // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
+  switch (obj.type()) {
   case SQUARE:  // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
   case TRIANGLE:  // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
   case CIRCE:  // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
-- 
GitLab


From 3f01e7fca5b998815cb437214c9cab560b5e487d Mon Sep 17 00:00:00 2001
From: Simon Marchi 
Date: Thu, 26 Jul 2018 18:55:02 +0000
Subject: [PATCH 0741/1023] [VirtualFileSystem] InMemoryFileSystem::status:
 Return a Status with the requested name

Summary:

InMemoryFileSystem::status behaves differently than
RealFileSystem::status.  The Name contained in the Status returned by
RealFileSystem::status will be the path as requested by the caller,
whereas InMemoryFileSystem::status returns the normalized path.

For example, when requested the status for "../src/first.h",
RealFileSystem returns a Status with "../src/first.h" as the Name.
InMemoryFileSystem returns "/absolute/path/to/src/first.h".

The reason for this change is that I want to make a unit test in the
clangd testsuite (where we use an InMemoryFileSystem) to reproduce a
bug I get with the clangd program (where a RealFileSystem is used).
This difference in behavior "hides" the bug in the unit test version.

Reviewers: malaperle, ilya-biryukov, bkramer

Subscribers: cfe-commits, ioeric, ilya-biryukov, bkramer, hokein, omtcyfz

Differential Revision: https://reviews.llvm.org/D48903

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338057 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/FileManager.cpp                 |  8 +--
 lib/Basic/VirtualFileSystem.cpp           | 65 ++++++++++++++++++-----
 unittests/Basic/VirtualFileSystemTest.cpp | 59 ++++++++++++++++----
 unittests/Driver/ToolChainTest.cpp        |  2 +-
 4 files changed, 106 insertions(+), 28 deletions(-)

diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 7e2d01c498..0a79800ed7 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -315,9 +315,11 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
   UFE.InPCH = Data.InPCH;
   UFE.File = std::move(F);
   UFE.IsValid = true;
-  if (UFE.File)
-    if (auto RealPathName = UFE.File->getName())
-      UFE.RealPathName = *RealPathName;
+
+  SmallString<128> RealPathName;
+  if (!FS->getRealPath(InterndFileName, RealPathName))
+    UFE.RealPathName = RealPathName.str();
+
   return &UFE;
 }
 
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index bcfcbdbb90..a7b8b024a4 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -474,12 +474,28 @@ class InMemoryNode {
   Status Stat;
   InMemoryNodeKind Kind;
 
+protected:
+  /// Return Stat.  This should only be used for internal/debugging use.  When
+  /// clients wants the Status of this node, they should use
+  /// \p getStatus(StringRef).
+  const Status &getStatus() const { return Stat; }
+
 public:
   InMemoryNode(Status Stat, InMemoryNodeKind Kind)
       : Stat(std::move(Stat)), Kind(Kind) {}
   virtual ~InMemoryNode() = default;
 
-  const Status &getStatus() const { return Stat; }
+  /// Return the \p Status for this node. \p RequestedName should be the name
+  /// through which the caller referred to this node. It will override
+  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
+  Status getStatus(StringRef RequestedName) const {
+    return Status::copyWithNewName(Stat, RequestedName);
+  }
+
+  /// Get the filename of this node (the name without the directory part).
+  StringRef getFileName() const {
+    return llvm::sys::path::filename(Stat.getName());
+  }
   InMemoryNodeKind getKind() const { return Kind; }
   virtual std::string toString(unsigned Indent) const = 0;
 };
@@ -504,14 +520,21 @@ public:
   }
 };
 
-/// Adapt a InMemoryFile for VFS' File interface.
+/// Adapt a InMemoryFile for VFS' File interface.  The goal is to make
+/// \p InMemoryFileAdaptor mimic as much as possible the behavior of
+/// \p RealFile.
 class InMemoryFileAdaptor : public File {
   InMemoryFile &Node;
+  /// The name to use when returning a Status for this file.
+  std::string RequestedName;
 
 public:
-  explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
+  explicit InMemoryFileAdaptor(InMemoryFile &Node, std::string RequestedName)
+      : Node(Node), RequestedName(std::move(RequestedName)) {}
 
-  llvm::ErrorOr status() override { return Node.getStatus(); }
+  llvm::ErrorOr status() override {
+    return Node.getStatus(RequestedName);
+  }
 
   llvm::ErrorOr>
   getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
@@ -711,7 +734,7 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
 llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path) {
   auto Node = lookupInMemoryNode(*this, Root.get(), Path);
   if (Node)
-    return (*Node)->getStatus();
+    return (*Node)->getStatus(Path.str());
   return Node.getError();
 }
 
@@ -724,7 +747,8 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) {
   // When we have a file provide a heap-allocated wrapper for the memory buffer
   // to match the ownership semantics for File.
   if (auto *F = dyn_cast(*Node))
-    return std::unique_ptr(new detail::InMemoryFileAdaptor(*F));
+    return std::unique_ptr(
+        new detail::InMemoryFileAdaptor(*F, Path.str()));
 
   // FIXME: errc::not_a_file?
   return make_error_code(llvm::errc::invalid_argument);
@@ -736,21 +760,33 @@ namespace {
 class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
   detail::InMemoryDirectory::const_iterator I;
   detail::InMemoryDirectory::const_iterator E;
+  std::string RequestedDirName;
+
+  void setCurrentEntry() {
+    if (I != E) {
+      SmallString<256> Path(RequestedDirName);
+      llvm::sys::path::append(Path, I->second->getFileName());
+      CurrentEntry = I->second->getStatus(Path);
+    } else {
+      // When we're at the end, make CurrentEntry invalid and DirIterImpl will
+      // do the rest.
+      CurrentEntry = Status();
+    }
+  }
 
 public:
   InMemoryDirIterator() = default;
 
-  explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
-      : I(Dir.begin()), E(Dir.end()) {
-    if (I != E)
-      CurrentEntry = I->second->getStatus();
+  explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir,
+                               std::string RequestedDirName)
+      : I(Dir.begin()), E(Dir.end()),
+        RequestedDirName(std::move(RequestedDirName)) {
+    setCurrentEntry();
   }
 
   std::error_code increment() override {
     ++I;
-    // When we're at the end, make CurrentEntry invalid and DirIterImpl will do
-    // the rest.
-    CurrentEntry = I != E ? I->second->getStatus() : Status();
+    setCurrentEntry();
     return {};
   }
 };
@@ -766,7 +802,8 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
   }
 
   if (auto *DirNode = dyn_cast(*Node))
-    return directory_iterator(std::make_shared(*DirNode));
+    return directory_iterator(
+        std::make_shared(*DirNode, Dir.str()));
 
   EC = make_error_code(llvm::errc::not_a_directory);
   return directory_iterator(std::make_shared());
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index c795be07ac..a9b39b5b13 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -13,6 +13,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include 
@@ -151,6 +152,13 @@ public:
     addEntry(Path, S);
   }
 };
+
+/// Replace back-slashes by front-slashes.
+std::string getPosixPath(std::string S) {
+  SmallString<128> Result;
+  llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix);
+  return Result.str();
+};
 } // end anonymous namespace
 
 TEST(VirtualFileSystemTest, StatusQueries) {
@@ -782,7 +790,9 @@ TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
 
   I = FS.dir_begin("/b", EC);
   ASSERT_FALSE(EC);
-  ASSERT_EQ("/b/c", I->getName());
+  // When on Windows, we end up with "/b\\c" as the name.  Convert to Posix
+  // path for the sake of the comparison.
+  ASSERT_EQ("/b/c", getPosixPath(I->getName()));
   I.increment(EC);
   ASSERT_FALSE(EC);
   ASSERT_EQ(vfs::directory_iterator(), I);
@@ -794,23 +804,19 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
 
   auto Stat = FS.status("/b/c");
   ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
-  ASSERT_EQ("c", Stat->getName());
+  ASSERT_EQ("/b/c", Stat->getName());
   ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
 
   Stat = FS.status("c");
   ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
 
-  auto ReplaceBackslashes = [](std::string S) {
-    std::replace(S.begin(), S.end(), '\\', '/');
-    return S;
-  };
   NormalizedFS.setCurrentWorkingDirectory("/b/c");
   NormalizedFS.setCurrentWorkingDirectory(".");
-  ASSERT_EQ("/b/c", ReplaceBackslashes(
-                        NormalizedFS.getCurrentWorkingDirectory().get()));
+  ASSERT_EQ("/b/c",
+            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
   NormalizedFS.setCurrentWorkingDirectory("..");
-  ASSERT_EQ("/b", ReplaceBackslashes(
-                      NormalizedFS.getCurrentWorkingDirectory().get()));
+  ASSERT_EQ("/b",
+            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
 }
 
 #if !defined(_WIN32)
@@ -919,6 +925,39 @@ TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) {
   ASSERT_TRUE(Stat->isRegularFile());
 }
 
+// Test that the name returned by status() is in the same form as the path that
+// was requested (to match the behavior of RealFileSystem).
+TEST_F(InMemoryFileSystemTest, StatusName) {
+  NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"),
+                       /*User=*/None,
+                       /*Group=*/None, sys::fs::file_type::regular_file);
+  NormalizedFS.setCurrentWorkingDirectory("/a/b");
+
+  // Access using InMemoryFileSystem::status.
+  auto Stat = NormalizedFS.status("../b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
+                                << NormalizedFS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ("../b/c", Stat->getName());
+
+  // Access using InMemoryFileAdaptor::status.
+  auto File = NormalizedFS.openFileForRead("../b/c");
+  ASSERT_FALSE(File.getError()) << File.getError() << "\n"
+                                << NormalizedFS.toString();
+  Stat = (*File)->status();
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
+                                << NormalizedFS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ("../b/c", Stat->getName());
+
+  // Access using a directory iterator.
+  std::error_code EC;
+  clang::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC);
+  // When on Windows, we end up with "../b\\c" as the name.  Convert to Posix
+  // path for the sake of the comparison.
+  ASSERT_EQ("../b/c", getPosixPath(It->getName()));
+}
+
 // NOTE: in the tests below, we use '//root/' as our root directory, since it is
 // a legal *absolute* path on Windows as well as *nix.
 class VFSFromYAMLTest : public ::testing::Test {
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
index d4198eaeb1..0d4c545bd7 100644
--- a/unittests/Driver/ToolChainTest.cpp
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -113,7 +113,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
   std::replace(S.begin(), S.end(), '\\', '/');
 #endif
   EXPECT_EQ("Found candidate GCC installation: "
-            "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n"
+            "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
             "Selected GCC installation: "
             "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
             "Candidate multilib: .;@m32\n"
-- 
GitLab


From 7d295a322620d385499f7f704a3117e28a2d8fcd Mon Sep 17 00:00:00 2001
From: Sanjin Sijaric 
Date: Thu, 26 Jul 2018 22:18:28 +0000
Subject: [PATCH 0742/1023] [ARM64] [Windows] Follow MS X86_64 C++ ABI when
 passing structs

Summary: Microsoft's C++ object model for ARM64 is the same as that for X86_64.
For example, small structs with non-trivial copy constructors or virtual
function tables are passed indirectly.  Currently, they are passed in registers
when compiled with clang.

Reviewers: rnk, mstorsjo, TomTan, haripul, javed.absar

Reviewed By: rnk, mstorsjo

Subscribers: kristof.beyls, chrib, llvm-commits, cfe-commits

Differential Revision: https://reviews.llvm.org/D49770

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338076 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/TargetInfo.h                 | 2 +-
 lib/Basic/Targets/AArch64.cpp                    | 5 +++++
 lib/Basic/Targets/AArch64.h                      | 2 ++
 lib/Basic/Targets/X86.h                          | 2 +-
 lib/CodeGen/MicrosoftCXXABI.cpp                  | 1 +
 lib/Sema/SemaDeclCXX.cpp                         | 2 +-
 test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp | 6 ++++++
 7 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index ee97f2b8f6..ec5c59b239 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -1223,7 +1223,7 @@ public:
   enum CallingConvKind {
     CCK_Default,
     CCK_ClangABI4OrPS4,
-    CCK_MicrosoftX86_64
+    CCK_MicrosoftWin64
   };
 
   virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;
diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index 1665a21435..3444591ac5 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -533,6 +533,11 @@ void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
   getVisualStudioDefines(Opts, Builder);
 }
 
+TargetInfo::CallingConvKind
+MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
+  return CCK_MicrosoftWin64;
+}
+
 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
                                            const TargetOptions &Opts)
     : WindowsARM64TargetInfo(Triple, Opts) {
diff --git a/lib/Basic/Targets/AArch64.h b/lib/Basic/Targets/AArch64.h
index f493ff28d3..a9df895e4d 100644
--- a/lib/Basic/Targets/AArch64.h
+++ b/lib/Basic/Targets/AArch64.h
@@ -126,6 +126,8 @@ public:
                               MacroBuilder &Builder) const;
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
+  TargetInfo::CallingConvKind
+  getCallingConvKind(bool ClangABICompat4) const override;
 };
 
 // ARM64 MinGW target
diff --git a/lib/Basic/Targets/X86.h b/lib/Basic/Targets/X86.h
index dd04dee087..b6cb27977b 100644
--- a/lib/Basic/Targets/X86.h
+++ b/lib/Basic/Targets/X86.h
@@ -752,7 +752,7 @@ public:
 
   TargetInfo::CallingConvKind
   getCallingConvKind(bool ClangABICompat4) const override {
-    return CCK_MicrosoftX86_64;
+    return CCK_MicrosoftWin64;
   }
 };
 
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index a1122dc80a..81ed050595 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -827,6 +827,7 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
     return RAA_Default;
 
   case llvm::Triple::x86_64:
+  case llvm::Triple::aarch64:
     return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default;
   }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 031f8dbb38..4cf3abdf57 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5831,7 +5831,7 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
     return !D->hasNonTrivialDestructorForCall() &&
            !D->hasNonTrivialCopyConstructorForCall();
 
-  if (CCK == TargetInfo::CCK_MicrosoftX86_64) {
+  if (CCK == TargetInfo::CCK_MicrosoftWin64) {
     bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
     bool DtorIsTrivialForCall = false;
 
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index 36c9ca40db..a910a2d7f7 100644
--- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -2,6 +2,7 @@
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 %s
 
 struct Empty {};
 
@@ -163,6 +164,9 @@ void small_arg_with_dtor(SmallWithDtor s) {}
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: }
 
 // FIXME: MSVC incompatible!
 // WOA: define dso_local arm_aapcs_vfpcc void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
@@ -227,12 +231,14 @@ void small_arg_with_vftable(SmallWithVftable s) {}
 // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
 // WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
 // WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
+// WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
 
 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
 // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
 // WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
 // WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
 // WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
+// WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
 
 void big_arg(Big s) {}
 // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
-- 
GitLab


From 034aa09eac02832e77c7dc4fc638e53cf0f8aed3 Mon Sep 17 00:00:00 2001
From: Emmett Neyman 
Date: Thu, 26 Jul 2018 22:23:25 +0000
Subject: [PATCH 0743/1023] Updated llvm-proto-fuzzer to execute the compiled
 code

Summary:
Made changes to the llvm-proto-fuzzer
- Added loop vectorizer optimization pass in order to have two IR versions
- Updated old fuzz target to handle two different IR versions
- Wrote code to execute both versions in memory

Reviewers: morehouse, kcc, alexshap

Reviewed By: morehouse

Subscribers: pcc, mgorny, cfe-commits, llvm-commits

Differential Revision: https://reviews.llvm.org/D49526

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338077 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../fuzzer-initialize/fuzzer_initialize.cpp   |  23 ++-
 tools/clang-fuzzer/handle-llvm/CMakeLists.txt |  12 +-
 .../clang-fuzzer/handle-llvm/handle_llvm.cpp  | 171 ++++++++++++------
 3 files changed, 148 insertions(+), 58 deletions(-)

diff --git a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp
index e0131ed892..75bf22803b 100644
--- a/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp
+++ b/tools/clang-fuzzer/fuzzer-initialize/fuzzer_initialize.cpp
@@ -16,10 +16,13 @@
 
 #include "fuzzer_initialize.h"
 
+#include "llvm/InitializePasses.h"
+#include "llvm/PassRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include 
 
 using namespace clang_fuzzer;
+using namespace llvm;
 
 
 namespace clang_fuzzer {
@@ -33,10 +36,22 @@ const std::vector& GetCLArgs() {
 }
 
 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
-  llvm::InitializeAllTargets();
-  llvm::InitializeAllTargetMCs();
-  llvm::InitializeAllAsmPrinters();
-  llvm::InitializeAllAsmParsers();
+  InitializeAllTargets();
+  InitializeAllTargetMCs();
+  InitializeAllAsmPrinters();
+  InitializeAllAsmParsers();
+  
+  PassRegistry &Registry = *PassRegistry::getPassRegistry();
+  initializeCore(Registry);
+  initializeScalarOpts(Registry);
+  initializeVectorization(Registry);
+  initializeIPO(Registry);
+  initializeAnalysis(Registry);
+  initializeTransformUtils(Registry);
+  initializeInstCombine(Registry);
+  initializeAggressiveInstCombine(Registry);
+  initializeInstrumentation(Registry);
+  initializeTarget(Registry);
 
   CLArgs.push_back("-O2");
   for (int I = 1; I < *argc; I++) {
diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
index 27640a0bf5..9e275239ec 100644
--- a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
+++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt
@@ -1,10 +1,18 @@
 set(LLVM_LINK_COMPONENTS
+  CodeGen
   Core
+  ExecutionEngine
   IRReader
   MC
+  MCJIT
+  Object
+  RuntimeDyld
+  SelectionDAG
   Support
-  Analysis
-  )
+  Target
+  TransformUtils
+  native
+)
 
 # Depend on LLVM IR intrinsic generation.
 set(handle_llvm_deps intrinsics_gen)
diff --git a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
index 9dc895295f..ef544ae711 100644
--- a/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
+++ b/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -7,8 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// Implements HandleLLVM for use by the Clang fuzzers. Mimics the llc tool to
-// compile an LLVM IR file to X86_64 assembly.
+// Implements HandleLLVM for use by the Clang fuzzers. First runs a loop
+// vectorizer optimization pass over the given IR code. Then mimics lli on both
+// versions to JIT the generated code and execute it. Currently, functions are 
+// executed on dummy inputs.
 //
 //===----------------------------------------------------------------------===//
 
@@ -16,24 +18,37 @@
 
 #include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/CommandFlags.inc"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/LegacyPassNameParser.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IRReader/IRReader.h"
+#include "llvm/Pass.h"
 #include "llvm/PassRegistry.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
-
-#include 
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Vectorize.h"
 
 using namespace llvm;
 
+// Helper function to parse command line args and find the optimization level
 static void getOptLevel(const std::vector &ExtraArgs,
                               CodeGenOpt::Level &OLvl) {
   // Find the optimization level from the command line args
@@ -53,59 +68,111 @@ static void getOptLevel(const std::vector &ExtraArgs,
   }
 }
 
-void clang_fuzzer::HandleLLVM(const std::string &S,
-                              const std::vector &ExtraArgs) {
-  // Parse ExtraArgs to set the optimization level
-  CodeGenOpt::Level OLvl;
-  getOptLevel(ExtraArgs, OLvl);
+void ErrorAndExit(std::string message) {
+  errs()<< "ERROR: " << message << "\n";
+  std::exit(1);
+}
 
-  // Set the Module to include the the IR code to be compiled
-  SMDiagnostic Err;
+// Helper function to add optimization passes to the TargetMachine at the 
+// specified optimization level, OptLevel
+static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
+                                  CodeGenOpt::Level OptLevel,
+                                  unsigned SizeLevel) {
+  // Create and initialize a PassManagerBuilder
+  PassManagerBuilder Builder;
+  Builder.OptLevel = OptLevel;
+  Builder.SizeLevel = SizeLevel;
+  Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
+  Builder.LoopVectorize = true;
+  Builder.populateModulePassManager(MPM);
+}
 
+// Mimics the opt tool to run an optimization pass over the provided IR
+std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
+  // Create a module that will run the optimization passes
+  SMDiagnostic Err;
   LLVMContext Context;
-  std::unique_ptr M = parseIR(MemoryBufferRef(S, "IR"), Err, Context);
-  if (!M) {
-    errs() << "error: could not parse IR!\n";
-    std::exit(1);
-  }
+  std::unique_ptr M = parseIR(MemoryBufferRef(IR, "IR"), Err, Context);
+  if (!M || verifyModule(*M, &errs()))
+    ErrorAndExit("Could not parse IR");
 
-  // Create a new Target
-  std::string Error;
-  const Target *TheTarget = TargetRegistry::lookupTarget(
-      sys::getDefaultTargetTriple(), Error);
-  if (!TheTarget) {
-    errs() << Error;
-    std::exit(1);
-  }
+  setFunctionAttributes(getCPUStr(), getFeaturesStr(), *M);
+  
+  legacy::PassManager Passes;
+  Triple ModuleTriple(M->getTargetTriple());
+  
+  Passes.add(new TargetLibraryInfoWrapperPass(ModuleTriple));
+  Passes.add(createTargetTransformInfoWrapperPass(TargetIRAnalysis()));
+  Passes.add(createVerifierPass());
 
-  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
-
-  // Create a new Machine
-  std::string CPUStr = getCPUStr();
-  std::string FeaturesStr = getFeaturesStr();
-  std::unique_ptr Target(TheTarget->createTargetMachine(
-      sys::getDefaultTargetTriple(), CPUStr, FeaturesStr, Options,
-      getRelocModel(), getCodeModel(), OLvl));
-
-  // Create a new PassManager
-  legacy::PassManager PM;
-  TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
-  PM.add(new TargetLibraryInfoWrapperPass(TLII));
-  M->setDataLayout(Target->createDataLayout());
- 
-  // Make sure the Module has no errors
-  if (verifyModule(*M, &errs())) {
-    errs() << "error: input module is broken!\n";
-    std::exit(1);
-  } 
-
-  setFunctionAttributes(CPUStr, FeaturesStr, *M);
+  AddOptimizationPasses(Passes, OLvl, 0);
   
-  raw_null_ostream OS;
-  Target->addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_ObjectFile,
-                              false);
-  PM.run(*M);
+  // Add a pass that writes the optimized IR to an output stream
+  std::string outString;
+  raw_string_ostream OS(outString);
+  Passes.add(createPrintModulePass(OS, "", false));
 
-  return;
+  Passes.run(*M);
+
+  return OS.str();
 }
 
+void CreateAndRunJITFun(const std::string &IR, CodeGenOpt::Level OLvl) {
+  SMDiagnostic Err;
+  LLVMContext Context;
+  std::unique_ptr M = parseIR(MemoryBufferRef(IR, "IR"), Err,
+                                          Context);
+  if (!M)
+    ErrorAndExit("Could not parse IR");
+
+  Function *EntryFunc = M->getFunction("foo");
+  if (!EntryFunc)
+    ErrorAndExit("Function not found in module");
+
+  std::string ErrorMsg;
+  EngineBuilder builder(std::move(M));
+  builder.setMArch(MArch);
+  builder.setMCPU(getCPUStr());
+  builder.setMAttrs(getFeatureList());
+  builder.setErrorStr(&ErrorMsg);
+  builder.setEngineKind(EngineKind::JIT);
+  builder.setUseOrcMCJITReplacement(false);
+  builder.setMCJITMemoryManager(make_unique());
+  builder.setOptLevel(OLvl);
+  builder.setTargetOptions(InitTargetOptionsFromCodeGenFlags());
+
+  std::unique_ptr EE(builder.create());
+  if (!EE)
+    ErrorAndExit("Could not create execution engine");
+
+  EE->finalizeObject();
+  EE->runStaticConstructorsDestructors(false);
+
+  typedef void (*func)(int*, int*, int*, int);
+  func f = reinterpret_cast(EE->getPointerToFunction(EntryFunc)); 
+
+  // Define some dummy arrays to use an input for now
+  int a[] = {1};
+  int b[] = {1};
+  int c[] = {1};
+  f(a, b, c, 1);
+
+  EE->runStaticConstructorsDestructors(true);
+}
+
+// Main fuzz target called by ExampleClangLLVMProtoFuzzer.cpp
+// Mimics the lli tool to JIT the LLVM IR code and execute it
+void clang_fuzzer::HandleLLVM(const std::string &IR,
+                              const std::vector &ExtraArgs) {
+  // Parse ExtraArgs to set the optimization level
+  CodeGenOpt::Level OLvl;
+  getOptLevel(ExtraArgs, OLvl);
+
+  // First we optimize the IR by running a loop vectorizer pass
+  std::string OptIR = OptLLVM(IR, OLvl);
+
+  CreateAndRunJITFun(OptIR, OLvl);
+  CreateAndRunJITFun(IR, CodeGenOpt::None);
+  
+  return;
+}
-- 
GitLab


From 3eabc0d428ed870967574f5cca3771d2beb14777 Mon Sep 17 00:00:00 2001
From: Reid Kleckner 
Date: Thu, 26 Jul 2018 23:18:44 +0000
Subject: [PATCH 0744/1023] [MS] Add L__FUNCSIG__ for compatibility

Clang already has L__FUNCTION__ as a workaround for dealing with
pre-processor code that expects to be able to do L##__FUNCTION__ in a
macro. This patch implements the same logic for __FUNCSIG__.

Fixes PR38295.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338083 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/Expr.h              |  3 ++-
 include/clang/Basic/TokenKinds.def    |  1 +
 lib/AST/Expr.cpp                      | 10 +++++++---
 lib/Parse/ParseExpr.cpp               |  3 +++
 lib/Parse/ParseTentative.cpp          |  1 +
 lib/Sema/SemaExpr.cpp                 |  5 +++--
 test/Sema/ms_wide_predefined_expr.cpp |  2 ++
 7 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index a4c4769c1a..ca5bd95160 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1206,9 +1206,10 @@ public:
   enum IdentType {
     Func,
     Function,
-    LFunction,  // Same as Function, but as wide string.
+    LFunction, // Same as Function, but as wide string.
     FuncDName,
     FuncSig,
+    LFuncSig, // Same as FuncSig, but as as wide string
     PrettyFunction,
     /// The same as PrettyFunction, except that the
     /// 'virtual' keyword is omitted for virtual member functions.
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 7f363dbcc1..30cb022f1c 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -425,6 +425,7 @@ KEYWORD(typeof                      , KEYGNU)
 KEYWORD(__FUNCDNAME__               , KEYMS)
 KEYWORD(__FUNCSIG__                 , KEYMS)
 KEYWORD(L__FUNCTION__               , KEYMS)
+KEYWORD(L__FUNCSIG__                , KEYMS)
 TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
 TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
 
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 7e652b778b..193efa4e09 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -484,6 +484,8 @@ StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
     return "__PRETTY_FUNCTION__";
   case FuncSig:
     return "__FUNCSIG__";
+  case LFuncSig:
+    return "L__FUNCSIG__";
   case PrettyFunctionNoVirtual:
     break;
   }
@@ -536,7 +538,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
     return Out.str();
   }
   if (const FunctionDecl *FD = dyn_cast(CurrentDecl)) {
-    if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
+    if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual &&
+        IT != FuncSig && IT != LFuncSig)
       return FD->getNameAsString();
 
     SmallString<256> Name;
@@ -561,7 +564,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
     if (FD->hasWrittenPrototype())
       FT = dyn_cast(AFT);
 
-    if (IT == FuncSig) {
+    if (IT == FuncSig || IT == LFuncSig) {
       switch (AFT->getCallConv()) {
       case CC_C: POut << "__cdecl "; break;
       case CC_X86StdCall: POut << "__stdcall "; break;
@@ -586,7 +589,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
       if (FT->isVariadic()) {
         if (FD->getNumParams()) POut << ", ";
         POut << "...";
-      } else if ((IT == FuncSig || !Context.getLangOpts().CPlusPlus) &&
+      } else if ((IT == FuncSig || IT == LFuncSig ||
+                  !Context.getLangOpts().CPlusPlus) &&
                  !Decl->getNumParams()) {
         POut << "void";
       }
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 6904906403..4a0e1c5e34 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -617,6 +617,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
 /// [GNU]   '__FUNCTION__'
 /// [MS]    '__FUNCDNAME__'
 /// [MS]    'L__FUNCTION__'
+/// [MS]    '__FUNCSIG__'
+/// [MS]    'L__FUNCSIG__'
 /// [GNU]   '__PRETTY_FUNCTION__'
 /// [GNU]   '(' compound-statement ')'
 /// [GNU]   '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
@@ -1061,6 +1063,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   case tok::kw___FUNCDNAME__:   // primary-expression: __FUNCDNAME__ [MS]
   case tok::kw___FUNCSIG__:     // primary-expression: __FUNCSIG__ [MS]
   case tok::kw_L__FUNCTION__:   // primary-expression: L__FUNCTION__ [MS]
+  case tok::kw_L__FUNCSIG__:    // primary-expression: L__FUNCSIG__ [MS]
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
     Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
     ConsumeToken();
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 79860545c2..0603d8e75e 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -1019,6 +1019,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
   case tok::kw___FUNCDNAME__:
   case tok::kw___FUNCSIG__:
   case tok::kw_L__FUNCTION__:
+  case tok::kw_L__FUNCSIG__:
   case tok::kw___PRETTY_FUNCTION__:
   case tok::kw___uuidof:
 #define TYPE_TRAIT(N,Spelling,K) \
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a72f6c3796..effaa888f0 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3054,7 +3054,7 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
     unsigned Length = Str.length();
 
     llvm::APInt LengthI(32, Length + 1);
-    if (IT == PredefinedExpr::LFunction) {
+    if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) {
       ResTy =
           Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
       SmallString<32> RawChars;
@@ -3085,7 +3085,8 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
   case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
   case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
   case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
-  case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
+  case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS]
+  case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS]
   case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
   }
 
diff --git a/test/Sema/ms_wide_predefined_expr.cpp b/test/Sema/ms_wide_predefined_expr.cpp
index d56d1576cd..eb6efa5cdb 100644
--- a/test/Sema/ms_wide_predefined_expr.cpp
+++ b/test/Sema/ms_wide_predefined_expr.cpp
@@ -7,6 +7,8 @@
 void abcdefghi12(void) {
  const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
  static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
+ const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
+ static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
 }
 
 namespace PR13206 {
-- 
GitLab


From 40a54a7b6f9cd658e4cef7739b794f9025ab98ca Mon Sep 17 00:00:00 2001
From: Reid Kleckner 
Date: Thu, 26 Jul 2018 23:21:51 +0000
Subject: [PATCH 0745/1023] Revert r338057 "[VirtualFileSystem]
 InMemoryFileSystem::status: Return a Status with the requested name"

This broke clang/test/PCH/case-insensitive-include.c on Windows.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338084 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Basic/FileManager.cpp                 |  8 ++-
 lib/Basic/VirtualFileSystem.cpp           | 65 +++++------------------
 unittests/Basic/VirtualFileSystemTest.cpp | 59 ++++----------------
 unittests/Driver/ToolChainTest.cpp        |  2 +-
 4 files changed, 28 insertions(+), 106 deletions(-)

diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 0a79800ed7..7e2d01c498 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -315,11 +315,9 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
   UFE.InPCH = Data.InPCH;
   UFE.File = std::move(F);
   UFE.IsValid = true;
-
-  SmallString<128> RealPathName;
-  if (!FS->getRealPath(InterndFileName, RealPathName))
-    UFE.RealPathName = RealPathName.str();
-
+  if (UFE.File)
+    if (auto RealPathName = UFE.File->getName())
+      UFE.RealPathName = *RealPathName;
   return &UFE;
 }
 
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index a7b8b024a4..bcfcbdbb90 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -474,28 +474,12 @@ class InMemoryNode {
   Status Stat;
   InMemoryNodeKind Kind;
 
-protected:
-  /// Return Stat.  This should only be used for internal/debugging use.  When
-  /// clients wants the Status of this node, they should use
-  /// \p getStatus(StringRef).
-  const Status &getStatus() const { return Stat; }
-
 public:
   InMemoryNode(Status Stat, InMemoryNodeKind Kind)
       : Stat(std::move(Stat)), Kind(Kind) {}
   virtual ~InMemoryNode() = default;
 
-  /// Return the \p Status for this node. \p RequestedName should be the name
-  /// through which the caller referred to this node. It will override
-  /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
-  Status getStatus(StringRef RequestedName) const {
-    return Status::copyWithNewName(Stat, RequestedName);
-  }
-
-  /// Get the filename of this node (the name without the directory part).
-  StringRef getFileName() const {
-    return llvm::sys::path::filename(Stat.getName());
-  }
+  const Status &getStatus() const { return Stat; }
   InMemoryNodeKind getKind() const { return Kind; }
   virtual std::string toString(unsigned Indent) const = 0;
 };
@@ -520,21 +504,14 @@ public:
   }
 };
 
-/// Adapt a InMemoryFile for VFS' File interface.  The goal is to make
-/// \p InMemoryFileAdaptor mimic as much as possible the behavior of
-/// \p RealFile.
+/// Adapt a InMemoryFile for VFS' File interface.
 class InMemoryFileAdaptor : public File {
   InMemoryFile &Node;
-  /// The name to use when returning a Status for this file.
-  std::string RequestedName;
 
 public:
-  explicit InMemoryFileAdaptor(InMemoryFile &Node, std::string RequestedName)
-      : Node(Node), RequestedName(std::move(RequestedName)) {}
+  explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
 
-  llvm::ErrorOr status() override {
-    return Node.getStatus(RequestedName);
-  }
+  llvm::ErrorOr status() override { return Node.getStatus(); }
 
   llvm::ErrorOr>
   getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
@@ -734,7 +711,7 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
 llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path) {
   auto Node = lookupInMemoryNode(*this, Root.get(), Path);
   if (Node)
-    return (*Node)->getStatus(Path.str());
+    return (*Node)->getStatus();
   return Node.getError();
 }
 
@@ -747,8 +724,7 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) {
   // When we have a file provide a heap-allocated wrapper for the memory buffer
   // to match the ownership semantics for File.
   if (auto *F = dyn_cast(*Node))
-    return std::unique_ptr(
-        new detail::InMemoryFileAdaptor(*F, Path.str()));
+    return std::unique_ptr(new detail::InMemoryFileAdaptor(*F));
 
   // FIXME: errc::not_a_file?
   return make_error_code(llvm::errc::invalid_argument);
@@ -760,33 +736,21 @@ namespace {
 class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
   detail::InMemoryDirectory::const_iterator I;
   detail::InMemoryDirectory::const_iterator E;
-  std::string RequestedDirName;
-
-  void setCurrentEntry() {
-    if (I != E) {
-      SmallString<256> Path(RequestedDirName);
-      llvm::sys::path::append(Path, I->second->getFileName());
-      CurrentEntry = I->second->getStatus(Path);
-    } else {
-      // When we're at the end, make CurrentEntry invalid and DirIterImpl will
-      // do the rest.
-      CurrentEntry = Status();
-    }
-  }
 
 public:
   InMemoryDirIterator() = default;
 
-  explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir,
-                               std::string RequestedDirName)
-      : I(Dir.begin()), E(Dir.end()),
-        RequestedDirName(std::move(RequestedDirName)) {
-    setCurrentEntry();
+  explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
+      : I(Dir.begin()), E(Dir.end()) {
+    if (I != E)
+      CurrentEntry = I->second->getStatus();
   }
 
   std::error_code increment() override {
     ++I;
-    setCurrentEntry();
+    // When we're at the end, make CurrentEntry invalid and DirIterImpl will do
+    // the rest.
+    CurrentEntry = I != E ? I->second->getStatus() : Status();
     return {};
   }
 };
@@ -802,8 +766,7 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
   }
 
   if (auto *DirNode = dyn_cast(*Node))
-    return directory_iterator(
-        std::make_shared(*DirNode, Dir.str()));
+    return directory_iterator(std::make_shared(*DirNode));
 
   EC = make_error_code(llvm::errc::not_a_directory);
   return directory_iterator(std::make_shared());
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index a9b39b5b13..c795be07ac 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -13,7 +13,6 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include 
@@ -152,13 +151,6 @@ public:
     addEntry(Path, S);
   }
 };
-
-/// Replace back-slashes by front-slashes.
-std::string getPosixPath(std::string S) {
-  SmallString<128> Result;
-  llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix);
-  return Result.str();
-};
 } // end anonymous namespace
 
 TEST(VirtualFileSystemTest, StatusQueries) {
@@ -790,9 +782,7 @@ TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
 
   I = FS.dir_begin("/b", EC);
   ASSERT_FALSE(EC);
-  // When on Windows, we end up with "/b\\c" as the name.  Convert to Posix
-  // path for the sake of the comparison.
-  ASSERT_EQ("/b/c", getPosixPath(I->getName()));
+  ASSERT_EQ("/b/c", I->getName());
   I.increment(EC);
   ASSERT_FALSE(EC);
   ASSERT_EQ(vfs::directory_iterator(), I);
@@ -804,19 +794,23 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
 
   auto Stat = FS.status("/b/c");
   ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
-  ASSERT_EQ("/b/c", Stat->getName());
+  ASSERT_EQ("c", Stat->getName());
   ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
 
   Stat = FS.status("c");
   ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
 
+  auto ReplaceBackslashes = [](std::string S) {
+    std::replace(S.begin(), S.end(), '\\', '/');
+    return S;
+  };
   NormalizedFS.setCurrentWorkingDirectory("/b/c");
   NormalizedFS.setCurrentWorkingDirectory(".");
-  ASSERT_EQ("/b/c",
-            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
+  ASSERT_EQ("/b/c", ReplaceBackslashes(
+                        NormalizedFS.getCurrentWorkingDirectory().get()));
   NormalizedFS.setCurrentWorkingDirectory("..");
-  ASSERT_EQ("/b",
-            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
+  ASSERT_EQ("/b", ReplaceBackslashes(
+                      NormalizedFS.getCurrentWorkingDirectory().get()));
 }
 
 #if !defined(_WIN32)
@@ -925,39 +919,6 @@ TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) {
   ASSERT_TRUE(Stat->isRegularFile());
 }
 
-// Test that the name returned by status() is in the same form as the path that
-// was requested (to match the behavior of RealFileSystem).
-TEST_F(InMemoryFileSystemTest, StatusName) {
-  NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"),
-                       /*User=*/None,
-                       /*Group=*/None, sys::fs::file_type::regular_file);
-  NormalizedFS.setCurrentWorkingDirectory("/a/b");
-
-  // Access using InMemoryFileSystem::status.
-  auto Stat = NormalizedFS.status("../b/c");
-  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
-                                << NormalizedFS.toString();
-  ASSERT_TRUE(Stat->isRegularFile());
-  ASSERT_EQ("../b/c", Stat->getName());
-
-  // Access using InMemoryFileAdaptor::status.
-  auto File = NormalizedFS.openFileForRead("../b/c");
-  ASSERT_FALSE(File.getError()) << File.getError() << "\n"
-                                << NormalizedFS.toString();
-  Stat = (*File)->status();
-  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
-                                << NormalizedFS.toString();
-  ASSERT_TRUE(Stat->isRegularFile());
-  ASSERT_EQ("../b/c", Stat->getName());
-
-  // Access using a directory iterator.
-  std::error_code EC;
-  clang::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC);
-  // When on Windows, we end up with "../b\\c" as the name.  Convert to Posix
-  // path for the sake of the comparison.
-  ASSERT_EQ("../b/c", getPosixPath(It->getName()));
-}
-
 // NOTE: in the tests below, we use '//root/' as our root directory, since it is
 // a legal *absolute* path on Windows as well as *nix.
 class VFSFromYAMLTest : public ::testing::Test {
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
index 0d4c545bd7..d4198eaeb1 100644
--- a/unittests/Driver/ToolChainTest.cpp
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -113,7 +113,7 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
   std::replace(S.begin(), S.end(), '\\', '/');
 #endif
   EXPECT_EQ("Found candidate GCC installation: "
-            "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
+            "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n"
             "Selected GCC installation: "
             "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
             "Candidate multilib: .;@m32\n"
-- 
GitLab


From 8c7d7e685c53a8a55e82a258730b78bd22a30796 Mon Sep 17 00:00:00 2001
From: Mike Edwards 
Date: Thu, 26 Jul 2018 23:23:40 +0000
Subject: [PATCH 0746/1023] [WWW] Adding a test page to work out an
 auto-deployment issue.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338086 91177308-0d34-0410-b5e6-96231b3b80d8
---
 www/test.html | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 www/test.html

diff --git a/www/test.html b/www/test.html
new file mode 100644
index 0000000000..6c3ae992cf
--- /dev/null
+++ b/www/test.html
@@ -0,0 +1,6 @@
+
+    
+    
+        

Hello World!

+ + -- GitLab From 7b285ea85323013041d0c3e0121616b067001752 Mon Sep 17 00:00:00 2001 From: Mike Edwards Date: Thu, 26 Jul 2018 23:29:54 +0000 Subject: [PATCH 0747/1023] [WWW] Removing my test file as the auto-deployment script has been fixed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338087 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/test.html | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 www/test.html diff --git a/www/test.html b/www/test.html deleted file mode 100644 index 6c3ae992cf..0000000000 --- a/www/test.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -

Hello World!

- - -- GitLab From 89502c6873c1be53cb183cf57d41a65b74a6bbe6 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Thu, 26 Jul 2018 23:40:42 +0000 Subject: [PATCH 0748/1023] [Sema] Fix a crash by completing a type before using it Only apply this exception on a type that we're able to check. rdar://41903969 Differential revision: https://reviews.llvm.org/D49868 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338089 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 1 + ...xx1z-class-template-argument-deduction.cpp | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 9b5a918b71..0dddbdc36f 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -9130,6 +9130,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( Expr *E = ListInit->getInit(0); auto *RD = E->getType()->getAsCXXRecordDecl(); if (!isa(E) && RD && + isCompleteType(Kind.getLocation(), E->getType()) && isOrIsDerivedFromSpecializationOf(RD, Template)) TryListConstructors = false; } diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index de61e44a6e..f72cb886d8 100644 --- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -348,6 +348,31 @@ namespace member_guides { }; } +namespace rdar41903969 { +template struct A {}; +template struct B; +template struct C { + C(A&); + C(B&); +}; + +void foo(A &a, B &b) { + (void)C{b}; + (void)C{a}; +} + +template struct X { + X(std::initializer_list) = delete; + X(const X&); +}; + +template struct D : X {}; + +void bar(D& d) { + (void)X{d}; +} +} + #else // expected-no-diagnostics -- GitLab From 250e823036b44345438a3538b7f51e86a16a0117 Mon Sep 17 00:00:00 2001 From: Emmett Neyman Date: Fri, 27 Jul 2018 00:43:26 +0000 Subject: [PATCH 0749/1023] added shared library to fix buildbot Summary: added shared library to fix buildbot Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D49895 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338091 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-fuzzer/handle-llvm/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt index 9e275239ec..47f9fdf68f 100644 --- a/tools/clang-fuzzer/handle-llvm/CMakeLists.txt +++ b/tools/clang-fuzzer/handle-llvm/CMakeLists.txt @@ -1,7 +1,9 @@ set(LLVM_LINK_COMPONENTS + Analysis CodeGen Core ExecutionEngine + IPO IRReader MC MCJIT -- GitLab From 76de414d4346a0c564e0796b90b6520cadce1793 Mon Sep 17 00:00:00 2001 From: Mike Edwards Date: Fri, 27 Jul 2018 04:41:37 +0000 Subject: [PATCH 0750/1023] [WWW] Fixing file permissions for the .html pages. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338098 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/OpenProjects.html | 0 www/UniversalDriver.html | 0 www/clang_video-05-25-2007.html | 0 www/clang_video-07-25-2007.html | 0 www/comparison.html | 0 www/compatibility.html | 0 www/cxx_compatibility.html | 0 www/cxx_dr_status.html | 0 www/cxx_status.html | 0 www/diagnostics.html | 0 www/features.html | 0 www/get_involved.html | 0 www/get_started.html | 0 www/hacking.html | 0 www/index.html | 0 www/related.html | 0 16 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 www/OpenProjects.html mode change 100644 => 100755 www/UniversalDriver.html mode change 100644 => 100755 www/clang_video-05-25-2007.html mode change 100644 => 100755 www/clang_video-07-25-2007.html mode change 100644 => 100755 www/comparison.html mode change 100644 => 100755 www/compatibility.html mode change 100644 => 100755 www/cxx_compatibility.html mode change 100644 => 100755 www/cxx_dr_status.html mode change 100644 => 100755 www/cxx_status.html mode change 100644 => 100755 www/diagnostics.html mode change 100644 => 100755 www/features.html mode change 100644 => 100755 www/get_involved.html mode change 100644 => 100755 www/get_started.html mode change 100644 => 100755 www/hacking.html mode change 100644 => 100755 www/index.html mode change 100644 => 100755 www/related.html diff --git a/www/OpenProjects.html b/www/OpenProjects.html old mode 100644 new mode 100755 diff --git a/www/UniversalDriver.html b/www/UniversalDriver.html old mode 100644 new mode 100755 diff --git a/www/clang_video-05-25-2007.html b/www/clang_video-05-25-2007.html old mode 100644 new mode 100755 diff --git a/www/clang_video-07-25-2007.html b/www/clang_video-07-25-2007.html old mode 100644 new mode 100755 diff --git a/www/comparison.html b/www/comparison.html old mode 100644 new mode 100755 diff --git a/www/compatibility.html b/www/compatibility.html old mode 100644 new mode 100755 diff --git a/www/cxx_compatibility.html b/www/cxx_compatibility.html old mode 100644 new mode 100755 diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html old mode 100644 new mode 100755 diff --git a/www/cxx_status.html b/www/cxx_status.html old mode 100644 new mode 100755 diff --git a/www/diagnostics.html b/www/diagnostics.html old mode 100644 new mode 100755 diff --git a/www/features.html b/www/features.html old mode 100644 new mode 100755 diff --git a/www/get_involved.html b/www/get_involved.html old mode 100644 new mode 100755 diff --git a/www/get_started.html b/www/get_started.html old mode 100644 new mode 100755 diff --git a/www/hacking.html b/www/hacking.html old mode 100644 new mode 100755 diff --git a/www/index.html b/www/index.html old mode 100644 new mode 100755 diff --git a/www/related.html b/www/related.html old mode 100644 new mode 100755 -- GitLab From 5a987ef0b0d883c8f33502e47b9b6f32e0546980 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 27 Jul 2018 07:27:14 +0000 Subject: [PATCH 0751/1023] [AST] Sink 'part of explicit cast' down into ImplicitCastExpr Summary: As discussed in IRC with @rsmith, it is slightly not good to keep that in the `CastExpr` itself: Given the explicit cast, which is represented in AST as an `ExplicitCastExpr` + `ImplicitCastExpr`'s, only the `ImplicitCastExpr`'s will be marked as `PartOfExplicitCast`, but not the `ExplicitCastExpr` itself. Thus, it is only ever `true` for `ImplicitCastExpr`'s, so we don't need to write/read/dump it for `ExplicitCastExpr`'s. We don't need to worry that we write the `PartOfExplicitCast` in PCH after `CastExpr::path_iterator`, since the `ExprImplicitCastAbbrev` is only used when the `NumBaseSpecs == 0`, i.e. there is no 'path'. Reviewers: rsmith, rjmccall, erichkeane, aaron.ballman Reviewed By: rsmith, erichkeane Subscribers: vsk, cfe-commits, rsmith Tags: #clang Differential Revision: https://reviews.llvm.org/D49838 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338108 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 13 ++++++------- include/clang/AST/Stmt.h | 3 ++- lib/AST/ASTDumper.cpp | 6 +++++- lib/Sema/SemaCast.cpp | 4 ++-- lib/Serialization/ASTReaderStmt.cpp | 2 +- lib/Serialization/ASTWriterStmt.cpp | 2 +- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index ca5bd95160..7585231e62 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2830,6 +2830,7 @@ protected: /// Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { + CastExprBits.PartOfExplicitCast = false; setBasePathSize(BasePathSize); } @@ -2837,13 +2838,6 @@ public: CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } void setCastKind(CastKind K) { CastExprBits.Kind = K; } - bool getIsPartOfExplicitCast() const { - return CastExprBits.PartOfExplicitCast; - } - void setIsPartOfExplicitCast(bool PartOfExplicitCast) { - CastExprBits.PartOfExplicitCast = PartOfExplicitCast; - } - static const char *getCastKindName(CastKind CK); const char *getCastKindName() const { return getCastKindName(getCastKind()); } @@ -2932,6 +2926,11 @@ public: : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { } + bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; } + void setIsPartOfExplicitCast(bool PartOfExplicitCast) { + CastExprBits.PartOfExplicitCast = PartOfExplicitCast; + } + static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 9e70b218d3..91dbcb71a6 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -198,11 +198,12 @@ protected: class CastExprBitfields { friend class CastExpr; + friend class ImplicitCastExpr; unsigned : NumExprBits; unsigned Kind : 6; - unsigned PartOfExplicitCast : 1; + unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 6ccd913bd3..f46ae58d19 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -521,6 +521,7 @@ namespace { // Exprs void VisitExpr(const Expr *Node); void VisitCastExpr(const CastExpr *Node); + void VisitImplicitCastExpr(const ImplicitCastExpr *Node); void VisitDeclRefExpr(const DeclRefExpr *Node); void VisitPredefinedExpr(const PredefinedExpr *Node); void VisitCharacterLiteral(const CharacterLiteral *Node); @@ -2117,8 +2118,11 @@ void ASTDumper::VisitCastExpr(const CastExpr *Node) { } dumpBasePath(OS, Node); OS << ">"; +} - if (Node->getIsPartOfExplicitCast()) +void ASTDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { + VisitCastExpr(Node); + if (Node->isPartOfExplicitCast()) OS << " part_of_explicit_cast"; } diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index a669956422..b7f4629fba 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -93,8 +93,8 @@ namespace { // Walk down from the CE to the OrigSrcExpr, and mark all immediate // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched. - while ((CE = dyn_cast(CE->getSubExpr()))) - CE->setIsPartOfExplicitCast(true); + for (; auto *ICE = dyn_cast(CE->getSubExpr()); CE = ICE) + ICE->setIsPartOfExplicitCast(true); } /// Complete an apparently-successful cast operation that yields diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index ee03b6def0..d9d780b25b 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -723,7 +723,6 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { assert(NumBaseSpecs == E->path_size()); E->setSubExpr(Record.readSubExpr()); E->setCastKind((CastKind)Record.readInt()); - E->setIsPartOfExplicitCast(Record.readInt()); CastExpr::path_iterator BaseI = E->path_begin(); while (NumBaseSpecs--) { auto *BaseSpec = new (Record.getContext()) CXXBaseSpecifier; @@ -770,6 +769,7 @@ ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); + E->setIsPartOfExplicitCast(Record.readInt()); } void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 79156dcc5c..3efb6482dd 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -665,7 +665,6 @@ void ASTStmtWriter::VisitCastExpr(CastExpr *E) { Record.push_back(E->path_size()); Record.AddStmt(E->getSubExpr()); Record.push_back(E->getCastKind()); // FIXME: stable encoding - Record.push_back(E->getIsPartOfExplicitCast()); for (CastExpr::path_iterator PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) @@ -714,6 +713,7 @@ ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); + Record.push_back(E->isPartOfExplicitCast()); if (E->path_size() == 0) AbbrevToUse = Writer.getExprImplicitCastAbbrev(); -- GitLab From 3ef733230abb3cb8a8b7327fe8081525ffc5a61d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 27 Jul 2018 17:13:18 +0000 Subject: [PATCH 0752/1023] Add missing temporary materialization conversion on left-hand side of . in some member function calls. Specifically, when calling a conversion function, we would fail to create the AST node representing materialization of the class object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338135 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFG.cpp | 8 +- lib/Sema/SemaExpr.cpp | 6 + lib/Sema/SemaExprCXX.cpp | 25 +- lib/Sema/SemaInit.cpp | 10 - lib/Sema/SemaOverload.cpp | 7 + test/Analysis/cfg-rich-constructors.cpp | 55 +-- test/Analysis/lambda-notes.cpp | 2 +- test/Analysis/temp-obj-dtors-cfg-output.cpp | 439 +++++++++--------- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 2 +- test/CodeGenCXX/stack-reuse-miscompile.cpp | 36 +- test/CodeGenObjCXX/literals.mm | 14 +- 11 files changed, 325 insertions(+), 279 deletions(-) diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b895087e51..8a3ab15458 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -4408,9 +4408,11 @@ tryAgain: auto *LE = cast(E); CFGBlock *B = Block; for (Expr *Init : LE->capture_inits()) { - if (CFGBlock *R = VisitForTemporaryDtors( - Init, /*BindToTemporary=*/false, Context)) - B = R; + if (Init) { + if (CFGBlock *R = VisitForTemporaryDtors( + Init, /*BindToTemporary=*/false, Context)) + B = R; + } } return B; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index effaa888f0..60abd718e2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7138,6 +7138,10 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, E = E->IgnoreImpCasts(); E = E->IgnoreConversionOperator(); E = E->IgnoreImpCasts(); + if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); + E = E->IgnoreImpCasts(); + } // Built-in binary operator. if (BinaryOperator *OP = dyn_cast(E)) { @@ -7185,6 +7189,8 @@ static bool ExprLooksBoolean(Expr *E) { return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) return true; + // FIXME: What about overloaded operator calls returning "unspecified boolean + // type"s (commonly pointer-to-members)? return false; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 30876c09a9..a1168fa34d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -7114,10 +7114,17 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXConversionDecl *Method, bool HadMultipleCandidates) { + // Convert the expression to match the conversion function's implicit object + // parameter. + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + if (Method->getParent()->isLambda() && Method->getConversionType()->isBlockPointerType()) { // This is a lambda coversion to block pointer; check if the argument - // is a LambdaExpr. + // was a LambdaExpr. Expr *SubE = E; CastExpr *CE = dyn_cast(SubE); if (CE && CE->getCastKind() == CK_NoOp) @@ -7134,22 +7141,16 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, DiagnosticErrorTrap Trap(Diags); PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), - E->getExprLoc(), - Method, E); + ExprResult BlockExp = BuildBlockForLambdaConversion( + Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get()); PopExpressionEvaluationContext(); - if (Exp.isInvalid()) - Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); - return Exp; + if (BlockExp.isInvalid()) + Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv); + return BlockExp; } } - ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, - FoundDecl, Method); - if (Exp.isInvalid()) - return true; - MemberExpr *ME = new (Context) MemberExpr( Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(), Context.BoundMemberTy, VK_RValue, OK_Ordinary); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0dddbdc36f..3ee5ec4a49 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -7406,16 +7406,6 @@ InitializationSequence::Perform(Sema &S, if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); - // FIXME: Should we move this initialization into a separate - // derived-to-base conversion? I believe the answer is "no", because - // we don't want to turn off access control here for c-style casts. - CurInit = S.PerformObjectArgumentInitialization(CurInit.get(), - /*Qualifier=*/nullptr, - FoundFn, Conversion); - if (CurInit.isInvalid()) - return ExprError(); - - // Build the actual call to the conversion function. CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, HadMultipleCandidates); if (CurInit.isInvalid()) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a0b9498cdf..08af485ef4 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5165,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From, FromRecordType = From->getType(); DestType = ImplicitParamRecordType; FromClassification = From->Classify(Context); + + // When performing member access on an rvalue, materialize a temporary. + if (From->isRValue()) { + From = CreateMaterializeTemporaryExpr(FromRecordType, From, + Method->getRefQualifier() != + RefQualifierKind::RQ_RValue); + } } // Note that we always use the true parent context when performing diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp index ce3e5f84ba..6780cf1a7b 100644 --- a/test/Analysis/cfg-rich-constructors.cpp +++ b/test/Analysis/cfg-rich-constructors.cpp @@ -464,14 +464,14 @@ void simpleTemporary() { C(); } -// TODO: Should provide construction context for the constructor, // CHECK: void temporaryInCondition() -// CHECK: 1: C() (CXXConstructExpr, class C) -// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, NoOp, const class C) -// CHECK-NEXT: 3: [B2.2].operator bool -// CHECK-NEXT: 4: [B2.2] -// CHECK-NEXT: 5: [B2.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK-NEXT: T: if [B2.5] +// CHECK: 1: C() (CXXConstructExpr, [B2.2], class C) +// CHECK-NEXT: 2: [B2.1] +// CHECK-NEXT: 3: [B2.2] (ImplicitCastExpr, NoOp, const class C) +// CHECK-NEXT: 4: [B2.3].operator bool +// CHECK-NEXT: 5: [B2.3] +// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK-NEXT: T: if [B2.6] void temporaryInCondition() { if (C()); } @@ -583,14 +583,15 @@ void simpleTemporary() { } // CHECK: void temporaryInCondition() -// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], class temporary_object_expr_with_dtors::D) +// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], [B2.3], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 2: [B2.1] (BindTemporary) -// CHECK-NEXT: 3: [B2.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CHECK-NEXT: 4: [B2.3].operator bool -// CHECK-NEXT: 5: [B2.3] -// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK-NEXT: 7: ~temporary_object_expr_with_dtors::D() (Temporary object destructor) -// CHECK-NEXT: T: if [B2.6] +// CHECK-NEXT: 3: [B2.2] +// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 5: [B2.4].operator bool +// CHECK-NEXT: 6: [B2.4] +// CHECK-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK-NEXT: 8: ~temporary_object_expr_with_dtors::D() (Temporary object destructor) +// CHECK-NEXT: T: if [B2.7] void temporaryInCondition() { if (D()); } @@ -693,23 +694,25 @@ void referenceWithFunctionalCast() { // Test the condition constructor, we don't care about branch constructors here. // CHECK: void constructorInTernaryCondition() // CXX11: 1: 1 -// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], [B7.5], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 3: [B7.2] (BindTemporary) // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) -// CXX11-NEXT: 5: [B7.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CXX11-NEXT: 6: [B7.5].operator bool -// CXX11-NEXT: 7: [B7.5] -// CXX11-NEXT: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11-NEXT: T: [B7.8] ? ... : ... +// CXX11-NEXT: 5: [B7.4] +// CXX11-NEXT: 6: [B7.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B7.6].operator bool +// CXX11-NEXT: 8: [B7.6] +// CXX11-NEXT: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CXX11-NEXT: T: [B7.9] ? ... : ... // CXX17: 1: 1 -// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) +// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], [B4.5], class temporary_object_expr_with_dtors::D) // CXX17-NEXT: 3: [B4.2] (BindTemporary) // CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B4.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) -// CXX17-NEXT: 5: [B4.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CXX17-NEXT: 6: [B4.5].operator bool -// CXX17-NEXT: 7: [B4.5] -// CXX17-NEXT: 8: [B4.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX17-NEXT: T: [B4.8] ? ... : ... +// CXX17-NEXT: 5: [B4.4] +// CXX17-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CXX17-NEXT: 7: [B4.6].operator bool +// CXX17-NEXT: 8: [B4.6] +// CXX17-NEXT: 9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CXX17-NEXT: T: [B4.9] ? ... : ... void constructorInTernaryCondition() { const D &d = D(1) ? D(2) : D(3); } diff --git a/test/Analysis/lambda-notes.cpp b/test/Analysis/lambda-notes.cpp index 7abff35df1..d4318284df 100644 --- a/test/Analysis/lambda-notes.cpp +++ b/test/Analysis/lambda-notes.cpp @@ -69,7 +69,7 @@ void diagnosticFromLambda() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 -// CHECK-NEXT: col5 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index e2c6267630..d08b01cd39 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -311,44 +311,48 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) // CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2].operator int -// CHECK: 4: [B1.2] -// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 7: B() (CXXConstructExpr, class B) -// ANALYZER: 7: B() (CXXConstructExpr, [B1.8], class B) -// CHECK: 8: [B1.7] (BindTemporary) -// CHECK: 9: [B1.8].operator int -// CHECK: 10: [B1.8] -// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 13: [B1.6] + [B1.12] -// CHECK: 14: int a = int(A()) + int(B()); -// CHECK: 15: ~B() (Temporary object destructor) -// CHECK: 16: ~A() (Temporary object destructor) -// CHECK: 17: foo -// CHECK: 18: [B1.17] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) -// WARNINGS: 19: A() (CXXConstructExpr, class A) -// ANALYZER: 19: A() (CXXConstructExpr, [B1.20], class A) -// CHECK: 20: [B1.19] (BindTemporary) -// CHECK: 21: [B1.20].operator int -// CHECK: 22: [B1.20] -// CHECK: 23: [B1.22] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 24: int([B1.23]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 25: B() (CXXConstructExpr, class B) -// ANALYZER: 25: B() (CXXConstructExpr, [B1.26], class B) -// CHECK: 26: [B1.25] (BindTemporary) -// CHECK: 27: [B1.26].operator int -// CHECK: 28: [B1.26] -// CHECK: 29: [B1.28] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 30: int([B1.29]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 31: [B1.24] + [B1.30] -// CHECK: 32: [B1.18]([B1.31]) -// CHECK: 33: ~B() (Temporary object destructor) -// CHECK: 34: ~A() (Temporary object destructor) -// CHECK: 35: int b; +// CHECK: 3: [B1.2] +// CHECK: 4: [B1.3].operator int +// CHECK: 5: [B1.3] +// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 8: B() (CXXConstructExpr, class B) +// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B) +// CHECK: 9: [B1.8] (BindTemporary) +// CHECK: 10: [B1.9] +// CHECK: 11: [B1.10].operator int +// CHECK: 12: [B1.10] +// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 15: [B1.7] + [B1.14] +// CHECK: 16: int a = int(A()) + int(B()); +// CHECK: 17: ~B() (Temporary object destructor) +// CHECK: 18: ~A() (Temporary object destructor) +// CHECK: 19: foo +// CHECK: 20: [B1.19] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// WARNINGS: 21: A() (CXXConstructExpr, class A) +// ANALYZER: 21: A() (CXXConstructExpr, [B1.22], [B1.23], class A) +// CHECK: 22: [B1.21] (BindTemporary) +// CHECK: 23: [B1.22] +// CHECK: 24: [B1.23].operator int +// CHECK: 25: [B1.23] +// CHECK: 26: [B1.25] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 27: int([B1.26]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 28: B() (CXXConstructExpr, class B) +// ANALYZER: 28: B() (CXXConstructExpr, [B1.29], [B1.30], class B) +// CHECK: 29: [B1.28] (BindTemporary) +// CHECK: 30: [B1.29] +// CHECK: 31: [B1.30].operator int +// CHECK: 32: [B1.30] +// CHECK: 33: [B1.32] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 34: int([B1.33]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 35: [B1.27] + [B1.34] +// CHECK: 36: [B1.20]([B1.35]) +// CHECK: 37: ~B() (Temporary object destructor) +// CHECK: 38: ~A() (Temporary object destructor) +// CHECK: 39: int b; // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -365,18 +369,19 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] && [B4.5] +// CHECK: 1: [B5.9] && [B4.6] // CHECK: 2: [B5.3]([B3.1]) // CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B) // CHECK: 2: [B4.1] (BindTemporary) -// CHECK: 3: [B4.2].operator bool -// CHECK: 4: [B4.2] -// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B4.2] +// CHECK: 4: [B4.3].operator bool +// CHECK: 5: [B4.3] +// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] @@ -384,12 +389,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) // WARNINGS: 4: A() (CXXConstructExpr, class A) -// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], class A) +// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A) // CHECK: 5: [B5.4] (BindTemporary) -// CHECK: 6: [B5.5].operator bool -// CHECK: 7: [B5.5] -// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.8] && ... +// CHECK: 6: [B5.5] +// CHECK: 7: [B5.6].operator bool +// CHECK: 8: [B5.6] +// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.9] && ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B4 B3 // CHECK: [B6] @@ -397,28 +403,30 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] && [B8.5] +// CHECK: 1: [B9.6] && [B8.6] // CHECK: 2: bool a = A() && B(); // CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B) // CHECK: 2: [B8.1] (BindTemporary) -// CHECK: 3: [B8.2].operator bool -// CHECK: 4: [B8.2] -// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B8.2] +// CHECK: 4: [B8.3].operator bool +// CHECK: 5: [B8.3] +// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator bool -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B9.5] && ... +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator bool +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B9.6] && ... // CHECK: Preds (1): B10 // CHECK: Succs (2): B8 B7 // CHECK: [B0 (EXIT)] @@ -435,18 +443,19 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] || [B4.5] +// CHECK: 1: [B5.9] || [B4.6] // CHECK: 2: [B5.3]([B3.1]) // CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B) // CHECK: 2: [B4.1] (BindTemporary) -// CHECK: 3: [B4.2].operator bool -// CHECK: 4: [B4.2] -// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B4.2] +// CHECK: 4: [B4.3].operator bool +// CHECK: 5: [B4.3] +// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] @@ -454,12 +463,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) // WARNINGS: 4: A() (CXXConstructExpr, class A) -// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], class A) +// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A) // CHECK: 5: [B5.4] (BindTemporary) -// CHECK: 6: [B5.5].operator bool -// CHECK: 7: [B5.5] -// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.8] || ... +// CHECK: 6: [B5.5] +// CHECK: 7: [B5.6].operator bool +// CHECK: 8: [B5.6] +// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.9] || ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B3 B4 // CHECK: [B6] @@ -467,28 +477,30 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] || [B8.5] +// CHECK: 1: [B9.6] || [B8.6] // CHECK: 2: bool a = A() || B(); // CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B) // CHECK: 2: [B8.1] (BindTemporary) -// CHECK: 3: [B8.2].operator bool -// CHECK: 4: [B8.2] -// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B8.2] +// CHECK: 4: [B8.3].operator bool +// CHECK: 5: [B8.3] +// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator bool -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B9.5] || ... +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator bool +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B9.6] || ... // CHECK: Preds (1): B10 // CHECK: Succs (2): B7 B8 // CHECK: [B0 (EXIT)] @@ -517,13 +529,14 @@ const C &bar3(bool coin) { // CHECK: [B4] // CHECK: 1: ~B() (Temporary object destructor) // WARNINGS: 2: B() (CXXConstructExpr, class B) -// ANALYZER: 2: B() (CXXConstructExpr, [B4.3], class B) +// ANALYZER: 2: B() (CXXConstructExpr, [B4.3], [B4.4], class B) // CHECK: 3: [B4.2] (BindTemporary) -// CHECK: 4: [B4.3].operator bool -// CHECK: 5: [B4.3] -// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: 7: ~B() (Temporary object destructor) -// CHECK: T: if [B4.6] +// CHECK: 4: [B4.3] +// CHECK: 5: [B4.4].operator bool +// CHECK: 6: [B4.4] +// CHECK: 7: [B4.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 8: ~B() (Temporary object destructor) +// CHECK: T: if [B4.7] // CHECK: Preds (2): B5 B6 // CHECK: Succs (2): B3 B2 // CHECK: [B5] @@ -539,7 +552,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 // CHECK: [B7] -// CHECK: 1: [B10.5] ? [B8.6] : [B9.15] +// CHECK: 1: [B10.6] ? [B8.6] : [B9.16] // CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B7.2] // WARNINGS: 4: [B7.3] (CXXConstructExpr, class A) @@ -561,33 +574,35 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B9.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B9.2], [B9.3], class B) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator A -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B9.5] (BindTemporary) -// CHECK: 7: [B9.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B9.7] -// WARNINGS: 9: [B9.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], [B9.14], class A) -// CHECK: 10: [B9.9] (BindTemporary) -// CHECK: 11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B9.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B9.12] -// WARNINGS: 14: [B9.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], [B7.4], class A) -// CHECK: 15: [B9.14] (BindTemporary) +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator A +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B9.6] (BindTemporary) +// CHECK: 8: [B9.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B9.8] +// WARNINGS: 10: [B9.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B9.9] (CXXConstructExpr, [B9.11], [B9.14], [B9.15], class A) +// CHECK: 11: [B9.10] (BindTemporary) +// CHECK: 12: A([B9.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B9.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B9.13] +// WARNINGS: 15: [B9.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B9.14] (CXXConstructExpr, [B9.16], [B7.3], [B7.4], class A) +// CHECK: 16: [B9.15] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 // CHECK: [B10] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B10.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B10.2], [B10.3], class B) // CHECK: 2: [B10.1] (BindTemporary) -// CHECK: 3: [B10.2].operator bool -// CHECK: 4: [B10.2] -// CHECK: 5: [B10.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B10.5] ? ... : ... +// CHECK: 3: [B10.2] +// CHECK: 4: [B10.3].operator bool +// CHECK: 5: [B10.3] +// CHECK: 6: [B10.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B10.6] ? ... : ... // CHECK: Preds (1): B11 // CHECK: Succs (2): B8 B9 // CHECK: [B0 (EXIT)] @@ -650,13 +665,14 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B0 // CHECK: [B3] // WARNINGS: 1: C() (CXXConstructExpr, struct C) -// ANALYZER: 1: C() (CXXConstructExpr, [B3.2], struct C) +// ANALYZER: 1: C() (CXXConstructExpr, [B3.2], [B3.3], struct C) // CHECK: 2: [B3.1] (BindTemporary) -// CHECK: 3: [B3.2].operator bool -// CHECK: 4: [B3.2] -// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: 6: ~C() (Temporary object destructor) -// CHECK: T: if [B3.5] +// CHECK: 3: [B3.2] +// CHECK: 4: [B3.3].operator bool +// CHECK: 5: [B3.3] +// CHECK: 6: [B3.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 7: ~C() (Temporary object destructor) +// CHECK: T: if [B3.6] // CHECK: Preds (1): B4 // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] @@ -710,11 +726,13 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B0 // CHECK: [B3] -// CHECK: 1: D() (CXXConstructExpr, struct D) -// CHECK: 2: [B3.1].operator bool -// CHECK: 3: [B3.1] -// CHECK: 4: [B3.3] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: if [B3.4] +// WARNINGS: 1: D() (CXXConstructExpr, struct D) +// ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) +// CHECK: 2: [B3.1] +// CHECK: 3: [B3.2].operator bool +// CHECK: 4: [B3.2] +// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: if [B3.5] // CHECK: Preds (1): B4 // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] @@ -780,7 +798,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: [B7.8] ? [B5.6] : [B6.15] +// CHECK: 1: [B7.9] ? [B5.6] : [B6.16] // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] // CHECK: 4: [B7.3]([B4.3]) @@ -800,23 +818,24 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B6.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B6.2], [B6.3], class B) // CHECK: 2: [B6.1] (BindTemporary) -// CHECK: 3: [B6.2].operator A -// CHECK: 4: [B6.2] -// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B6.5] (BindTemporary) -// CHECK: 7: [B6.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B6.7] -// WARNINGS: 9: [B6.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B6.8] (CXXConstructExpr, [B6.10], [B6.13], [B6.14], class A) -// CHECK: 10: [B6.9] (BindTemporary) -// CHECK: 11: A([B6.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B6.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B6.12] -// WARNINGS: 14: [B6.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B6.13] (CXXConstructExpr, [B6.15], [B4.3], class A) -// CHECK: 15: [B6.14] (BindTemporary) +// CHECK: 3: [B6.2] +// CHECK: 4: [B6.3].operator A +// CHECK: 5: [B6.3] +// CHECK: 6: [B6.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B6.6] (BindTemporary) +// CHECK: 8: [B6.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B6.8] +// WARNINGS: 10: [B6.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B6.9] (CXXConstructExpr, [B6.11], [B6.14], [B6.15], class A) +// CHECK: 11: [B6.10] (BindTemporary) +// CHECK: 12: A([B6.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B6.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B6.13] +// WARNINGS: 15: [B6.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B6.14] (CXXConstructExpr, [B6.16], [B4.3], class A) +// CHECK: 16: [B6.15] (BindTemporary) // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 // CHECK: [B7] @@ -824,12 +843,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) // WARNINGS: 4: B() (CXXConstructExpr, class B) -// ANALYZER: 4: B() (CXXConstructExpr, [B7.5], class B) +// ANALYZER: 4: B() (CXXConstructExpr, [B7.5], [B7.6], class B) // CHECK: 5: [B7.4] (BindTemporary) -// CHECK: 6: [B7.5].operator bool -// CHECK: 7: [B7.5] -// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.8] ? ... : ... +// CHECK: 6: [B7.5] +// CHECK: 7: [B7.6].operator bool +// CHECK: 8: [B7.6] +// CHECK: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.9] ? ... : ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -843,7 +863,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 // CHECK: [B10] -// CHECK: 1: [B13.5] ? [B11.6] : [B12.15] +// CHECK: 1: [B13.6] ? [B11.6] : [B12.16] // CHECK: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B10.2] // CHECK: 4: const A &a = B() ? A() : A(B()); @@ -863,33 +883,35 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B10 // CHECK: [B12] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B12.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B12.2], [B12.3], class B) // CHECK: 2: [B12.1] (BindTemporary) -// CHECK: 3: [B12.2].operator A -// CHECK: 4: [B12.2] -// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B12.5] (BindTemporary) -// CHECK: 7: [B12.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B12.7] -// WARNINGS: 9: [B12.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B12.8] (CXXConstructExpr, [B12.10], [B12.13], [B12.14], class A) -// CHECK: 10: [B12.9] (BindTemporary) -// CHECK: 11: A([B12.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B12.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B12.12] -// WARNINGS: 14: [B12.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B12.13] (CXXConstructExpr, [B10.3], class A) -// CHECK: 15: [B12.14] (BindTemporary) +// CHECK: 3: [B12.2] +// CHECK: 4: [B12.3].operator A +// CHECK: 5: [B12.3] +// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B12.6] (BindTemporary) +// CHECK: 8: [B12.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B12.8] +// WARNINGS: 10: [B12.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B12.9] (CXXConstructExpr, [B12.11], [B12.14], [B12.15], class A) +// CHECK: 11: [B12.10] (BindTemporary) +// CHECK: 12: A([B12.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B12.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B12.13] +// WARNINGS: 15: [B12.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B12.14] (CXXConstructExpr, [B10.3], class A) +// CHECK: 16: [B12.15] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 // CHECK: [B13] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B13.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B13.2], [B13.3], class B) // CHECK: 2: [B13.1] (BindTemporary) -// CHECK: 3: [B13.2].operator bool -// CHECK: 4: [B13.2] -// CHECK: 5: [B13.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B13.5] ? ... : ... +// CHECK: 3: [B13.2] +// CHECK: 4: [B13.3].operator bool +// CHECK: 5: [B13.3] +// CHECK: 6: [B13.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B13.6] ? ... : ... // CHECK: Preds (1): B14 // CHECK: Succs (2): B11 B12 // CHECK: [B0 (EXIT)] @@ -949,15 +971,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B7.2], [B7.3], class A) // ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B7.2], class A) // CHECK: 2: [B7.1] (BindTemporary) -// CXX98: 3: [B7.2].operator bool -// CXX98: 4: [B7.2] -// CXX98: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B7.5] ? ... : ... -// CXX11: 3: [B7.2] -// CXX11: 4: [B7.3].operator bool -// CXX11: 5: [B7.3] -// CXX11: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B7.6] ? ... : ... +// CHECK: 3: [B7.2] +// CHECK: 4: [B7.3].operator bool +// CHECK: 5: [B7.3] +// CHECK: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.6] ? ... : ... // CHECK: Preds (1): B8 // CHECK: Succs (2): B5 B6 // CHECK: [B0 (EXIT)] @@ -1017,15 +1035,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 3: A() (CXXConstructExpr, [B7.4], class A) // ANALYZER-CXX11: 3: A() (CXXConstructExpr, class A) // CHECK: 4: [B7.3] (BindTemporary) -// CXX98: 5: [B7.4].operator bool -// CXX98: 6: [B7.4] -// CXX98: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B7.7] ? ... : ... -// CXX11: 5: [B7.4] -// CXX11: 6: [B7.5].operator bool -// CXX11: 7: [B7.5] -// CXX11: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B7.8] ? ... : ... +// CHECK: 5: [B7.4] +// CHECK: 6: [B7.5].operator bool +// CHECK: 7: [B7.5] +// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -1069,15 +1083,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B12.2], [B12.3], class A) // ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B12.2], class A) // CHECK: 2: [B12.1] (BindTemporary) -// CXX98: 3: [B12.2].operator bool -// CXX98: 4: [B12.2] -// CXX98: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B12.5] ? ... : ... -// CXX11: 3: [B12.2] -// CXX11: 4: [B12.3].operator bool -// CXX11: 5: [B12.3] -// CXX11: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B12.6] ? ... : ... +// CHECK: 3: [B12.2] +// CHECK: 4: [B12.3].operator bool +// CHECK: 5: [B12.3] +// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B12.6] ? ... : ... // CHECK: Preds (1): B13 // CHECK: Succs (2): B10 B11 // CHECK: [B0 (EXIT)] @@ -1177,15 +1187,16 @@ const C &bar3(bool coin) { // CHECK: [B1] // CHECK: 1: int a; // WARNINGS: 2: A() (CXXConstructExpr, class A) -// ANALYZER: 2: A() (CXXConstructExpr, [B1.3], class A) +// ANALYZER: 2: A() (CXXConstructExpr, [B1.3], [B1.4], class A) // CHECK: 3: [B1.2] (BindTemporary) -// CHECK: 4: [B1.3].operator int -// CHECK: 5: [B1.3] -// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 7: a -// CHECK: 8: [B1.7] = [B1.6] -// CHECK: 9: ~A() (Temporary object destructor) -// CHECK: 10: int b; +// CHECK: 4: [B1.3] +// CHECK: 5: [B1.4].operator int +// CHECK: 6: [B1.4] +// CHECK: 7: [B1.6] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 8: a +// CHECK: 9: [B1.8] = [B1.7] +// CHECK: 10: ~A() (Temporary object destructor) +// CHECK: 11: int b; // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -1194,25 +1205,27 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) // CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2].operator int -// CHECK: 4: [B1.2] -// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 7: B() (CXXConstructExpr, class B) -// ANALYZER: 7: B() (CXXConstructExpr, [B1.8], class B) -// CHECK: 8: [B1.7] (BindTemporary) -// CHECK: 9: [B1.8].operator int -// CHECK: 10: [B1.8] -// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 13: [B1.6] + [B1.12] -// CHECK: 14: a([B1.13]) (Member initializer) -// CHECK: 15: ~B() (Temporary object destructor) -// CHECK: 16: ~A() (Temporary object destructor) -// CHECK: 17: /*implicit*/(int)0 -// CHECK: 18: b([B1.17]) (Member initializer) +// CHECK: 3: [B1.2] +// CHECK: 4: [B1.3].operator int +// CHECK: 5: [B1.3] +// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 8: B() (CXXConstructExpr, class B) +// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B) +// CHECK: 9: [B1.8] (BindTemporary) +// CHECK: 10: [B1.9] +// CHECK: 11: [B1.10].operator int +// CHECK: 12: [B1.10] +// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 15: [B1.7] + [B1.14] +// CHECK: 16: a([B1.15]) (Member initializer) +// CHECK: 17: ~B() (Temporary object destructor) +// CHECK: 18: ~A() (Temporary object destructor) +// CHECK: 19: /*implicit*/(int)0 +// CHECK: 20: b([B1.19]) (Member initializer) // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp index 370f732fd9..88ad6a4a3c 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -35,7 +35,7 @@ template struct ConstexprMember { constexpr R F() const { return 0; } }; constexpr int d = ConstexprMember().F(); // ok -constexpr int e = ConstexprMember().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'const NonLiteral' cannot be used in a constant expression}} +constexpr int e = ConstexprMember().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} template struct ConstexprCtor { constexpr ConstexprCtor(P...) {} diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp index 3b860a5739..4e824d94f5 100644 --- a/test/CodeGenCXX/stack-reuse-miscompile.cpp +++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -1,8 +1,4 @@ -// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s - -// This test should not to generate llvm.lifetime.start/llvm.lifetime.end for -// f function because all temporary objects in this function are used for the -// final result +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s --implicit-check-not=llvm.lifetime class S { char *ptr; @@ -23,14 +19,36 @@ public: const char * f(S s) { +// It's essential that the lifetimes of all three T temporaries here are +// overlapping. They must all remain alive through the call to str(). +// // CHECK: [[T1:%.*]] = alloca %class.T, align 4 // CHECK: [[T2:%.*]] = alloca %class.T, align 4 // CHECK: [[T3:%.*]] = alloca %class.T, align 4 -// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T1]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) -// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T2]], [2 x i32] %{{.*}}) -// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T3]], %class.T* [[T1]], %class.T* dereferenceable(16) [[T2]]) -// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T3]]) +// +// FIXME: We could defer starting the lifetime of the return object of concat +// until the call. +// CHECK: [[T1i8:%.*]] = bitcast %class.T* [[T1]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T1i8]]) +// +// CHECK: [[T2i8:%.*]] = bitcast %class.T* [[T2]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T2i8]]) +// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T2]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) +// +// CHECK: [[T3i8:%.*]] = bitcast %class.T* [[T3]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T3i8]]) +// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T3]], [2 x i32] %{{.*}}) +// +// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T1]], %class.T* [[T2]], %class.T* dereferenceable(16) [[T3]]) +// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T1]]) +// +// CHECK: call void @llvm.lifetime.end.p0i8( +// CHECK: call void @llvm.lifetime.end.p0i8( +// CHECK: call void @llvm.lifetime.end.p0i8( // CHECK: ret i8* [[T6]] return T("[").concat(T(s)).str(); } + +// CHECK: declare {{.*}}llvm.lifetime.start +// CHECK: declare {{.*}}llvm.lifetime.end diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm index 6a112312bd..a42070b00c 100644 --- a/test/CodeGenObjCXX/literals.mm +++ b/test/CodeGenObjCXX/literals.mm @@ -18,19 +18,25 @@ struct Y { void test_array() { // CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8* // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*] + // CHECK: [[TMPX:%[a-zA-Z0-9.]+]] = alloca % + // CHECK: [[TMPY:%[a-zA-Z0-9.]+]] = alloca % // Initializing first element // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]]) // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 - // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPX]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) + // CHECK-NEXT: call void @_ZN1XC1Ev({{.*}} [[TMPX]]) // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 - // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPY]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) + // CHECK-NEXT: invoke void @_ZN1YC1Ev({{.*}} [[TMPY]]) // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] @@ -75,14 +81,14 @@ void test_array_instantiation() { // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]]) // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 - // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK: call void @_ZN1XC1Ev // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 - // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK: invoke void @_ZN1YC1Ev // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] -- GitLab From f0389c4d454a484b8c48b1e5c4d9aafa5444aed6 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 27 Jul 2018 17:26:11 +0000 Subject: [PATCH 0753/1023] [ASTMatchers] Introduce a matcher for `ObjCIvarExpr`, support getting it's declaration. ObjCIvarExpr is *not* a subclass of MemberExpr, and a separate matcher is required to support it. Adding a hasDeclaration support as well, as it's not very useful without it. Differential Revision: https://reviews.llvm.org/D49701 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338137 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 30 +++++++++++++++++++ include/clang/ASTMatchers/ASTMatchers.h | 16 ++++++++++ .../clang/ASTMatchers/ASTMatchersInternal.h | 9 +++++- lib/ASTMatchers/ASTMatchersInternal.cpp | 1 + lib/ASTMatchers/Dynamic/Registry.cpp | 1 + .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 10 +++++++ 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index e8335d95e1..cf32a5ce4a 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1267,6 +1267,20 @@ Example matches @finally
+Matcher<Stmt>objcIvarRefExprMatcher<ObjCIvarRefExpr>... +
Matches a reference to an ObjCIvar.
+
+Example: matches "a" in "init" method:
+@implementation A {
+  NSString *a;
+}
+- (void) init {
+  a = @"hello";
+}
+}
+
+ + Matcher<Stmt>objcMessageExprMatcher<ObjCMessageExpr>...
Matches ObjectiveC Message invocation expressions.
 
@@ -4251,6 +4265,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -4547,6 +4562,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -4750,6 +4766,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -4900,6 +4917,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -5061,6 +5079,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -5247,6 +5266,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -5667,6 +5687,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -5700,6 +5721,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -5733,6 +5755,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6093,6 +6116,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6174,6 +6198,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6326,6 +6351,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6448,6 +6474,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6501,6 +6528,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6565,6 +6593,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
@@ -6629,6 +6658,7 @@ The associated declaration is:
 - for MemberExpr, the declaration of the referenced member
 - for CXXConstructExpr, the declaration of the constructor
 - for CXXNewExpr, the declaration of the operator new
+- for ObjCIvarExpr, the declaration of the ivar
 
 For type nodes, hasDeclaration will generally match the declaration of the
 sugared type. Given
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 75dc654905..58f65a39fb 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -1644,6 +1644,21 @@ extern const internal::VariadicDynCastAllOfMatcher expr;
 extern const internal::VariadicDynCastAllOfMatcher
     declRefExpr;
 
+/// Matches a reference to an ObjCIvar.
+///
+/// Example: matches "a" in "init" method:
+/// \code
+/// @implementation A {
+///   NSString *a;
+/// }
+/// - (void) init {
+///   a = @"hello";
+/// }
+//}
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher
+    objcIvarRefExpr;
+
 /// Matches if statements.
 ///
 /// Example matches 'if (x) {}'
@@ -2655,6 +2670,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
 /// - for MemberExpr, the declaration of the referenced member
 /// - for CXXConstructExpr, the declaration of the constructor
 /// - for CXXNewExpr, the declaration of the operator new
+/// - for ObjCIvarExpr, the declaration of the ivar
 ///
 /// For type nodes, hasDeclaration will generally match the declaration of the
 /// sugared type. Given
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index c5ca6188a2..b0a45789d9 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -42,6 +42,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
@@ -865,6 +866,12 @@ private:
     return matchesDecl(Node.getConstructor(), Finder, Builder);
   }
 
+  bool matchesSpecialized(const ObjCIvarRefExpr &Node,
+                          ASTMatchFinder *Finder,
+                          BoundNodesTreeBuilder *Builder) const {
+    return matchesDecl(Node.getDecl(), Finder, Builder);
+  }
+
   /// Extracts the operator new of the new call and returns whether the
   /// inner matcher matches on it.
   bool matchesSpecialized(const CXXNewExpr &Node,
@@ -1110,7 +1117,7 @@ using HasDeclarationSupportedTypes =
              ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
              MemberExpr, QualType, RecordType, TagType,
              TemplateSpecializationType, TemplateTypeParmType, TypedefType,
-             UnresolvedUsingType>;
+             UnresolvedUsingType, ObjCIvarRefExpr>;
 
 /// Converts a \c Matcher to a matcher of desired type \c To by
 /// "adapting" a \c To into a \c T.
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 0c5902d20c..9cea2f5efc 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -679,6 +679,7 @@ const internal::VariadicDynCastAllOfMatcher
     cxxOperatorCallExpr;
 const internal::VariadicDynCastAllOfMatcher expr;
 const internal::VariadicDynCastAllOfMatcher declRefExpr;
+const internal::VariadicDynCastAllOfMatcher objcIvarRefExpr;
 const internal::VariadicDynCastAllOfMatcher ifStmt;
 const internal::VariadicDynCastAllOfMatcher forStmt;
 const internal::VariadicDynCastAllOfMatcher
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 982156f6dc..4d2d76f6a7 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -410,6 +410,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(objcImplementationDecl);
   REGISTER_MATCHER(objcInterfaceDecl);
   REGISTER_MATCHER(objcIvarDecl);
+  REGISTER_MATCHER(objcIvarRefExpr);
   REGISTER_MATCHER(objcMessageExpr);
   REGISTER_MATCHER(objcMethodDecl);
   REGISTER_MATCHER(objcObjectPointerType);
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 7426dd926d..1e7b10e99e 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1354,6 +1354,16 @@ TEST(Matcher, HandlesNullQualTypes) {
       ))))));
 }
 
+TEST(ObjCIvarRefExprMatcher, IvarExpr) {
+  std::string ObjCString =
+    "@interface A @end "
+    "@implementation A { A *x; } - (void) func { x = 0; } @end";
+  EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr()));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr(
+        hasDeclaration(namedDecl(hasName("x"))))));
+  EXPECT_FALSE(matchesObjC(ObjCString, objcIvarRefExpr(
+        hasDeclaration(namedDecl(hasName("y"))))));
+}
 
 TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
   EXPECT_TRUE(matches("void f() { }",
-- 
GitLab


From 3d38d9f1f0abbc8f2279786a736712b6e8889272 Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Fri, 27 Jul 2018 17:37:32 +0000
Subject: [PATCH 0754/1023] [OPENMP] Static variables on device must be
 externally visible.

Do not mark static variable as internal on the device as they must be
visible from the host to be mapped correctly.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338139 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/ASTContext.cpp                        | 21 +++++++++++++++++++
 test/OpenMP/declare_target_codegen.cpp        |  7 +++++--
 ...x_declare_target_var_ctor_dtor_codegen.cpp |  2 +-
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 9cd0844184..25dc4441aa 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -9504,6 +9504,21 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
   return GVA_DiscardableODR;
 }
 
+static bool isDeclareTargetToDeclaration(const Decl *VD) {
+  for (const Decl *D : VD->redecls()) {
+    if (!D->hasAttrs())
+      continue;
+    if (const auto *Attr = D->getAttr())
+      return Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_To;
+  }
+  if (const auto *V = dyn_cast(VD)) {
+    if (const VarDecl *TD = V->getTemplateInstantiationPattern())
+      return isDeclareTargetToDeclaration(TD);
+  }
+
+  return false;
+}
+
 static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
                                                 const Decl *D, GVALinkage L) {
   // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
@@ -9520,6 +9535,12 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context,
     // visible externally so they can be launched from host.
     if (L == GVA_DiscardableODR || L == GVA_Internal)
       return GVA_StrongODR;
+  } else if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice &&
+             isDeclareTargetToDeclaration(D)) {
+    // Static variables must be visible externally so they can be mapped from
+    // host.
+    if (L == GVA_Internal)
+      return GVA_StrongODR;
   }
   return L;
 }
diff --git a/test/OpenMP/declare_target_codegen.cpp b/test/OpenMP/declare_target_codegen.cpp
index dfc65d8dda..a221387c73 100644
--- a/test/OpenMP/declare_target_codegen.cpp
+++ b/test/OpenMP/declare_target_codegen.cpp
@@ -18,12 +18,14 @@
 // CHECK-DAG: @d = global i32 0,
 // CHECK-DAG: @c = external global i32,
 // CHECK-DAG: @globals = global %struct.S zeroinitializer,
-// CHECK-DAG: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+41]]_ctor to i8*)], section "llvm.metadata"
+// CHECK-DAG: @{{.+}}stat = weak_odr global %struct.S zeroinitializer,
+// CHECK-DAG: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @__omp_offloading__{{.+}}_globals_l[[@LINE+42]]_ctor to i8*), i8* bitcast (void ()* @__omp_offloading__{{.+}}_stat_l[[@LINE+43]]_ctor to i8*)], section "llvm.metadata"
 
 // CHECK-DAG: define {{.*}}i32 @{{.*}}{{foo|bar|baz2|baz3|FA|f_method}}{{.*}}()
 // CHECK-DAG: define {{.*}}void @{{.*}}TemplateClass{{.*}}(%class.TemplateClass* %{{.*}})
 // CHECK-DAG: define {{.*}}i32 @{{.*}}TemplateClass{{.*}}f_method{{.*}}(%class.TemplateClass* %{{.*}})
-// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+36]]_ctor()
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_globals_l[[@LINE+37]]_ctor()
+// CHECK-DAG: define {{.*}}void @__omp_offloading__{{.*}}_stat_l[[@LINE+37]]_ctor()
 
 #ifndef HEADER
 #define HEADER
@@ -60,6 +62,7 @@ int foo() { return 0; }
 int b = 15;
 int d;
 S globals(d);
+static S stat(d);
 #pragma omp end declare target
 int c;
 
diff --git a/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
index b9049a4028..3cd85eefbc 100644
--- a/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
+++ b/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp
@@ -15,7 +15,7 @@
 
 // SIMD-ONLY-NOT: {{__kmpc|__tgt}}
 
-// DEVICE-DAG: [[C_ADDR:.+]] = internal global i32 0,
+// DEVICE-DAG: [[C_ADDR:.+]] = weak_odr global i32 0,
 // DEVICE-DAG: [[CD_ADDR:@.+]] = global %struct.S zeroinitializer,
 // HOST-DAG: @[[C_ADDR:.+]] = internal global i32 0,
 // HOST-DAG: @[[CD_ADDR:.+]] = global %struct.S zeroinitializer,
-- 
GitLab


From 8ac9d0b254a50f7418a1e82d9c2f140edd06334d Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Fri, 27 Jul 2018 17:40:59 +0000
Subject: [PATCH 0755/1023] [ASTMatchers] Introduce a matcher for
 `ObjCIvarExpr`, support getting it's declaration

ObjCIvarExpr is *not* a subclass of MemberExpr, and a separate matcher
is required to support it.
Adding a hasDeclaration support as well, as it's not very useful without
it.

Differential Revision: https://reviews.llvm.org/D49701

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338140 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/ASTMatchers/ASTMatchersInternal.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index b0a45789d9..9d9f867d05 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -41,6 +41,7 @@
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
-- 
GitLab


From 107f2b748033f442cead2ccfe343269d6b1fe1a4 Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Fri, 27 Jul 2018 18:06:54 +0000
Subject: [PATCH 0756/1023] Fix typos in comment.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338141 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/TypeLoc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 73909e50ff..25cd014efe 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -93,8 +93,8 @@ public:
   }
 
   /// Convert to the specified TypeLoc type, returning a null TypeLoc if
-  /// this TypeLock is not of the desired type. It will consider type
-  /// adjustments from a type that wad written as a T to another type that is
+  /// this TypeLoc is not of the desired type. It will consider type
+  /// adjustments from a type that was written as a T to another type that is
   /// still canonically a T (ignores parens, attributes, elaborated types, etc).
   template 
   T getAsAdjusted() const;
-- 
GitLab


From ab6efb3942a5bf75bffc29430f2870f0e77c70da Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Fri, 27 Jul 2018 18:26:40 +0000
Subject: [PATCH 0757/1023] [analyzer] Extend NoStoreFuncVisitor to insert a
 note on IVars

The note is added in the following situation:

 - We are throwing a nullability-related warning on an IVar
 - The path goes through a method which *could have* (syntactically
   determined) written into that IVar, but did not

rdar://42444460

Differential Revision: https://reviews.llvm.org/D49689

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338149 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../Core/BugReporterVisitors.cpp              | 63 +++++++++++++++----
 .../diagnostics/no-store-func-path-notes.cpp  | 19 +++++-
 .../diagnostics/no-store-func-path-notes.m    | 35 ++++++++++-
 3 files changed, 100 insertions(+), 17 deletions(-)

diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 6213fc0598..c87bc685d8 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
 #include "clang/Analysis/CFGStmtMap.h"
@@ -306,15 +307,26 @@ public:
 
     CallEventRef<> Call =
         BRC.getStateManager().getCallEventManager().getCaller(SCtx, State);
-
     const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy();
     const SourceManager &SM = BRC.getSourceManager();
+
+    // Region of interest corresponds to an IVar, exiting a method
+    // which could have written into that IVar, but did not.
+    if (const auto *MC = dyn_cast(Call))
+      if (const auto *IvarR = dyn_cast(RegionOfInterest))
+        if (potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
+                                      IvarR->getDecl()) &&
+            !isRegionOfInterestModifiedInFrame(N))
+          return notModifiedMemberDiagnostics(
+              Ctx, SM, PP, *CallExitLoc, Call,
+              MC->getReceiverSVal().getAsRegion());
+
     if (const auto *CCall = dyn_cast(Call)) {
       const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion();
       if (RegionOfInterest->isSubRegionOf(ThisRegion)
           && !CCall->getDecl()->isImplicit()
           && !isRegionOfInterestModifiedInFrame(N))
-        return notModifiedInConstructorDiagnostics(Ctx, SM, PP, *CallExitLoc,
+        return notModifiedMemberDiagnostics(Ctx, SM, PP, *CallExitLoc,
                                                    CCall, ThisRegion);
     }
 
@@ -331,7 +343,7 @@ public:
           if (isRegionOfInterestModifiedInFrame(N))
             return nullptr;
 
-          return notModifiedDiagnostics(
+          return notModifiedParameterDiagnostics(
               Ctx, SM, PP, *CallExitLoc, Call, PVD, R, IndirectionLevel);
         }
         QualType PT = T->getPointeeType();
@@ -346,6 +358,22 @@ public:
   }
 
 private:
+
+  /// \return Whether the method declaration \p Parent
+  /// syntactically has a binary operation writing into the ivar \p Ivar.
+  bool potentiallyWritesIntoIvar(const Decl *Parent,
+                                 const ObjCIvarDecl *Ivar) {
+    using namespace ast_matchers;
+    if (!Parent || !Parent->getBody())
+      return false;
+    StatementMatcher WriteIntoIvarM = binaryOperator(
+        hasOperatorName("="), hasLHS(ignoringParenImpCasts(objcIvarRefExpr(
+                                  hasDeclaration(equalsNode(Ivar))))));
+    StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
+    auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
+    return !Matches.empty();
+  }
+
   /// Check and lazily calculate whether the region of interest is
   /// modified in the stack frame to which \p N belongs.
   /// The calculation is cached in FramesModifyingRegion.
@@ -414,19 +442,21 @@ private:
            Ty->getPointeeType().getCanonicalType().isConstQualified();
   }
 
-  std::shared_ptr notModifiedInConstructorDiagnostics(
+  /// \return Diagnostics piece for the member field not modified
+  /// in a given function.
+  std::shared_ptr notModifiedMemberDiagnostics(
       const LocationContext *Ctx,
       const SourceManager &SM,
       const PrintingPolicy &PP,
       CallExitBegin &CallExitLoc,
-      const CXXConstructorCall *Call,
+      CallEventRef<> Call,
       const MemRegion *ArgRegion) {
+    const char *TopRegionName = isa(Call) ? "self" : "this";
     SmallString<256> sbuf;
     llvm::raw_svector_ostream os(sbuf);
     os << DiagnosticsMsg;
-    bool out = prettyPrintRegionName(
-        "this", "->", /*IsReference=*/true,
-        /*IndirectionLevel=*/1, ArgRegion, os, PP);
+    bool out = prettyPrintRegionName(TopRegionName, "->", /*IsReference=*/true,
+                                     /*IndirectionLevel=*/1, ArgRegion, os, PP);
 
     // Return nothing if we have failed to pretty-print.
     if (!out)
@@ -434,14 +464,16 @@ private:
 
     os << "'";
     PathDiagnosticLocation L =
-        getPathDiagnosticLocation(nullptr, SM, Ctx, Call);
+        getPathDiagnosticLocation(CallExitLoc.getReturnStmt(), SM, Ctx, Call);
     return std::make_shared(L, os.str());
   }
 
+  /// \return Diagnostics piece for the parameter \p PVD not modified
+  /// in a given function.
   /// \p IndirectionLevel How many times \c ArgRegion has to be dereferenced
   /// before we get to the super region of \c RegionOfInterest
   std::shared_ptr
-  notModifiedDiagnostics(const LocationContext *Ctx,
+  notModifiedParameterDiagnostics(const LocationContext *Ctx,
                          const SourceManager &SM,
                          const PrintingPolicy &PP,
                          CallExitBegin &CallExitLoc,
@@ -481,8 +513,8 @@ private:
 
   /// Pretty-print region \p ArgRegion starting from parent to \p os.
   /// \return whether printing has succeeded
-  bool prettyPrintRegionName(const char *TopRegionName,
-                             const char *Sep,
+  bool prettyPrintRegionName(StringRef TopRegionName,
+                             StringRef Sep,
                              bool IsReference,
                              int IndirectionLevel,
                              const MemRegion *ArgRegion,
@@ -491,7 +523,8 @@ private:
     SmallVector Subregions;
     const MemRegion *R = RegionOfInterest;
     while (R != ArgRegion) {
-      if (!(isa(R) || isa(R)))
+      if (!(isa(R) || isa(R) ||
+            isa(R)))
         return false; // Pattern-matching failed.
       Subregions.push_back(R);
       R = cast(R)->getSuperRegion();
@@ -519,6 +552,10 @@ private:
         os << Sep;
         FR->getDecl()->getDeclName().print(os, PP);
         Sep = ".";
+      } else if (const auto *IR = dyn_cast(*I)) {
+        os << "->";
+        IR->getDecl()->getDeclName().print(os, PP);
+        Sep = ".";
       } else if (isa(*I)) {
         continue; // Just keep going up to the base region.
       } else {
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
index b96dc4cf2a..17ec96ae5b 100644
--- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp
@@ -97,6 +97,14 @@ struct C {
   int x;
   int y;
   C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}}
+
+  C(int pX, int pY, bool Flag) {
+    x = pX;
+    if (Flag) // expected-note{{Assuming 'Flag' is not equal to 0}}
+              // expected-note@-1{{Taking true branch}}
+      return; // expected-note{{Returning without writing to 'this->y'}}
+    y = pY;
+  }
 };
 
 int use_constructor() {
@@ -106,6 +114,15 @@ int use_constructor() {
               // expected-warning@-1{{Undefined or garbage value returned to caller}}
 }
 
+int coin();
+
+int use_other_constructor() {
+  C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}}
+                     // expected-note@-1{{Returning from constructor for 'C'}}
+  return c.y; // expected-note{{Undefined or garbage value returned to caller}}
+              // expected-warning@-1{{Undefined or garbage value returned to caller}}
+}
+
 struct D {
   void initialize(int *);
 };
@@ -122,8 +139,6 @@ int use_d_initializer(D* d) {
                                 // expected-warning@-1{{Undefined or garbage value returned to caller}}
 }
 
-int coin();
-
 struct S2 {
   int x;
 };
diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.m b/test/Analysis/diagnostics/no-store-func-path-notes.m
index 3ae97ef564..51d1515e86 100644
--- a/test/Analysis/diagnostics/no-store-func-path-notes.m
+++ b/test/Analysis/diagnostics/no-store-func-path-notes.m
@@ -1,6 +1,10 @@
-// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -x objective-c -analyzer-checker=core,nullability -analyzer-output=text -Wno-objc-root-class -fblocks -verify %s
 
-@interface I
+#include "../Inputs/system-header-simulator-for-nullability.h"
+
+extern int coin();
+
+@interface I : NSObject
 - (int)initVar:(int *)var param:(int)param;
 @end
 
@@ -44,3 +48,30 @@ int initFromBlock() {
   }();
   return z;
 }
+
+extern void expectNonNull(NSString * _Nonnull a);
+
+@interface A : NSObject
+- (void) func;
+- (void) initAMaybe;
+@end
+
+@implementation A {
+  NSString * a;
+}
+
+- (void) initAMaybe {
+  if (coin()) // expected-note{{Assuming the condition is false}}
+              // expected-note@-1{{Taking false branch}}
+    a = @"string";
+} // expected-note{{Returning without writing to 'self->a'}}
+
+- (void) func {
+  a = nil; // expected-note{{nil object reference stored to 'a'}}
+  [self initAMaybe]; // expected-note{{Calling 'initAMaybe'}}
+                     // expected-note@-1{{Returning from 'initAMaybe'}}
+  expectNonNull(a); // expected-warning{{nil passed to a callee that requires a non-null 1st parameter}}
+                    // expected-note@-1{{nil passed to a callee that requires a non-null 1st parameter}}
+}
+
+@end
-- 
GitLab


From f97144939fe9df83df29bae7c1ecda9d97bb657a Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Fri, 27 Jul 2018 19:45:14 +0000
Subject: [PATCH 0758/1023] [DEBUGINFO] Disable unsupported debug info options
 for NVPTX target.

Summary:
Some targets support only default set of the debug options and do not
support additional debug options, like NVPTX target. Patch introduced
virtual function supportsDebugInfoOptions() that can be overloaded
by the toolchain, checks if the target supports some debug
options and emits warning when an unsupported debug option is
found.

Reviewers: echristo

Subscribers: aprantl, JDevlieghere, cfe-commits

Differential Revision: https://reviews.llvm.org/D49148

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338155 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticDriverKinds.td  |   3 +
 include/clang/Basic/DiagnosticGroups.td       |   1 +
 include/clang/Driver/ToolChain.h              |   5 +
 lib/Driver/ToolChains/Clang.cpp               | 211 +++++++++++-------
 lib/Driver/ToolChains/Cuda.cpp                |  12 +
 lib/Driver/ToolChains/Cuda.h                  |   1 +
 test/Driver/cuda-dwarf-2.cu                   |   3 +
 test/Driver/cuda-unsupported-debug-options.cu |  21 ++
 test/Driver/openmp-offload-gpu.c              |   3 +
 .../Driver/openmp-unsupported-debug-options.c |  21 ++
 10 files changed, 201 insertions(+), 80 deletions(-)
 create mode 100644 test/Driver/cuda-unsupported-debug-options.cu
 create mode 100644 test/Driver/openmp-unsupported-debug-options.c

diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index a6be0595e1..eb8e3c8b34 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -226,6 +226,9 @@ def warn_ignored_clang_option : Warning<"the flag '%0' has been deprecated and w
 def warn_drv_unsupported_opt_for_target : Warning<
   "optimization flag '%0' is not supported for target '%1'">,
   InGroup;
+def warn_drv_unsupported_debug_info_opt_for_target : Warning<
+  "debug information option '%0' is not supported for target '%1'">,
+  InGroup;
 def warn_c_kext : Warning<
   "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
 def warn_drv_input_file_unused : Warning<
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 7087db7f0f..eedd4308d0 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -72,6 +72,7 @@ def UnsupportedNan : DiagGroup<"unsupported-nan">;
 def UnsupportedAbs : DiagGroup<"unsupported-abs">;
 def UnsupportedCB : DiagGroup<"unsupported-cb">;
 def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">;
+def UnsupportedTargetOpt : DiagGroup<"unsupported-target-opt">;
 def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
 def NullConversion : DiagGroup<"null-conversion">;
 def ImplicitConversionFloatingPointToBool :
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index addf7aa6a9..2f9c2c190e 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -413,6 +413,11 @@ public:
     return llvm::DebuggerKind::GDB;
   }
 
+  /// Does this toolchain supports given debug info option or not.
+  virtual bool supportsDebugInfoOption(const llvm::opt::Arg *) const {
+    return true;
+  }
+
   /// GetExceptionModel - Return the tool chain exception model.
   virtual llvm::ExceptionHandling
   GetExceptionModel(const llvm::opt::ArgList &Args) const;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index eaff940a1c..8e9c4c6aec 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -919,34 +919,46 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
   }
 }
 
+static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
+                                 const Driver &D, const ToolChain &TC) {
+  assert(A && "Expected non-nullptr argument.");
+  if (TC.supportsDebugInfoOption(A))
+    return true;
+  D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
+      << A->getAsString(Args) << TC.getTripleString();
+  return false;
+}
+
 static void RenderDebugInfoCompressionArgs(const ArgList &Args,
                                            ArgStringList &CmdArgs,
-                                           const Driver &D) {
+                                           const Driver &D,
+                                           const ToolChain &TC) {
   const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ);
   if (!A)
     return;
+  if (checkDebugInfoOption(A, Args, D, TC)) {
+    if (A->getOption().getID() == options::OPT_gz) {
+      if (llvm::zlib::isAvailable())
+        CmdArgs.push_back("-compress-debug-sections");
+      else
+        D.Diag(diag::warn_debug_compression_unavailable);
+      return;
+    }
 
-  if (A->getOption().getID() == options::OPT_gz) {
-    if (llvm::zlib::isAvailable())
-      CmdArgs.push_back("-compress-debug-sections");
-    else
-      D.Diag(diag::warn_debug_compression_unavailable);
-    return;
-  }
-
-  StringRef Value = A->getValue();
-  if (Value == "none") {
-    CmdArgs.push_back("-compress-debug-sections=none");
-  } else if (Value == "zlib" || Value == "zlib-gnu") {
-    if (llvm::zlib::isAvailable()) {
-      CmdArgs.push_back(
-          Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
+    StringRef Value = A->getValue();
+    if (Value == "none") {
+      CmdArgs.push_back("-compress-debug-sections=none");
+    } else if (Value == "zlib" || Value == "zlib-gnu") {
+      if (llvm::zlib::isAvailable()) {
+        CmdArgs.push_back(
+            Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
+      } else {
+        D.Diag(diag::warn_debug_compression_unavailable);
+      }
     } else {
-      D.Diag(diag::warn_debug_compression_unavailable);
+      D.Diag(diag::err_drv_unsupported_option_argument)
+          << A->getOption().getName() << Value;
     }
-  } else {
-    D.Diag(diag::err_drv_unsupported_option_argument)
-        << A->getOption().getName() << Value;
   }
 }
 
@@ -2867,7 +2879,9 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
                                codegenoptions::DebugInfoKind &DebugInfoKind,
                                const Arg *&SplitDWARFArg) {
   if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
-                   options::OPT_fno_debug_info_for_profiling, false))
+                   options::OPT_fno_debug_info_for_profiling, false) &&
+      checkDebugInfoOption(
+          Args.getLastArg(options::OPT_fdebug_info_for_profiling), Args, D, TC))
     CmdArgs.push_back("-fdebug-info-for-profiling");
 
   // The 'g' groups options involve a somewhat intricate sequence of decisions
@@ -2890,29 +2904,38 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
 
   SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
 
+  if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
+    SplitDWARFArg = nullptr;
+    SplitDWARFInlining = false;
+  }
+
   if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
-    // If the last option explicitly specified a debug-info level, use it.
-    if (A->getOption().matches(options::OPT_gN_Group)) {
-      DebugInfoKind = DebugLevelToInfoKind(*A);
-      // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
-      // But -gsplit-dwarf is not a g_group option, hence we have to check the
-      // order explicitly. If -gsplit-dwarf wins, we fix DebugInfoKind later.
-      // This gets a bit more complicated if you've disabled inline info in the
-      // skeleton CUs (SplitDWARFInlining) - then there's value in composing
-      // split-dwarf and line-tables-only, so let those compose naturally in
-      // that case.
-      // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
-      if (SplitDWARFArg) {
-        if (A->getIndex() > SplitDWARFArg->getIndex()) {
-          if (DebugInfoKind == codegenoptions::NoDebugInfo ||
-              (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
-               SplitDWARFInlining))
-            SplitDWARFArg = nullptr;
-        } else if (SplitDWARFInlining)
-          DebugInfoKind = codegenoptions::NoDebugInfo;
+    if (checkDebugInfoOption(A, Args, D, TC)) {
+      // If the last option explicitly specified a debug-info level, use it.
+      if (A->getOption().matches(options::OPT_gN_Group)) {
+        DebugInfoKind = DebugLevelToInfoKind(*A);
+        // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
+        // But -gsplit-dwarf is not a g_group option, hence we have to check the
+        // order explicitly. If -gsplit-dwarf wins, we fix DebugInfoKind later.
+        // This gets a bit more complicated if you've disabled inline info in
+        // the skeleton CUs (SplitDWARFInlining) - then there's value in
+        // composing split-dwarf and line-tables-only, so let those compose
+        // naturally in that case. And if you just turned off debug info,
+        // (-gsplit-dwarf -g0) - do that.
+        if (SplitDWARFArg) {
+          if (A->getIndex() > SplitDWARFArg->getIndex()) {
+            if (DebugInfoKind == codegenoptions::NoDebugInfo ||
+                (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
+                 SplitDWARFInlining))
+              SplitDWARFArg = nullptr;
+          } else if (SplitDWARFInlining)
+            DebugInfoKind = codegenoptions::NoDebugInfo;
+        }
+      } else {
+        // For any other 'g' option, use Limited.
+        DebugInfoKind = codegenoptions::LimitedDebugInfo;
       }
     } else {
-      // For any other 'g' option, use Limited.
       DebugInfoKind = codegenoptions::LimitedDebugInfo;
     }
   }
@@ -2920,39 +2943,50 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
   // If a debugger tuning argument appeared, remember it.
   if (const Arg *A =
           Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
-    if (A->getOption().matches(options::OPT_glldb))
-      DebuggerTuning = llvm::DebuggerKind::LLDB;
-    else if (A->getOption().matches(options::OPT_gsce))
-      DebuggerTuning = llvm::DebuggerKind::SCE;
-    else
-      DebuggerTuning = llvm::DebuggerKind::GDB;
+    if (checkDebugInfoOption(A, Args, D, TC)) {
+      if (A->getOption().matches(options::OPT_glldb))
+        DebuggerTuning = llvm::DebuggerKind::LLDB;
+      else if (A->getOption().matches(options::OPT_gsce))
+        DebuggerTuning = llvm::DebuggerKind::SCE;
+      else
+        DebuggerTuning = llvm::DebuggerKind::GDB;
+    }
   }
 
   // If a -gdwarf argument appeared, remember it.
   if (const Arg *A =
           Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
                           options::OPT_gdwarf_4, options::OPT_gdwarf_5))
-    DWARFVersion = DwarfVersionNum(A->getSpelling());
+    if (checkDebugInfoOption(A, Args, D, TC))
+      DWARFVersion = DwarfVersionNum(A->getSpelling());
 
   // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
   // argument parsing.
   if (EmitCodeView) {
-    // DWARFVersion remains at 0 if no explicit choice was made.
-    CmdArgs.push_back("-gcodeview");
-  } else if (DWARFVersion == 0 &&
-             DebugInfoKind != codegenoptions::NoDebugInfo) {
-    DWARFVersion = TC.GetDefaultDwarfVersion();
+    if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
+      EmitCodeView = checkDebugInfoOption(A, Args, D, TC);
+      if (EmitCodeView) {
+        // DWARFVersion remains at 0 if no explicit choice was made.
+        CmdArgs.push_back("-gcodeview");
+      }
+    }
   }
 
+  if (!EmitCodeView && DWARFVersion == 0 &&
+      DebugInfoKind != codegenoptions::NoDebugInfo)
+    DWARFVersion = TC.GetDefaultDwarfVersion();
+
   // We ignore flag -gstrict-dwarf for now.
   // And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
   Args.ClaimAllArgs(options::OPT_g_flags_Group);
 
-  // Column info is included by default for everything except SCE and CodeView.
-  // Clang doesn't track end columns, just starting columns, which, in theory,
-  // is fine for CodeView (and PDB).  In practice, however, the Microsoft
-  // debuggers don't handle missing end columns well, so it's better not to
-  // include any column info.
+  // Column info is included by default for everything except SCE and
+  // CodeView. Clang doesn't track end columns, just starting columns, which,
+  // in theory, is fine for CodeView (and PDB).  In practice, however, the
+  // Microsoft debuggers don't handle missing end columns well, so it's better
+  // not to include any column info.
+  if (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info))
+    (void)checkDebugInfoOption(A, Args, D, TC);
   if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
                    /*Default=*/!EmitCodeView &&
                        DebuggerTuning != llvm::DebuggerKind::SCE))
@@ -2960,12 +2994,14 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
 
   // FIXME: Move backend command line options to the module.
   // If -gline-tables-only is the last option it wins.
-  if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
-      Args.hasArg(options::OPT_gmodules)) {
-    DebugInfoKind = codegenoptions::LimitedDebugInfo;
-    CmdArgs.push_back("-dwarf-ext-refs");
-    CmdArgs.push_back("-fmodule-format=obj");
-  }
+  if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
+    if (checkDebugInfoOption(A, Args, D, TC)) {
+      if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) {
+        DebugInfoKind = codegenoptions::LimitedDebugInfo;
+        CmdArgs.push_back("-dwarf-ext-refs");
+        CmdArgs.push_back("-fmodule-format=obj");
+      }
+    }
 
   // -gsplit-dwarf should turn on -g and enable the backend dwarf
   // splitting and extraction.
@@ -2989,19 +3025,23 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
   bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
                                     options::OPT_fno_standalone_debug,
                                     TC.GetDefaultStandaloneDebug());
+  if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
+    (void)checkDebugInfoOption(A, Args, D, TC);
   if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
     DebugInfoKind = codegenoptions::FullDebugInfo;
 
-  if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source, false)) {
+  if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source,
+                   false)) {
     // Source embedding is a vendor extension to DWARF v5. By now we have
     // checked if a DWARF version was stated explicitly, and have otherwise
-    // fallen back to the target default, so if this is still not at least 5 we
-    // emit an error.
+    // fallen back to the target default, so if this is still not at least 5
+    // we emit an error.
+    const Arg *A = Args.getLastArg(options::OPT_gembed_source);
     if (DWARFVersion < 5)
       D.Diag(diag::err_drv_argument_only_allowed_with)
-          << Args.getLastArg(options::OPT_gembed_source)->getAsString(Args)
-          << "-gdwarf-5";
-    CmdArgs.push_back("-gembed-source");
+          << A->getAsString(Args) << "-gdwarf-5";
+    else if (checkDebugInfoOption(A, Args, D, TC))
+      CmdArgs.push_back("-gembed-source");
   }
 
   RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
@@ -3010,31 +3050,41 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
   // -fdebug-macro turns on macro debug info generation.
   if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
                    false))
-    CmdArgs.push_back("-debug-info-macro");
+    if (checkDebugInfoOption(Args.getLastArg(options::OPT_fdebug_macro), Args,
+                             D, TC))
+      CmdArgs.push_back("-debug-info-macro");
 
   // -ggnu-pubnames turns on gnu style pubnames in the backend.
   if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
                    false))
-    CmdArgs.push_back("-ggnu-pubnames");
+    if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args,
+                             D, TC))
+      CmdArgs.push_back("-ggnu-pubnames");
 
   // -gdwarf-aranges turns on the emission of the aranges section in the
   // backend.
   // Always enabled for SCE tuning.
-  if (Args.hasArg(options::OPT_gdwarf_aranges) ||
-      DebuggerTuning == llvm::DebuggerKind::SCE) {
+  bool NeedAranges = DebuggerTuning == llvm::DebuggerKind::SCE;
+  if (const Arg *A = Args.getLastArg(options::OPT_gdwarf_aranges))
+    NeedAranges = checkDebugInfoOption(A, Args, D, TC) || NeedAranges;
+  if (NeedAranges) {
     CmdArgs.push_back("-mllvm");
     CmdArgs.push_back("-generate-arange-section");
   }
 
   if (Args.hasFlag(options::OPT_fdebug_types_section,
                    options::OPT_fno_debug_types_section, false)) {
-    if (!T.isOSBinFormatELF())
+    if (!T.isOSBinFormatELF()) {
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << Args.getLastArg(options::OPT_fdebug_types_section)
                  ->getAsString(Args)
           << T.getTriple();
-    CmdArgs.push_back("-mllvm");
-    CmdArgs.push_back("-generate-type-units");
+    } else if (checkDebugInfoOption(
+                   Args.getLastArg(options::OPT_fdebug_types_section), Args, D,
+                   TC)) {
+      CmdArgs.push_back("-mllvm");
+      CmdArgs.push_back("-generate-type-units");
+    }
   }
 
   // Decide how to render forward declarations of template instantiations.
@@ -3042,11 +3092,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
   if (DebuggerTuning == llvm::DebuggerKind::SCE)
     CmdArgs.push_back("-debug-forward-template-params");
 
-  // Do we need to explicitly import anonymous namespaces into the parent scope?
+  // Do we need to explicitly import anonymous namespaces into the parent
+  // scope?
   if (DebuggerTuning == llvm::DebuggerKind::SCE)
     CmdArgs.push_back("-dwarf-explicit-import");
 
-  RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
+  RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
 }
 
 void Clang::ConstructJob(Compilation &C, const JobAction &JA,
@@ -5388,7 +5439,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
   }
   RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
                           llvm::DebuggerKind::Default);
-  RenderDebugInfoCompressionArgs(Args, CmdArgs, D);
+  RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
 
 
   // Handle -fPIC et al -- the relocation-model affects the assembler
diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp
index d17c4c3953..7fb4ae4ea9 100644
--- a/lib/Driver/ToolChains/Cuda.cpp
+++ b/lib/Driver/ToolChains/Cuda.cpp
@@ -679,6 +679,18 @@ void CudaToolChain::addClangTargetOptions(
   }
 }
 
+bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
+  const Option &O = A->getOption();
+  return (O.matches(options::OPT_gN_Group) &&
+          !O.matches(options::OPT_gmodules)) ||
+         O.matches(options::OPT_g_Flag) ||
+         O.matches(options::OPT_ggdbN_Group) || O.matches(options::OPT_ggdb) ||
+         O.matches(options::OPT_gdwarf) || O.matches(options::OPT_gdwarf_2) ||
+         O.matches(options::OPT_gdwarf_3) || O.matches(options::OPT_gdwarf_4) ||
+         O.matches(options::OPT_gdwarf_5) ||
+         O.matches(options::OPT_gcolumn_info);
+}
+
 void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
                                        ArgStringList &CC1Args) const {
   // Check our CUDA version if we're going to include the CUDA headers.
diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h
index 99d5a4a628..01580cb669 100644
--- a/lib/Driver/ToolChains/Cuda.h
+++ b/lib/Driver/ToolChains/Cuda.h
@@ -158,6 +158,7 @@ public:
   bool isPIEDefault() const override { return false; }
   bool isPICDefaultForced() const override { return false; }
   bool SupportsProfiling() const override { return false; }
+  bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
   bool IsMathErrnoDefault() const override { return false; }
 
   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/test/Driver/cuda-dwarf-2.cu b/test/Driver/cuda-dwarf-2.cu
index b6c7f500f5..7956e6ddbe 100644
--- a/test/Driver/cuda-dwarf-2.cu
+++ b/test/Driver/cuda-dwarf-2.cu
@@ -15,6 +15,8 @@
 // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -gline-tables-only -O2 --cuda-noopt-device-debug 2>&1 | \
 // RUN:   FileCheck %s -check-prefix NO_DEBUG -check-prefix LINE_TABLE
 
+// NO_DEBUG-NOT: warning: debug
+// LINE_TABLE-NOT: warning: debug
 // NO_DEBUG: ptxas
 // NO_DEBUG-NOT: "-g"
 // LINE_TABLE: "-lineinfo"
@@ -36,6 +38,7 @@
 // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s -ggdb3 -O3 --cuda-noopt-device-debug 2>&1 | \
 // RUN:   FileCheck %s -check-prefix HAS_DEBUG
 
+// HAS_DEBUG-NOT: warning: debug
 // HAS_DEBUG: "-fcuda-is-device"
 // HAS_DEBUG-SAME: "-dwarf-version=2"
 // HAS_DEBUG: ptxas
diff --git a/test/Driver/cuda-unsupported-debug-options.cu b/test/Driver/cuda-unsupported-debug-options.cu
new file mode 100644
index 0000000000..0069851961
--- /dev/null
+++ b/test/Driver/cuda-unsupported-debug-options.cu
@@ -0,0 +1,21 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -g -gz 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf -fdebug-info-for-profiling 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf-2 -gsplit-dwarf 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf-3 -glldb 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf-4 -gcodeview 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf-5 -gmodules 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -ggdb -gembed-source -gdwarf-5 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -ggdb1 -fdebug-macro 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -ggdb2 -ggnu-pubnames 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -ggdb3 -gdwarf-aranges 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -c %s -g -gcolumn-info -fdebug-types-section 2>&1 | FileCheck %s
+// CHECK: debug information option '{{-gz|-fdebug-info-for-profiling|-gsplit-dwarf|-glldb|-gcodeview|-gmodules|-gembed-source|-fdebug-macro|-ggnu-pubnames|-gdwarf-aranges|-fdebug-types-section}}' is not supported for target 'nvptx64-nvidia-cuda' [-Wunsupported-target-opt]
+// CHECK-NOT: debug information option '{{.*}}' is not supported for target 'x86
+// CHECK: "-triple" "nvptx64-nvidia-cuda"
+// CHECK-NOT: {{-compress-debug|-fdebug-info-for-profiling|split-dwarf|lldb|codeview|module-format|embed-source|debug-info-macro|gnu-pubnames|generate-arange-section|generate-type-units}}
+// CHECK: "-triple" "x86_64
+// CHECK-SAME: {{-compress-debug|-fdebug-info-for-profiling|split-dwarf|lldb|codeview|module-format|embed-source|debug-info-macro|gnu-pubnames|generate-arange-section|generate-type-units}}
diff --git a/test/Driver/openmp-offload-gpu.c b/test/Driver/openmp-offload-gpu.c
index 3d14041a13..ca3d944544 100644
--- a/test/Driver/openmp-offload-gpu.c
+++ b/test/Driver/openmp-offload-gpu.c
@@ -182,6 +182,8 @@
 // RUN:   %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb1 -O2 --cuda-noopt-device-debug 2>&1 \
 // RUN:   | FileCheck -check-prefix=NO_DEBUG -check-prefix=LINE_TABLE %s
 
+// LINE_TABLE-NOT: warning: debug
+// NO_DEBUG-NOT: warning: debug
 // NO_DEBUG: ptxas
 // LINE_TABLE: "-lineinfo"
 // NO_DEBUG-NOT: "-g"
@@ -203,6 +205,7 @@
 // RUN:   %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target -march=sm_60 %s -ggdb3 -O2 --cuda-noopt-device-debug 2>&1 \
 // RUN:   | FileCheck -check-prefix=HAS_DEBUG %s
 
+// HAS_DEBUG-NOT: warning: debug
 // HAS_DEBUG: "-triple" "nvptx64-nvidia-cuda"
 // HAS_DEBUG-SAME: "-dwarf-version=2"
 // HAS_DEBUG-SAME: "-fopenmp-is-device"
diff --git a/test/Driver/openmp-unsupported-debug-options.c b/test/Driver/openmp-unsupported-debug-options.c
new file mode 100644
index 0000000000..2242077b77
--- /dev/null
+++ b/test/Driver/openmp-unsupported-debug-options.c
@@ -0,0 +1,21 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -g -gz 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf -fdebug-info-for-profiling 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf-2 -gsplit-dwarf 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf-3 -glldb 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf-4 -gcodeview 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf-5 -gmodules 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -ggdb -gembed-source -gdwarf-5 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -ggdb1 -fdebug-macro 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -ggdb2 -ggnu-pubnames 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -ggdb3 -gdwarf-aranges 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -g -gcolumn-info -fdebug-types-section 2>&1 | FileCheck %s
+// CHECK: debug information option '{{-gz|-fdebug-info-for-profiling|-gsplit-dwarf|-glldb|-gcodeview|-gmodules|-gembed-source|-fdebug-macro|-ggnu-pubnames|-gdwarf-aranges|-fdebug-types-section}}' is not supported for target 'nvptx64-nvidia-cuda' [-Wunsupported-target-opt]
+// CHECK-NOT: debug information option '{{.*}}' is not supported for target 'x86
+// CHECK: "-triple" "nvptx64-nvidia-cuda"
+// CHECK-NOT: {{-compress-debug|-fdebug-info-for-profiling|split-dwarf|lldb|codeview|module-format|embed-source|debug-info-macro|gnu-pubnames|generate-arange-section|generate-type-units}}
+// CHECK: "-triple" "x86_64
+// CHECK-SAME: {{-compress-debug|-fdebug-info-for-profiling|split-dwarf|lldb|codeview|module-format|embed-source|debug-info-macro|gnu-pubnames|generate-arange-section|generate-type-units}}
-- 
GitLab


From e88e9fc64db66b8dfbd3a83bc4ef94a9a2220671 Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Fri, 27 Jul 2018 20:16:44 +0000
Subject: [PATCH 0759/1023] [DEBUG_INFO] Fix tests, NFC.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338158 91177308-0d34-0410-b5e6-96231b3b80d8
---
 test/Driver/cuda-unsupported-debug-options.cu  | 1 +
 test/Driver/openmp-unsupported-debug-options.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/test/Driver/cuda-unsupported-debug-options.cu b/test/Driver/cuda-unsupported-debug-options.cu
index 0069851961..3aa1bc0b47 100644
--- a/test/Driver/cuda-unsupported-debug-options.cu
+++ b/test/Driver/cuda-unsupported-debug-options.cu
@@ -1,6 +1,7 @@
 // REQUIRES: clang-driver
 // REQUIRES: x86-registered-target
 // REQUIRES: nvptx-registered-target
+// REQUIRES: zlib
 
 // RUN: %clang -### -target x86_64-linux-gnu -c %s -g -gz 2>&1 | FileCheck %s
 // RUN: %clang -### -target x86_64-linux-gnu -c %s -gdwarf -fdebug-info-for-profiling 2>&1 | FileCheck %s
diff --git a/test/Driver/openmp-unsupported-debug-options.c b/test/Driver/openmp-unsupported-debug-options.c
index 2242077b77..20e0c47f7f 100644
--- a/test/Driver/openmp-unsupported-debug-options.c
+++ b/test/Driver/openmp-unsupported-debug-options.c
@@ -1,6 +1,7 @@
 // REQUIRES: clang-driver
 // REQUIRES: x86-registered-target
 // REQUIRES: nvptx-registered-target
+// REQUIRES: zlib
 
 // RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -g -gz 2>&1 | FileCheck %s
 // RUN: %clang -### -target x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s -gdwarf -fdebug-info-for-profiling 2>&1 | FileCheck %s
-- 
GitLab


From 66f2c636c465bc9be68ba58db395b7075d52574a Mon Sep 17 00:00:00 2001
From: Erik Pilkington 
Date: Fri, 27 Jul 2018 21:23:48 +0000
Subject: [PATCH 0760/1023] [Sema] Use a TreeTransform to extract deduction
 guide parameter types

Previously, we just canonicalized the type, but this lead to crashes with
parameter types that referred to ParmVarDecls of the constructor. There may be
more cases that this TreeTransform needs to handle though, such as a constructor
parameter type referring to a member in an unevaluated context. Canonicalization
doesn't address these cases either though, so we can address them as-needed in
follow-up commits.

rdar://41330135

Differential revision: https://reviews.llvm.org/D49439

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338165 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaTemplate.cpp                     | 40 ++++++++++++-------
 ...xx1z-class-template-argument-deduction.cpp | 29 ++++++++++++++
 2 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index dd11632671..919bc7b63d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1659,6 +1659,23 @@ DeclResult Sema::CheckClassTemplate(
 }
 
 namespace {
+/// Tree transform to "extract" a transformed type from a class template's
+/// constructor to a deduction guide.
+class ExtractTypeForDeductionGuide
+  : public TreeTransform {
+public:
+  typedef TreeTransform Base;
+  ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {}
+
+  TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
+
+  QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
+    return TransformType(
+        TLB,
+        TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc());
+  }
+};
+
 /// Transform to convert portions of a constructor declaration into the
 /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
 struct ConvertConstructorToDeductionGuideTransform {
@@ -1880,9 +1897,7 @@ private:
                              MultiLevelTemplateArgumentList &Args) {
     TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
     TypeSourceInfo *NewDI;
-    if (!Args.getNumLevels())
-      NewDI = OldDI;
-    else if (auto PackTL = OldDI->getTypeLoc().getAs()) {
+    if (auto PackTL = OldDI->getTypeLoc().getAs()) {
       // Expand out the one and only element in each inner pack.
       Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0);
       NewDI =
@@ -1898,23 +1913,17 @@ private:
     if (!NewDI)
       return nullptr;
 
-    // Canonicalize the type. This (for instance) replaces references to
-    // typedef members of the current instantiations with the definitions of
-    // those typedefs, avoiding triggering instantiation of the deduced type
-    // during deduction.
-    // FIXME: It would be preferable to retain type sugar and source
-    // information here (and handle this in substitution instead).
-    NewDI = SemaRef.Context.getTrivialTypeSourceInfo(
-        SemaRef.Context.getCanonicalType(NewDI->getType()),
-        OldParam->getLocation());
+    // Extract the type. This (for instance) replaces references to typedef
+    // members of the current instantiations with the definitions of those
+    // typedefs, avoiding triggering instantiation of the deduced type during
+    // deduction.
+    NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI);
 
     // Resolving a wording defect, we also inherit default arguments from the
     // constructor.
     ExprResult NewDefArg;
     if (OldParam->hasDefaultArg()) {
-      NewDefArg = Args.getNumLevels()
-                      ? SemaRef.SubstExpr(OldParam->getDefaultArg(), Args)
-                      : OldParam->getDefaultArg();
+      NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args);
       if (NewDefArg.isInvalid())
         return nullptr;
     }
@@ -1929,6 +1938,7 @@ private:
                                                 NewDefArg.get());
     NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
                            OldParam->getFunctionScopeIndex());
+    SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
     return NewParam;
   }
 
diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index f72cb886d8..cbf7c2eee5 100644
--- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -373,6 +373,35 @@ void bar(D& d) {
 }
 }
 
+namespace rdar41330135 {
+template  struct A {};
+template 
+struct S {
+  template 
+  S(T a, U t, A);
+};
+template  struct D {
+  D(T t, A);
+};
+int f() {
+  S s(0, 0, A());
+  D d(0, A());
+}
+
+namespace test_dupls {
+template struct X {};
+template struct A {
+  A(T t, X);
+};
+A a(0, {});
+template struct B {
+  B(U u, X);
+};
+B b(0, {});
+}
+
+}
+
 #else
 
 // expected-no-diagnostics
-- 
GitLab


From 459648c52ee1c2cc321223d61aae39b169104e9c Mon Sep 17 00:00:00 2001
From: Nicolas Lesser 
Date: Fri, 27 Jul 2018 21:55:12 +0000
Subject: [PATCH 0761/1023] Parse a possible trailing postfix expression suffix
 after a fold expression

Summary:
This patch allows the parsing of a postfix expression involving a fold expression, which is legal as a fold-expression is a primary-expression.

See also https://llvm.org/pr38282

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D49848

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338170 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Parse/Parser.h           |  1 +
 lib/Parse/ParseExpr.cpp                | 20 +++++++++++++++-----
 test/Parser/cxx1z-fold-expressions.cpp | 26 ++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d7b83803af..41ccabf380 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1653,6 +1653,7 @@ private:
   /// ParenParseOption - Control what ParseParenExpression will parse.
   enum ParenParseOption {
     SimpleExpr,      // Only parse '(' expression ')'
+    FoldExpr,        // Also allow fold-expression 
     CompoundStmt,    // Also allow '(' compound-statement ')'
     CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
     CastExpr         // Also allow '(' type-name ')' 
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 4a0e1c5e34..5a70c9e295 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -789,6 +789,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
       // We have parsed the cast-expression and no postfix-expr pieces are
       // following.
       return Res;
+    case FoldExpr:
+      // We only parsed a fold-expression. There might be postfix-expr pieces
+      // afterwards; parse them now.
+      break;
     }
 
     break;
@@ -2523,8 +2527,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
       Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
       return ExprError();
     }
-  } else if (Tok.is(tok::ellipsis) &&
+  } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
              isFoldOperator(NextToken().getKind())) {
+    ExprType = FoldExpr;
     return ParseFoldExpression(ExprResult(), T);
   } else if (isTypeCast) {
     // Parse the expression-list.
@@ -2536,9 +2541,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
     if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
       // FIXME: If we ever support comma expressions as operands to
       // fold-expressions, we'll need to allow multiple ArgExprs here.
-      if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-          NextToken().is(tok::ellipsis))
+      if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
+          isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+        ExprType = FoldExpr;
         return ParseFoldExpression(ArgExprs[0], T);
+      }
 
       ExprType = SimpleExpr;
       Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2553,10 +2560,13 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
       // expressions are parsed correctly.
       Result = Actions.CorrectDelayedTyposInExpr(Result);
     }
-    ExprType = SimpleExpr;
 
-    if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+    if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
+        NextToken().is(tok::ellipsis)) {
+      ExprType = FoldExpr;
       return ParseFoldExpression(Result, T);
+    }
+    ExprType = SimpleExpr;
 
     // Don't build a paren expression unless we actually match a ')'.
     if (!Result.isInvalid() && Tok.is(tok::r_paren))
diff --git a/test/Parser/cxx1z-fold-expressions.cpp b/test/Parser/cxx1z-fold-expressions.cpp
index 342f11555f..93ee6f20ff 100644
--- a/test/Parser/cxx1z-fold-expressions.cpp
+++ b/test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,29 @@ template  constexpr int nestedFoldOperator() {
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+template 
+constexpr auto simpleSum(Ts... Args) {
+  return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+  simpleSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+    int Value;
+    constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+  static_assert(simpleSum(Number{1}, Number{2}) == 3);
+}
-- 
GitLab


From 8e4ee77b16eaae6b330d5059933fff25bec51d3b Mon Sep 17 00:00:00 2001
From: Fangrui Song 
Date: Sat, 28 Jul 2018 00:48:05 +0000
Subject: [PATCH 0762/1023] [CFG] Remove duplicate function/class names at the
 beginning of comments

Some functions/classes have renamed while the comments still use the old names. Delete them per coding style.

Also some whitespace cleanup.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338183 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../Analyses/CFGReachabilityAnalysis.h        |   4 +-
 include/clang/Analysis/CFG.h                  | 117 +++++++++---------
 include/clang/Analysis/CFGStmtMap.h           |   8 +-
 lib/Analysis/CFGReachabilityAnalysis.cpp      |  12 +-
 4 files changed, 67 insertions(+), 74 deletions(-)

diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index da59514c4f..49da6815ac 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -23,7 +23,7 @@ namespace clang {
 
 class CFG;
 class CFGBlock;
-  
+
 // A class that performs reachability queries for CFGBlocks. Several internal
 // checks in this checker require reachability information. The requests all
 // tend to have a common destination, so we lazily do a predecessor search
@@ -45,7 +45,7 @@ public:
 private:
   void mapReachability(const CFGBlock *Dst);
 };
-  
+
 } // namespace clang
 
 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index f25789822d..9c996688df 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -51,7 +51,7 @@ class FieldDecl;
 class LangOptions;
 class VarDecl;
 
-/// CFGElement - Represents a top-level expression in a basic block.
+/// Represents a top-level expression in a basic block.
 class CFGElement {
 public:
   enum Kind {
@@ -144,9 +144,9 @@ protected:
   CFGStmt() = default;
 };
 
-/// CFGConstructor - Represents C++ constructor call. Maintains information
-/// necessary to figure out what memory is being initialized by the
-/// constructor expression. For now this is only used by the analyzer's CFG.
+/// Represents C++ constructor call. Maintains information necessary to figure
+/// out what memory is being initialized by the constructor expression. For now
+/// this is only used by the analyzer's CFG.
 class CFGConstructor : public CFGStmt {
 public:
   explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
@@ -169,12 +169,12 @@ private:
   }
 };
 
-/// CFGCXXRecordTypedCall - Represents a function call that returns a C++ object
-/// by value. This, like constructor, requires a construction context in order
-/// to understand the storage of the returned object . In C such tracking is not
-/// necessary because no additional effort is required for destroying the object
-/// or modeling copy elision. Like CFGConstructor, this element is for now only
-/// used by the analyzer's CFG.
+/// Represents a function call that returns a C++ object by value. This, like
+/// constructor, requires a construction context in order to understand the
+/// storage of the returned object . In C such tracking is not necessary because
+/// no additional effort is required for destroying the object or modeling copy
+/// elision. Like CFGConstructor, this element is for now only used by the
+/// analyzer's CFG.
 class CFGCXXRecordTypedCall : public CFGStmt {
 public:
   /// Returns true when call expression \p CE needs to be represented
@@ -210,8 +210,8 @@ private:
   }
 };
 
-/// CFGInitializer - Represents C++ base or member initializer from
-/// constructor's initialization list.
+/// Represents C++ base or member initializer from constructor's initialization
+/// list.
 class CFGInitializer : public CFGElement {
 public:
   explicit CFGInitializer(CXXCtorInitializer *initializer)
@@ -231,7 +231,7 @@ private:
   }
 };
 
-/// CFGNewAllocator - Represents C++ allocator call.
+/// Represents C++ allocator call.
 class CFGNewAllocator : public CFGElement {
 public:
   explicit CFGNewAllocator(const CXXNewExpr *S)
@@ -349,8 +349,8 @@ private:
   }
 };
 
-/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
-/// by compiler on various occasions.
+/// Represents C++ object destructor implicitly generated by compiler on various
+/// occasions.
 class CFGImplicitDtor : public CFGElement {
 protected:
   CFGImplicitDtor() = default;
@@ -373,9 +373,9 @@ private:
   }
 };
 
-/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
-/// for automatic object or temporary bound to const reference at the point
-/// of leaving its local scope.
+/// Represents C++ object destructor implicitly generated for automatic object
+/// or temporary bound to const reference at the point of leaving its local
+/// scope.
 class CFGAutomaticObjDtor: public CFGImplicitDtor {
 public:
   CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
@@ -400,8 +400,7 @@ private:
   }
 };
 
-/// CFGDeleteDtor - Represents C++ object destructor generated
-/// from a call to delete.
+/// Represents C++ object destructor generated from a call to delete.
 class CFGDeleteDtor : public CFGImplicitDtor {
 public:
   CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
@@ -426,8 +425,8 @@ private:
   }
 };
 
-/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
-/// base object in destructor.
+/// Represents C++ object destructor implicitly generated for base object in
+/// destructor.
 class CFGBaseDtor : public CFGImplicitDtor {
 public:
   CFGBaseDtor(const CXXBaseSpecifier *base)
@@ -447,8 +446,8 @@ private:
   }
 };
 
-/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
-/// member object in destructor.
+/// Represents C++ object destructor implicitly generated for member object in
+/// destructor.
 class CFGMemberDtor : public CFGImplicitDtor {
 public:
   CFGMemberDtor(const FieldDecl *field)
@@ -468,8 +467,8 @@ private:
   }
 };
 
-/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
-/// at the end of full expression for temporary object.
+/// Represents C++ object destructor implicitly generated at the end of full
+/// expression for temporary object.
 class CFGTemporaryDtor : public CFGImplicitDtor {
 public:
   CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
@@ -489,7 +488,7 @@ private:
   }
 };
 
-/// CFGTerminator - Represents CFGBlock terminator statement.
+/// Represents CFGBlock terminator statement.
 ///
 /// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
 /// in control flow of destructors of temporaries. In this case terminator
@@ -520,7 +519,7 @@ public:
   explicit operator bool() const { return getStmt(); }
 };
 
-/// CFGBlock - Represents a single basic block in a source-level CFG.
+/// Represents a single basic block in a source-level CFG.
 ///  It consists of:
 ///
 ///  (1) A set of statements/expressions (which may contain subexpressions).
@@ -588,26 +587,24 @@ class CFGBlock {
     bool empty() const { return Impl.empty(); }
   };
 
-  /// Stmts - The set of statements in the basic block.
+  /// The set of statements in the basic block.
   ElementList Elements;
 
-  /// Label - An (optional) label that prefixes the executable
-  ///  statements in the block.  When this variable is non-NULL, it is
-  ///  either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
+  /// An (optional) label that prefixes the executable statements in the block.
+  /// When this variable is non-NULL, it is either an instance of LabelStmt,
+  /// SwitchCase or CXXCatchStmt.
   Stmt *Label = nullptr;
 
-  /// Terminator - The terminator for a basic block that
-  ///  indicates the type of control-flow that occurs between a block
-  ///  and its successors.
+  /// The terminator for a basic block that indicates the type of control-flow
+  /// that occurs between a block and its successors.
   CFGTerminator Terminator;
 
-  /// LoopTarget - Some blocks are used to represent the "loop edge" to
-  ///  the start of a loop from within the loop body.  This Stmt* will be
-  ///  refer to the loop statement for such blocks (and be null otherwise).
+  /// Some blocks are used to represent the "loop edge" to the start of a loop
+  /// from within the loop body. This Stmt* will be refer to the loop statement
+  /// for such blocks (and be null otherwise).
   const Stmt *LoopTarget = nullptr;
 
-  /// BlockID - A numerical ID assigned to a CFGBlock during construction
-  ///   of the CFG.
+  /// A numerical ID assigned to a CFGBlock during construction of the CFG.
   unsigned BlockID;
 
 public:
@@ -629,7 +626,7 @@ public:
   public:
     /// Construct an AdjacentBlock with a possibly unreachable block.
     AdjacentBlock(CFGBlock *B, bool IsReachable);
-    
+
     /// Construct an AdjacentBlock with a reachable block and an alternate
     /// unreachable block.
     AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
@@ -665,13 +662,12 @@ public:
   };
 
 private:
-  /// Predecessors/Successors - Keep track of the predecessor / successor
-  /// CFG blocks.
+  /// Keep track of the predecessor / successor CFG blocks.
   using AdjacentBlocks = BumpVector;
   AdjacentBlocks Preds;
   AdjacentBlocks Succs;
 
-  /// NoReturn - This bit is set when the basic block contains a function call
+  /// This bit is set when the basic block contains a function call
   /// or implicit destructor that is attributed as 'noreturn'. In that case,
   /// control cannot technically ever proceed past this block. All such blocks
   /// will have a single immediate successor: the exit block. This allows them
@@ -682,7 +678,7 @@ private:
   /// storage if the memory usage of CFGBlock becomes an issue.
   unsigned HasNoReturnElement : 1;
 
-  /// Parent - The parent CFG that owns this CFGBlock.
+  /// The parent CFG that owns this CFGBlock.
   CFG *Parent;
 
 public:
@@ -992,7 +988,7 @@ public:
                                       bool isAlwaysTrue) {}
 };
 
-/// CFG - Represents a source-level, intra-procedural CFG that represents the
+/// Represents a source-level, intra-procedural CFG that represents the
 ///  control-flow of a Stmt.  The Stmt can represent an entire function body,
 ///  or a single expression.  A CFG will always contain one empty block that
 ///  represents the Exit point of the CFG.  A CFG will also contain a designated
@@ -1044,21 +1040,21 @@ public:
     }
   };
 
-  /// buildCFG - Builds a CFG from an AST.
+  /// Builds a CFG from an AST.
   static std::unique_ptr buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
                                        const BuildOptions &BO);
 
-  /// createBlock - Create a new block in the CFG.  The CFG owns the block;
-  ///  the caller should not directly free it.
+  /// Create a new block in the CFG. The CFG owns the block; the caller should
+  /// not directly free it.
   CFGBlock *createBlock();
 
-  /// setEntry - Set the entry block of the CFG.  This is typically used
-  ///  only during CFG construction.  Most CFG clients expect that the
-  ///  entry block has no predecessors and contains no statements.
+  /// Set the entry block of the CFG. This is typically used only during CFG
+  /// construction. Most CFG clients expect that the entry block has no
+  /// predecessors and contains no statements.
   void setEntry(CFGBlock *B) { Entry = B; }
 
-  /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
-  ///  This is typically used only during CFG construction.
+  /// Set the block used for indirect goto jumps. This is typically used only
+  /// during CFG construction.
   void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
 
   //===--------------------------------------------------------------------===//
@@ -1152,8 +1148,8 @@ public:
 
   template 
   void VisitBlockStmts(CALLBACK& O) const {
-    for (const_iterator I=begin(), E=end(); I != E; ++I)
-      for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
+    for (const_iterator I = begin(), E = end(); I != E; ++I)
+      for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
            BI != BE; ++BI) {
         if (Optional stmt = BI->getAs())
           O(const_cast(stmt->getStmt()));
@@ -1164,13 +1160,12 @@ public:
   // CFG Introspection.
   //===--------------------------------------------------------------------===//
 
-  /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
-  /// start at 0).
+  /// Returns the total number of BlockIDs allocated (which start at 0).
   unsigned getNumBlockIDs() const { return NumBlockIDs; }
 
-  /// size - Return the total number of CFGBlocks within the CFG
-  /// This is simply a renaming of the getNumBlockIDs(). This is necessary 
-  /// because the dominator implementation needs such an interface.
+  /// Return the total number of CFGBlocks within the CFG This is simply a
+  /// renaming of the getNumBlockIDs(). This is necessary because the dominator
+  /// implementation needs such an interface.
   unsigned size() const { return NumBlockIDs; }
 
   //===--------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
index 4dfa91df0f..78e637daf3 100644
--- a/include/clang/Analysis/CFGStmtMap.h
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -19,20 +19,18 @@
 
 namespace clang {
 
-class CFG;
-class CFGBlock;
 class ParentMap;
 class Stmt;
 
 class CFGStmtMap {
   ParentMap *PM;
   void *M;
-  
+
   CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
-  
+
 public:
   ~CFGStmtMap();
-  
+
   /// Returns a new CFGMap for the given CFG.  It is the caller's
   /// responsibility to 'delete' this object when done using it.
   static CFGStmtMap *Build(CFG* C, ParentMap *PM);
diff --git a/lib/Analysis/CFGReachabilityAnalysis.cpp b/lib/Analysis/CFGReachabilityAnalysis.cpp
index 6f557e092f..076f54c7bf 100644
--- a/lib/Analysis/CFGReachabilityAnalysis.cpp
+++ b/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -27,13 +27,13 @@ CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(
 bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
                                           const CFGBlock *Dst) {
   const unsigned DstBlockID = Dst->getBlockID();
-  
+
   // If we haven't analyzed the destination node, run the analysis now
   if (!analyzed[DstBlockID]) {
     mapReachability(Dst);
     analyzed[DstBlockID] = true;
   }
-  
+
   // Return the cached result
   return reachable[DstBlockID][Src->getBlockID()];
 }
@@ -43,10 +43,10 @@ bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
 void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
   SmallVector worklist;
   llvm::BitVector visited(analyzed.size());
-  
+
   ReachableSet &DstReachability = reachable[Dst->getBlockID()];
   DstReachability.resize(analyzed.size(), false);
-  
+
   // Start searching from the destination node, since we commonly will perform
   // multiple queries relating to a destination node.
   worklist.push_back(Dst);
@@ -58,7 +58,7 @@ void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
     if (visited[block->getBlockID()])
       continue;
     visited[block->getBlockID()] = true;
-    
+
     // Update reachability information for this node -> Dst
     if (!firstRun) {
       // Don't insert Dst -> Dst unless it was a predecessor of itself
@@ -66,7 +66,7 @@ void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
     }
     else
       firstRun = false;
-    
+
     // Add the predecessors to the worklist.
     for (CFGBlock::const_pred_iterator i = block->pred_begin(), 
          e = block->pred_end(); i != e; ++i) {
-- 
GitLab


From 8d109915b3b02e56f04fec9c22e97c1230a3fb3d Mon Sep 17 00:00:00 2001
From: Erik Pilkington 
Date: Sat, 28 Jul 2018 01:29:31 +0000
Subject: [PATCH 0763/1023] Compile SemaTemplate.cpp with /bigobj on MSVC

This should fix some bot failures introduced by r338165.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338186 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index bad42a2ce2..3d21d79f2b 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
 if (MSVC)
   set_source_files_properties(SemaDeclAttr.cpp PROPERTIES COMPILE_FLAGS /bigobj)
   set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj)
+  set_source_files_properties(SemaTemplate.cpp PROPERTIES COMPILE_FLAGS /bigobj)
 endif()
 
 add_clang_library(clangSema
-- 
GitLab


From e7b4d96d686d72107432d1a316522d7d91fb0cb0 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Sat, 28 Jul 2018 02:16:13 +0000
Subject: [PATCH 0764/1023] [AST] Add a convenient getter from QualType to
 RecordDecl

Differential Revision: https://reviews.llvm.org/D49951

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338187 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/Type.h              | 3 +++
 lib/AST/Decl.cpp                      | 9 +++------
 lib/AST/Type.cpp                      | 4 ++++
 lib/Analysis/BodyFarm.cpp             | 2 +-
 lib/CodeGen/CGExprConstant.cpp        | 3 +--
 lib/CodeGen/CGRecordLayoutBuilder.cpp | 5 ++---
 6 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index c692707847..81e799c3ba 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -2017,6 +2017,9 @@ public:
   /// type of a class template or class template partial specialization.
   CXXRecordDecl *getAsCXXRecordDecl() const;
 
+  /// Retrieves the RecordDecl this type refers to.
+  RecordDecl *getAsRecordDecl() const;
+
   /// Retrieves the TagDecl that this type refers to, either
   /// because the type is a TagType or because it is the injected-class-name
   /// type of a class template or class template partial specialization.
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3b9b85a20a..b85e82d56d 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3149,12 +3149,9 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
 
 const Attr *FunctionDecl::getUnusedResultAttr() const {
   QualType RetType = getReturnType();
-  if (RetType->isRecordType()) {
-    if (const auto *Ret =
-            dyn_cast_or_null(RetType->getAsTagDecl())) {
-      if (const auto *R = Ret->getAttr())
-        return R;
-    }
+  if (const auto *Ret = RetType->getAsRecordDecl()) {
+    if (const auto *R = Ret->getAttr())
+      return R;
   } else if (const auto *ET = RetType->getAs()) {
     if (const EnumDecl *ED = ET->getDecl()) {
       if (const auto *R = ED->getAttr())
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index fad8c0d1c6..64d16c4783 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1628,6 +1628,10 @@ CXXRecordDecl *Type::getAsCXXRecordDecl() const {
   return dyn_cast_or_null(getAsTagDecl());
 }
 
+RecordDecl *Type::getAsRecordDecl() const {
+  return dyn_cast_or_null(getAsTagDecl());
+}
+
 TagDecl *Type::getAsTagDecl() const {
   if (const auto *TT = getAs())
     return TT->getDecl();
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index b9fb15b2db..05a311e5b2 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -342,7 +342,7 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
   // Nullable pointer, non-null iff function is a CXXRecordDecl.
   CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
   QualType FlagType = Flag->getType().getNonReferenceType();
-  auto *FlagRecordDecl = dyn_cast_or_null(FlagType->getAsTagDecl());
+  auto *FlagRecordDecl = FlagType->getAsRecordDecl();
 
   if (!FlagRecordDecl) {
     LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: "
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index cfd0b85923..a738ecb0a3 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -2064,8 +2064,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
     if (record->isUnion()) {
       if (Field->getIdentifier())
         break;
-      if (const auto *FieldRD =
-              dyn_cast_or_null(Field->getType()->getAsTagDecl()))
+      if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
         if (FieldRD->findFirstNamedDataMember())
           break;
     }
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 4ee6c8e714..a38df508dc 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -313,9 +313,8 @@ void CGRecordLowering::lowerUnion() {
     if (!SeenNamedMember) {
       SeenNamedMember = Field->getIdentifier();
       if (!SeenNamedMember)
-        if (const auto *FieldRD =
-                dyn_cast_or_null(Field->getType()->getAsTagDecl()))
-        SeenNamedMember = FieldRD->findFirstNamedDataMember();
+        if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
+          SeenNamedMember = FieldRD->findFirstNamedDataMember();
       if (SeenNamedMember && !isZeroInitializable(Field)) {
         IsZeroInitializable = IsZeroInitializableAsBase = false;
         StorageType = FieldType;
-- 
GitLab


From 3c1089c07193f11d6d94c3aac5c0e7cae46ed75d Mon Sep 17 00:00:00 2001
From: Yaxun Liu 
Date: Sat, 28 Jul 2018 03:05:25 +0000
Subject: [PATCH 0765/1023] [CUDA][HIP] Allow function-scope static const
 variable

CUDA 8.0 E.3.9.4 says: Within the body of a __device__ or __global__
function, only __shared__ variables or variables without any device
memory qualifiers may be declared with static storage class.

It is unclear how a function-scope non-const static variable
without device memory qualifier is implemented, therefore only static
const variable without device memory qualifier is allowed, which
can be emitted as a global variable in constant address space.

Currently clang only allows function-scope static variable with
__shared__ qualifier.

This patch also allows function-scope static const variable without
device memory qualifier and emits it as a global variable in constant
address space.

Differential Revision: https://reviews.llvm.org/D49931


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338188 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td |  3 ++-
 lib/CodeGen/CodeGenModule.cpp              |  4 ++++
 lib/Sema/SemaDecl.cpp                      | 27 +++++++++++++++-------
 test/CodeGenCUDA/device-var-init.cu        |  6 +++++
 test/SemaCUDA/device-var-init.cu           | 13 +++++++----
 5 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d0a2bec780..b2ad27328a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7129,7 +7129,8 @@ def err_shared_var_init : Error<
     "initialization is not supported for __shared__ variables.">;
 def err_device_static_local_var : Error<
     "within a %select{__device__|__global__|__host__|__host__ __device__}0 "
-    "function, only __shared__ variables may be marked 'static'">;
+    "function, only __shared__ variables or const variables without device "
+    "memory qualifier may be marked 'static'">;
 def err_cuda_vla : Error<
     "cannot use variable-length arrays in "
     "%select{__device__|__global__|__host__|__host__ __device__}0 functions">;
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index ecdf78d4b3..ae2c134c45 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -3176,6 +3176,10 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
       return LangAS::cuda_constant;
     else if (D && D->hasAttr())
       return LangAS::cuda_shared;
+    else if (D && D->hasAttr())
+      return LangAS::cuda_device;
+    else if (D && D->getType().isConstQualified())
+      return LangAS::cuda_constant;
     else
       return LangAS::cuda_device;
   }
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 55542828f7..6bee72a398 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -11914,14 +11914,25 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
         NewAttr->setInherited(true);
         VD->addAttr(NewAttr);
       }
-      // CUDA E.2.9.4: Within the body of a __device__ or __global__
-      // function, only __shared__ variables may be declared with
-      // static storage class.
-      if (getLangOpts().CUDA && !VD->hasAttr() &&
-          CUDADiagIfDeviceCode(VD->getLocation(),
-                               diag::err_device_static_local_var)
-              << CurrentCUDATarget())
-        VD->setInvalidDecl();
+      // CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
+      // function, only __shared__ variables or variables without any device
+      // memory qualifiers may be declared with static storage class.
+      // Note: It is unclear how a function-scope non-const static variable
+      // without device memory qualifier is implemented, therefore only static
+      // const variable without device memory qualifier is allowed.
+      [&]() {
+        if (!getLangOpts().CUDA)
+          return;
+        if (VD->hasAttr())
+          return;
+        if (VD->getType().isConstQualified() &&
+            !(VD->hasAttr() || VD->hasAttr()))
+          return;
+        if (CUDADiagIfDeviceCode(VD->getLocation(),
+                                 diag::err_device_static_local_var)
+            << CurrentCUDATarget())
+          VD->setInvalidDecl();
+      }();
     }
   }
 
diff --git a/test/CodeGenCUDA/device-var-init.cu b/test/CodeGenCUDA/device-var-init.cu
index 9f788b764f..f96e42d971 100644
--- a/test/CodeGenCUDA/device-var-init.cu
+++ b/test/CodeGenCUDA/device-var-init.cu
@@ -112,6 +112,9 @@ __constant__ EC_I_EC c_ec_i_ec;
 // CHECK: @_ZZ2dfvE4s_ec = internal addrspace(3) global %struct.EC undef
 // CHECK: @_ZZ2dfvE5s_etc = internal addrspace(3) global %struct.ETC undef
 
+// CHECK: @_ZZ2dfvE11const_array = internal addrspace(4) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
+// CHECK: @_ZZ2dfvE9const_int = internal addrspace(4) constant i32 123
+
 // We should not emit global initializers for device-side variables.
 // CHECK-NOT: @__cxx_global_var_init
 
@@ -234,6 +237,9 @@ __device__ void df() {
   static __shared__ ETC s_etc;
   // CHECK-NOT: call void @_ZN3ETCC1IJEEEDpT_(%struct.ETC* addrspacecast (%struct.ETC addrspace(3)* @_ZZ2dfvE5s_etc to %struct.ETC*))
 
+  static const int const_array[] = {1, 2, 3, 4, 5};
+  static const int const_int = 123;
+
   // anchor point separating constructors and destructors
   df(); // CHECK: call void @_Z2dfv()
 
diff --git a/test/SemaCUDA/device-var-init.cu b/test/SemaCUDA/device-var-init.cu
index 46cb90da2e..dd5d19a6a2 100644
--- a/test/SemaCUDA/device-var-init.cu
+++ b/test/SemaCUDA/device-var-init.cu
@@ -207,17 +207,22 @@ __device__ void df_sema() {
   // expected-error@-1 {{initialization is not supported for __shared__ variables.}}
 
   static __device__ int ds;
-  // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
+  // expected-error@-1 {{within a __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
   static __constant__ int dc;
-  // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
+  // expected-error@-1 {{within a __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
   static int v;
-  // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
+  // expected-error@-1 {{within a __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
+  static const int cv = 1;
+  static const __device__ int cds = 1;
+  // expected-error@-1 {{within a __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
+  static const __constant__ int cdc = 1;
+  // expected-error@-1 {{within a __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
 }
 
 __host__ __device__ void hd_sema() {
   static int x = 42;
 #ifdef __CUDA_ARCH__
-  // expected-error@-2 {{within a __host__ __device__ function, only __shared__ variables may be marked 'static'}}
+  // expected-error@-2 {{within a __host__ __device__ function, only __shared__ variables or const variables without device memory qualifier may be marked 'static'}}
 #endif
 }
 
-- 
GitLab


From 9b9b7f28bd98eb00ba4a1e7a60f4d504f0e39232 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka 
Date: Sat, 28 Jul 2018 04:06:13 +0000
Subject: [PATCH 0766/1023] [Sema][ObjC] Warn when a method declared in a
 protocol takes a non-escaping parameter but the implementation's method takes
 an escaping parameter.

rdar://problem/39548196

Differential Revision: https://reviews.llvm.org/D49119

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338189 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td |  2 +
 lib/Sema/SemaDeclObjC.cpp                  | 48 ++++++++++++++++++----
 test/SemaObjCXX/noescape.mm                | 39 ++++++++++++++++++
 3 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index b2ad27328a..8ad9049227 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1733,6 +1733,8 @@ def warn_overriding_method_missing_noescape : Warning<
   "__attribute__((noescape))">, InGroup;
 def note_overridden_marked_noescape : Note<
   "parameter of overridden method is annotated with __attribute__((noescape))">;
+def note_cat_conform_to_noescape_prot : Note<
+  "%select{category|class extension}0 conforms to protocol %1 which defines method %2">;
 
 def err_covariant_return_inaccessible_base : Error<
   "invalid covariant return for virtual function: %1 is a "
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index e1b033ea82..ab0ff0c4c9 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -109,6 +109,30 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
   return true;
 }
 
+/// Issue a warning if the parameter of the overridden method is non-escaping
+/// but the parameter of the overriding method is not.
+static bool diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
+                             Sema &S) {
+  if (OldD->hasAttr() && !NewD->hasAttr()) {
+    S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape);
+    S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape);
+    return false;
+  }
+
+  return true;
+}
+
+/// Produce additional diagnostics if a category conforms to a protocol that
+/// defines a method taking a non-escaping parameter.
+static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
+                             const ObjCCategoryDecl *CD,
+                             const ObjCProtocolDecl *PD, Sema &S) {
+  if (!diagnoseNoescape(NewD, OldD, S))
+    S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot)
+        << CD->IsClassExtension() << PD
+        << cast(NewD->getDeclContext());
+}
+
 void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, 
                                    const ObjCMethodDecl *Overridden) {
   if (Overridden->hasRelatedResultType() && 
@@ -192,13 +216,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
       Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";
     }
 
-    // A parameter of the overriding method should be annotated with noescape
-    // if the corresponding parameter of the overridden method is annotated.
-    if (oldDecl->hasAttr() && !newDecl->hasAttr()) {
-      Diag(newDecl->getLocation(),
-           diag::warn_overriding_method_missing_noescape);
-      Diag(oldDecl->getLocation(), diag::note_overridden_marked_noescape);
-    }
+    diagnoseNoescape(newDecl, oldDecl, *this);
   }
 }
 
@@ -4643,6 +4661,22 @@ Decl *Sema::ActOnMethodDeclaration(
             << ObjCMethod->getDeclName();
         }
       }
+
+      // Warn if a method declared in a protocol to which a category or
+      // extension conforms is non-escaping and the implementation's method is
+      // escaping.
+      for (auto *C : IDecl->visible_categories())
+        for (auto &P : C->protocols())
+          if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(),
+                                          ObjCMethod->isInstanceMethod())) {
+            assert(ObjCMethod->parameters().size() ==
+                       IMD->parameters().size() &&
+                   "Methods have different number of parameters");
+            auto OI = IMD->param_begin(), OE = IMD->param_end();
+            auto NI = ObjCMethod->param_begin();
+            for (; OI != OE; ++OI, ++NI)
+              diagnoseNoescape(*NI, *OI, C, P, *this);
+          }
     }
   } else {
     cast(ClassDecl)->addDecl(ObjCMethod);
diff --git a/test/SemaObjCXX/noescape.mm b/test/SemaObjCXX/noescape.mm
index 6c5d9897aa..9432a3a48a 100644
--- a/test/SemaObjCXX/noescape.mm
+++ b/test/SemaObjCXX/noescape.mm
@@ -88,3 +88,42 @@ void test0() {
 
   S5<&noescapeFunc2> ne1;
 }
+
+@protocol NoescapeProt
+-(void) m0:(int*)__attribute__((noescape)) p; // expected-note 2 {{parameter of overridden method is annotated with __attribute__((noescape))}}
++(void) m1:(int*)__attribute__((noescape)) p;
+-(void) m1:(int*) p;
+@end
+
+__attribute__((objc_root_class))
+@interface C3
+-(void) m0:(int*) p;
++(void) m1:(int*)__attribute__((noescape)) p;
+-(void) m1:(int*) p;
+@end
+
+@interface C3 ()  // expected-note {{class extension conforms to protocol 'NoescapeProt' which defines method 'm0:'}}
+@end
+
+@implementation C3
+-(void) m0:(int*) p { // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
+}
++(void) m1:(int*)__attribute__((noescape)) p {
+}
+-(void) m1:(int*) p {
+}
+@end
+
+__attribute__((objc_root_class))
+@interface C4 
+-(void) m0:(int*) p; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
+@end
+
+@implementation C4
+-(void) m0:(int*) p {
+}
++(void) m1:(int*)__attribute__((noescape)) p {
+}
+-(void) m1:(int*) p {
+}
+@end
-- 
GitLab


From 3ed5b235b1148ad0c5bf9bc69c5bb92a1859eea8 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Sat, 28 Jul 2018 15:33:03 +0000
Subject: [PATCH 0767/1023] [UBSan] Strengthen pointer checks in 'new'
 expressions

With this change compiler generates alignment checks for wider range
of types. Previously such checks were generated only for the record types
with non-trivial default constructor. So the types like:

    struct alignas(32) S2 { int x; };
    typedef __attribute__((ext_vector_type(2), aligned(32))) float float32x2_t;

did not get checks when allocated by 'new' expression.

This change also optimizes the checks generated for the arrays created
in 'new' expressions. Previously the check was generated for each
invocation of type constructor. Now the check is generated only once
for entire array.

Differential Revision: https://reviews.llvm.org/D49589


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338199 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/CGClass.cpp              |  46 +++++----
 lib/CodeGen/CGExprCXX.cpp            |  20 +++-
 lib/CodeGen/CGValue.h                |  21 +++-
 lib/CodeGen/CodeGenFunction.h        |   8 +-
 test/CodeGenCXX/ubsan-new-checks.cpp | 146 +++++++++++++++++++++++++++
 5 files changed, 215 insertions(+), 26 deletions(-)
 create mode 100644 test/CodeGenCXX/ubsan-new-checks.cpp

diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 0b9311f777..c1915e4d0c 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -685,7 +685,10 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
             AggValueSlot::IsDestructed,
             AggValueSlot::DoesNotNeedGCBarriers,
             AggValueSlot::IsNotAliased,
-            overlapForFieldInit(Field));
+            overlapForFieldInit(Field),
+            AggValueSlot::IsNotZeroed,
+            // Checks are made by the code that calls constructor.
+            AggValueSlot::IsSanitizerChecked);
     EmitAggExpr(Init, Slot);
     break;
   }
@@ -1869,12 +1872,14 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
 ///   zero-initialized before it is constructed
 void CodeGenFunction::EmitCXXAggrConstructorCall(
     const CXXConstructorDecl *ctor, const ArrayType *arrayType,
-    Address arrayBegin, const CXXConstructExpr *E, bool zeroInitialize) {
+    Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked,
+    bool zeroInitialize) {
   QualType elementType;
   llvm::Value *numElements =
     emitArrayLength(arrayType, elementType, arrayBegin);
 
-  EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E, zeroInitialize);
+  EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E,
+                             NewPointerIsChecked, zeroInitialize);
 }
 
 /// EmitCXXAggrConstructorCall - Emit a loop to call a particular
@@ -1890,6 +1895,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
                                                  llvm::Value *numElements,
                                                  Address arrayBase,
                                                  const CXXConstructExpr *E,
+                                                 bool NewPointerIsChecked,
                                                  bool zeroInitialize) {
   // It's legal for numElements to be zero.  This can happen both
   // dynamically, because x can be zero in 'new A[x]', and statically,
@@ -1966,7 +1972,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
 
     EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
                            /*Delegating=*/false, curAddr, E,
-                           AggValueSlot::DoesNotOverlap);
+                           AggValueSlot::DoesNotOverlap, NewPointerIsChecked);
   }
 
   // Go to the next element.
@@ -2002,7 +2008,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
                                              bool ForVirtualBase,
                                              bool Delegating, Address This,
                                              const CXXConstructExpr *E,
-                                             AggValueSlot::Overlap_t Overlap) {
+                                             AggValueSlot::Overlap_t Overlap,
+                                             bool NewPointerIsChecked) {
   CallArgList Args;
 
   // Push the this ptr.
@@ -2031,7 +2038,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
                /*ParamsToSkip*/ 0, Order);
 
   EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args,
-                         Overlap, E->getExprLoc());
+                         Overlap, E->getExprLoc(), NewPointerIsChecked);
 }
 
 static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
@@ -2065,14 +2072,13 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
                                              Address This,
                                              CallArgList &Args,
                                              AggValueSlot::Overlap_t Overlap,
-                                             SourceLocation Loc) {
+                                             SourceLocation Loc,
+                                             bool NewPointerIsChecked) {
   const CXXRecordDecl *ClassDecl = D->getParent();
 
-  // C++11 [class.mfct.non-static]p2:
-  //   If a non-static member function of a class X is called for an object that
-  //   is not of type X, or of a type derived from X, the behavior is undefined.
-  EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc,
-                This.getPointer(), getContext().getRecordType(ClassDecl));
+  if (!NewPointerIsChecked)
+    EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(),
+                  getContext().getRecordType(ClassDecl), CharUnits::Zero());
 
   if (D->isTrivial() && D->isDefaultConstructor()) {
     assert(Args.size() == 1 && "trivial default ctor with args");
@@ -2181,7 +2187,7 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
 
   EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
                          This, Args, AggValueSlot::MayOverlap,
-                         E->getLocation());
+                         E->getLocation(), /*NewPointerIsChecked*/true);
 }
 
 void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
@@ -2277,8 +2283,10 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
   EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
                /*ParamsToSkip*/ 1);
 
-  EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args,
-                         AggValueSlot::MayOverlap, E->getExprLoc());
+  EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false,
+                         /*Delegating*/false, This, Args,
+                         AggValueSlot::MayOverlap, E->getExprLoc(),
+                         /*NewPointerIsChecked*/false);
 }
 
 void
@@ -2314,7 +2322,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
 
   EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
                          /*Delegating=*/true, This, DelegateArgs,
-                         AggValueSlot::MayOverlap, Loc);
+                         AggValueSlot::MayOverlap, Loc,
+                         /*NewPointerIsChecked=*/true);
 }
 
 namespace {
@@ -2346,7 +2355,10 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
                           AggValueSlot::IsDestructed,
                           AggValueSlot::DoesNotNeedGCBarriers,
                           AggValueSlot::IsNotAliased,
-                          AggValueSlot::MayOverlap);
+                          AggValueSlot::MayOverlap,
+                          AggValueSlot::IsNotZeroed,
+                          // Checks are made by the code that calls constructor.
+                          AggValueSlot::IsSanitizerChecked);
 
   EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
 
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 8955d8a4a8..26cb42ce03 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -607,7 +607,8 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
   
   if (const ArrayType *arrayType
         = getContext().getAsArrayType(E->getType())) {
-    EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E);
+    EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E,
+                               Dest.isSanitizerChecked());
   } else {
     CXXCtorType Type = Ctor_Complete;
     bool ForVirtualBase = false;
@@ -634,7 +635,8 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
     
     // Call the constructor.
     EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating,
-                           Dest.getAddress(), E, Dest.mayOverlap());
+                           Dest.getAddress(), E, Dest.mayOverlap(),
+                           Dest.isSanitizerChecked());
   }
 }
 
@@ -954,7 +956,8 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
                               AggValueSlot::IsDestructed,
                               AggValueSlot::DoesNotNeedGCBarriers,
                               AggValueSlot::IsNotAliased,
-                              MayOverlap);
+                              MayOverlap, AggValueSlot::IsNotZeroed,
+                              AggValueSlot::IsSanitizerChecked);
     CGF.EmitAggExpr(Init, Slot);
     return;
   }
@@ -1024,7 +1027,9 @@ void CodeGenFunction::EmitNewArrayInitializer(
                                 AggValueSlot::IsDestructed,
                                 AggValueSlot::DoesNotNeedGCBarriers,
                                 AggValueSlot::IsNotAliased,
-                                AggValueSlot::DoesNotOverlap);
+                                AggValueSlot::DoesNotOverlap,
+                                AggValueSlot::IsNotZeroed,
+                                AggValueSlot::IsSanitizerChecked);
       EmitAggExpr(ILE->getInit(0), Slot);
 
       // Move past these elements.
@@ -1154,6 +1159,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
           NumElements,
           llvm::ConstantInt::get(NumElements->getType(), InitListElements));
     EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE,
+                               /*NewPointerIsChecked*/true,
                                CCE->requiresZeroInitialization());
     return;
   }
@@ -1705,6 +1711,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
     result = Address(Builder.CreateLaunderInvariantGroup(result.getPointer()),
                      result.getAlignment());
 
+  // Emit sanitizer checks for pointer value now, so that in the case of an
+  // array it was checked only once and not at each constructor call.
+  EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall,
+      E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+      result.getPointer(), allocType);
+
   EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
                      allocSizeWithoutCookie);
   if (E->isArray()) {
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 418bda1f41..60f205932b 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -479,12 +479,20 @@ class AggValueSlot {
   /// the size of the type.
   bool OverlapFlag : 1;
 
+  /// If is set to true, sanitizer checks are already generated for this address
+  /// or not required. For instance, if this address represents an object
+  /// created in 'new' expression, sanitizer checks for memory is made as a part
+  /// of 'operator new' emission and object constructor should not generate
+  /// them.
+  bool SanitizerCheckedFlag : 1;
+
 public:
   enum IsAliased_t { IsNotAliased, IsAliased };
   enum IsDestructed_t { IsNotDestructed, IsDestructed };
   enum IsZeroed_t { IsNotZeroed, IsZeroed };
   enum Overlap_t { DoesNotOverlap, MayOverlap };
   enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
+  enum IsSanitizerChecked_t { IsNotSanitizerChecked, IsSanitizerChecked };
 
   /// ignored - Returns an aggregate value slot indicating that the
   /// aggregate value is being ignored.
@@ -509,7 +517,8 @@ public:
                               NeedsGCBarriers_t needsGC,
                               IsAliased_t isAliased,
                               Overlap_t mayOverlap,
-                              IsZeroed_t isZeroed = IsNotZeroed) {
+                              IsZeroed_t isZeroed = IsNotZeroed,
+                       IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) {
     AggValueSlot AV;
     if (addr.isValid()) {
       AV.Addr = addr.getPointer();
@@ -524,6 +533,7 @@ public:
     AV.ZeroedFlag = isZeroed;
     AV.AliasedFlag = isAliased;
     AV.OverlapFlag = mayOverlap;
+    AV.SanitizerCheckedFlag = isChecked;
     return AV;
   }
 
@@ -532,9 +542,10 @@ public:
                                 NeedsGCBarriers_t needsGC,
                                 IsAliased_t isAliased,
                                 Overlap_t mayOverlap,
-                                IsZeroed_t isZeroed = IsNotZeroed) {
+                                IsZeroed_t isZeroed = IsNotZeroed,
+                       IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) {
     return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC,
-                   isAliased, mayOverlap, isZeroed);
+                   isAliased, mayOverlap, isZeroed, isChecked);
   }
 
   IsDestructed_t isExternallyDestructed() const {
@@ -586,6 +597,10 @@ public:
     return Overlap_t(OverlapFlag);
   }
 
+  bool isSanitizerChecked() const {
+    return SanitizerCheckedFlag;
+  }
+
   RValue asRValue() const {
     if (isIgnored()) {
       return RValue::getIgnored();
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 79870ed59c..1f8f3367db 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2490,13 +2490,15 @@ public:
   void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
                               bool ForVirtualBase, bool Delegating,
                               Address This, const CXXConstructExpr *E,
-                              AggValueSlot::Overlap_t Overlap);
+                              AggValueSlot::Overlap_t Overlap,
+                              bool NewPointerIsChecked);
 
   void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
                               bool ForVirtualBase, bool Delegating,
                               Address This, CallArgList &Args,
                               AggValueSlot::Overlap_t Overlap,
-                              SourceLocation Loc);
+                              SourceLocation Loc,
+                              bool NewPointerIsChecked);
 
   /// Emit assumption load for all bases. Requires to be be called only on
   /// most-derived class and not under construction of the object.
@@ -2513,12 +2515,14 @@ public:
                                   const ArrayType *ArrayTy,
                                   Address ArrayPtr,
                                   const CXXConstructExpr *E,
+                                  bool NewPointerIsChecked,
                                   bool ZeroInitialization = false);
 
   void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
                                   llvm::Value *NumElements,
                                   Address ArrayPtr,
                                   const CXXConstructExpr *E,
+                                  bool NewPointerIsChecked,
                                   bool ZeroInitialization = false);
 
   static Destroyer destroyCXXObject;
diff --git a/test/CodeGenCXX/ubsan-new-checks.cpp b/test/CodeGenCXX/ubsan-new-checks.cpp
new file mode 100644
index 0000000000..019fcf15a2
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-new-checks.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -S -emit-llvm -fsanitize=alignment %s -o - | FileCheck %s
+
+struct alignas(32) S1 {
+  int x;
+  S1();
+};
+
+struct alignas(32) S2 {
+  int x;
+};
+
+struct alignas(32) S3 {
+  int x;
+  S3(int *p = new int[4]);
+};
+
+struct S4 : public S3 {
+  S4() : S3() {}
+};
+
+typedef __attribute__((ext_vector_type(2), aligned(32))) float float32x2_t;
+
+struct S5 {
+  float32x2_t x;
+};
+
+void *operator new (unsigned long, void *p) { return p; }
+void *operator new[] (unsigned long, void *p) { return p; }
+
+S1 *func_01() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_01v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       call void @_ZN2S1C1Ev(
+  // CHECK-NOT:   and i64 %{{.*}}, 31
+  // CHECK:       ret %struct.S1*
+  return new S1[20];
+}
+
+S2 *func_02() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_02v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret %struct.S2*
+  return new S2;
+}
+
+S2 *func_03() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_03v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64 %{{.*}}, 31
+  // CHECK:       ret %struct.S2*
+  return new S2[20];
+}
+
+float32x2_t *func_04() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_04v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret <2 x float>*
+  return new float32x2_t;
+}
+
+float32x2_t *func_05() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_05v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64 %{{.*}}, 31
+  // CHECK:       ret <2 x float>*
+  return new float32x2_t[20];
+}
+
+S3 *func_07() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_07v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       and i64 %{{.*}}, 3, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret %struct.S3*
+  return new S3;
+}
+
+S3 *func_08() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_08v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       and i64 %{{.*}}, 3, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret %struct.S3*
+  return new S3[10];
+}
+
+
+S2 *func_10(void *p) {
+  // CHECK-LABEL: define {{.*}} @_Z7func_10Pv
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret %struct.S2*
+  return new(p) S2;
+}
+
+S2 *func_11(void *p) {
+  // CHECK-LABEL: define {{.*}} @_Z7func_11Pv
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64 %{{.*}}, 31, !nosanitize
+  // CHECK-NOT:   icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret %struct.S2*
+  return new(p) S2[10];
+}
+
+float32x2_t *func_12() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_12v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK:       ret <2 x float>*
+  return new float32x2_t;
+}
+
+float32x2_t *func_13() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_13v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64 %{{.*}}, 31
+  // CHECK:       ret <2 x float>*
+  return new float32x2_t[20];
+}
+
+S4 *func_14() {
+  // CHECK-LABEL: define {{.*}} @_Z7func_14v
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64 %{{.*}}, 31
+  // CHECK:       ret %struct.S4*
+  return new S4;
+}
+
+S5 *func_15(const S5 *ptr) {
+  // CHECK-LABEL: define {{.*}} @_Z7func_15PK2S5
+  // CHECK:       and i64 %{{.*}}, 31, !nosanitize
+  // CHECK:       icmp eq i64 %{{.*}}, 0, !nosanitize
+  // CHECK-NOT:   and i64
+  // CHECK:       ret %struct.S5*
+  return new S5(*ptr);
+}
-- 
GitLab


From a3ba348aeea36f4cd6155854364e088bfd66d14d Mon Sep 17 00:00:00 2001
From: Chandler Carruth 
Date: Sun, 29 Jul 2018 03:05:07 +0000
Subject: [PATCH 0768/1023] Revert r337456: [CodeGen] Disable aggressive
 structor optimizations at -O0, take 3

This commit increases the number of sections and overall output size of
.o files by 10% and sometimes a bit more. This alone is challenging for
some users, but it also appears to trigger an as-yet unexplained
behavior in the Gold linker where the memory usage increases
considerably more than 10% (we think).

The increase is also frustrating because in many (if not all) cases we
end up with almost all of the growth coming from the ELF overhead of
-ffunction-sections and such, not from actual extra code being emitted.

Richard Smith and Eric Christopher are both going to investigate this
and try to get to the bottom of what is triggering this and whether the
kinds of increases here are sustainable or what options we might have to
minimize the impact they have. However, this is currently breaking
a pretty large number of our users' builds so reverting it while we sort
out how to make progress here. I've seen a longer and more detailed
update to the commit thread.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338209 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/ItaniumCXXABI.cpp            | 18 +++--------
 test/CodeGenCXX/ctor-dtor-alias.cpp      | 41 +++++-------------------
 test/CodeGenCXX/float16-declarations.cpp |  2 +-
 3 files changed, 13 insertions(+), 48 deletions(-)

diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 16fdd1c16a..00fff144b5 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3744,22 +3744,12 @@ static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
   }
   llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
 
-  // All discardable structors can be RAUWed, but we don't want to do that in
-  // unoptimized code, as that makes complete structor symbol disappear
-  // completely, which degrades debugging experience.
-  // Symbols with private linkage can be safely aliased, so we special case them
-  // here.
-  if (llvm::GlobalValue::isLocalLinkage(Linkage))
-    return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW
-                                                      : StructorCodegen::Alias;
+  if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
+    return StructorCodegen::RAUW;
 
-  // Linkonce structors cannot be aliased nor placed in a comdat, so these need
-  // to be emitted separately.
   // FIXME: Should we allow available_externally aliases?
-  if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) ||
-      !llvm::GlobalAlias::isValidLinkage(Linkage))
-    return CGM.getCodeGenOpts().OptimizationLevel > 0 ? StructorCodegen::RAUW
-                                                      : StructorCodegen::Emit;
+  if (!llvm::GlobalAlias::isValidLinkage(Linkage))
+    return StructorCodegen::RAUW;
 
   if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
     // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
index 4715111a14..89244cc105 100644
--- a/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases > %t
-// RUN: FileCheck --check-prefix=NOOPT1 --input-file=%t %s
-// RUN: FileCheck --check-prefix=NOOPT2 --input-file=%t %s
-// RUN: FileCheck --check-prefix=NOOPT3 --input-file=%t %s
+// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
+
 // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes > %t
 // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s
 // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s
@@ -23,13 +21,6 @@ namespace test1 {
 // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
 // CHECK1-NOT: comdat
 
-// This should happen regardless of the opt level.
-// NOOPT1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev
-// NOOPT1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
-// NOOPT1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev)
-// NOOPT1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
-// NOOPT1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
-
 // COFF doesn't support comdats with arbitrary names (C5/D5).
 // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC2Ev({{.*}} comdat align
 // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC1Ev({{.*}} comdat align
@@ -46,17 +37,12 @@ template struct foobar;
 }
 
 namespace test2 {
-// test that when the destructor is linkonce_odr we just replace every use of
+// test that when the destrucor is linkonce_odr we just replace every use of
 // C1 with C2.
 
 // CHECK1: define internal void @__cxx_global_var_init()
 // CHECK1: call void @_ZN5test26foobarIvEC2Ev
 // CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev({{.*}} comdat align
-
-// At -O0, we should still emit the complete constructor.
-// NOOPT1: define internal void @__cxx_global_var_init()
-// NOOPT1: call void @_ZN5test26foobarIvEC1Ev
-// NOOPT1: define linkonce_odr void @_ZN5test26foobarIvEC1Ev({{.*}} comdat align
 void g();
 template  struct foobar {
   foobar() { g(); }
@@ -71,11 +57,6 @@ namespace test3 {
 // CHECK1: define internal void @__cxx_global_var_init.1()
 // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
 // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
-
-// We can use an alias for internal symbols at -O0.
-// NOOPT2: _ZN5test312_GLOBAL__N_11BD1Ev = internal unnamed_addr alias void {{.*}} @_ZN5test312_GLOBAL__N_11BD2Ev
-// NOOPT2: define internal void @__cxx_global_var_init.1()
-// NOOPT2: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11BD1Ev
 namespace {
 struct A {
   ~A() {}
@@ -96,12 +77,11 @@ namespace test4 {
   // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
   // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align
 
-  // Test that we don't do this optimization at -O0 and call the complete
-  // destructor for B instead. This enables the debugger to see both
-  // destructors.
-  // NOOPT2: define internal void @__cxx_global_var_init.2()
-  // NOOPT2: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD1Ev
-  // NOOPT2: define linkonce_odr void @_ZN5test41BD1Ev({{.*}} comdat align
+  // test that we don't do this optimization at -O0 so that the debugger can
+  // see both destructors.
+  // NOOPT: define internal void @__cxx_global_var_init.2()
+  // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
+  // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align
   struct A {
     virtual ~A() {}
   };
@@ -149,11 +129,6 @@ namespace test7 {
   // out if we should).
   // pr17875.
   // CHECK3: define void @_ZN5test71BD2Ev
-
-  // At -O0, we should emit both destructors, the complete can be an alias to
-  // the base one.
-  // NOOPT3: @_ZN5test71BD1Ev = unnamed_addr alias void {{.*}} @_ZN5test71BD2Ev
-  // NOOPT3: define void @_ZN5test71BD2Ev
   template  struct A {
     ~A() {}
   };
diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp
index 1d6999fef0..e82c05ec8c 100644
--- a/test/CodeGenCXX/float16-declarations.cpp
+++ b/test/CodeGenCXX/float16-declarations.cpp
@@ -103,7 +103,7 @@ int main(void) {
 
   C1 c1(f1l);
 // CHECK-DAG:  [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2
-// CHECK-DAG:  call void @_ZN2C1C1EDF16_(%class.C1* %{{.*}}, half %{{.*}})
+// CHECK-DAG:  call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}})
 
   S1<_Float16> s1 = { 132.f16 };
 // CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
-- 
GitLab


From 884df2d15b81bdc0bdb562af2ba90586848a48b7 Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Mon, 30 Jul 2018 07:19:54 +0000
Subject: [PATCH 0769/1023] PR38355 Prevent infinite recursion when checking
 initializer lifetime if an initializer is self-referential.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338230 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaInit.cpp                | 3 ++-
 test/SemaCXX/warn-dangling-local.cpp | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 3ee5ec4a49..be0a74d8f8 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -6570,7 +6570,8 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
           [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
         if (auto *DRE = dyn_cast(L)) {
           auto *VD = dyn_cast(DRE->getDecl());
-          if (VD && VD->getType().isConstQualified() && VD->getInit()) {
+          if (VD && VD->getType().isConstQualified() && VD->getInit() &&
+              !isVarOnPath(Path, VD)) {
             Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
             visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true);
           }
diff --git a/test/SemaCXX/warn-dangling-local.cpp b/test/SemaCXX/warn-dangling-local.cpp
index 19a722f84d..5c1d569729 100644
--- a/test/SemaCXX/warn-dangling-local.cpp
+++ b/test/SemaCXX/warn-dangling-local.cpp
@@ -18,3 +18,9 @@ void f() {
   // points to, which doesn't live long enough.
   int *const &s = (int *const &)T{1, 2, 3}; // expected-warning {{temporary bound to local reference 's' will be destroyed at the end of the full-expression}}
 }
+
+// PR38355
+void g() {
+  const int a[] = {a[0]};
+  const int b[] = {a[0]};
+}
-- 
GitLab


From 323c6c5e527ef0ff13566ba8360581d051365bdc Mon Sep 17 00:00:00 2001
From: Krasimir Georgiev 
Date: Mon, 30 Jul 2018 08:45:45 +0000
Subject: [PATCH 0770/1023] [clang-format] Indent after breaking Javadoc
 annotated line

Summary:
This patch makes clang-format indent the subsequent lines created by breaking a
long javadoc annotated line.

Reviewers: mprobst

Reviewed By: mprobst

Subscribers: acoomans, cfe-commits

Differential Revision: https://reviews.llvm.org/D49797

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338232 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Format/BreakableToken.cpp           |  54 +++++++++++--
 lib/Format/BreakableToken.h             |  25 +++++-
 lib/Format/ContinuationIndenter.cpp     |  25 +++++-
 lib/Format/Format.cpp                   |   7 +-
 unittests/Format/FormatTestComments.cpp | 100 ++++++++++++++++++++++++
 unittests/Format/FormatTestJS.cpp       |  77 ++++++++++--------
 6 files changed, 242 insertions(+), 46 deletions(-)

diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index cc68f70100..9974ed0a51 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -235,6 +235,7 @@ BreakableToken::Split BreakableStringLiteral::getSplit(
 
 void BreakableStringLiteral::insertBreak(unsigned LineIndex,
                                          unsigned TailOffset, Split Split,
+                                         unsigned ContentIndent,
                                          WhitespaceManager &Whitespaces) const {
   Whitespaces.replaceWhitespaceInToken(
       Tok, Prefix.size() + TailOffset + Split.first, Split.second, Postfix,
@@ -510,8 +511,33 @@ unsigned BreakableBlockComment::getContentStartColumn(unsigned LineIndex,
   return std::max(0, ContentColumn[LineIndex]);
 }
 
+const llvm::StringSet<>
+    BreakableBlockComment::ContentIndentingJavadocAnnotations = {
+        "@param", "@return",     "@returns", "@throws",  "@type", "@template",
+        "@see",   "@deprecated", "@define",  "@exports", "@mods",
+};
+
+unsigned BreakableBlockComment::getContentIndent(unsigned LineIndex) const {
+  if (Style.Language != FormatStyle::LK_Java &&
+      Style.Language != FormatStyle::LK_JavaScript)
+    return 0;
+  // The content at LineIndex 0 of a comment like:
+  // /** line 0 */
+  // is "* line 0", so we need to skip over the decoration in that case.
+  StringRef ContentWithNoDecoration = Content[LineIndex];
+  if (LineIndex == 0 && ContentWithNoDecoration.startswith("*")) {
+    ContentWithNoDecoration = ContentWithNoDecoration.substr(1).ltrim(Blanks);
+  }
+  StringRef FirstWord = ContentWithNoDecoration.substr(
+      0, ContentWithNoDecoration.find_first_of(Blanks));
+  if (ContentIndentingJavadocAnnotations.find(FirstWord) !=
+      ContentIndentingJavadocAnnotations.end())
+    return Style.ContinuationIndentWidth;
+  return 0;
+}
+
 void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
-                                        Split Split,
+                                        Split Split, unsigned ContentIndent,
                                         WhitespaceManager &Whitespaces) const {
   StringRef Text = Content[LineIndex].substr(TailOffset);
   StringRef Prefix = Decoration;
@@ -532,10 +558,14 @@ void BreakableBlockComment::insertBreak(unsigned LineIndex, unsigned TailOffset,
       Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
   unsigned CharsToRemove = Split.second;
   assert(LocalIndentAtLineBreak >= Prefix.size());
+  std::string PrefixWithTrailingIndent = Prefix;
+  for (unsigned I = 0; I < ContentIndent; ++I)
+    PrefixWithTrailingIndent += " ";
   Whitespaces.replaceWhitespaceInToken(
-      tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "", Prefix,
-      InPPDirective, /*Newlines=*/1,
-      /*Spaces=*/LocalIndentAtLineBreak - Prefix.size());
+      tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
+      PrefixWithTrailingIndent, InPPDirective, /*Newlines=*/1,
+      /*Spaces=*/LocalIndentAtLineBreak + ContentIndent -
+          PrefixWithTrailingIndent.size());
 }
 
 BreakableToken::Split
@@ -543,8 +573,17 @@ BreakableBlockComment::getReflowSplit(unsigned LineIndex,
                                       llvm::Regex &CommentPragmasRegex) const {
   if (!mayReflow(LineIndex, CommentPragmasRegex))
     return Split(StringRef::npos, 0);
-
+  
+  // If we're reflowing into a line with content indent, only reflow the next
+  // line if its starting whitespace matches the content indent.
   size_t Trimmed = Content[LineIndex].find_first_not_of(Blanks);
+  if (LineIndex) {
+    unsigned PreviousContentIndent = getContentIndent(LineIndex - 1);
+    if (PreviousContentIndent && Trimmed != StringRef::npos &&
+        Trimmed != PreviousContentIndent)
+      return Split(StringRef::npos, 0);
+  }
+
   return Split(0, Trimmed != StringRef::npos ? Trimmed : 0);
 }
 
@@ -583,7 +622,8 @@ void BreakableBlockComment::adaptStartOfLine(
       // break length are the same.
       size_t BreakLength = Lines[0].substr(1).find_first_not_of(Blanks);
       if (BreakLength != StringRef::npos)
-        insertBreak(LineIndex, 0, Split(1, BreakLength), Whitespaces);
+        insertBreak(LineIndex, 0, Split(1, BreakLength), /*ContentIndent=*/0,
+                    Whitespaces);
     }
     return;
   }
@@ -754,7 +794,7 @@ unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
 
 void BreakableLineCommentSection::insertBreak(
     unsigned LineIndex, unsigned TailOffset, Split Split,
-    WhitespaceManager &Whitespaces) const {
+    unsigned ContentIndent, WhitespaceManager &Whitespaces) const {
   StringRef Text = Content[LineIndex].substr(TailOffset);
   // Compute the offset of the split relative to the beginning of the token
   // text.
diff --git a/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h
index 0fac8f08c0..a2a818f911 100644
--- a/lib/Format/BreakableToken.h
+++ b/lib/Format/BreakableToken.h
@@ -21,6 +21,7 @@
 #include "Encoding.h"
 #include "TokenAnnotator.h"
 #include "WhitespaceManager.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Regex.h"
 #include 
 
@@ -135,6 +136,19 @@ public:
   virtual unsigned getContentStartColumn(unsigned LineIndex,
                                          bool Break) const = 0;
 
+  /// Returns additional content indent required for the second line after the
+  /// content at line \p LineIndex is broken.
+  ///
+  /// For example, Javadoc @param annotations require and indent of 4 spaces and
+  /// in this example getContentIndex(1) returns 4.
+  /// /**
+  ///  * @param loooooooooooooong line
+  ///  *     continuation
+  ///  */
+  virtual unsigned getContentIndent(unsigned LineIndex) const {
+    return 0;
+  }
+
   /// Returns a range (offset, length) at which to break the line at
   /// \p LineIndex, if previously broken at \p TailOffset. If possible, do not
   /// violate \p ColumnLimit, assuming the text starting at \p TailOffset in
@@ -146,6 +160,7 @@ public:
 
   /// Emits the previously retrieved \p Split via \p Whitespaces.
   virtual void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                           unsigned ContentIndent,
                            WhitespaceManager &Whitespaces) const = 0;
 
   /// Returns the number of columns needed to format
@@ -210,7 +225,7 @@ public:
                                       Split SplitAfterLastLine,
                                       WhitespaceManager &Whitespaces) const {
     insertBreak(getLineCount() - 1, TailOffset, SplitAfterLastLine,
-                Whitespaces);
+                /*ContentIndent=*/0, Whitespaces);
   }
 
   /// Updates the next token of \p State to the next token after this
@@ -245,6 +260,7 @@ public:
                  unsigned ContentStartColumn,
                  llvm::Regex &CommentPragmasRegex) const override;
   void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                   unsigned ContentIndent,
                    WhitespaceManager &Whitespaces) const override;
   void compressWhitespace(unsigned LineIndex, unsigned TailOffset, Split Split,
                           WhitespaceManager &Whitespaces) const override {}
@@ -354,7 +370,9 @@ public:
   unsigned getRemainingLength(unsigned LineIndex, unsigned Offset,
                               unsigned StartColumn) const override;
   unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
+  unsigned getContentIndent(unsigned LineIndex) const override;
   void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                   unsigned ContentIndent,
                    WhitespaceManager &Whitespaces) const override;
   Split getReflowSplit(unsigned LineIndex,
                        llvm::Regex &CommentPragmasRegex) const override;
@@ -368,6 +386,10 @@ public:
   bool mayReflow(unsigned LineIndex,
                  llvm::Regex &CommentPragmasRegex) const override;
 
+  // Contains Javadoc annotations that require additional indent when continued
+  // on multiple lines.
+  static const llvm::StringSet<> ContentIndentingJavadocAnnotations;
+
 private:
   // Rearranges the whitespace between Lines[LineIndex-1] and Lines[LineIndex].
   //
@@ -423,6 +445,7 @@ public:
                           unsigned StartColumn) const override;
   unsigned getContentStartColumn(unsigned LineIndex, bool Break) const override;
   void insertBreak(unsigned LineIndex, unsigned TailOffset, Split Split,
+                   unsigned ContentIndent,
                    WhitespaceManager &Whitespaces) const override;
   Split getReflowSplit(unsigned LineIndex,
                        llvm::Regex &CommentPragmasRegex) const override;
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 90d2a99971..7ca588a675 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -1809,6 +1809,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
   if (!DryRun)
     Token->adaptStartOfLine(0, Whitespaces);
 
+  unsigned ContentIndent = 0;
   unsigned Penalty = 0;
   LLVM_DEBUG(llvm::dbgs() << "Breaking protruding token at column "
                           << StartColumn << ".\n");
@@ -1930,11 +1931,28 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
         }
       }
       LLVM_DEBUG(llvm::dbgs() << "    Breaking...\n");
-      ContentStartColumn =
-          Token->getContentStartColumn(LineIndex, /*Break=*/true);
+      // Update the ContentIndent only if the current line was not reflown with
+      // the previous line, since in that case the previous line should still
+      // determine the ContentIndent. Also never intent the last line.
+      if (!Reflow)
+        ContentIndent = Token->getContentIndent(LineIndex);
+      LLVM_DEBUG(llvm::dbgs()
+                 << "    ContentIndent: " << ContentIndent << "\n");
+      ContentStartColumn = ContentIndent + Token->getContentStartColumn(
+                                               LineIndex, /*Break=*/true);
+
       unsigned NewRemainingTokenColumns = Token->getRemainingLength(
           LineIndex, TailOffset + Split.first + Split.second,
           ContentStartColumn);
+      if (NewRemainingTokenColumns == 0) {
+        // No content to indent.
+        ContentIndent = 0;
+        ContentStartColumn =
+            Token->getContentStartColumn(LineIndex, /*Break=*/true);
+        NewRemainingTokenColumns = Token->getRemainingLength(
+            LineIndex, TailOffset + Split.first + Split.second,
+            ContentStartColumn);
+      }
 
       // When breaking before a tab character, it may be moved by a few columns,
       // but will still be expanded to the next tab stop, so we don't save any
@@ -1948,7 +1966,8 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
       LLVM_DEBUG(llvm::dbgs() << "    Breaking at: " << TailOffset + Split.first
                               << ", " << Split.second << "\n");
       if (!DryRun)
-        Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
+        Token->insertBreak(LineIndex, TailOffset, Split, ContentIndent,
+                           Whitespaces);
 
       Penalty += NewBreakPenalty;
       TailOffset += Split.first + Split.second;
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 59d34308c0..ec96eaa98d 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -808,10 +808,9 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
     GoogleStyle.BreakBeforeTernaryOperators = false;
-    // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot
-    // of JSDoc tags, and @see, which is commonly followed by overlong URLs.
-    GoogleStyle.CommentPragmas =
-        "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)";
+    // taze:, triple slash directives (`/// <...`), @see, which is commonly
+    // followed by overlong URLs.
+    GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|@see)";
     GoogleStyle.MaxEmptyLinesToKeep = 3;
     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
     GoogleStyle.SpacesInContainerLiterals = false;
diff --git a/unittests/Format/FormatTestComments.cpp b/unittests/Format/FormatTestComments.cpp
index cacd2024fe..2b07dedf67 100644
--- a/unittests/Format/FormatTestComments.cpp
+++ b/unittests/Format/FormatTestComments.cpp
@@ -3105,6 +3105,106 @@ TEST_F(FormatTestComments, ReflowBackslashCrash) {
 // clang-format on
 }
 
+TEST_F(FormatTestComments, IndentsLongJavadocAnnotatedLines) {
+  FormatStyle Style = getGoogleStyle(FormatStyle::LK_Java);
+  Style.ColumnLimit = 60;
+  FormatStyle Style20 = getGoogleStyle(FormatStyle::LK_Java);
+  Style20.ColumnLimit = 20;
+  EXPECT_EQ(
+      "/**\n"
+      " * @param x long long long long long long long long long\n"
+      " *     long\n"
+      " */\n",
+      format("/**\n"
+             " * @param x long long long long long long long long long long\n"
+             " */\n",
+             Style));
+  EXPECT_EQ("/**\n"
+            " * @param x long long long long long long long long long\n"
+            " *     long long long long long long long long long long\n"
+            " */\n",
+            format("/**\n"
+                   " * @param x long long long long long long long long long "
+                   "long long long long long long long long long long\n"
+                   " */\n",
+                   Style));
+  EXPECT_EQ("/**\n"
+            " * @param x long long long long long long long long long\n"
+            " *     long long long long long long long long long long\n"
+            " *     long\n"
+            " */\n",
+            format("/**\n"
+                   " * @param x long long long long long long long long long "
+                   "long long long long long long long long long long long\n"
+                   " */\n",
+                   Style));
+  EXPECT_EQ(
+      "/**\n"
+      " * Sentence that\n"
+      " * should be broken.\n"
+      " * @param short\n"
+      " * keep indentation\n"
+      " */\n", format(
+          "/**\n"
+          " * Sentence that should be broken.\n"
+          " * @param short\n"
+          " * keep indentation\n"
+          " */\n", Style20));
+
+  EXPECT_EQ("/**\n"
+            " * @param l1 long1\n"
+            " *     to break\n"
+            " * @param l2 long2\n"
+            " *     to break\n"
+            " */\n",
+            format("/**\n"
+                   " * @param l1 long1 to break\n"
+                   " * @param l2 long2 to break\n"
+                   " */\n",
+                   Style20));
+
+  EXPECT_EQ("/**\n"
+            " * @param xx to\n"
+            " *     break\n"
+            " * no reflow\n"
+            " */\n",
+            format("/**\n"
+                   " * @param xx to break\n"
+                   " * no reflow\n"
+                   " */\n",
+                   Style20));
+
+  EXPECT_EQ("/**\n"
+            " * @param xx to\n"
+            " *     break yes\n"
+            " *     reflow\n"
+            " */\n",
+            format("/**\n"
+                   " * @param xx to break\n"
+                   " *     yes reflow\n"
+                   " */\n",
+                   Style20));
+
+  FormatStyle JSStyle20 = getGoogleStyle(FormatStyle::LK_JavaScript);
+  JSStyle20.ColumnLimit = 20;
+  EXPECT_EQ("/**\n"
+            " * @param l1 long1\n"
+            " *     to break\n"
+            " */\n",
+            format("/**\n"
+                   " * @param l1 long1 to break\n"
+                   " */\n",
+                   JSStyle20));
+  EXPECT_EQ("/**\n"
+            " * @param {l1 long1\n"
+            " *     to break}\n"
+            " */\n",
+            format("/**\n"
+                   " * @param {l1 long1 to break}\n"
+                   " */\n",
+                   JSStyle20));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index 9975b7d311..e7808c6596 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -191,19 +191,28 @@ TEST_F(FormatTestJS, JSDocComments) {
 
   // Break a single line long jsdoc comment pragma.
   EXPECT_EQ("/**\n"
-            " * @returns {string} jsdoc line 12\n"
+            " * @returns\n"
+            " *     {string}\n"
+            " *     jsdoc line 12\n"
             " */",
             format("/** @returns {string} jsdoc line 12 */",
                    getGoogleJSStyleWithColumns(20)));
 
   EXPECT_EQ("/**\n"
-            " * @returns {string} jsdoc line 12\n"
+            " * @returns\n"
+            " *     {string}\n"
+            " *     jsdoc line 12\n"
             " */",
             format("/** @returns {string} jsdoc line 12  */",
                    getGoogleJSStyleWithColumns(20)));
 
+  // FIXME: this overcounts the */ as a continuation of the 12 when breaking.
+  // Related to the FIXME in BreakableBlockComment::getRangeLength.
   EXPECT_EQ("/**\n"
-            " * @returns {string} jsdoc line 12\n"
+            " * @returns\n"
+            " *     {string}\n"
+            " *     jsdoc line\n"
+            " *     12\n"
             " */",
             format("/** @returns {string} jsdoc line 12*/",
                    getGoogleJSStyleWithColumns(20)));
@@ -212,7 +221,8 @@ TEST_F(FormatTestJS, JSDocComments) {
   EXPECT_EQ("/**\n"
             " * line 1\n"
             " * line 2\n"
-            " * @returns {string} jsdoc line 12\n"
+            " * @returns {string}\n"
+            " *     jsdoc line 12\n"
             " */",
             format("/** line 1\n"
                    " * line 2\n"
@@ -2028,21 +2038,24 @@ TEST_F(FormatTestJS, WrapAfterParen) {
 
 TEST_F(FormatTestJS, JSDocAnnotations) {
   verifyFormat("/**\n"
-               " * @export {this.is.a.long.path.to.a.Type}\n"
+               " * @exports\n"
+               " *     {this.is.a.long.path.to.a.Type}\n"
                " */",
                "/**\n"
-               " * @export {this.is.a.long.path.to.a.Type}\n"
+               " * @exports {this.is.a.long.path.to.a.Type}\n"
                " */",
                getGoogleJSStyleWithColumns(20));
   verifyFormat("/**\n"
-               " * @mods {this.is.a.long.path.to.a.Type}\n"
+               " * @mods\n"
+               " *     {this.is.a.long.path.to.a.Type}\n"
                " */",
                "/**\n"
                " * @mods {this.is.a.long.path.to.a.Type}\n"
                " */",
                getGoogleJSStyleWithColumns(20));
   verifyFormat("/**\n"
-               " * @param {this.is.a.long.path.to.a.Type}\n"
+               " * @param\n"
+               " *     {this.is.a.long.path.to.a.Type}\n"
                " */",
                "/**\n"
                " * @param {this.is.a.long.path.to.a.Type}\n"
@@ -2058,34 +2071,36 @@ TEST_F(FormatTestJS, JSDocAnnotations) {
   verifyFormat(
       "/**\n"
       " * @param This is a\n"
-      " * long comment but\n"
-      " * no type\n"
+      " *     long comment\n"
+      " *     but no type\n"
       " */",
       "/**\n"
       " * @param This is a long comment but no type\n"
       " */",
       getGoogleJSStyleWithColumns(20));
-  // Don't break @param line, but reindent it and reflow unrelated lines.
-  verifyFormat("{\n"
-               "  /**\n"
-               "   * long long long\n"
-               "   * long\n"
-               "   * @param {this.is.a.long.path.to.a.Type} a\n"
-               "   * long long long\n"
-               "   * long long\n"
-               "   */\n"
-               "  function f(a) {}\n"
-               "}",
-               "{\n"
-               "/**\n"
-               " * long long long long\n"
-               " * @param {this.is.a.long.path.to.a.Type} a\n"
-               " * long long long long\n"
-               " * long\n"
-               " */\n"
-               "  function f(a) {}\n"
-               "}",
-               getGoogleJSStyleWithColumns(20));
+  // Break and reindent @param line and reflow unrelated lines.
+  EXPECT_EQ("{\n"
+            "  /**\n"
+            "   * long long long\n"
+            "   * long\n"
+            "   * @param\n"
+            "   *     {this.is.a.long.path.to.a.Type}\n"
+            "   *     a\n"
+            "   * long long long\n"
+            "   * long long\n"
+            "   */\n"
+            "  function f(a) {}\n"
+            "}",
+            format("{\n"
+                   "/**\n"
+                   " * long long long long\n"
+                   " * @param {this.is.a.long.path.to.a.Type} a\n"
+                   " * long long long long\n"
+                   " * long\n"
+                   " */\n"
+                   "  function f(a) {}\n"
+                   "}",
+                   getGoogleJSStyleWithColumns(20)));
 }
 
 TEST_F(FormatTestJS, RequoteStringsSingle) {
-- 
GitLab


From 0412c73790e89745e5da15323eb4048457a59057 Mon Sep 17 00:00:00 2001
From: Adam Balogh 
Date: Mon, 30 Jul 2018 08:52:21 +0000
Subject: [PATCH 0771/1023] [Analyzer] Iterator Checker Hotfix: Defer deletion
 of container data until its last iterator is cleaned up

The analyzer may consider a container region as dead while it still has live
iterators. We must defer deletion of the data belonging to such containers
until all its iterators are dead as well to be able to compare the iterator
to the begin and the end of the container which is stored in the container
data.

Differential Revision: https://reviews.llvm.org/D48427



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338234 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../Checkers/IteratorChecker.cpp              | 23 ++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 56c250cd16..fc713bc499 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -291,6 +291,7 @@ const ContainerData *getContainerData(ProgramStateRef State,
                                       const MemRegion *Cont);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
                                  const ContainerData &CData);
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
 bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos);
 bool isZero(ProgramStateRef State, const NonLoc &Val);
 } // namespace
@@ -536,7 +537,11 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
   auto ContMap = State->get();
   for (const auto Cont : ContMap) {
     if (!SR.isLiveRegion(Cont.first)) {
-      State = State->remove(Cont.first);
+      // We must keep the container data while it has live iterators to be able
+      // to compare them to the begin and the end of the container.
+      if (!hasLiveIterators(State, Cont.first)) {
+        State = State->remove(Cont.first);
+      }
     }
   }
 
@@ -1188,6 +1193,22 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State,
   return NewState;
 }
 
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
+  auto RegionMap = State->get();
+  for (const auto Reg : RegionMap) {
+    if (Reg.second.getContainer() == Cont)
+      return true;
+  }
+
+  auto SymbolMap = State->get();
+  for (const auto Sym : SymbolMap) {
+    if (Sym.second.getContainer() == Cont)
+      return true;
+  }
+
+  return false;
+}
+
 bool isZero(ProgramStateRef State, const NonLoc &Val) {
   auto &BVF = State->getBasicVals();
   return compare(State, Val,
-- 
GitLab


From 24e0c703528cbf51eea7f69e5b7575685349845b Mon Sep 17 00:00:00 2001
From: Simon Pilgrim 
Date: Mon, 30 Jul 2018 10:07:47 +0000
Subject: [PATCH 0772/1023] Fix -Wdocumentation warning. NFCI.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338238 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/ASTMatchers/ASTMatchers.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 58f65a39fb..d83242cec9 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -1654,7 +1654,6 @@ extern const internal::VariadicDynCastAllOfMatcher
 /// - (void) init {
 ///   a = @"hello";
 /// }
-//}
 /// \endcode
 extern const internal::VariadicDynCastAllOfMatcher
     objcIvarRefExpr;
-- 
GitLab


From a1448de5327a4828d65844a659d7e9c6af722fe1 Mon Sep 17 00:00:00 2001
From: Stefan Maksimovic 
Date: Mon, 30 Jul 2018 10:44:46 +0000
Subject: [PATCH 0773/1023] [mips64][clang] Provide the signext attribute for
 i32 return values

Additional info: see r338019.

Differential Revision: https://reviews.llvm.org/D49289


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338239 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/TargetInfo.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index fa9b0a27af..7652cb142c 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -6985,8 +6985,14 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
   if (const EnumType *EnumTy = RetTy->getAs())
     RetTy = EnumTy->getDecl()->getIntegerType();
 
-  return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
-                                           : ABIArgInfo::getDirect());
+  if (RetTy->isPromotableIntegerType())
+    return ABIArgInfo::getExtend(RetTy);
+
+  if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
+      RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
+    return ABIArgInfo::getSignExtend(RetTy);
+
+  return ABIArgInfo::getDirect();
 }
 
 void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
-- 
GitLab


From fc8388f1fbbca891c016e50dd261c1db384ad82c Mon Sep 17 00:00:00 2001
From: Krasimir Georgiev 
Date: Mon, 30 Jul 2018 12:22:41 +0000
Subject: [PATCH 0774/1023] [clang-format] Silence -Wdocumentation warnings

introduced in r338232

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338245 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Format/BreakableToken.h | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/lib/Format/BreakableToken.h b/lib/Format/BreakableToken.h
index a2a818f911..10e1801780 100644
--- a/lib/Format/BreakableToken.h
+++ b/lib/Format/BreakableToken.h
@@ -139,12 +139,14 @@ public:
   /// Returns additional content indent required for the second line after the
   /// content at line \p LineIndex is broken.
   ///
-  /// For example, Javadoc @param annotations require and indent of 4 spaces and
-  /// in this example getContentIndex(1) returns 4.
-  /// /**
-  ///  * @param loooooooooooooong line
-  ///  *     continuation
-  ///  */
+  // (Next lines do not start with `///` since otherwise -Wdocumentation picks
+  // up the example annotations and generates warnings for them)
+  // For example, Javadoc @param annotations require and indent of 4 spaces and
+  // in this example getContentIndex(1) returns 4.
+  // /**
+  //  * @param loooooooooooooong line
+  //  *     continuation
+  //  */
   virtual unsigned getContentIndent(unsigned LineIndex) const {
     return 0;
   }
-- 
GitLab


From 3e9c4d90d458e0e0e6fc387c44793aafb374ad1f Mon Sep 17 00:00:00 2001
From: Stefan Maksimovic 
Date: Mon, 30 Jul 2018 12:27:40 +0000
Subject: [PATCH 0775/1023] [mips64][clang] Adjust tests to account for changes
 in r338239

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338246 91177308-0d34-0410-b5e6-96231b3b80d8
---
 test/CodeGen/mips-unsigned-ext-var.c | 6 +++---
 test/CodeGen/mips-varargs.c          | 8 ++++++--
 test/CodeGen/mips-vector-arg.c       | 4 ++--
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/test/CodeGen/mips-unsigned-ext-var.c b/test/CodeGen/mips-unsigned-ext-var.c
index 2e04792cf3..a4dae53c18 100644
--- a/test/CodeGen/mips-unsigned-ext-var.c
+++ b/test/CodeGen/mips-unsigned-ext-var.c
@@ -17,6 +17,6 @@ void foo1() {
   foo(1,f);
 }
 
-//N64: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
-//N32: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
-//O32: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
\ No newline at end of file
+//N64: call signext i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
+//N32: call signext i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
+//O32: call i32 (i32, ...) @foo(i32 signext undef, i32 signext -32)
diff --git a/test/CodeGen/mips-varargs.c b/test/CodeGen/mips-varargs.c
index 343914ad8d..8f1a633b7d 100644
--- a/test/CodeGen/mips-varargs.c
+++ b/test/CodeGen/mips-varargs.c
@@ -19,7 +19,9 @@ int test_i32(char *fmt, ...) {
   return v;
 }
 
-// ALL-LABEL: define i32 @test_i32(i8*{{.*}} %fmt, ...)
+// O32-LABEL: define i32 @test_i32(i8*{{.*}} %fmt, ...)
+// N32-LABEL: define signext i32 @test_i32(i8*{{.*}} %fmt, ...)
+// N64-LABEL: define signext i32 @test_i32(i8*{{.*}} %fmt, ...)
 //
 // O32:   %va = alloca i8*, align [[$PTRALIGN:4]]
 // N32:   %va = alloca i8*, align [[$PTRALIGN:4]]
@@ -133,7 +135,9 @@ int test_v4i32(char *fmt, ...) {
   return v[0];
 }
 
-// ALL-LABEL: define i32 @test_v4i32(i8*{{.*}} %fmt, ...)
+// O32-LABEL: define i32 @test_v4i32(i8*{{.*}} %fmt, ...)
+// N32-LABEL: define signext i32 @test_v4i32(i8*{{.*}} %fmt, ...)
+// N64-LABEL: define signext i32 @test_v4i32(i8*{{.*}} %fmt, ...)
 //
 // ALL:   %va = alloca i8*, align [[$PTRALIGN]]
 // ALL:   [[V:%.+]] = alloca <4 x i32>, align 16
diff --git a/test/CodeGen/mips-vector-arg.c b/test/CodeGen/mips-vector-arg.c
index 1b9d7abe4d..c9eafc958b 100644
--- a/test/CodeGen/mips-vector-arg.c
+++ b/test/CodeGen/mips-vector-arg.c
@@ -11,7 +11,7 @@ typedef int v4i32 __attribute__ ((__vector_size__ (16)));
 // O32: define void @test_v4sf(i32 inreg %a1.coerce0, i32 inreg %a1.coerce1, i32 inreg %a1.coerce2, i32 inreg %a1.coerce3, i32 signext %a2, i32, i32 inreg %a3.coerce0, i32 inreg %a3.coerce1, i32 inreg %a3.coerce2, i32 inreg %a3.coerce3) local_unnamed_addr [[NUW:#[0-9]+]]
 // O32: declare i32 @test_v4sf_2(i32 inreg, i32 inreg, i32 inreg, i32 inreg, i32 signext, i32, i32 inreg, i32 inreg, i32 inreg, i32 inreg)
 // N64: define void @test_v4sf(i64 inreg %a1.coerce0, i64 inreg %a1.coerce1, i32 signext %a2, i64, i64 inreg %a3.coerce0, i64 inreg %a3.coerce1) local_unnamed_addr [[NUW:#[0-9]+]]
-// N64: declare i32 @test_v4sf_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg)
+// N64: declare signext i32 @test_v4sf_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg)
 extern test_v4sf_2(v4sf, int, v4sf);
 void test_v4sf(v4sf a1, int a2, v4sf a3) {
   test_v4sf_2(a3, a2, a1);
@@ -20,7 +20,7 @@ void test_v4sf(v4sf a1, int a2, v4sf a3) {
 // O32: define void @test_v4i32(i32 inreg %a1.coerce0, i32 inreg %a1.coerce1, i32 inreg %a1.coerce2, i32 inreg %a1.coerce3, i32 signext %a2, i32, i32 inreg %a3.coerce0, i32 inreg %a3.coerce1, i32 inreg %a3.coerce2, i32 inreg %a3.coerce3) local_unnamed_addr [[NUW]]
 // O32: declare i32 @test_v4i32_2(i32 inreg, i32 inreg, i32 inreg, i32 inreg, i32 signext, i32, i32 inreg, i32 inreg, i32 inreg, i32 inreg)
 // N64: define void @test_v4i32(i64 inreg %a1.coerce0, i64 inreg %a1.coerce1, i32 signext %a2, i64, i64 inreg %a3.coerce0, i64 inreg %a3.coerce1) local_unnamed_addr [[NUW]]
-// N64: declare i32 @test_v4i32_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg)
+// N64: declare signext i32 @test_v4i32_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg)
 extern test_v4i32_2(v4i32, int, v4i32);
 void test_v4i32(v4i32 a1, int a2, v4i32 a3) {
   test_v4i32_2(a3, a2, a1);
-- 
GitLab


From 149f92fc41c347021159ddd56ef3b72342487a44 Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Mon, 30 Jul 2018 14:44:29 +0000
Subject: [PATCH 0776/1023] [OPENMP] Modify the info about OpenMP support in
 UsersManual, NFC.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338252 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/UsersManual.rst | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 418afb2d54..1881d9430a 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -2155,13 +2155,8 @@ Objective-C++ Language Features
 OpenMP Features
 ===============
 
-Clang supports all OpenMP 3.1 directives and clauses.  In addition, some
-features of OpenMP 4.0 are supported.  For example, ``#pragma omp simd``,
-``#pragma omp for simd``, ``#pragma omp parallel for simd`` directives, extended
-set of atomic constructs, ``proc_bind`` clause for all parallel-based
-directives, ``depend`` clause for ``#pragma omp task`` directive (except for
-array sections), ``#pragma omp cancel`` and ``#pragma omp cancellation point``
-directives, and ``#pragma omp taskgroup`` directive.
+Clang supports all OpenMP 4.5 directives and clauses. See :doc:`OpenMPSupport`
+for additional details.
 
 Use `-fopenmp` to enable OpenMP. Support for OpenMP can be disabled with
 `-fno-openmp`.
-- 
GitLab


From 1b2dafb41e63b904e18ef700ad103be513100a66 Mon Sep 17 00:00:00 2001
From: Ilya Biryukov 
Date: Mon, 30 Jul 2018 15:19:05 +0000
Subject: [PATCH 0777/1023] [CodeComplete] Fix the crash in code completion on
 access checking

Started crashing in r337453. See the added test case for the crash repro.

The fix reverts part of r337453 that causes the crash and does
not actually break anything when reverted.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338255 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaCodeComplete.cpp               | 30 ++-------------------
 test/Index/complete-access-checks-crash.cpp | 13 +++++++++
 2 files changed, 15 insertions(+), 28 deletions(-)
 create mode 100644 test/Index/complete-access-checks-crash.cpp

diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 4e571eba17..30af826ef6 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1303,34 +1303,8 @@ namespace {
     void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
                    bool InBaseClass) override {
       bool Accessible = true;
-      if (Ctx) {
-        DeclContext *AccessingCtx = Ctx;
-        // If ND comes from a base class, set the naming class back to the
-        // derived class if the search starts from the derived class (i.e.
-        // InBaseClass is true).
-        //
-        // Example:
-        //   class B { protected: int X; }
-        //   class D : public B { void f(); }
-        //   void D::f() { this->^; }
-        // The completion after "this->" will have `InBaseClass` set to true and
-        // `Ctx` set to "B", when looking up in `B`. We need to set the actual
-        // accessing context (i.e. naming class) to "D" so that access can be
-        // calculated correctly.
-        if (InBaseClass && isa(Ctx)) {
-          CXXRecordDecl *RC = nullptr;
-          // Get the enclosing record.
-          for (DeclContext *DC = CurContext; !DC->isFileContext();
-               DC = DC->getParent()) {
-            if ((RC = dyn_cast(DC)))
-              break;
-          }
-          if (RC)
-            AccessingCtx = RC;
-        }
-        Accessible = Results.getSema().IsSimplyAccessible(ND, AccessingCtx);
-      }
-
+      if (Ctx)
+        Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
       ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
                                    false, Accessible, FixIts);
       Results.AddResult(Result, CurContext, Hiding, InBaseClass);
diff --git a/test/Index/complete-access-checks-crash.cpp b/test/Index/complete-access-checks-crash.cpp
new file mode 100644
index 0000000000..c7ac4d6563
--- /dev/null
+++ b/test/Index/complete-access-checks-crash.cpp
@@ -0,0 +1,13 @@
+struct Base {
+protected:
+  bool bar();
+};
+struct Derived : Base {
+};
+
+struct X {
+  int foo() {
+    Derived(). // RUN: c-index-test -code-completion-at=%s:10:15 %s | FileCheck %s
+    // CHECK: bar{{.*}}(inaccessible)
+  }
+};
-- 
GitLab


From c4f64d0f6e92647c7c3fcab8614ffe7fe27ac23d Mon Sep 17 00:00:00 2001
From: Reka Kovacs 
Date: Mon, 30 Jul 2018 15:43:45 +0000
Subject: [PATCH 0778/1023] [analyzer] Add support for more invalidating
 functions in InnerPointerChecker.

According to the standard, pointers referring to the elements of a
`basic_string` may be invalidated if they are used as an argument to
any standard library function taking a reference to non-const
`basic_string` as an argument. This patch makes InnerPointerChecker warn
for these cases.

Differential Revision: https://reviews.llvm.org/D49656

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338259 91177308-0d34-0410-b5e6-96231b3b80d8
---
 .../Checkers/InnerPointerChecker.cpp          | 188 ++++++++++++------
 lib/StaticAnalyzer/Checkers/MallocChecker.cpp |   5 +
 test/Analysis/inner-pointer.cpp               |  92 ++++++++-
 3 files changed, 214 insertions(+), 71 deletions(-)

diff --git a/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
index ed877ab345..29677f737f 100644
--- a/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -91,37 +91,53 @@ public:
         ReserveFn("reserve"), ResizeFn("resize"),
         ShrinkToFitFn("shrink_to_fit"), SwapFn("swap") {}
 
-  /// Check whether the function called on the container object is a
-  /// member function that potentially invalidates pointers referring
-  /// to the objects's internal buffer.
-  bool mayInvalidateBuffer(const CallEvent &Call) const;
-
-  /// Record the connection between the symbol returned by c_str() and the
-  /// corresponding string object region in the ProgramState. Mark the symbol
-  /// released if the string object is destroyed.
+  /// Check if the object of this member function call is a `basic_string`.
+  bool isCalledOnStringObject(const CXXInstanceCall *ICall) const;
+
+  /// Check whether the called member function potentially invalidates
+  /// pointers referring to the container object's inner buffer.
+  bool isInvalidatingMemberFunction(const CallEvent &Call) const;
+
+  /// Mark pointer symbols associated with the given memory region released
+  /// in the program state.
+  void markPtrSymbolsReleased(const CallEvent &Call, ProgramStateRef State,
+                              const MemRegion *ObjRegion,
+                              CheckerContext &C) const;
+
+  /// Standard library functions that take a non-const `basic_string` argument by
+  /// reference may invalidate its inner pointers. Check for these cases and
+  /// mark the pointers released.
+  void checkFunctionArguments(const CallEvent &Call, ProgramStateRef State,
+                              CheckerContext &C) const;
+
+  /// Record the connection between raw pointers referring to a container
+  /// object's inner buffer and the object's memory region in the program state.
+  /// Mark potentially invalidated pointers released.
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
 
-  /// Clean up the ProgramState map.
+  /// Clean up the program state map.
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
 };
 
 } // end anonymous namespace
 
-// [string.require]
-//
-// "References, pointers, and iterators referring to the elements of a
-// basic_string sequence may be invalidated by the following uses of that
-// basic_string object:
-//
-// -- TODO: As an argument to any standard library function taking a reference
-// to non-const basic_string as an argument. For example, as an argument to
-// non-member functions swap(), operator>>(), and getline(), or as an argument
-// to basic_string::swap().
-//
-// -- Calling non-const member functions, except operator[], at, front, back,
-// begin, rbegin, end, and rend."
-//
-bool InnerPointerChecker::mayInvalidateBuffer(const CallEvent &Call) const {
+bool InnerPointerChecker::isCalledOnStringObject(
+        const CXXInstanceCall *ICall) const {
+  const auto *ObjRegion =
+    dyn_cast_or_null(ICall->getCXXThisVal().getAsRegion());
+  if (!ObjRegion)
+    return false;
+
+  QualType ObjTy = ObjRegion->getValueType();
+  if (ObjTy.isNull() ||
+      ObjTy->getAsCXXRecordDecl()->getName() != "basic_string")
+    return false;
+
+  return true;
+}
+
+bool InnerPointerChecker::isInvalidatingMemberFunction(
+        const CallEvent &Call) const {
   if (const auto *MemOpCall = dyn_cast(&Call)) {
     OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator();
     if (Opc == OO_Equal || Opc == OO_PlusEqual)
@@ -137,53 +153,104 @@ bool InnerPointerChecker::mayInvalidateBuffer(const CallEvent &Call) const {
           Call.isCalled(SwapFn));
 }
 
-void InnerPointerChecker::checkPostCall(const CallEvent &Call,
-                                        CheckerContext &C) const {
-  const auto *ICall = dyn_cast(&Call);
-  if (!ICall)
+void InnerPointerChecker::markPtrSymbolsReleased(const CallEvent &Call,
+                                                 ProgramStateRef State,
+                                                 const MemRegion *MR,
+                                                 CheckerContext &C) const {
+  if (const PtrSet *PS = State->get(MR)) {
+    const Expr *Origin = Call.getOriginExpr();
+    for (const auto Symbol : *PS) {
+      // NOTE: `Origin` may be null, and will be stored so in the symbol's
+      // `RefState` in MallocChecker's `RegionState` program state map.
+      State = allocation_state::markReleased(State, Symbol, Origin);
+    }
+    State = State->remove(MR);
+    C.addTransition(State);
     return;
+  }
+}
 
-  SVal Obj = ICall->getCXXThisVal();
-  const auto *ObjRegion = dyn_cast_or_null(Obj.getAsRegion());
-  if (!ObjRegion)
-    return;
+void InnerPointerChecker::checkFunctionArguments(const CallEvent &Call,
+                                                 ProgramStateRef State,
+                                                 CheckerContext &C) const {
+  if (const auto *FC = dyn_cast(&Call)) {
+    const FunctionDecl *FD = FC->getDecl();
+    if (!FD || !FD->isInStdNamespace())
+      return;
 
-  auto *TypeDecl = ObjRegion->getValueType()->getAsCXXRecordDecl();
-  if (TypeDecl->getName() != "basic_string")
-    return;
+    for (unsigned I = 0, E = FD->getNumParams(); I != E; ++I) {
+      QualType ParamTy = FD->getParamDecl(I)->getType();
+      if (!ParamTy->isReferenceType() ||
+          ParamTy->getPointeeType().isConstQualified())
+        continue;
 
-  ProgramStateRef State = C.getState();
+      // In case of member operator calls, `this` is counted as an
+      // argument but not as a parameter.
+      bool isaMemberOpCall = isa(FC);
+      unsigned ArgI = isaMemberOpCall ? I+1 : I;
 
-  if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
-    SVal RawPtr = Call.getReturnValue();
-    if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
-      // Start tracking this raw pointer by adding it to the set of symbols
-      // associated with this container object in the program state map.
-      PtrSet::Factory &F = State->getStateManager().get_context();
-      const PtrSet *SetPtr = State->get(ObjRegion);
-      PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
-      assert(C.wasInlined || !Set.contains(Sym));
-      Set = F.add(Set, Sym);
-      State = State->set(ObjRegion, Set);
-      C.addTransition(State);
+      SVal Arg = FC->getArgSVal(ArgI);
+      const auto *ArgRegion =
+          dyn_cast_or_null(Arg.getAsRegion());
+      if (!ArgRegion)
+        continue;
+
+      markPtrSymbolsReleased(Call, State, ArgRegion, C);
     }
-    return;
   }
+}
 
-  if (mayInvalidateBuffer(Call)) {
-    if (const PtrSet *PS = State->get(ObjRegion)) {
-      // Mark all pointer symbols associated with the deleted object released.
-      const Expr *Origin = Call.getOriginExpr();
-      for (const auto Symbol : *PS) {
-        // NOTE: `Origin` may be null, and will be stored so in the symbol's
-        // `RefState` in MallocChecker's `RegionState` program state map.
-        State = allocation_state::markReleased(State, Symbol, Origin);
+// [string.require]
+//
+// "References, pointers, and iterators referring to the elements of a
+// basic_string sequence may be invalidated by the following uses of that
+// basic_string object:
+//
+// -- As an argument to any standard library function taking a reference
+// to non-const basic_string as an argument. For example, as an argument to
+// non-member functions swap(), operator>>(), and getline(), or as an argument
+// to basic_string::swap().
+//
+// -- Calling non-const member functions, except operator[], at, front, back,
+// begin, rbegin, end, and rend."
+
+void InnerPointerChecker::checkPostCall(const CallEvent &Call,
+                                        CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+
+  if (const auto *ICall = dyn_cast(&Call)) {
+    if (isCalledOnStringObject(ICall)) {
+      const auto *ObjRegion = dyn_cast_or_null(
+              ICall->getCXXThisVal().getAsRegion());
+
+      if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
+        SVal RawPtr = Call.getReturnValue();
+        if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
+          // Start tracking this raw pointer by adding it to the set of symbols
+          // associated with this container object in the program state map.
+
+          PtrSet::Factory &F = State->getStateManager().get_context();
+          const PtrSet *SetPtr = State->get(ObjRegion);
+          PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
+          assert(C.wasInlined || !Set.contains(Sym));
+          Set = F.add(Set, Sym);
+
+          State = State->set(ObjRegion, Set);
+          C.addTransition(State);
+        }
+        return;
+      }
+
+      // Check [string.require] / second point.
+      if (isInvalidatingMemberFunction(Call)) {
+        markPtrSymbolsReleased(Call, State, ObjRegion, C);
+        return;
       }
-      State = State->remove(ObjRegion);
-      C.addTransition(State);
-      return;
     }
   }
+
+  // Check [string.require] / first point.
+  checkFunctionArguments(Call, State, C);
 }
 
 void InnerPointerChecker::checkDeadSymbols(SymbolReaper &SymReaper,
@@ -216,7 +283,6 @@ InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N,
                                                       const ExplodedNode *PrevN,
                                                       BugReporterContext &BRC,
                                                       BugReport &BR) {
-
   if (!isSymbolTracked(N->getState(), PtrToBuf) ||
       isSymbolTracked(PrevN->getState(), PtrToBuf))
     return nullptr;
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 8f07f413e8..11df35a50b 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -2930,6 +2930,11 @@ std::shared_ptr MallocChecker::MallocBugVisitor::VisitNode(
               OS << MemCallE->getMethodDecl()->getNameAsString();
             } else if (const auto *OpCallE = dyn_cast(S)) {
               OS << OpCallE->getDirectCallee()->getNameAsString();
+            } else if (const auto *CallE = dyn_cast(S)) {
+              auto &CEMgr = BRC.getStateManager().getCallEventManager();
+              CallEventRef<> Call = CEMgr.getSimpleCall(CallE, state, CurrentLC);
+              const auto *D = dyn_cast_or_null(Call->getDecl());
+              OS << (D ? D->getNameAsString() : "unknown");
             }
             OS << "'";
           }
diff --git a/test/Analysis/inner-pointer.cpp b/test/Analysis/inner-pointer.cpp
index db9bf43109..9e5ed380e7 100644
--- a/test/Analysis/inner-pointer.cpp
+++ b/test/Analysis/inner-pointer.cpp
@@ -38,6 +38,18 @@ typedef basic_string wstring;
 typedef basic_string u16string;
 typedef basic_string u32string;
 
+template 
+void func_ref(T &a);
+
+template 
+void func_const_ref(const T &a);
+
+template 
+void func_value(T a);
+
+string my_string = "default";
+void default_arg(int a = 42, string &b = my_string);
+
 } // end namespace std
 
 void consume(const char *) {}
@@ -45,6 +57,10 @@ void consume(const wchar_t *) {}
 void consume(const char16_t *) {}
 void consume(const char32_t *) {}
 
+//=--------------------------------------=//
+//     `std::string` member functions     //
+//=--------------------------------------=//
+
 void deref_after_scope_char(bool cond) {
   const char *c, *d;
   {
@@ -151,6 +167,19 @@ void multiple_symbols(bool cond) {
   }              // expected-note@-1 {{Use of memory after it is freed}}
 }
 
+void deref_after_scope_ok(bool cond) {
+  const char *c, *d;
+  std::string s;
+  {
+    c = s.c_str();
+    d = s.data();
+  }
+  if (cond)
+    consume(c); // no-warning
+  else
+    consume(d); // no-warning
+}
+
 void deref_after_equals() {
   const char *c;
   std::string s = "hello";
@@ -277,15 +306,58 @@ void deref_after_swap() {
   // expected-note@-1 {{Use of memory after it is freed}}
 }
 
-void deref_after_scope_ok(bool cond) {
-  const char *c, *d;
+//=---------------------------=//
+//     Other STL functions     //
+//=---------------------------=//
+
+void STL_func_ref() {
+  const char *c;
   std::string s;
-  {
-    c = s.c_str();
-    d = s.data();
-  }
-  if (cond)
-    consume(c); // no-warning
-  else
-    consume(d); // no-warning
+  c = s.c_str();    // expected-note {{Dangling inner pointer obtained here}}
+  std::func_ref(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
+  consume(c);       // expected-warning {{Use of memory after it is freed}}
+  // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void STL_func_const_ref() {
+  const char *c;
+  std::string s;
+  c = s.c_str();
+  std::func_const_ref(s);
+  consume(c); // no-warning
+}
+
+void STL_func_value() {
+  const char *c;
+  std::string s;
+  c = s.c_str();
+  std::func_value(s);
+  consume(c); // no-warning
+}
+
+void func_ptr_known() {
+  const char *c;
+  std::string s;
+  void (*func_ptr)(std::string &) = std::func_ref;
+  c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+  func_ptr(s);   // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
+  consume(c);    // expected-warning {{Use of memory after it is freed}}
+  // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+void func_ptr_unknown(void (*func_ptr)(std::string &)) {
+  const char *c;
+  std::string s;
+  c = s.c_str();
+  func_ptr(s);
+  consume(c); // no-warning
+}
+
+void func_default_arg() {
+  const char *c;
+  std::string s;
+  c = s.c_str();     // expected-note {{Dangling inner pointer obtained here}}
+  default_arg(3, s); // expected-note {{Inner pointer invalidated by call to 'default_arg'}}
+  consume(c);        // expected-warning {{Use of memory after it is freed}}
+  // expected-note@-1 {{Use of memory after it is freed}}
 }
-- 
GitLab


From 84dd838f3a1e456fec6b7c2fca0cc5cac4e7553d Mon Sep 17 00:00:00 2001
From: Reka Kovacs 
Date: Mon, 30 Jul 2018 16:14:59 +0000
Subject: [PATCH 0779/1023] [analyzer] Add missing state transition in
 IteratorChecker.

After cleaning up program state maps in `checkDeadSymbols()`,
a transition should be added to generate the new state.

Differential Revision: https://reviews.llvm.org/D47417

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338263 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/StaticAnalyzer/Checkers/IteratorChecker.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index fc713bc499..520c32e1c7 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -551,6 +551,8 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
       State = State->remove(Comp.first);
     }
   }
+
+  C.addTransition(State);
 }
 
 ProgramStateRef IteratorChecker::evalAssume(ProgramStateRef State, SVal Cond,
-- 
GitLab


From 82b074f75871a4b42c11e4d3dc11af8e62563730 Mon Sep 17 00:00:00 2001
From: Momchil Velikov 
Date: Mon, 30 Jul 2018 17:48:23 +0000
Subject: [PATCH 0780/1023] [ARM, AArch64]: Use unadjusted alignment when
 passing composites as arguments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The "Procedure Call Procedure Call Standard for the ARM® Architecture"
(https://static.docs.arm.com/ihi0042/f/IHI0042F_aapcs.pdf), specifies that
composite types are passed according to their "natural alignment", i.e. the
alignment before alignment adjustment on the entire composite is applied.

The same applies for AArch64 ABI.

Clang, however, used the adjusted alignment.

GCC already implements the ABI correctly. With this patch Clang becomes
compatible with GCC and passes such arguments in accordance with AAPCS.

Differential Revision: https://reviews.llvm.org/D46013



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338279 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/ASTContext.h   |  22 +++++
 include/clang/AST/RecordLayout.h |  10 +++
 lib/AST/ASTContext.cpp           |  31 +++++++
 lib/AST/RecordLayout.cpp         |   4 +
 lib/AST/RecordLayoutBuilder.cpp  |  20 +++--
 lib/CodeGen/TargetInfo.cpp       |  19 +++--
 test/CodeGen/aapcs-align.cc      | 141 +++++++++++++++++++++++++++++++
 test/CodeGen/aapcs64-align.cc    | 103 ++++++++++++++++++++++
 test/CodeGen/arm-arguments.c     |  17 ++--
 9 files changed, 350 insertions(+), 17 deletions(-)
 create mode 100644 test/CodeGen/aapcs-align.cc
 create mode 100644 test/CodeGen/aapcs64-align.cc

diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index c6f8e2973e..7a50ce8d52 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -226,6 +226,12 @@ class ASTContext : public RefCountedBase {
   using TypeInfoMap = llvm::DenseMap;
   mutable TypeInfoMap MemoizedTypeInfo;
 
+  /// A cache from types to unadjusted alignment information. Only ARM and
+  /// AArch64 targets need this information, keeping it separate prevents
+  /// imposing overhead on TypeInfo size.
+  using UnadjustedAlignMap = llvm::DenseMap;
+  mutable UnadjustedAlignMap MemoizedUnadjustedAlign;
+
   /// A cache mapping from CXXRecordDecls to key functions.
   llvm::DenseMap KeyFunctions;
 
@@ -2067,6 +2073,16 @@ public:
   unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
   unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
 
+  /// Return the ABI-specified natural alignment of a (complete) type \p T,
+  /// before alignment adjustments, in bits.
+  ///
+  /// This alignment is curently used only by ARM and AArch64 when passing
+  /// arguments of a composite type.
+  unsigned getTypeUnadjustedAlign(QualType T) const {
+    return getTypeUnadjustedAlign(T.getTypePtr());
+  }
+  unsigned getTypeUnadjustedAlign(const Type *T) const;
+
   /// Return the ABI-specified alignment of a type, in bits, or 0 if
   /// the type is incomplete and we cannot determine the alignment (for
   /// example, from alignment attributes).
@@ -2077,6 +2093,12 @@ public:
   CharUnits getTypeAlignInChars(QualType T) const;
   CharUnits getTypeAlignInChars(const Type *T) const;
 
+  /// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a type,
+  /// in characters, before alignment adjustments. This method does not work on
+  /// incomplete types.
+  CharUnits getTypeUnadjustedAlignInChars(QualType T) const;
+  CharUnits getTypeUnadjustedAlignInChars(const Type *T) const;
+
   // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the
   // type is a record, its data size is returned.
   std::pair getTypeInfoDataSizeInChars(QualType T) const;
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index dc60ef892b..ba60008589 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -71,6 +71,10 @@ private:
   // Alignment - Alignment of record in characters.
   CharUnits Alignment;
 
+  // UnadjustedAlignment - Maximum of the alignments of the record members in
+  // characters.
+  CharUnits UnadjustedAlignment;
+
   /// RequiredAlignment - The required alignment of the object.  In the MS-ABI
   /// the __declspec(align()) trumps #pramga pack and must always be obeyed.
   CharUnits RequiredAlignment;
@@ -136,6 +140,7 @@ private:
   CXXRecordLayoutInfo *CXXInfo = nullptr;
 
   ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+                  CharUnits unadjustedAlignment,
                   CharUnits requiredAlignment, CharUnits datasize,
                   ArrayRef fieldoffsets);
 
@@ -144,6 +149,7 @@ private:
   // Constructor for C++ records.
   ASTRecordLayout(const ASTContext &Ctx,
                   CharUnits size, CharUnits alignment,
+                  CharUnits unadjustedAlignment,
                   CharUnits requiredAlignment,
                   bool hasOwnVFPtr, bool hasExtendableVFPtr,
                   CharUnits vbptroffset,
@@ -170,6 +176,10 @@ public:
   /// getAlignment - Get the record alignment in characters.
   CharUnits getAlignment() const { return Alignment; }
 
+  /// getUnadjustedAlignment - Get the record alignment in characters, before
+  /// alignment adjustement.
+  CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
+
   /// getSize - Get the record size in characters.
   CharUnits getSize() const { return Size; }
 
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 25dc4441aa..ab428e3fc5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2056,6 +2056,27 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
   return TypeInfo(Width, Align, AlignIsRequired);
 }
 
+unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const {
+  UnadjustedAlignMap::iterator I = MemoizedUnadjustedAlign.find(T);
+  if (I != MemoizedUnadjustedAlign.end())
+    return I->second;
+
+  unsigned UnadjustedAlign;
+  if (const auto *RT = T->getAs()) {
+    const RecordDecl *RD = RT->getDecl();
+    const ASTRecordLayout &Layout = getASTRecordLayout(RD);
+    UnadjustedAlign = toBits(Layout.getUnadjustedAlignment());
+  } else if (const auto *ObjCI = T->getAs()) {
+    const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
+    UnadjustedAlign = toBits(Layout.getUnadjustedAlignment());
+  } else {
+    UnadjustedAlign = getTypeAlign(T);
+  }
+
+  MemoizedUnadjustedAlign[T] = UnadjustedAlign;
+  return UnadjustedAlign;
+}
+
 unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const {
   unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
   // Target ppc64 with QPX: simd default alignment for pointer to double is 32.
@@ -2095,6 +2116,16 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
   return toCharUnitsFromBits(getTypeAlign(T));
 }
 
+/// getTypeUnadjustedAlignInChars - Return the ABI-specified alignment of a
+/// type, in characters, before alignment adustments. This method does
+/// not work on incomplete types.
+CharUnits ASTContext::getTypeUnadjustedAlignInChars(QualType T) const {
+  return toCharUnitsFromBits(getTypeUnadjustedAlign(T));
+}
+CharUnits ASTContext::getTypeUnadjustedAlignInChars(const Type *T) const {
+  return toCharUnitsFromBits(getTypeUnadjustedAlign(T));
+}
+
 /// getPreferredTypeAlign - Return the "preferred" alignment of the specified
 /// type for the current target in bits.  This can be different than the ABI
 /// alignment in cases where it is beneficial for performance to overalign
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 37fe029f53..af3d0af8bb 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -30,10 +30,12 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) {
 
 ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
                                  CharUnits alignment,
+                                 CharUnits unadjustedAlignment,
                                  CharUnits requiredAlignment,
                                  CharUnits datasize,
                                  ArrayRef fieldoffsets)
     : Size(size), DataSize(datasize), Alignment(alignment),
+      UnadjustedAlignment(unadjustedAlignment),
       RequiredAlignment(requiredAlignment) {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
 }
@@ -41,6 +43,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
 // Constructor for C++ records.
 ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
                                  CharUnits size, CharUnits alignment,
+                                 CharUnits unadjustedAlignment,
                                  CharUnits requiredAlignment,
                                  bool hasOwnVFPtr, bool hasExtendableVFPtr,
                                  CharUnits vbptroffset,
@@ -57,6 +60,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
                                  const BaseOffsetsMapTy& BaseOffsets,
                                  const VBaseOffsetsMapTy& VBaseOffsets)
   : Size(size), DataSize(datasize), Alignment(alignment),
+    UnadjustedAlignment(unadjustedAlignment),
     RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
 {
   FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end());
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index b4b09c7cec..c92ac20f1f 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -582,6 +582,9 @@ protected:
   /// The alignment if attribute packed is not used.
   CharUnits UnpackedAlignment;
 
+  /// \brief The maximum of the alignments of top-level members.
+  CharUnits UnadjustedAlignment;
+
   SmallVector FieldOffsets;
 
   /// Whether the external AST source has provided a layout for this
@@ -662,6 +665,7 @@ protected:
                              EmptySubobjectMap *EmptySubobjects)
       : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
         Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
+        UnadjustedAlignment(CharUnits::One()),
         UseExternalLayout(false), InferAlignment(false), Packed(false),
         IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
         UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
@@ -1707,7 +1711,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
   setSize(std::max(getSizeInBits(), getDataSizeInBits()));
 
   // Remember max struct/class alignment.
-  UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign), 
+  UnadjustedAlignment =
+      std::max(UnadjustedAlignment, Context.toCharUnitsFromBits(FieldAlign));
+  UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
                   Context.toCharUnitsFromBits(UnpackedFieldAlign));
 }
 
@@ -1862,6 +1868,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
   setSize(std::max(getSizeInBits(), getDataSizeInBits()));
 
   // Remember max struct/class alignment.
+  UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
   UpdateAlignment(FieldAlign, UnpackedFieldAlign);
 }
 
@@ -2988,7 +2995,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
     if (const auto *RD = dyn_cast(D)) {
       Builder.cxxLayout(RD);
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+          *this, Builder.Size, Builder.Alignment, Builder.Alignment,
+          Builder.RequiredAlignment,
           Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
           Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
           Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
@@ -2998,7 +3006,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
     } else {
       Builder.layout(D);
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+          *this, Builder.Size, Builder.Alignment, Builder.Alignment,
+          Builder.RequiredAlignment,
           Builder.Size, Builder.FieldOffsets);
     }
   } else {
@@ -3019,7 +3028,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
       CharUnits NonVirtualSize =
           skipTailPadding ? DataSize : Builder.NonVirtualSize;
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment,
+          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
           Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
           CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
@@ -3032,7 +3041,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
       Builder.Layout(D);
 
       NewEntry = new (*this) ASTRecordLayout(
-          *this, Builder.getSize(), Builder.Alignment,
+          *this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
           Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
     }
@@ -3186,6 +3195,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
   const ASTRecordLayout *NewEntry =
     new (*this) ASTRecordLayout(*this, Builder.getSize(),
                                 Builder.Alignment,
+                                Builder.UnadjustedAlignment,
                                 /*RequiredAlignment : used by MS-ABI)*/
                                 Builder.Alignment,
                                 Builder.getDataSize(),
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 7652cb142c..838e52f883 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -5063,7 +5063,13 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
     if (getTarget().isRenderScriptTarget()) {
       return coerceToIntArray(Ty, getContext(), getVMContext());
     }
-    unsigned Alignment = getContext().getTypeAlign(Ty);
+    unsigned Alignment;
+    if (Kind == AArch64ABIInfo::AAPCS) {
+      Alignment = getContext().getTypeUnadjustedAlign(Ty);
+      Alignment = Alignment < 128 ? 64 : 128;
+    } else {
+      Alignment = getContext().getTypeAlign(Ty);
+    }
     Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
 
     // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
@@ -5801,11 +5807,14 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
   // most 8-byte. We realign the indirect argument if type alignment is bigger
   // than ABI alignment.
   uint64_t ABIAlign = 4;
-  uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
+  uint64_t TyAlign;
   if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
-       getABIKind() == ARMABIInfo::AAPCS)
+      getABIKind() == ARMABIInfo::AAPCS) {
+    TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
     ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
-
+  } else {
+    TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
+  }
   if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
     assert(getABIKind() != ARMABIInfo::AAPCS16_VFP && "unexpected byval");
     return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign),
@@ -5824,7 +5833,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
   unsigned SizeRegs;
   // FIXME: Try to match the types of the arguments more accurately where
   // we can.
-  if (getContext().getTypeAlign(Ty) <= 32) {
+  if (TyAlign <= 4) {
     ElemTy = llvm::Type::getInt32Ty(getVMContext());
     SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
   } else {
diff --git a/test/CodeGen/aapcs-align.cc b/test/CodeGen/aapcs-align.cc
new file mode 100644
index 0000000000..40fba78235
--- /dev/null
+++ b/test/CodeGen/aapcs-align.cc
@@ -0,0 +1,141 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple arm-none-none-eabi \
+// RUN:   -O2 \
+// RUN:   -target-cpu cortex-a8 \
+// RUN:   -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+// Base case, nothing interesting.
+struct S {
+  int x, y;
+};
+
+void f0(int, S);
+void f0m(int, int, int, int, int, S);
+void g0() {
+  S s = {6, 7};
+  f0(1, s);
+  f0m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g0
+// CHECK: call void @f0(i32 1, [2 x i32] [i32 6, i32 7]
+// CHECK: call void @f0m(i32 1, i32 2, i32 3, i32 4, i32 5, [2 x i32] [i32 6, i32 7]
+// CHECK: declare void @f0(i32, [2 x i32])
+// CHECK: declare void @f0m(i32, i32, i32, i32, i32, [2 x i32])
+
+// Aligned struct, passed according to its natural alignment.
+struct __attribute__((aligned(8))) S8 {
+  int x, y;
+} s8;
+
+void f1(int, S8);
+void f1m(int, int, int, int, int, S8);
+void g1() {
+  S8 s = {6, 7};
+  f1(1, s);
+  f1m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g1
+// CHECK: call void @f1(i32 1, [2 x i32] [i32 6, i32 7]
+// CHECK: call void @f1m(i32 1, i32 2, i32 3, i32 4, i32 5, [2 x i32] [i32 6, i32 7]
+// CHECK: declare void @f1(i32, [2 x i32])
+// CHECK: declare void @f1m(i32, i32, i32, i32, i32, [2 x i32])
+
+// Aligned struct, passed according to its natural alignment.
+struct alignas(16) S16 {
+  int x, y;
+};
+
+extern "C" void f2(int, S16);
+extern "C" void f2m(int, int, int, int, int, S16);
+
+void g2() {
+  S16 s = {6, 7};
+  f2(1, s);
+  f2m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g2
+// CHECK: call void @f2(i32 1, [4 x i32] [i32 6, i32 7
+// CHECK: call void @f2m(i32 1, i32 2, i32 3, i32 4, i32 5, [4 x i32] [i32 6, i32 7
+// CHECK: declare void @f2(i32, [4 x i32])
+// CHECK: declare void @f2m(i32, i32, i32, i32, i32, [4 x i32])
+
+// Increased natural alignment.
+struct SF8 {
+  int x __attribute__((aligned(8)));
+  int y;
+};
+
+void f3(int, SF8);
+void f3m(int, int, int, int, int, SF8);
+void g3() {
+  SF8 s = {6, 7};
+  f3(1, s);
+  f3m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g3
+// CHECK: call void @f3(i32 1, [1 x i64] [i64 30064771078]
+// CHECK: call void @f3m(i32 1, i32 2, i32 3, i32 4, i32 5, [1 x i64] [i64 30064771078]
+// CHECK: declare void @f3(i32, [1 x i64])
+// CHECK: declare void @f3m(i32, i32, i32, i32, i32, [1 x i64])
+
+// Increased natural alignment, capped to 8 though.
+struct SF16 {
+  int x;
+  int y alignas(16);
+  int z, a, b, c, d, e, f, g, h, i, j, k;
+};
+
+void f4(int, SF16);
+void f4m(int, int, int, int, int, SF16);
+void g4() {
+  SF16 s = {6, 7};
+  f4(1, s);
+  f4m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g4
+// CHECK: call void @f4(i32 1, %struct.SF16* byval nonnull align 8
+// CHECK: call void @f4m(i32 1, i32 2, i32 3, i32 4, i32 5, %struct.SF16* byval nonnull align 8
+// CHECK: declare void @f4(i32, %struct.SF16* byval align 8)
+// CHECK: declare void @f4m(i32, i32, i32, i32, i32, %struct.SF16* byval align 8)
+
+// Packed structure.
+struct  __attribute__((packed)) P {
+  int x;
+  long long u;
+};
+
+void f5(int, P);
+void f5m(int, int, int, int, int, P);
+void g5() {
+  P s = {6, 7};
+  f5(1, s);
+  f5m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g5
+// CHECK: call void @f5(i32 1, [3 x i32] [i32 6, i32 7, i32 0])
+// CHECK: call void @f5m(i32 1, i32 2, i32 3, i32 4, i32 5, [3 x i32] [i32 6, i32 7, i32 0])
+// CHECK: declare void @f5(i32, [3 x i32])
+// CHECK: declare void @f5m(i32, i32, i32, i32, i32, [3 x i32])
+
+
+// Packed and aligned, alignement causes padding at the end.
+struct  __attribute__((packed, aligned(8))) P8 {
+  int x;
+  long long u;
+};
+
+void f6(int, P8);
+void f6m(int, int, int, int, int, P8);
+void g6() {
+  P8 s = {6, 7};
+  f6(1, s);
+  f6m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g6
+// CHECK: call void @f6(i32 1, [4 x i32] [i32 6, i32 7, i32 0, i32 0])
+// CHECK: call void @f6m(i32 1, i32 2, i32 3, i32 4, i32 5, [4 x i32] [i32 6, i32 7, i32 0, i32 0])
+// CHECK: declare void @f6(i32, [4 x i32])
+// CHECK: declare void @f6m(i32, i32, i32, i32, i32, [4 x i32])
+}
diff --git a/test/CodeGen/aapcs64-align.cc b/test/CodeGen/aapcs64-align.cc
new file mode 100644
index 0000000000..1b7c99ea87
--- /dev/null
+++ b/test/CodeGen/aapcs64-align.cc
@@ -0,0 +1,103 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-none-eabi \
+// RUN:   -O2 \
+// RUN:   -emit-llvm -o - %s | FileCheck %s
+
+extern "C" {
+
+// Base case, nothing interesting.
+struct S {
+  long x, y;
+};
+
+void f0(long, S);
+void f0m(long, long, long, long, long, S);
+void g0() {
+  S s = {6, 7};
+  f0(1, s);
+  f0m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g0
+// CHECK: call void @f0(i64 1, [2 x i64] [i64 6, i64 7]
+// CHECK: call void @f0m{{.*}}[2 x i64] [i64 6, i64 7]
+// CHECK: declare void @f0(i64, [2 x i64])
+// CHECK: declare void @f0m(i64, i64, i64, i64, i64, [2 x i64])
+
+// Aligned struct, passed according to its natural alignment.
+struct __attribute__((aligned(16))) S16 {
+  long x, y;
+} s16;
+
+void f1(long, S16);
+void f1m(long, long, long, long, long, S16);
+void g1() {
+  S16 s = {6, 7};
+  f1(1, s);
+  f1m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g1
+// CHECK: call void @f1{{.*}}[2 x i64] [i64 6, i64 7]
+// CHECK: call void @f1m{{.*}}[2 x i64] [i64 6, i64 7]
+// CHECK: declare void @f1(i64, [2 x i64])
+// CHECK: declare void @f1m(i64, i64, i64, i64, i64, [2 x i64])
+
+// Increased natural alignment.
+struct SF16 {
+  long x __attribute__((aligned(16)));
+  long y;
+};
+
+void f3(long, SF16);
+void f3m(long, long, long, long, long, SF16);
+void g3() {
+  SF16 s = {6, 7};
+  f3(1, s);
+  f3m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g3
+// CHECK: call void @f3(i64 1, i128 129127208515966861318)
+// CHECK: call void @f3m(i64 1, i64 2, i64 3, i64 4, i64 5, i128 129127208515966861318)
+// CHECK: declare void @f3(i64, i128)
+// CHECK: declare void @f3m(i64, i64, i64, i64, i64, i128)
+
+
+// Packed structure.
+struct  __attribute__((packed)) P {
+  int x;
+  long u;
+};
+
+void f4(int, P);
+void f4m(int, int, int, int, int, P);
+void g4() {
+  P s = {6, 7};
+  f4(1, s);
+  f4m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g4()
+// CHECK: call void @f4(i32 1, [2 x i64] [i64 30064771078, i64 0])
+// CHECK: void @f4m(i32 1, i32 2, i32 3, i32 4, i32 5, [2 x i64] [i64 30064771078, i64 0])
+// CHECK: declare void @f4(i32, [2 x i64])
+// CHECK: declare void @f4m(i32, i32, i32, i32, i32, [2 x i64])
+
+
+// Packed structure, overaligned, same as above.
+struct  __attribute__((packed, aligned(16))) P16 {
+  int x;
+  long y;
+};
+
+void f5(int, P16);
+void f5m(int, int, int, int, int, P16);
+  void g5() {
+    P16 s = {6, 7};
+    f5(1, s);
+    f5m(1, 2, 3, 4, 5, s);
+}
+// CHECK: define void @g5()
+// CHECK: call void @f5(i32 1, [2 x i64] [i64 30064771078, i64 0])
+// CHECK: void @f5m(i32 1, i32 2, i32 3, i32 4, i32 5, [2 x i64] [i64 30064771078, i64 0])
+// CHECK: declare void @f5(i32, [2 x i64])
+// CHECK: declare void @f5m(i32, i32, i32, i32, i32, [2 x i64])
+
+}
diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c
index ef4e76054f..ca6b70b446 100644
--- a/test/CodeGen/arm-arguments.c
+++ b/test/CodeGen/arm-arguments.c
@@ -211,10 +211,13 @@ float32x4_t f35(int i, s35_with_align s1, s35_with_align s2) {
 // APCS-GNU: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align {{[0-9]+}} %[[b]], i8* align {{[0-9]+}} %[[c]]
 // APCS-GNU: %[[d:.*]] = bitcast %struct.s35* %[[a]] to <4 x float>*
 // APCS-GNU: load <4 x float>, <4 x float>* %[[d]], align 16
-// AAPCS-LABEL: define arm_aapcscc <4 x float> @f35(i32 %i, %struct.s35* byval align 8, %struct.s35* byval align 8)
-// AAPCS: %[[a:.*]] = alloca %struct.s35, align 16
-// AAPCS: %[[b:.*]] = bitcast %struct.s35* %[[a]] to i8*
-// AAPCS: %[[c:.*]] = bitcast %struct.s35* %0 to i8*
-// AAPCS: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %[[b]], i8* align 8 %[[c]]
-// AAPCS: %[[d:.*]] = bitcast %struct.s35* %[[a]] to <4 x float>*
-// AAPCS: load <4 x float>, <4 x float>* %[[d]], align 16
+
+// AAPCS-LABEL: define arm_aapcscc <4 x float> @f35(i32 %i, %struct.s35* byval align 4 %s1, %struct.s35* byval align 4 %s2)
+// AAPCS: %[[a_addr:.*]] = alloca <4 x float>, align 16
+// AAPCS: %[[b_addr:.*]] = alloca <4 x float>, align 16
+// AAPCS: %[[p1:.*]] = bitcast %struct.s35* %s1 to <4 x float>*
+// AAPCS: %[[a:.*]] = load <4 x float>, <4 x float>* %[[p1]], align 4
+// AAPCS: %[[p2:.*]] = bitcast %struct.s35* %s2 to <4 x float>*
+// AAPCS: %[[b:.*]] = load <4 x float>, <4 x float>* %[[p2]], align 4
+// AAPCS: store <4 x float> %[[a]], <4 x float>* %[[a_addr]], align 16
+// AAPCS: store <4 x float> %[[b]], <4 x float>* %[[b_addr]], align 16
-- 
GitLab


From 38025c8580e4dd5e40cce8e97ed245f72fb00e0f Mon Sep 17 00:00:00 2001
From: Richard Smith 
Date: Mon, 30 Jul 2018 18:05:19 +0000
Subject: [PATCH 0781/1023] Delete some unreachable AST printing code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338282 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/TypePrinter.cpp | 30 ------------------------------
 1 file changed, 30 deletions(-)

diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index c5e2244e26..de6638e853 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -1489,36 +1489,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
     break;
   }
 
-  case AttributedType::attr_objc_gc: {
-    OS << "objc_gc(";
-
-    QualType tmp = T->getEquivalentType();
-    while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
-      QualType next = tmp->getPointeeType();
-      if (next == tmp) break;
-      tmp = next;
-    }
-
-    if (tmp.isObjCGCWeak())
-      OS << "weak";
-    else
-      OS << "strong";
-    OS << ')';
-    break;
-  }
-
-  case AttributedType::attr_objc_ownership:
-    OS << "objc_ownership(";
-    switch (T->getEquivalentType().getObjCLifetime()) {
-    case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
-    case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
-    case Qualifiers::OCL_Strong: OS << "strong"; break;
-    case Qualifiers::OCL_Weak: OS << "weak"; break;
-    case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
-    }
-    OS << ')';
-    break;
-
   case AttributedType::attr_ns_returns_retained:
     OS << "ns_returns_retained";
     break;
-- 
GitLab


From 55d0abdd355122c4d7a7c8e08e4818329aab5252 Mon Sep 17 00:00:00 2001
From: George Karpenkov 
Date: Mon, 30 Jul 2018 18:57:13 +0000
Subject: [PATCH 0782/1023] [analyzer] Store ValueDecl in DeclRegion

All use cases of DeclRegion actually have ValueDecl there,
and getting the name from declaration comes in very handy.

Differential Revision: https://reviews.llvm.org/D49998

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338286 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index f3846eba6b..9bc79a8f10 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -897,9 +897,9 @@ public:
 
 class DeclRegion : public TypedValueRegion {
 protected:
-  const Decl *D;
+  const ValueDecl *D;
 
-  DeclRegion(const Decl *d, const MemRegion *sReg, Kind k)
+  DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)
       : TypedValueRegion(sReg, k), D(d) {
     assert(classof(this));
     assert(d);
@@ -909,7 +909,7 @@ protected:
                       const MemRegion* superRegion, Kind k);
 
 public:
-  const Decl *getDecl() const { return D; }
+  const ValueDecl *getDecl() const { return D; }
   void Profile(llvm::FoldingSetNodeID& ID) const override;
 
   static bool classof(const MemRegion* R) {
-- 
GitLab


From 5e2a3ae204528fafb4a1e8a245d12961a573bdb3 Mon Sep 17 00:00:00 2001
From: Roman Lebedev 
Date: Mon, 30 Jul 2018 18:58:30 +0000
Subject: [PATCH 0783/1023] [clang][ubsan] Implicit Conversion Sanitizer -
 integer truncation  - clang part

Summary:
C and C++ are interesting languages. They are statically typed, but weakly.
The implicit conversions are allowed. This is nice, allows to write code
while balancing between getting drowned in everything being convertible,
and nothing being convertible. As usual, this comes with a price:

```
unsigned char store = 0;

bool consume(unsigned int val);

void test(unsigned long val) {
  if (consume(val)) {
    // the 'val' is `unsigned long`, but `consume()` takes `unsigned int`.
    // If their bit widths are different on this platform, the implicit
    // truncation happens. And if that `unsigned long` had a value bigger
    // than UINT_MAX, then you may or may not have a bug.

    // Similarly, integer addition happens on `int`s, so `store` will
    // be promoted to an `int`, the sum calculated (0+768=768),
    // and the result demoted to `unsigned char`, and stored to `store`.
    // In this case, the `store` will still be 0. Again, not always intended.
    store = store + 768; // before addition, 'store' was promoted to int.
  }

  // But yes, sometimes this is intentional.
  // You can either make the conversion explicit
  (void)consume((unsigned int)val);
  // or mask the value so no bits will be *implicitly* lost.
  (void)consume((~((unsigned int)0)) & val);
}
```

Yes, there is a `-Wconversion`` diagnostic group, but first, it is kinda
noisy, since it warns on everything (unlike sanitizers, warning on an
actual issues), and second, there are cases where it does **not** warn.
So a Sanitizer is needed. I don't have any motivational numbers, but i know
i had this kind of problem 10-20 times, and it was never easy to track down.

The logic to detect whether an truncation has happened is pretty simple
if you think about it - https://godbolt.org/g/NEzXbb - basically, just
extend (using the new, not original!, signedness) the 'truncated' value
back to it's original width, and equality-compare it with the original value.

The most non-trivial thing here is the logic to detect whether this
`ImplicitCastExpr` AST node is **actually** an implicit conversion, //or//
part of an explicit cast. Because the explicit casts are modeled as an outer
`ExplicitCastExpr` with some `ImplicitCastExpr`'s as **direct** children.
https://godbolt.org/g/eE1GkJ

Nowadays, we can just use the new `part_of_explicit_cast` flag, which is set
on all the implicitly-added `ImplicitCastExpr`'s of an `ExplicitCastExpr`.
So if that flag is **not** set, then it is an actual implicit conversion.

As you may have noted, this isn't just named `-fsanitize=implicit-integer-truncation`.
There are potentially some more implicit conversions to be warned about.
Namely, implicit conversions that result in sign change; implicit conversion
between different floating point types, or between fp and an integer,
when again, that conversion is lossy.

One thing i know isn't handled is bitfields.

This is a clang part.
The compiler-rt part is D48959.

Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=21530 | PR21530 ]], [[ https://bugs.llvm.org/show_bug.cgi?id=37552 | PR37552 ]], [[ https://bugs.llvm.org/show_bug.cgi?id=35409 | PR35409 ]].
Partially fixes [[ https://bugs.llvm.org/show_bug.cgi?id=9821 | PR9821 ]].
Fixes https://github.com/google/sanitizers/issues/940. (other than sign-changing implicit conversions)

Reviewers: rjmccall, rsmith, samsonov, pcc, vsk, eugenis, efriedma, kcc, erichkeane

Reviewed By: rsmith, vsk, erichkeane

Subscribers: erichkeane, klimek, #sanitizers, aaron.ballman, RKSimon, dtzWill, filcab, danielaustin, ygribov, dvyukov, milianw, mclow.lists, cfe-commits, regehr

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D48958

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338288 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst                         |  32 +-
 docs/UndefinedBehaviorSanitizer.rst           |  34 +-
 include/clang/Basic/Sanitizers.def            |   9 +-
 include/clang/Basic/Sanitizers.h              |   3 +-
 lib/CodeGen/CGExprScalar.cpp                  | 105 ++++-
 lib/CodeGen/CodeGenFunction.h                 |   1 +
 lib/Driver/SanitizerArgs.cpp                  |  10 +-
 lib/Driver/ToolChain.cpp                      |   4 +-
 .../catch-implicit-integer-truncations.c      | 395 ++++++++++++++++++
 .../catch-implicit-integer-truncations.cpp    | 256 ++++++++++++
 test/Driver/fsanitize.c                       |  17 +-
 11 files changed, 829 insertions(+), 37 deletions(-)
 create mode 100644 test/CodeGen/catch-implicit-integer-truncations.c
 create mode 100644 test/CodeGenCXX/catch-implicit-integer-truncations.cpp

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 342fed3393..1e45a13ef9 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -46,7 +46,9 @@ sections with improvements to Clang's support for those languages.
 Major New Features
 ------------------
 
--  ...
+- A new Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
+  was added. Please refer to the :ref:`release-notes-ubsan` section of the
+  release notes for the details.
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -280,10 +282,36 @@ Static Analyzer
 
 ...
 
+.. _release-notes-ubsan:
+
 Undefined Behavior Sanitizer (UBSan)
 ------------------------------------
 
-* ...
+* A new Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
+  was added.
+
+  Currently, only one type of issues is caught - implicit integer truncation
+  (``-fsanitize=implicit-integer-truncation``), also known as integer demotion.
+  While there is a ``-Wconversion`` diagnostic group that catches this kind of
+  issues, it is both noisy, and does not catch **all** the cases.
+
+  .. code-block:: c++
+
+      unsigned char store = 0;
+
+      bool consume(unsigned int val);
+
+      void test(unsigned long val) {
+        if (consume(val)) // the value may have been silently truncated.
+          store = store + 768; // before addition, 'store' was promoted to int.
+        (void)consume((unsigned int)val); // OK, the truncation is explicit.
+      }
+
+  Just like other ``-fsanitize=integer`` checks, these issues are **not**
+  undefined behaviour. But they are not *always* intentional, and are somewhat
+  hard to track down. This group is **not** enabled by ``-fsanitize=undefined``,
+  but the ``-fsanitize=implicit-integer-truncation`` check
+  is enabled by ``-fsanitize=integer``.
 
 Core Analysis Improvements
 ==========================
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index 71a8ebd4bc..6cf53f5683 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -89,6 +89,12 @@ Available checks are:
   -  ``-fsanitize=function``: Indirect call of a function through a
      function pointer of the wrong type (Darwin/Linux, C++ and x86/x86_64
      only).
+  -  ``-fsanitize=implicit-integer-truncation``: Implicit conversion from
+     integer of larger bit width to smaller bit width, if that results in data
+     loss. That is, if the demoted value, after casting back to the original
+     width, is not equal to the original value before the downcast.
+     Issues caught by this sanitizer are not undefined behavior,
+     but are often unintentional.
   -  ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
   -  ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
      parameter which is declared to never be null.
@@ -121,15 +127,21 @@ Available checks are:
      unsigned overflow in C++. You can use ``-fsanitize=shift-base`` or
      ``-fsanitize=shift-exponent`` to check only left-hand side or
      right-hand side of shift operation, respectively.
-  -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow,
-     including all the checks added by ``-ftrapv``, and checking for
-     overflow in signed division (``INT_MIN / -1``).
+  -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
+     result of a signed integer computation cannot be represented in its type.
+     This includes all the checks covered by ``-ftrapv``, as well as checks for
+     signed division overflow (``INT_MIN/-1``), but not checks for
+     lossy implicit conversions performed after the computation
+     (see ``-fsanitize=implicit-conversion``). Both of these two issues are
+     handled by ``-fsanitize=implicit-conversion`` group of checks.
   -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
      program point.
-  -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer
-     overflows. Note that unlike signed integer overflow, unsigned integer
-     is not undefined behavior. However, while it has well-defined semantics,
-     it is often unintentional, so UBSan offers to catch it.
+  -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
+     the result of an unsigned integer computation cannot be represented in its
+     type. Unlike signed integer overflow, this is not undefined behavior, but
+     it is often unintentional. This sanitizer does not check for lossy implicit
+     conversions performed after such a computation
+     (see ``-fsanitize=implicit-conversion``).
   -  ``-fsanitize=vla-bound``: A variable-length array whose bound
      does not evaluate to a positive value.
   -  ``-fsanitize=vptr``: Use of an object whose vptr indicates that it is of
@@ -140,11 +152,17 @@ Available checks are:
 
 You can also use the following check groups:
   -  ``-fsanitize=undefined``: All of the checks listed above other than
-     ``unsigned-integer-overflow`` and the ``nullability-*`` checks.
+     ``unsigned-integer-overflow``, ``implicit-conversion`` and the
+     ``nullability-*`` group of checks.
   -  ``-fsanitize=undefined-trap``: Deprecated alias of
      ``-fsanitize=undefined``.
   -  ``-fsanitize=integer``: Checks for undefined or suspicious integer
      behavior (e.g. unsigned integer overflow).
+     Enables ``signed-integer-overflow``, ``unsigned-integer-overflow``,
+     ``shift``, ``integer-divide-by-zero``, and ``implicit-integer-truncation``.
+  -  ``-fsanitize=implicit-conversion``: Checks for suspicious behaviours of
+     implicit conversions.
+     Currently, only ``-fsanitize=implicit-integer-truncation`` is implemented.
   -  ``-fsanitize=nullability``: Enables ``nullability-arg``,
      ``nullability-assign``, and ``nullability-return``. While violating
      nullability does not have undefined behavior, it is often unintentional,
diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def
index 5a36822a63..ae5c75fc5b 100644
--- a/include/clang/Basic/Sanitizers.def
+++ b/include/clang/Basic/Sanitizers.def
@@ -131,9 +131,14 @@ SANITIZER_GROUP("undefined", Undefined,
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
 
+// ImplicitConversionSanitizer
+SANITIZER("implicit-integer-truncation", ImplicitIntegerTruncation)
+SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
+                ImplicitIntegerTruncation)
+
 SANITIZER_GROUP("integer", Integer,
-                SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
-                IntegerDivideByZero)
+                ImplicitIntegerTruncation | IntegerDivideByZero | Shift |
+                    SignedIntegerOverflow | UnsignedIntegerOverflow)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h
index 469d9e2e95..2ecbde8215 100644
--- a/include/clang/Basic/Sanitizers.h
+++ b/include/clang/Basic/Sanitizers.h
@@ -84,7 +84,8 @@ SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
 /// Return the sanitizers which do not affect preprocessing.
 inline SanitizerMask getPPTransparentSanitizers() {
   return SanitizerKind::CFI | SanitizerKind::Integer |
-         SanitizerKind::Nullability | SanitizerKind::Undefined;
+         SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
+         SanitizerKind::Undefined;
 }
 
 } // namespace clang
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 783f74c502..b9fcb507a6 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -299,13 +299,31 @@ public:
                                 Value *Src, QualType SrcType, QualType DstType,
                                 llvm::Type *DstTy, SourceLocation Loc);
 
+  /// Known implicit conversion check kinds.
+  /// Keep in sync with the enum of the same name in ubsan_handlers.h
+  enum ImplicitConversionCheckKind : unsigned char {
+    ICCK_IntegerTruncation = 0,
+  };
+
+  /// Emit a check that an [implicit] truncation of an integer  does not
+  /// discard any bits. It is not UB, so we use the value after truncation.
+  void EmitIntegerTruncationCheck(Value *Src, QualType SrcType, Value *Dst,
+                                  QualType DstType, SourceLocation Loc);
+
   /// Emit a conversion from the specified type to the specified destination
   /// type, both of which are LLVM scalar types.
-  Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
-                              SourceLocation Loc);
+  struct ScalarConversionOpts {
+    bool TreatBooleanAsSigned;
+    bool EmitImplicitIntegerTruncationChecks;
 
-  Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
-                              SourceLocation Loc, bool TreatBooleanAsSigned);
+    ScalarConversionOpts()
+        : TreatBooleanAsSigned(false),
+          EmitImplicitIntegerTruncationChecks(false) {}
+  };
+  Value *
+  EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
+                       SourceLocation Loc,
+                       ScalarConversionOpts Opts = ScalarConversionOpts());
 
   /// Emit a conversion from the specified complex type to the specified
   /// destination type, where the destination type is an LLVM scalar type.
@@ -923,18 +941,59 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
                 SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
 }
 
-/// Emit a conversion from the specified type to the specified destination type,
-/// both of which are LLVM scalar types.
-Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
-                                               QualType DstType,
-                                               SourceLocation Loc) {
-  return EmitScalarConversion(Src, SrcType, DstType, Loc, false);
+void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
+                                                   Value *Dst, QualType DstType,
+                                                   SourceLocation Loc) {
+  if (!CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation))
+    return;
+
+  llvm::Type *SrcTy = Src->getType();
+  llvm::Type *DstTy = Dst->getType();
+
+  // We only care about int->int conversions here.
+  // We ignore conversions to/from pointer and/or bool.
+  if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
+    return;
+
+  assert(isa(SrcTy) && isa(DstTy) &&
+         "clang integer type lowered to non-integer llvm type");
+
+  unsigned SrcBits = SrcTy->getScalarSizeInBits();
+  unsigned DstBits = DstTy->getScalarSizeInBits();
+  // This must be truncation. Else we do not care.
+  if (SrcBits <= DstBits)
+    return;
+
+  assert(!DstType->isBooleanType() && "we should not get here with booleans.");
+
+  CodeGenFunction::SanitizerScope SanScope(&CGF);
+
+  llvm::Value *Check = nullptr;
+
+  // 1. Extend the truncated value back to the same width as the Src.
+  bool InputSigned = DstType->isSignedIntegerOrEnumerationType();
+  Check = Builder.CreateIntCast(Dst, SrcTy, InputSigned, "anyext");
+  // 2. Equality-compare with the original source value
+  Check = Builder.CreateICmpEQ(Check, Src, "truncheck");
+  // If the comparison result is 'i1 false', then the truncation was lossy.
+
+  llvm::Constant *StaticArgs[] = {
+      CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
+      CGF.EmitCheckTypeDescriptor(DstType),
+      llvm::ConstantInt::get(Builder.getInt8Ty(), ICCK_IntegerTruncation)};
+  CGF.EmitCheck(std::make_pair(Check, SanitizerKind::ImplicitIntegerTruncation),
+                SanitizerHandler::ImplicitConversion, StaticArgs, {Src, Dst});
 }
 
+/// Emit a conversion from the specified type to the specified destination type,
+/// both of which are LLVM scalar types.
 Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
                                                QualType DstType,
                                                SourceLocation Loc,
-                                               bool TreatBooleanAsSigned) {
+                                               ScalarConversionOpts Opts) {
+  QualType NoncanonicalSrcType = SrcType;
+  QualType NoncanonicalDstType = DstType;
+
   SrcType = CGF.getContext().getCanonicalType(SrcType);
   DstType = CGF.getContext().getCanonicalType(DstType);
   if (SrcType == DstType) return Src;
@@ -1083,7 +1142,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
 
   if (isa(SrcTy)) {
     bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
-    if (SrcType->isBooleanType() && TreatBooleanAsSigned) {
+    if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) {
       InputSigned = true;
     }
     if (isa(DstTy))
@@ -1118,6 +1177,10 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
     }
   }
 
+  if (Opts.EmitImplicitIntegerTruncationChecks)
+    EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res,
+                               NoncanonicalDstType, Loc);
+
   return Res;
 }
 
@@ -1812,16 +1875,26 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
     return Builder.CreateVectorSplat(NumElements, Elt, "splat");
   }
 
-  case CK_IntegralCast:
+  case CK_IntegralCast: {
+    ScalarConversionOpts Opts;
+    if (CGF.SanOpts.has(SanitizerKind::ImplicitIntegerTruncation)) {
+      if (auto *ICE = dyn_cast(CE))
+        Opts.EmitImplicitIntegerTruncationChecks = !ICE->isPartOfExplicitCast();
+    }
+    return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+                                CE->getExprLoc(), Opts);
+  }
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
     return EmitScalarConversion(Visit(E), E->getType(), DestTy,
                                 CE->getExprLoc());
-  case CK_BooleanToSignedIntegral:
+  case CK_BooleanToSignedIntegral: {
+    ScalarConversionOpts Opts;
+    Opts.TreatBooleanAsSigned = true;
     return EmitScalarConversion(Visit(E), E->getType(), DestTy,
-                                CE->getExprLoc(),
-                                /*TreatBooleanAsSigned=*/true);
+                                CE->getExprLoc(), Opts);
+  }
   case CK_IntegralToBoolean:
     return EmitIntToBoolConversion(Visit(E));
   case CK_PointerToBoolean:
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 1f8f3367db..f9e2842329 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -116,6 +116,7 @@ enum TypeEvaluationKind {
   SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0)            \
   SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0)                   \
   SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0)             \
+  SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0)                  \
   SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0)                          \
   SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0)                     \
   SANITIZER_CHECK(MissingReturn, missing_return, 0)                            \
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index bdc17d11c9..55036daa44 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -27,22 +27,22 @@ using namespace clang::driver;
 using namespace llvm::opt;
 
 enum : SanitizerMask {
-  NeedsUbsanRt = Undefined | Integer | Nullability | CFI,
+  NeedsUbsanRt = Undefined | Integer | ImplicitConversion | Nullability | CFI,
   NeedsUbsanCxxRt = Vptr | CFI,
   NotAllowedWithTrap = Vptr,
   NotAllowedWithMinimalRuntime = Vptr,
   RequiresPIE = DataFlow | HWAddress | Scudo,
   NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
   SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
-                     Memory | Leak | Undefined | Integer | Nullability |
-                     DataFlow | Fuzzer | FuzzerNoLink,
-  RecoverableByDefault = Undefined | Integer | Nullability,
+                     Memory | Leak | Undefined | Integer | ImplicitConversion |
+                     Nullability | DataFlow | Fuzzer | FuzzerNoLink,
+  RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
   Unrecoverable = Unreachable | Return,
   AlwaysRecoverable = KernelAddress | KernelHWAddress,
   LegacyFsanitizeRecoverMask = Undefined | Integer,
   NeedsLTO = CFI,
   TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow |
-                      Nullability | LocalBounds | CFI,
+                      ImplicitConversion | Nullability | LocalBounds | CFI,
   TrappingDefault = CFI,
   CFIClasses =
       CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast,
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index d62ba12533..39a6d9b4cc 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -803,8 +803,8 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
   using namespace SanitizerKind;
 
   SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
-                      CFICastStrict | UnsignedIntegerOverflow | Nullability |
-                      LocalBounds;
+                      CFICastStrict | UnsignedIntegerOverflow |
+                      ImplicitConversion | Nullability | LocalBounds;
   if (getTriple().getArch() == llvm::Triple::x86 ||
       getTriple().getArch() == llvm::Triple::x86_64 ||
       getTriple().getArch() == llvm::Triple::arm ||
diff --git a/test/CodeGen/catch-implicit-integer-truncations.c b/test/CodeGen/catch-implicit-integer-truncations.c
new file mode 100644
index 0000000000..b09f7ddfae
--- /dev/null
+++ b/test/CodeGen/catch-implicit-integer-truncations.c
@@ -0,0 +1,395 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 }
+
+// CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" }
+// CHECK-SANITIZE-ANYRECOVER: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 0 }
+
+// ========================================================================== //
+// The expected true-positives. These are implicit conversions, and they truncate.
+// ========================================================================== //
+
+// CHECK-LABEL: @unsigned_int_to_unsigned_char
+unsigned char unsigned_int_to_unsigned_char(unsigned int src) {
+  // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
+  // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+  // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+  // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+  // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+  // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+  // CHECK-SANITIZE: [[CONT]]:
+  // CHECK: ret i8 %[[DST]]
+#line 100
+  return src;
+}
+
+// CHECK-LABEL: @signed_int_to_unsigned_char
+unsigned char signed_int_to_unsigned_char(signed int src) {
+  // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
+  // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+  // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+  // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+  // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+  // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+  // CHECK-SANITIZE: [[CONT]]:
+  // CHECK: ret i8 %[[DST]]
+#line 200
+  return src;
+}
+
+// CHECK-LABEL: @unsigned_int_to_signed_char
+signed char unsigned_int_to_signed_char(unsigned int src) {
+  // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
+  // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+  // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+  // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+  // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+  // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+  // CHECK-SANITIZE: [[CONT]]:
+  // CHECK: ret i8 %[[DST]]
+#line 300
+  return src;
+}
+
+// CHECK-LABEL: @signed_int_to_signed_char
+signed char signed_int_to_signed_char(signed int src) {
+  // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
+  // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
+  // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+  // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+  // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+  // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+  // CHECK-SANITIZE: [[CONT]]:
+  // CHECK: ret i8 %[[DST]]
+#line 400
+  return src;
+}
+
+// ========================================================================== //
+// Check canonical type stuff
+// ========================================================================== //
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+
+// CHECK-LABEL: @uint32_to_uint8
+uint8_t uint32_to_uint8(uint32_t src) {
+  // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
+  // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
+  // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
+  // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
+  // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
+  // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
+  // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize
+  // CHECK-SANITIZE-TRAP-NEXT: unreachable, !nosanitize
+  // CHECK-SANITIZE: [[CONT]]:
+  // CHECK: ret i8 %[[DST]]
+#line 500
+  return src;
+}
+
+// ========================================================================== //
+// Check that explicit conversion does not interfere with implicit conversion
+// ========================================================================== //
+// These contain one implicit truncating conversion, and one explicit truncating conversion.
+// We want to make sure that we still diagnose the implicit conversion.
+
+// Implicit truncation after explicit truncation.
+// CHECK-LABEL: @explicit_conversion_interference0
+unsigned char explicit_conversion_interference0(unsigned int c) {
+  // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
+  // CHECK-SANITIZE: call
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned short)c;
+}
+
+// Implicit truncation before explicit truncation.
+// CHECK-LABEL: @explicit_conversion_interference1
+unsigned char explicit_conversion_interference1(unsigned int c) {
+  // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
+  // CHECK-SANITIZE: call
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  unsigned short b;
+  return (unsigned char)(b = c);
+}
+
+// ========================================================================== //
+// The expected true-negatives.
+// ========================================================================== //
+
+// Sanitization is explicitly disabled.
+// ========================================================================== //
+
+// CHECK-LABEL: @blacklist_0
+__attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) {
+  // We are not in "undefined" group, so that doesn't work.
+  // CHECK-SANITIZE: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @blacklist_1
+__attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_1(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @blacklist_2
+__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_2(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// Explicit truncating conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
+unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_unsigned_char
+unsigned char explicit_signed_int_to_unsigned_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_signed_char
+signed char explicit_unsigned_int_to_signed_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_signed_char
+signed char explicit_signed_int_to_signed_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// Explicit NOP conversions.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
+unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_signed_int
+signed int explicit_signed_int_to_signed_int(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed int)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_char_to_signed_char
+unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_char_to_signed_char
+signed char explicit_signed_char_to_signed_char(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// upcasts.
+// ========================================================================== //
+
+// CHECK-LABEL: @unsigned_char_to_unsigned_int
+unsigned int unsigned_char_to_unsigned_int(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @signed_char_to_unsigned_int
+unsigned int signed_char_to_unsigned_int(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @unsigned_char_to_signed_int
+signed int unsigned_char_to_signed_int(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @signed_char_to_signed_int
+signed int signed_char_to_signed_int(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// Explicit upcasts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int
+unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_signed_char_to_unsigned_int
+unsigned int explicit_signed_char_to_unsigned_int(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_char_to_signed_int
+signed int explicit_unsigned_char_to_signed_int(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed int)src;
+}
+
+// CHECK-LABEL: @explicit_signed_char_to_signed_int
+signed int explicit_signed_char_to_signed_int(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed int)src;
+}
+
+// conversions to to boolean type are not counted as truncation.
+// ========================================================================== //
+
+// CHECK-LABEL: @unsigned_int_to_bool
+_Bool unsigned_int_to_bool(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @signed_int_to_bool
+_Bool signed_int_to_bool(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_bool
+_Bool explicit_unsigned_int_to_bool(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (_Bool)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_bool
+_Bool explicit_signed_int_to_bool(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (_Bool)src;
+}
+
+// Explicit truncating conversions from pointer to a much-smaller integer.
+// Can not have an implicit conversion from pointer to an integer.
+// Can not have an implicit conversion between two enums.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_voidptr_to_unsigned_char
+unsigned char explicit_voidptr_to_unsigned_char(void *src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_voidptr_to_signed_char
+signed char explicit_voidptr_to_signed_char(void *src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// Implicit truncating conversions from floating-point may result in precision loss.
+// ========================================================================== //
+
+// CHECK-LABEL: @float_to_unsigned_int
+unsigned int float_to_unsigned_int(float src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @float_to_signed_int
+signed int float_to_signed_int(float src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @double_to_unsigned_int
+unsigned int double_to_unsigned_int(double src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// CHECK-LABEL: @double_to_signed_int
+signed int double_to_signed_int(double src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
+
+// Implicit truncating conversions between fp may result in precision loss.
+// ========================================================================== //
+
+// CHECK-LABEL: @double_to_float
+float double_to_float(double src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return src;
+}
diff --git a/test/CodeGenCXX/catch-implicit-integer-truncations.cpp b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
new file mode 100644
index 0000000000..ba7676a350
--- /dev/null
+++ b/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
@@ -0,0 +1,256 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-recover=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fsanitize-trap=implicit-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP
+
+extern "C" { // Disable name mangling.
+
+// ========================================================================== //
+// Check that explicit cast does not interfere with implicit conversion
+// ========================================================================== //
+// These contain one implicit truncating conversion, and one explicit truncating cast.
+// We want to make sure that we still diagnose the implicit conversion.
+
+// Implicit truncation after explicit truncation.
+// CHECK-LABEL: @explicit_cast_interference0
+unsigned char explicit_cast_interference0(unsigned int c) {
+  // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
+  // CHECK-SANITIZE: call
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned short)c;
+}
+
+// Implicit truncation before explicit truncation.
+// CHECK-LABEL: @explicit_cast_interference1
+unsigned char explicit_cast_interference1(unsigned int c) {
+  // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
+  // CHECK-SANITIZE: call
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  unsigned short b;
+  return (unsigned char)(b = c);
+}
+
+// ========================================================================== //
+// The expected true-negatives.
+// ========================================================================== //
+
+// Explicit truncating casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
+unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_unsigned_char
+unsigned char explicit_signed_int_to_unsigned_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_int_to_signed_char
+signed char explicit_unsigned_int_to_signed_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_signed_char
+signed char explicit_signed_int_to_signed_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// Explicit NOP casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
+unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned int)src;
+}
+
+// CHECK-LABEL: @explicit_signed_int_to_signed_int
+signed int explicit_signed_int_to_signed_int(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed int)src;
+}
+
+// CHECK-LABEL: @explicit_unsigned_char_to_signed_char
+unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (unsigned char)src;
+}
+
+// CHECK-LABEL: @explicit_signed_char_to_signed_char
+signed char explicit_signed_char_to_signed_char(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return (signed char)src;
+}
+
+// Explicit functional truncating casts.
+// ========================================================================== //
+
+using UnsignedChar = unsigned char;
+using SignedChar = signed char;
+using UnsignedInt = unsigned int;
+using SignedInt = signed int;
+
+// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_char
+unsigned char explicit_functional_unsigned_int_to_unsigned_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return UnsignedChar(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_int_to_unsigned_char
+unsigned char explicit_functional_signed_int_to_unsigned_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return UnsignedChar(src);
+}
+
+// CHECK-LABEL: @explicit_functional_unsigned_int_to_signed_char
+signed char explicit_functional_unsigned_int_to_signed_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return SignedChar(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_int_to_signed_char
+signed char explicit_functional_signed_int_to_signed_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return SignedChar(src);
+}
+
+// Explicit functional NOP casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_int
+unsigned int explicit_functional_unsigned_int_to_unsigned_int(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return UnsignedInt(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_int_to_signed_int
+signed int explicit_functional_signed_int_to_signed_int(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return SignedInt(src);
+}
+
+// CHECK-LABEL: @explicit_functional_unsigned_char_to_signed_char
+unsigned char explicit_functional_unsigned_char_to_signed_char(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return UnsignedChar(src);
+}
+
+// CHECK-LABEL: @explicit_functional_signed_char_to_signed_char
+signed char explicit_functional_signed_char_to_signed_char(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return SignedChar(src);
+}
+
+// Explicit C++-style casts truncating casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_cppstyleunsigned_int_to_unsigned_char
+unsigned char explicit_cppstyleunsigned_int_to_unsigned_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstylesigned_int_to_unsigned_char
+unsigned char explicit_cppstylesigned_int_to_unsigned_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstyleunsigned_int_to_signed_char
+signed char explicit_cppstyleunsigned_int_to_signed_char(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstylesigned_int_to_signed_char
+signed char explicit_cppstylesigned_int_to_signed_char(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// Explicit C++-style casts NOP casts.
+// ========================================================================== //
+
+// CHECK-LABEL: @explicit_cppstyleunsigned_int_to_unsigned_int
+unsigned int explicit_cppstyleunsigned_int_to_unsigned_int(unsigned int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstylesigned_int_to_signed_int
+signed int explicit_cppstylesigned_int_to_signed_int(signed int src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstyleunsigned_char_to_signed_char
+unsigned char explicit_cppstyleunsigned_char_to_signed_char(unsigned char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+// CHECK-LABEL: @explicit_cppstylesigned_char_to_signed_char
+signed char explicit_cppstylesigned_char_to_signed_char(signed char src) {
+  // CHECK-SANITIZE-NOT: call
+  // CHECK: }
+  return static_cast(src);
+}
+
+} // extern "C"
+
+// ---------------------------------------------------------------------------//
+// A problematic true-negative involving simple C++ code.
+// The problem is tha the NoOp ExplicitCast is directly within MaterializeTemporaryExpr(),
+// so a special care is neeeded.
+// See https://reviews.llvm.org/D48958#1161345
+template 
+a b(a c, const a &d) {
+  if (d)
+    ;
+  return c;
+}
+
+extern "C" { // Disable name mangling.
+
+// CHECK-LABEL: @false_positive_with_MaterializeTemporaryExpr
+int false_positive_with_MaterializeTemporaryExpr() {
+  // CHECK-SANITIZE-NOT: call{{.*}}ubsan
+  // CHECK: }
+  int e = b(4, static_cast(4294967296));
+  return e;
+}
+
+// ---------------------------------------------------------------------------//
+
+} // extern "C"
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index e6d94649f0..458bbf96e2 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -29,7 +29,22 @@
 // CHECK-COVERAGE-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib"
 
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER -implicit-check-not="-fsanitize-address-use-after-scope"
-// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent),?){5}"}}
+// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|implicit-integer-truncation),?){6}"}}
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fno-sanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-NORECOVER
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-trap=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-TRAP
+// CHECK-implicit-conversion: "-fsanitize={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-RECOVER: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-RECOVER-NOT: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}} // ???
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-TRAP: "-fsanitize-trap={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-TRAP-NOT: "-fsanitize-recover={{((implicit-integer-truncation),?){1}"}}
+// CHECK-implicit-conversion-TRAP-NOT: "-fno-sanitize-recover={{((implicit-integer-truncation),?){1}"}}
 
 // RUN: %clang -fsanitize=bounds -### -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=CHECK-BOUNDS
 // CHECK-BOUNDS: "-fsanitize={{((array-bounds|local-bounds),?){2}"}}
-- 
GitLab


From 19e630a4739c684e5848d2f926d0beb114bbce7b Mon Sep 17 00:00:00 2001
From: David Greene 
Date: Mon, 30 Jul 2018 19:08:20 +0000
Subject: [PATCH 0784/1023] Make test/Driver/baremetal.cpp work with linkers
 other than lld

This test fails if clang is configure with, for example, gold as the
default linker. It does not appear that this test really relies on lld
so make the checks accept ld, ld.gold and ld.bfd too.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338290 91177308-0d34-0410-b5e6-96231b3b80d8
---
 test/Driver/baremetal.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/test/Driver/baremetal.cpp b/test/Driver/baremetal.cpp
index a433e2df07..2e93734651 100644
--- a/test/Driver/baremetal.cpp
+++ b/test/Driver/baremetal.cpp
@@ -10,7 +10,7 @@
 // CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECk-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include"
 // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp"
-// CHECK-V6M-C-NEXT: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-V6M-C-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-V6M-C-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for"
 // CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
@@ -32,7 +32,7 @@
 // RUN:     -target armv6m-none-eabi \
 // RUN:     --sysroot=%S/Inputs/baremetal_arm \
 // RUN:   | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s
-// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-V6M-DEFAULTCXX: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
 // CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
@@ -45,7 +45,7 @@
 // RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s
 // CHECK-V6M-LIBCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}{{[^v].*}}"
 // CHECK-V6M-LIBCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
-// CHECK-V6M-LIBCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-V6M-LIBCXX: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
 // CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
@@ -58,7 +58,7 @@
 // RUN:   | FileCheck --check-prefix=CHECK-V6M-LIBSTDCXX %s
 // CHECK-V6M-LIBSTDCXX-NOT: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-V6M-LIBSTDCXX: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0"
-// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-V6M-LIBSTDCXX: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind"
 // CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m.a"
@@ -69,7 +69,7 @@
 // RUN:     --sysroot=%S/Inputs/baremetal_arm \
 // RUN:     -nodefaultlibs \
 // RUN:   | FileCheck --check-prefix=CHECK-V6M-NDL %s
-// CHECK-V6M-NDL: "{{[^"]*}}ld.lld{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-V6M-NDL: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-V6M-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}lib{{(64)?}}{{[/\\]+}}clang{{[/\\]+}}{{.*}}{{[/\\]+}}lib{{[/\\]+}}baremetal" "-o" "{{.*}}.o"
 
 // RUN: %clangxx -target arm-none-eabi -v 2>&1 \
-- 
GitLab


From abdbb605f2c3cbe63cd589da230f648535dff76b Mon Sep 17 00:00:00 2001
From: Fangrui Song 
Date: Mon, 30 Jul 2018 19:24:48 +0000
Subject: [PATCH 0785/1023] Remove trailing space

sed -Ei 's/[[:space:]]+$//' include/**/*.{def,h,td} lib/**/*.{cpp,h}

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338291 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang-c/Index.h                       | 272 ++---
 include/clang/ARCMigrate/FileRemapper.h       |   2 +-
 include/clang/AST/ASTContext.h                |   2 +-
 include/clang/AST/ASTDiagnostic.h             |   4 +-
 include/clang/AST/ASTImporter.h               |  48 +-
 include/clang/AST/ASTLambda.h                 |  14 +-
 include/clang/AST/ASTMutationListener.h       |   4 +-
 include/clang/AST/Attr.h                      |   2 +-
 include/clang/AST/AttrIterator.h              |   2 +-
 include/clang/AST/BaseSubobject.h             |  10 +-
 include/clang/AST/CXXInheritance.h            |  44 +-
 include/clang/AST/CanonicalType.h             |   6 +-
 include/clang/AST/CharUnits.h                 |  32 +-
 include/clang/AST/Comment.h                   |  16 +-
 include/clang/AST/CommentCommandTraits.h      |   8 +-
 include/clang/AST/CommentLexer.h              |   4 +-
 include/clang/AST/CommentSema.h               |   6 +-
 include/clang/AST/Decl.h                      |  52 +-
 include/clang/AST/DeclBase.h                  |  22 +-
 include/clang/AST/DeclCXX.h                   |  66 +-
 include/clang/AST/DeclFriend.h                |   2 +-
 include/clang/AST/DeclLookups.h               |   2 +-
 include/clang/AST/DeclObjC.h                  | 144 +--
 include/clang/AST/DeclTemplate.h              |  22 +-
 include/clang/AST/DeclarationName.h           |   8 +-
 include/clang/AST/DependentDiagnostic.h       |   4 +-
 include/clang/AST/EvaluatedExprVisitor.h      |   4 +-
 include/clang/AST/Expr.h                      |   4 +-
 include/clang/AST/ExprCXX.h                   |  46 +-
 include/clang/AST/ExprObjC.h                  | 176 ++--
 include/clang/AST/ExternalASTMerger.h         |   8 +-
 include/clang/AST/ExternalASTSource.h         |  28 +-
 include/clang/AST/GlobalDecl.h                |  16 +-
 include/clang/AST/LambdaCapture.h             |   2 +-
 include/clang/AST/Mangle.h                    |   2 +-
 include/clang/AST/NSAPI.h                     |   2 +-
 include/clang/AST/NestedNameSpecifier.h       |   6 +-
 include/clang/AST/OperationKinds.def          |   6 +-
 include/clang/AST/OperationKinds.h            |   2 +-
 include/clang/AST/PrettyPrinter.h             |  10 +-
 include/clang/AST/RecordLayout.h              |   8 +-
 include/clang/AST/Stmt.h                      |  10 +-
 include/clang/AST/StmtIterator.h              |   4 +-
 include/clang/AST/StmtObjC.h                  |  34 +-
 include/clang/AST/StmtOpenMP.h                |  20 +-
 include/clang/AST/TemplateBase.h              |  34 +-
 include/clang/AST/TemplateName.h              |  74 +-
 include/clang/AST/Type.h                      |  14 +-
 include/clang/AST/TypeLoc.h                   |  12 +-
 include/clang/AST/TypeOrdering.h              |  10 +-
 include/clang/AST/UnresolvedSet.h             |   2 +-
 include/clang/AST/VTTBuilder.h                |  28 +-
 include/clang/AST/VTableBuilder.h             |   2 +-
 include/clang/ASTMatchers/ASTMatchers.h       |  12 +-
 include/clang/Analysis/Analyses/Consumed.h    |  60 +-
 include/clang/Analysis/Analyses/Dominators.h  |   2 +-
 .../clang/Analysis/Analyses/FormatString.h    |   2 +-
 .../clang/Analysis/Analyses/LiveVariables.h   |  34 +-
 .../clang/Analysis/Analyses/ReachableCode.h   |   2 +-
 .../Analysis/Analyses/ThreadSafetyCommon.h    |   2 +-
 include/clang/Analysis/AnalysisDeclContext.h  |  12 +-
 include/clang/Analysis/CloneDetection.h       |   2 +-
 .../DomainSpecific/CocoaConventions.h         |  10 +-
 .../Analysis/DomainSpecific/ObjCNoReturn.h    |   4 +-
 include/clang/Analysis/ProgramPoint.h         |  28 +-
 include/clang/Analysis/Support/BumpVector.h   |  52 +-
 include/clang/Basic/ABI.h                     |  20 +-
 include/clang/Basic/AllDiagnostics.h          |   4 +-
 include/clang/Basic/Attr.td                   |   8 +-
 include/clang/Basic/Builtins.def              |   2 +-
 include/clang/Basic/BuiltinsPPC.def           |   2 +-
 include/clang/Basic/Diagnostic.h              |  60 +-
 include/clang/Basic/DiagnosticASTKinds.td     |   2 +-
 include/clang/Basic/DiagnosticCommentKinds.td |   6 +-
 include/clang/Basic/DiagnosticCommonKinds.td  |  10 +-
 include/clang/Basic/DiagnosticDriverKinds.td  |   2 +-
 .../clang/Basic/DiagnosticFrontendKinds.td    |   6 +-
 include/clang/Basic/DiagnosticGroups.td       |   6 +-
 include/clang/Basic/DiagnosticIDs.h           |  22 +-
 include/clang/Basic/DiagnosticLexKinds.td     |  12 +-
 include/clang/Basic/DiagnosticOptions.def     |   6 +-
 include/clang/Basic/DiagnosticOptions.h       |   2 +-
 include/clang/Basic/DiagnosticParseKinds.td   |  28 +-
 include/clang/Basic/DiagnosticSemaKinds.td    | 114 +--
 .../Basic/DiagnosticSerializationKinds.td     |   2 +-
 include/clang/Basic/FileSystemStatCache.h     |   6 +-
 include/clang/Basic/IdentifierTable.h         |  38 +-
 include/clang/Basic/LLVM.h                    |   2 +-
 include/clang/Basic/LangOptions.h             |  14 +-
 include/clang/Basic/Linkage.h                 |   4 +-
 include/clang/Basic/Module.h                  |  58 +-
 include/clang/Basic/ObjCRuntime.h             |   2 +-
 include/clang/Basic/OperatorKinds.h           |   2 +-
 include/clang/Basic/SourceLocation.h          |  20 +-
 include/clang/Basic/SourceManager.h           |   8 +-
 include/clang/Basic/SourceManagerInternals.h  |   2 +-
 include/clang/Basic/Specifiers.h              |   6 +-
 include/clang/Basic/StmtNodes.td              |   2 +-
 include/clang/Basic/TemplateKinds.h           |   4 +-
 include/clang/Basic/arm_neon.td               |   6 +-
 include/clang/Basic/arm_neon_incl.td          |   2 +-
 include/clang/Driver/CC1Options.td            |   8 +-
 include/clang/Driver/Driver.h                 |  10 +-
 include/clang/Edit/Commit.h                   |   2 +-
 include/clang/Edit/EditedSource.h             |   2 +-
 include/clang/Edit/Rewriters.h                |   2 +-
 include/clang/Frontend/ASTUnit.h              |  96 +-
 include/clang/Frontend/CompilerInstance.h     |  22 +-
 include/clang/Frontend/CompilerInvocation.h   |  12 +-
 include/clang/Frontend/DiagnosticRenderer.h   |  12 +-
 include/clang/Frontend/FrontendActions.h      |   8 +-
 include/clang/Frontend/LayoutOverrideSource.h |  12 +-
 include/clang/Frontend/LogDiagnosticPrinter.h |  10 +-
 .../clang/Frontend/PCHContainerOperations.h   |   8 +-
 .../clang/Frontend/VerifyDiagnosticConsumer.h |   2 +-
 include/clang/Lex/CodeCompletionHandler.h     |  20 +-
 include/clang/Lex/DirectoryLookup.h           |  12 +-
 .../clang/Lex/ExternalPreprocessorSource.h    |  10 +-
 include/clang/Lex/HeaderSearch.h              |  54 +-
 include/clang/Lex/HeaderSearchOptions.h       |   6 +-
 include/clang/Lex/LiteralSupport.h            |   4 +-
 include/clang/Lex/MacroArgs.h                 |  12 +-
 include/clang/Lex/MacroInfo.h                 |   2 +-
 include/clang/Lex/ModuleLoader.h              |  14 +-
 include/clang/Lex/ModuleMap.h                 |  18 +-
 include/clang/Lex/PPCallbacks.h               |  18 +-
 .../clang/Lex/PPConditionalDirectiveRecord.h  |   4 +-
 include/clang/Lex/PTHLexer.h                  |   2 +-
 include/clang/Lex/Pragma.h                    |   8 +-
 include/clang/Lex/PreprocessingRecord.h       |  58 +-
 include/clang/Lex/Preprocessor.h              |  26 +-
 include/clang/Lex/PreprocessorLexer.h         |   8 +-
 include/clang/Lex/PreprocessorOptions.h       |  16 +-
 include/clang/Lex/Token.h                     |   2 +-
 include/clang/Lex/TokenConcatenation.h        |   4 +-
 include/clang/Lex/TokenLexer.h                |   2 +-
 include/clang/Lex/VariadicMacroSupport.h      |  32 +-
 include/clang/Parse/ParseAST.h                |   2 +-
 include/clang/Parse/Parser.h                  |  20 +-
 include/clang/Parse/RAIIObjectsForParser.h    |  50 +-
 include/clang/Sema/DeclSpec.h                 | 136 +--
 include/clang/Sema/DelayedDiagnostic.h        |   2 +-
 include/clang/Sema/ExternalSemaSource.h       |  18 +-
 include/clang/Sema/IdentifierResolver.h       |  10 +-
 include/clang/Sema/Initialization.h           | 156 +--
 include/clang/Sema/Lookup.h                   |  10 +-
 .../clang/Sema/MultiplexExternalSemaSource.h  |  24 +-
 include/clang/Sema/Overload.h                 |  38 +-
 include/clang/Sema/ParsedAttr.h               |  12 +-
 include/clang/Sema/ParsedTemplate.h           |  76 +-
 include/clang/Sema/Scope.h                    |   4 +-
 include/clang/Sema/ScopeInfo.h                |  98 +-
 include/clang/Sema/SemaInternal.h             |  16 +-
 include/clang/Sema/SemaLambda.h               |   6 +-
 include/clang/Sema/Template.h                 |  62 +-
 include/clang/Serialization/ASTBitCodes.h     |  68 +-
 include/clang/Serialization/ASTReader.h       |  36 +-
 include/clang/Serialization/ASTWriter.h       |   6 +-
 .../clang/Serialization/ContinuousRangeMap.h  |  10 +-
 .../clang/Serialization/GlobalModuleIndex.h   |   4 +-
 include/clang/Serialization/Module.h          |  16 +-
 .../clang/Serialization/ModuleFileExtension.h |   4 +-
 include/clang/Serialization/ModuleManager.h   |  14 +-
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   2 +-
 .../StaticAnalyzer/Checkers/ObjCRetainCount.h |  18 +-
 .../StaticAnalyzer/Core/AnalyzerOptions.h     |  26 +-
 .../Core/BugReporter/BugReporter.h            |  16 +-
 .../Core/BugReporter/BugReporterVisitors.h    |   2 +-
 .../StaticAnalyzer/Core/BugReporter/BugType.h |   2 +-
 .../Core/BugReporter/PathDiagnostic.h         |  50 +-
 include/clang/StaticAnalyzer/Core/Checker.h   |  12 +-
 .../StaticAnalyzer/Core/CheckerManager.h      |  40 +-
 .../StaticAnalyzer/Core/CheckerOptInfo.h      |   2 +-
 .../StaticAnalyzer/Core/CheckerRegistry.h     |   2 +-
 include/clang/StaticAnalyzer/Core/IssueHash.h |   2 +-
 .../Core/PathSensitive/APSIntType.h           |   4 +-
 .../Core/PathSensitive/AnalysisManager.h      |   6 +-
 .../Core/PathSensitive/BasicValueFactory.h    |   4 +-
 .../Core/PathSensitive/BlockCounter.h         |   4 +-
 .../Core/PathSensitive/CallEvent.h            |  20 +-
 .../Core/PathSensitive/CheckerContext.h       |  10 +-
 .../Core/PathSensitive/CoreEngine.h           |  20 +-
 .../Core/PathSensitive/Environment.h          |   4 +-
 .../Core/PathSensitive/ExplodedGraph.h        |  12 +-
 .../Core/PathSensitive/ExprEngine.h           |  56 +-
 .../Core/PathSensitive/MemRegion.h            |  42 +-
 .../Core/PathSensitive/SValBuilder.h          |  14 +-
 .../StaticAnalyzer/Core/PathSensitive/SVals.h |  14 +-
 .../StaticAnalyzer/Core/PathSensitive/Store.h |  16 +-
 .../Core/PathSensitive/StoreRef.h             |  10 +-
 .../Core/PathSensitive/SubEngine.h            |   6 +-
 .../Core/PathSensitive/SummaryManager.h       |  16 +-
 .../Core/PathSensitive/SymbolManager.h        |  12 +-
 .../Core/PathSensitive/WorkList.h             |   6 +-
 lib/ARCMigrate/ARCMT.cpp                      |   6 +-
 lib/ARCMigrate/FileRemapper.cpp               |   6 +-
 lib/ARCMigrate/Internals.h                    |   2 +-
 lib/ARCMigrate/ObjCMT.cpp                     | 144 +--
 lib/ARCMigrate/PlistReporter.cpp              |   2 +-
 lib/ARCMigrate/TransARCAssign.cpp             |   2 +-
 lib/ARCMigrate/TransAutoreleasePool.cpp       |  10 +-
 lib/ARCMigrate/TransBlockObjCVariable.cpp     |   6 +-
 .../TransEmptyStatementsAndDealloc.cpp        |   2 +-
 lib/ARCMigrate/TransGCAttrs.cpp               |   6 +-
 lib/ARCMigrate/TransProperties.cpp            |  14 +-
 lib/ARCMigrate/TransProtectedScope.cpp        |   2 +-
 lib/ARCMigrate/TransRetainReleaseDealloc.cpp  |   4 +-
 lib/ARCMigrate/TransUnbridgedCasts.cpp        |   4 +-
 lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp |  14 +-
 lib/ARCMigrate/TransformActions.cpp           |   6 +-
 lib/ARCMigrate/Transforms.cpp                 |  38 +-
 lib/ARCMigrate/Transforms.h                   |   2 +-
 lib/AST/ASTContext.cpp                        | 344 +++----
 lib/AST/ASTDiagnostic.cpp                     |  12 +-
 lib/AST/ASTDumper.cpp                         |   2 +-
 lib/AST/ASTImporter.cpp                       | 478 ++++-----
 lib/AST/ASTStructuralEquivalence.cpp          |   4 +-
 lib/AST/CXXInheritance.cpp                    |  64 +-
 lib/AST/Comment.cpp                           |   2 +-
 lib/AST/CommentLexer.cpp                      |   2 +-
 lib/AST/Decl.cpp                              | 120 +--
 lib/AST/DeclBase.cpp                          |  50 +-
 lib/AST/DeclCXX.cpp                           | 156 +--
 lib/AST/DeclObjC.cpp                          |  62 +-
 lib/AST/DeclPrinter.cpp                       |  28 +-
 lib/AST/DeclTemplate.cpp                      |  14 +-
 lib/AST/DeclarationName.cpp                   |  14 +-
 lib/AST/Expr.cpp                              | 162 +--
 lib/AST/ExprCXX.cpp                           |  62 +-
 lib/AST/ExprClassification.cpp                |  12 +-
 lib/AST/ExprConstant.cpp                      |  64 +-
 lib/AST/ExternalASTSource.cpp                 |   2 +-
 lib/AST/ItaniumCXXABI.cpp                     |   2 +-
 lib/AST/ItaniumMangle.cpp                     | 136 +--
 lib/AST/Mangle.cpp                            |   2 +-
 lib/AST/MicrosoftMangle.cpp                   |   2 +-
 lib/AST/NSAPI.cpp                             |   6 +-
 lib/AST/NestedNameSpecifier.cpp               | 104 +-
 lib/AST/ParentMap.cpp                         |   2 +-
 lib/AST/RecordLayout.cpp                      |   2 +-
 lib/AST/RecordLayoutBuilder.cpp               | 180 ++--
 lib/AST/StmtOpenMP.cpp                        |  12 +-
 lib/AST/StmtPrinter.cpp                       |  16 +-
 lib/AST/StmtProfile.cpp                       |  50 +-
 lib/AST/TemplateBase.cpp                      |  68 +-
 lib/AST/TemplateName.cpp                      |  14 +-
 lib/AST/Type.cpp                              | 152 +--
 lib/AST/TypeLoc.cpp                           |  20 +-
 lib/AST/TypePrinter.cpp                       | 166 +--
 lib/AST/VTTBuilder.cpp                        |  50 +-
 lib/AST/VTableBuilder.cpp                     | 566 +++++-----
 lib/Analysis/AnalysisDeclContext.cpp          |  18 +-
 lib/Analysis/BodyFarm.cpp                     |  50 +-
 lib/Analysis/CFG.cpp                          |  66 +-
 lib/Analysis/CFGReachabilityAnalysis.cpp      |   2 +-
 lib/Analysis/CFGStmtMap.cpp                   |  12 +-
 lib/Analysis/CallGraph.cpp                    |   2 +-
 lib/Analysis/CocoaConventions.cpp             |  32 +-
 lib/Analysis/Consumed.cpp                     | 216 ++--
 lib/Analysis/FormatString.cpp                 |  10 +-
 lib/Analysis/FormatStringParsing.h            |  10 +-
 lib/Analysis/LiveVariables.cpp                |  78 +-
 lib/Analysis/ObjCNoReturn.cpp                 |   8 +-
 lib/Analysis/PostOrderCFGView.cpp             |   6 +-
 lib/Analysis/PrintfFormatString.cpp           |   6 +-
 lib/Analysis/ProgramPoint.cpp                 |   2 +-
 lib/Analysis/ReachableCode.cpp                |  22 +-
 lib/Analysis/ScanfFormatString.cpp            |  26 +-
 lib/Analysis/UninitializedValues.cpp          |  22 +-
 lib/Basic/Diagnostic.cpp                      |  12 +-
 lib/Basic/DiagnosticIDs.cpp                   |   2 +-
 lib/Basic/FileManager.cpp                     |  16 +-
 lib/Basic/FileSystemStatCache.cpp             |   8 +-
 lib/Basic/IdentifierTable.cpp                 |  18 +-
 lib/Basic/Module.cpp                          |  28 +-
 lib/Basic/ObjCRuntime.cpp                     |   2 +-
 lib/Basic/SourceLocation.cpp                  |   2 +-
 lib/Basic/SourceManager.cpp                   |  64 +-
 lib/Basic/Targets/X86.cpp                     |   2 +-
 lib/Basic/Targets/X86.h                       |   8 +-
 lib/Basic/Warnings.cpp                        |  20 +-
 lib/CodeGen/CGBlocks.cpp                      |  38 +-
 lib/CodeGen/CGBlocks.h                        |  10 +-
 lib/CodeGen/CGBuilder.h                       |   2 +-
 lib/CodeGen/CGBuiltin.cpp                     |   6 +-
 lib/CodeGen/CGCXX.cpp                         |   4 +-
 lib/CodeGen/CGCXXABI.cpp                      |   4 +-
 lib/CodeGen/CGCall.cpp                        |  20 +-
 lib/CodeGen/CGCall.h                          |   4 +-
 lib/CodeGen/CGClass.cpp                       |   6 +-
 lib/CodeGen/CGCleanup.cpp                     |  18 +-
 lib/CodeGen/CGCleanup.h                       |   2 +-
 lib/CodeGen/CGDeclCXX.cpp                     |  14 +-
 lib/CodeGen/CGException.cpp                   |   8 +-
 lib/CodeGen/CGExpr.cpp                        |  10 +-
 lib/CodeGen/CGExprAgg.cpp                     |  54 +-
 lib/CodeGen/CGExprCXX.cpp                     |  64 +-
 lib/CodeGen/CGExprConstant.cpp                |  34 +-
 lib/CodeGen/CGExprScalar.cpp                  |   2 +-
 lib/CodeGen/CGLoopInfo.cpp                    |   2 +-
 lib/CodeGen/CGObjC.cpp                        | 162 +--
 lib/CodeGen/CGObjCGNU.cpp                     |  48 +-
 lib/CodeGen/CGObjCMac.cpp                     | 228 ++---
 lib/CodeGen/CGObjCRuntime.cpp                 |   4 +-
 lib/CodeGen/CGObjCRuntime.h                   |  12 +-
 lib/CodeGen/CGRecordLayoutBuilder.cpp         |  18 +-
 lib/CodeGen/CGVTT.cpp                         |  30 +-
 lib/CodeGen/CGVTables.cpp                     |   2 +-
 lib/CodeGen/CGVTables.h                       |  14 +-
 lib/CodeGen/CGValue.h                         |  12 +-
 lib/CodeGen/CodeGenAction.cpp                 |   2 +-
 lib/CodeGen/CodeGenModule.cpp                 |   2 +-
 lib/CodeGen/CodeGenModule.h                   |  28 +-
 lib/CodeGen/CodeGenTypes.cpp                  |  50 +-
 lib/CodeGen/CodeGenTypes.h                    |  14 +-
 lib/CodeGen/ConstantInitBuilder.cpp           |   2 +-
 lib/CodeGen/MicrosoftCXXABI.cpp               |  14 +-
 lib/CodeGen/SwiftCallingConv.cpp              |   4 +-
 lib/CodeGen/TargetInfo.cpp                    |  24 +-
 lib/Driver/SanitizerArgs.cpp                  |   2 +-
 lib/Driver/ToolChain.cpp                      |   2 +-
 lib/Driver/ToolChains/Arch/RISCV.cpp          |   2 +-
 lib/Edit/Commit.cpp                           |   4 +-
 lib/Edit/RewriteObjCFoundationAPI.cpp         |  18 +-
 lib/Format/BreakableToken.cpp                 |   2 +-
 lib/Format/ContinuationIndenter.h             |   2 +-
 lib/Frontend/ASTConsumers.cpp                 |   2 +-
 lib/Frontend/ASTMerge.cpp                     |  10 +-
 lib/Frontend/ChainedIncludesSource.cpp        |   6 +-
 lib/Frontend/CompilerInstance.cpp             |  38 +-
 lib/Frontend/DependencyFile.cpp               |   2 +-
 lib/Frontend/DependencyGraph.cpp              |  20 +-
 lib/Frontend/DiagnosticRenderer.cpp           |   6 +-
 lib/Frontend/FrontendAction.cpp               |   8 +-
 lib/Frontend/FrontendActions.cpp              |  10 +-
 lib/Frontend/LayoutOverrideSource.cpp         |  58 +-
 lib/Frontend/MultiplexConsumer.cpp            |   6 +-
 lib/Frontend/PrintPreprocessedOutput.cpp      |  12 +-
 lib/Frontend/Rewrite/FixItRewriter.cpp        |   2 +-
 lib/Frontend/Rewrite/FrontendActions.cpp      |   4 +-
 lib/Frontend/Rewrite/RewriteModernObjC.cpp    | 964 +++++++++---------
 lib/Frontend/Rewrite/RewriteObjC.cpp          | 388 +++----
 lib/Frontend/SerializedDiagnosticPrinter.cpp  |  46 +-
 lib/Frontend/TestModuleFileExtension.cpp      |   2 +-
 lib/Frontend/TextDiagnostic.cpp               |  28 +-
 .../ExecuteCompilerInvocation.cpp             |   4 +-
 lib/Headers/avx512fintrin.h                   |   4 +-
 lib/Headers/avx512vlcdintrin.h                |   2 +-
 lib/Headers/clzerointrin.h                    |   2 +-
 lib/Headers/lwpintrin.h                       |   4 +-
 lib/Headers/opencl-c.h                        |   8 +-
 lib/Index/IndexBody.cpp                       |   4 +-
 lib/Index/IndexTypeSourceInfo.cpp             |   4 +-
 lib/Index/IndexingContext.cpp                 |   2 +-
 lib/Index/USRGeneration.cpp                   |  40 +-
 lib/Lex/HeaderSearch.cpp                      |  32 +-
 lib/Lex/LiteralSupport.cpp                    |   6 +-
 lib/Lex/MacroArgs.cpp                         |  14 +-
 lib/Lex/ModuleMap.cpp                         | 178 ++--
 lib/Lex/PPDirectives.cpp                      |   6 +-
 lib/Lex/PPExpressions.cpp                     |  10 +-
 lib/Lex/PPLexerChange.cpp                     |  14 +-
 lib/Lex/PPMacroExpansion.cpp                  |   6 +-
 lib/Lex/Pragma.cpp                            |  26 +-
 lib/Lex/PreprocessingRecord.cpp               |  46 +-
 lib/Lex/Preprocessor.cpp                      |  24 +-
 lib/Lex/TokenLexer.cpp                        |  20 +-
 lib/Parse/ParseAST.cpp                        |   4 +-
 lib/Parse/ParseCXXInlineMethods.cpp           |   8 +-
 lib/Parse/ParseDecl.cpp                       |  32 +-
 lib/Parse/ParseDeclCXX.cpp                    |  64 +-
 lib/Parse/ParseExpr.cpp                       | 128 +--
 lib/Parse/ParseExprCXX.cpp                    | 190 ++--
 lib/Parse/ParseInit.cpp                       |  50 +-
 lib/Parse/ParseObjc.cpp                       | 224 ++--
 lib/Parse/ParsePragma.cpp                     |  30 +-
 lib/Parse/ParseStmtAsm.cpp                    |   2 +-
 lib/Parse/ParseTemplate.cpp                   |  74 +-
 lib/Parse/ParseTentative.cpp                  |  38 +-
 lib/Parse/Parser.cpp                          |  68 +-
 lib/Rewrite/DeltaTree.cpp                     |   4 +-
 lib/Rewrite/HTMLRewrite.cpp                   |   2 +-
 lib/Rewrite/Rewriter.cpp                      |   6 +-
 lib/Sema/AnalysisBasedWarnings.cpp            |  52 +-
 lib/Sema/CodeCompleteConsumer.cpp             | 110 +-
 lib/Sema/DeclSpec.cpp                         |  50 +-
 lib/Sema/DelayedDiagnostic.cpp                |   4 +-
 lib/Sema/IdentifierResolver.cpp               |  54 +-
 lib/Sema/MultiplexExternalSemaSource.cpp      |  14 +-
 lib/Sema/Sema.cpp                             |   2 +-
 lib/Sema/SemaAccess.cpp                       |  36 +-
 lib/Sema/SemaAttr.cpp                         |   4 +-
 lib/Sema/SemaCXXScopeSpec.cpp                 |  34 +-
 lib/Sema/SemaCast.cpp                         | 120 +--
 lib/Sema/SemaChecking.cpp                     | 174 ++--
 lib/Sema/SemaDecl.cpp                         |   6 +-
 lib/Sema/SemaDeclAttr.cpp                     |  74 +-
 lib/Sema/SemaDeclObjC.cpp                     | 334 +++---
 lib/Sema/SemaExceptionSpec.cpp                |   2 +-
 lib/Sema/SemaExpr.cpp                         | 446 ++++----
 lib/Sema/SemaExprMember.cpp                   |  36 +-
 lib/Sema/SemaExprObjC.cpp                     | 380 +++----
 lib/Sema/SemaInit.cpp                         |  58 +-
 lib/Sema/SemaLambda.cpp                       | 198 ++--
 lib/Sema/SemaLookup.cpp                       |  26 +-
 lib/Sema/SemaObjCProperty.cpp                 | 138 +--
 lib/Sema/SemaPseudoObject.cpp                 | 134 +--
 lib/Sema/SemaStmt.cpp                         |  12 +-
 lib/Sema/SemaStmtAsm.cpp                      |   2 +-
 lib/Sema/SemaTemplate.cpp                     |  28 +-
 lib/Sema/SemaTemplateDeduction.cpp            |   2 +-
 lib/Sema/SemaTemplateInstantiate.cpp          | 292 +++---
 lib/Sema/SemaTemplateInstantiateDecl.cpp      |  16 +-
 lib/Sema/SemaTemplateVariadic.cpp             | 114 +--
 lib/Sema/SemaType.cpp                         |  44 +-
 lib/Sema/TreeTransform.h                      |  10 +-
 lib/Sema/TypeLocBuilder.h                     |  12 +-
 lib/Serialization/ASTReader.cpp               |   2 +-
 lib/Serialization/ASTReaderDecl.cpp           |  44 +-
 lib/Serialization/ASTReaderInternals.h        |  54 +-
 lib/Serialization/ASTWriterDecl.cpp           |  52 +-
 lib/Serialization/ASTWriterStmt.cpp           |  24 +-
 lib/Serialization/Module.cpp                  |  24 +-
 lib/Serialization/ModuleManager.cpp           |  10 +-
 lib/StaticAnalyzer/Checkers/MallocChecker.cpp |  38 +-
 .../Checkers/RetainCountChecker.cpp           |   2 +-
 .../Checkers/StackAddrEscapeChecker.cpp       |  10 +-
 lib/StaticAnalyzer/Core/ExprEngine.cpp        |   8 +-
 lib/StaticAnalyzer/Core/ExprEngineC.cpp       |   2 +-
 lib/StaticAnalyzer/Core/IssueHash.cpp         |   2 +-
 lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp |   2 +-
 lib/StaticAnalyzer/Core/Store.cpp             |   4 +-
 432 files changed, 7748 insertions(+), 7748 deletions(-)

diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 0ad90010cc..65dada38b0 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -160,7 +160,7 @@ typedef struct CXVersion {
   int Major;
   /**
    * The minor version number, e.g., the '7' in '10.7.3'. This value
-   * will be negative if no minor version number was provided, e.g., for 
+   * will be negative if no minor version number was provided, e.g., for
    * version '10'.
    */
   int Minor;
@@ -387,7 +387,7 @@ CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
  * multiple inclusions, either with the conventional
  * \#ifndef/\#define/\#endif macro guards or with \#pragma once.
  */
-CINDEX_LINKAGE unsigned 
+CINDEX_LINKAGE unsigned
 clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
 
 /**
@@ -786,7 +786,7 @@ typedef void *CXDiagnostic;
  * A group of CXDiagnostics.
  */
 typedef void *CXDiagnosticSet;
-  
+
 /**
  * Determine the number of diagnostics in a CXDiagnosticSet.
  */
@@ -802,7 +802,7 @@ CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
  * via a call to \c clang_disposeDiagnostic().
  */
 CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
-                                                     unsigned Index);  
+                                                     unsigned Index);
 
 /**
  * Describes the kind of error that occurred (if any) in a call to
@@ -813,26 +813,26 @@ enum CXLoadDiag_Error {
    * Indicates that no error occurred.
    */
   CXLoadDiag_None = 0,
-  
+
   /**
    * Indicates that an unknown error occurred while attempting to
    * deserialize diagnostics.
    */
   CXLoadDiag_Unknown = 1,
-  
+
   /**
    * Indicates that the file containing the serialized diagnostics
    * could not be opened.
    */
   CXLoadDiag_CannotLoad = 2,
-  
+
   /**
    * Indicates that the serialized diagnostics file is invalid or
    * corrupt.
    */
   CXLoadDiag_InvalidFile = 3
 };
-  
+
 /**
  * Deserialize a set of diagnostics from a Clang diagnostics bitcode
  * file.
@@ -856,7 +856,7 @@ CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
 CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
 
 /**
- * Retrieve the child diagnostics of a CXDiagnostic. 
+ * Retrieve the child diagnostics of a CXDiagnostic.
  *
  * This CXDiagnosticSet does not need to be released by
  * clang_disposeDiagnosticSet.
@@ -888,7 +888,7 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit,
  * \param Unit the translation unit to query.
  */
 CINDEX_LINKAGE CXDiagnosticSet
-  clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);  
+  clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
 
 /**
  * Destroy a diagnostic.
@@ -934,7 +934,7 @@ enum CXDiagnosticDisplayOptions {
    * \c -fdiagnostics-print-source-range-info.
    */
   CXDiagnostic_DisplaySourceRanges = 0x04,
-  
+
   /**
    * Display the option name associated with this diagnostic, if any.
    *
@@ -943,12 +943,12 @@ enum CXDiagnosticDisplayOptions {
    * \c -fdiagnostics-show-option.
    */
   CXDiagnostic_DisplayOption = 0x08,
-  
+
   /**
    * Display the category number associated with this diagnostic, if any.
    *
    * The category number is displayed within brackets after the diagnostic text.
-   * This option corresponds to the clang flag 
+   * This option corresponds to the clang flag
    * \c -fdiagnostics-show-category=id.
    */
   CXDiagnostic_DisplayCategoryId = 0x10,
@@ -957,7 +957,7 @@ enum CXDiagnosticDisplayOptions {
    * Display the category name associated with this diagnostic, if any.
    *
    * The category name is displayed within brackets after the diagnostic text.
-   * This option corresponds to the clang flag 
+   * This option corresponds to the clang flag
    * \c -fdiagnostics-show-category=name.
    */
   CXDiagnostic_DisplayCategoryName = 0x20
@@ -1019,7 +1019,7 @@ CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
  * diagnostic (if any).
  *
  * \returns A string that contains the command-line option used to enable this
- * warning, such as "-Wconversion" or "-pedantic". 
+ * warning, such as "-Wconversion" or "-pedantic".
  */
 CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
                                                   CXString *Disable);
@@ -1028,7 +1028,7 @@ CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
  * Retrieve the category number for this diagnostic.
  *
  * Diagnostics can be categorized into groups along with other, related
- * diagnostics (e.g., diagnostics under the same warning flag). This routine 
+ * diagnostics (e.g., diagnostics under the same warning flag). This routine
  * retrieves the category number for the given diagnostic.
  *
  * \returns The number of the category that contains this diagnostic, or zero
@@ -1041,7 +1041,7 @@ CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
  *  is now deprecated.  Use clang_getDiagnosticCategoryText()
  *  instead.
  *
- * \param Category A diagnostic category number, as returned by 
+ * \param Category A diagnostic category number, as returned by
  * \c clang_getDiagnosticCategory().
  *
  * \returns The name of the given diagnostic category.
@@ -1055,7 +1055,7 @@ CXString clang_getDiagnosticCategoryName(unsigned Category);
  * \returns The text of the given diagnostic category.
  */
 CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
-  
+
 /**
  * Determine the number of source ranges associated with the given
  * diagnostic.
@@ -1242,9 +1242,9 @@ enum CXTranslationUnit_Flags {
    * intent of producing a precompiled header.
    */
   CXTranslationUnit_Incomplete = 0x02,
-  
+
   /**
-   * Used to indicate that the translation unit should be built with an 
+   * Used to indicate that the translation unit should be built with an
    * implicit precompiled header for the preamble.
    *
    * An implicit precompiled header is used as an optimization when a
@@ -1258,7 +1258,7 @@ enum CXTranslationUnit_Flags {
    * precompiled header to improve parsing performance.
    */
   CXTranslationUnit_PrecompiledPreamble = 0x04,
-  
+
   /**
    * Used to indicate that the translation unit should cache some
    * code-completion results with each reparse of the source file.
@@ -1343,7 +1343,7 @@ enum CXTranslationUnit_Flags {
  * to indicate that the translation unit is likely to be reparsed many times,
  * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
  * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
- * set contains an unspecified set of optimizations (e.g., the precompiled 
+ * set contains an unspecified set of optimizations (e.g., the precompiled
  * preamble) geared toward improving the performance of these routines. The
  * set of optimizations enabled may change from one version to the next.
  */
@@ -1374,7 +1374,7 @@ clang_parseTranslationUnit(CXIndex CIdx,
  * command-line arguments so that the compilation can be configured in the same
  * way that the compiler is configured on the command line.
  *
- * \param CIdx The index object with which the translation unit will be 
+ * \param CIdx The index object with which the translation unit will be
  * associated.
  *
  * \param source_filename The name of the source file to load, or NULL if the
@@ -1383,7 +1383,7 @@ clang_parseTranslationUnit(CXIndex CIdx,
  * \param command_line_args The command-line arguments that would be
  * passed to the \c clang executable if it were being invoked out-of-process.
  * These command-line options will be parsed and will affect how the translation
- * unit is parsed. Note that the following options are ignored: '-c', 
+ * unit is parsed. Note that the following options are ignored: '-c',
  * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \'.
  *
  * \param num_command_line_args The number of command-line arguments in
@@ -1463,32 +1463,32 @@ enum CXSaveError {
    * Indicates that no error occurred while saving a translation unit.
    */
   CXSaveError_None = 0,
-  
+
   /**
    * Indicates that an unknown error occurred while attempting to save
    * the file.
    *
-   * This error typically indicates that file I/O failed when attempting to 
+   * This error typically indicates that file I/O failed when attempting to
    * write the file.
    */
   CXSaveError_Unknown = 1,
-  
+
   /**
    * Indicates that errors during translation prevented this attempt
    * to save the translation unit.
-   * 
+   *
    * Errors that prevent the translation unit from being saved can be
    * extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic().
    */
   CXSaveError_TranslationErrors = 2,
-  
+
   /**
    * Indicates that the translation unit to be saved was somehow
    * invalid (e.g., NULL).
    */
   CXSaveError_InvalidTU = 3
 };
-  
+
 /**
  * Saves a translation unit into a serialized representation of
  * that translation unit on disk.
@@ -1509,7 +1509,7 @@ enum CXSaveError {
  * CXSaveTranslationUnit_XXX flags.
  *
  * \returns A value that will match one of the enumerators of the CXSaveError
- * enumeration. Zero (CXSaveError_None) indicates that the translation unit was 
+ * enumeration. Zero (CXSaveError_None) indicates that the translation unit was
  * saved successfully, while a non-zero value indicates that a problem occurred.
  */
 CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
@@ -1543,7 +1543,7 @@ enum CXReparse_Flags {
    */
   CXReparse_None = 0x0
 };
- 
+
 /**
  * Returns the set of flags that is suitable for reparsing a translation
  * unit.
@@ -1551,7 +1551,7 @@ enum CXReparse_Flags {
  * The set of flags returned provide options for
  * \c clang_reparseTranslationUnit() by default. The returned flag
  * set contains an unspecified set of optimizations geared toward common uses
- * of reparsing. The set of optimizations enabled may change from one version 
+ * of reparsing. The set of optimizations enabled may change from one version
  * to the next.
  */
 CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
@@ -1563,17 +1563,17 @@ CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
  * created the given translation unit, for example because those source files
  * have changed (either on disk or as passed via \p unsaved_files). The
  * source code will be reparsed with the same command-line options as it
- * was originally parsed. 
+ * was originally parsed.
  *
  * Reparsing a translation unit invalidates all cursors and source locations
  * that refer into that translation unit. This makes reparsing a translation
  * unit semantically equivalent to destroying the translation unit and then
  * creating a new translation unit with the same command-line arguments.
- * However, it may be more efficient to reparse a translation 
+ * However, it may be more efficient to reparse a translation
  * unit using this routine.
  *
  * \param TU The translation unit whose contents will be re-parsed. The
- * translation unit must originally have been built with 
+ * translation unit must originally have been built with
  * \c clang_createTranslationUnitFromSourceFile().
  *
  * \param num_unsaved_files The number of unsaved file entries in \p
@@ -1584,7 +1584,7 @@ CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
  * those files.  The contents and name of these files (as specified by
  * CXUnsavedFile) are copied when necessary, so the client only needs to
  * guarantee their validity until the call to this function returns.
- * 
+ *
  * \param options A bitset of options composed of the flags in CXReparse_Flags.
  * The function \c clang_defaultReparseOptions() produces a default set of
  * options recommended for most uses, based on the translation unit.
@@ -1612,8 +1612,8 @@ enum CXTUResourceUsageKind {
   CXTUResourceUsage_AST_SideTables = 6,
   CXTUResourceUsage_SourceManager_Membuffer_Malloc = 7,
   CXTUResourceUsage_SourceManager_Membuffer_MMap = 8,
-  CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9, 
-  CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10, 
+  CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9,
+  CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
   CXTUResourceUsage_Preprocessor = 11,
   CXTUResourceUsage_PreprocessingRecord = 12,
   CXTUResourceUsage_SourceManager_DataStructures = 13,
@@ -1635,8 +1635,8 @@ const char *clang_getTUResourceUsageName(enum CXTUResourceUsageKind kind);
 
 typedef struct CXTUResourceUsageEntry {
   /* The memory usage category. */
-  enum CXTUResourceUsageKind kind;  
-  /* Amount of resources used. 
+  enum CXTUResourceUsageKind kind;
+  /* Amount of resources used.
       The units will depend on the resource kind. */
   unsigned long amount;
 } CXTUResourceUsageEntry;
@@ -1819,7 +1819,7 @@ enum CXCursorKind {
    */
   CXCursor_TypeRef                       = 43,
   CXCursor_CXXBaseSpecifier              = 44,
-  /** 
+  /**
    * A reference to a class template, function template, template
    * template parameter, or class template partial specialization.
    */
@@ -1829,14 +1829,14 @@ enum CXCursorKind {
    */
   CXCursor_NamespaceRef                  = 46,
   /**
-   * A reference to a member of a struct, union, or class that occurs in 
+   * A reference to a member of a struct, union, or class that occurs in
    * some non-expression context, e.g., a designated initializer.
    */
   CXCursor_MemberRef                     = 47,
   /**
    * A reference to a labeled statement.
    *
-   * This cursor kind is used to describe the jump to "start_over" in the 
+   * This cursor kind is used to describe the jump to "start_over" in the
    * goto statement in the following example:
    *
    * \code
@@ -1849,7 +1849,7 @@ enum CXCursorKind {
    * A label reference cursor refers to a label statement.
    */
   CXCursor_LabelRef                      = 48,
-  
+
   /**
    * A reference to a set of overloaded functions or function templates
    * that has not yet been resolved to a specific function or function template.
@@ -1882,18 +1882,18 @@ enum CXCursorKind {
    * argument-dependent lookup (e.g., the "swap" function at the end of the
    * example).
    *
-   * The functions \c clang_getNumOverloadedDecls() and 
+   * The functions \c clang_getNumOverloadedDecls() and
    * \c clang_getOverloadedDecl() can be used to retrieve the definitions
    * referenced by this cursor.
    */
   CXCursor_OverloadedDeclRef             = 49,
-  
+
   /**
-   * A reference to a variable that occurs in some non-expression 
+   * A reference to a variable that occurs in some non-expression
    * context, e.g., a C++ lambda capture list.
    */
   CXCursor_VariableRef                   = 50,
-  
+
   CXCursor_LastRef                       = CXCursor_VariableRef,
 
   /* Error conditions */
@@ -2153,7 +2153,7 @@ enum CXCursorKind {
    * \endcode
    */
   CXCursor_LambdaExpr                    = 144,
-  
+
   /** Objective-c Boolean Literal.
    */
   CXCursor_ObjCBoolLiteralExpr           = 145,
@@ -2189,10 +2189,10 @@ enum CXCursorKind {
    * reported.
    */
   CXCursor_UnexposedStmt                 = 200,
-  
-  /** A labelled statement in a function. 
+
+  /** A labelled statement in a function.
    *
-   * This cursor kind is used to describe the "start_over:" label statement in 
+   * This cursor kind is used to describe the "start_over:" label statement in
    * the following example:
    *
    * \code
@@ -2650,7 +2650,7 @@ CINDEX_LINKAGE int clang_Cursor_isNull(CXCursor cursor);
  * Compute a hash value for the given cursor.
  */
 CINDEX_LINKAGE unsigned clang_hashCursor(CXCursor);
-  
+
 /**
  * Retrieve the kind of the given cursor.
  */
@@ -2718,7 +2718,7 @@ CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
  * element, such as a preprocessor directive or macro instantiation.
  */
 CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind);
-  
+
 /***
  * Determine whether the given cursor represents a currently
  *  unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
@@ -2785,7 +2785,7 @@ CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
  *
  * \returns The availability of the cursor.
  */
-CINDEX_LINKAGE enum CXAvailabilityKind 
+CINDEX_LINKAGE enum CXAvailabilityKind
 clang_getCursorAvailability(CXCursor cursor);
 
 /**
@@ -2831,10 +2831,10 @@ typedef struct CXPlatformAvailability {
  *
  * \param cursor The cursor to query.
  *
- * \param always_deprecated If non-NULL, will be set to indicate whether the 
+ * \param always_deprecated If non-NULL, will be set to indicate whether the
  * entity is deprecated on all platforms.
  *
- * \param deprecated_message If non-NULL, will be set to the message text 
+ * \param deprecated_message If non-NULL, will be set to the message text
  * provided along with the unconditional deprecation of this entity. The client
  * is responsible for deallocating this string.
  *
@@ -2842,7 +2842,7 @@ typedef struct CXPlatformAvailability {
  * entity is unavailable on all platforms.
  *
  * \param unavailable_message If non-NULL, will be set to the message text
- * provided along with the unconditional unavailability of this entity. The 
+ * provided along with the unconditional unavailability of this entity. The
  * client is responsible for deallocating this string.
  *
  * \param availability If non-NULL, an array of CXPlatformAvailability instances
@@ -2850,15 +2850,15 @@ typedef struct CXPlatformAvailability {
  * the number of platforms for which availability information is available (as
  * returned by this function) or \c availability_size, whichever is smaller.
  *
- * \param availability_size The number of elements available in the 
+ * \param availability_size The number of elements available in the
  * \c availability array.
  *
  * \returns The number of platforms (N) for which availability information is
  * available (which is unrelated to \c availability_size).
  *
- * Note that the client is responsible for calling 
- * \c clang_disposeCXPlatformAvailability to free each of the 
- * platform-availability structures returned. There are 
+ * Note that the client is responsible for calling
+ * \c clang_disposeCXPlatformAvailability to free each of the
+ * platform-availability structures returned. There are
  * \c min(N, availability_size) such structures.
  */
 CINDEX_LINKAGE int
@@ -2875,7 +2875,7 @@ clang_getCursorPlatformAvailability(CXCursor cursor,
  */
 CINDEX_LINKAGE void
 clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
-  
+
 /**
  * Describe the "language" of the entity referred to by a cursor.
  */
@@ -2948,7 +2948,7 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset,
  *
  * The semantic parent of a cursor is the cursor that semantically contains
  * the given \p cursor. For many declarations, the lexical and semantic parents
- * are equivalent (the lexical parent is returned by 
+ * are equivalent (the lexical parent is returned by
  * \c clang_getCursorLexicalParent()). They diverge when declarations or
  * definitions are provided out-of-line. For example:
  *
@@ -2983,7 +2983,7 @@ CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor);
  *
  * The lexical parent of a cursor is the cursor in which the given \p cursor
  * was actually written. For many declarations, the lexical and semantic parents
- * are equivalent (the semantic parent is returned by 
+ * are equivalent (the semantic parent is returned by
  * \c clang_getCursorSemanticParent()). They diverge when declarations or
  * definitions are provided out-of-line. For example:
  *
@@ -3046,18 +3046,18 @@ CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
  * \param cursor A cursor representing an Objective-C or C++
  * method. This routine will compute the set of methods that this
  * method overrides.
- * 
+ *
  * \param overridden A pointer whose pointee will be replaced with a
  * pointer to an array of cursors, representing the set of overridden
  * methods. If there are no overridden methods, the pointee will be
- * set to NULL. The pointee must be freed via a call to 
+ * set to NULL. The pointee must be freed via a call to
  * \c clang_disposeOverriddenCursors().
  *
  * \param num_overridden A pointer to the number of overridden
  * functions, will be set to the number of overridden functions in the
  * array pointed to by \p overridden.
  */
-CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor, 
+CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
                                                CXCursor **overridden,
                                                unsigned *num_overridden);
 
@@ -3072,7 +3072,7 @@ CINDEX_LINKAGE void clang_disposeOverriddenCursors(CXCursor *overridden);
  * cursor.
  */
 CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor);
-  
+
 /**
  * @}
  */
@@ -3133,7 +3133,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
 /**
  * @}
  */
-    
+
 /**
  * \defgroup CINDEX_TYPES Type information for CXCursors
  *
@@ -3582,7 +3582,7 @@ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C);
 /**
  * Returns the Objective-C type encoding for the specified CXType.
  */
-CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type); 
+CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type);
 
 /**
  * Retrieve the spelling of a given CXTypeKind.
@@ -3842,7 +3842,7 @@ CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C);
  *   CX_CXXBaseSpecifier is virtual.
  */
 CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
-    
+
 /**
  * Represents the C++ access control level to a base class for a
  * cursor with kind CX_CXXBaseSpecifier.
@@ -3887,7 +3887,7 @@ enum CX_StorageClass {
 CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor);
 
 /**
- * Determine the number of overloaded declarations referenced by a 
+ * Determine the number of overloaded declarations referenced by a
  * \c CXCursor_OverloadedDeclRef cursor.
  *
  * \param cursor The cursor whose overloaded declarations are being queried.
@@ -3906,18 +3906,18 @@ CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor);
  * \param index The zero-based index into the set of overloaded declarations in
  * the cursor.
  *
- * \returns A cursor representing the declaration referenced by the given 
- * \c cursor at the specified \c index. If the cursor does not have an 
+ * \returns A cursor representing the declaration referenced by the given
+ * \c cursor at the specified \c index. If the cursor does not have an
  * associated set of overloaded declarations, or if the index is out of bounds,
  * returns \c clang_getNullCursor();
  */
-CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor, 
+CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
                                                 unsigned index);
-  
+
 /**
  * @}
  */
-  
+
 /**
  * \defgroup CINDEX_ATTRIBUTES Information for attributes
  *
@@ -4021,7 +4021,7 @@ CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
  * The visitor should return one of the \c CXChildVisitResult values
  * to direct clang_visitChildrenWithBlock().
  */
-typedef enum CXChildVisitResult 
+typedef enum CXChildVisitResult
      (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
 
 /**
@@ -4109,10 +4109,10 @@ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
  * Most of the times there is only one range for the complete spelling but for
  * Objective-C methods and Objective-C message expressions, there are multiple
  * pieces for each selector identifier.
- * 
+ *
  * \param pieceIndex the index of the spelling name piece. If this is greater
  * than the actual number of pieces, it will return a NULL (invalid) range.
- *  
+ *
  * \param options Reserved.
  */
 CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
@@ -4206,11 +4206,11 @@ CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
  * Retrieve the display name for the entity referenced by this cursor.
  *
  * The display name contains extra information that helps identify the cursor,
- * such as the parameters of a function or template or the arguments of a 
+ * such as the parameters of a function or template or the arguments of a
  * class template specialization.
  */
 CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor);
-  
+
 /** For a cursor that is a reference, retrieve a cursor representing the
  * entity that it references.
  *
@@ -4274,10 +4274,10 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
  * };
  * \endcode
  *
- * The declarations and the definition of \c X are represented by three 
- * different cursors, all of which are declarations of the same underlying 
+ * The declarations and the definition of \c X are represented by three
+ * different cursors, all of which are declarations of the same underlying
  * entity. One of these cursor is considered the "canonical" cursor, which
- * is effectively the representative for the underlying entity. One can 
+ * is effectively the representative for the underlying entity. One can
  * determine if two cursors are declarations of the same underlying entity by
  * comparing their canonical cursors.
  *
@@ -4301,11 +4301,11 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
 /**
  * Given a cursor pointing to a C++ method call or an Objective-C
  * message, returns non-zero if the method/message is "dynamic", meaning:
- * 
+ *
  * For a C++ method: the call is virtual.
  * For an Objective-C message: the receiver is an object instance, not 'super'
  * or a specific class.
- * 
+ *
  * If the method/message is "static" or the cursor does not point to a
  * method/message, it will return zero.
  */
@@ -4575,7 +4575,7 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isDefaulted(CXCursor C);
 CINDEX_LINKAGE unsigned clang_CXXMethod_isPureVirtual(CXCursor C);
 
 /**
- * Determine if a C++ member function or member function template is 
+ * Determine if a C++ member function or member function template is
  * declared 'static'.
  */
 CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
@@ -4622,16 +4622,16 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C);
  * \c CXCursor_NoDeclFound.
  */
 CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
-  
+
 /**
  * Given a cursor that may represent a specialization or instantiation
  * of a template, retrieve the cursor that represents the template that it
  * specializes or from which it was instantiated.
  *
- * This routine determines the template involved both for explicit 
+ * This routine determines the template involved both for explicit
  * specializations of templates and for implicit instantiations of the template,
  * both of which are referred to as "specializations". For a class template
- * specialization (e.g., \c std::vector), this routine will return 
+ * specialization (e.g., \c std::vector), this routine will return
  * either the primary template (\c std::vector) or, if the specialization was
  * instantiated from a class template partial specialization, the class template
  * partial specialization. For a class template partial specialization and a
@@ -4639,7 +4639,7 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
  * this routine will return the specialized template.
  *
  * For members of a class template (e.g., member functions, member classes, or
- * static data members), returns the specialized or instantiated member. 
+ * static data members), returns the specialized or instantiated member.
  * Although not strictly "templates" in the C++ language, members of class
  * templates have the same notions of specializations and instantiations that
  * templates do, so this routine treats them similarly.
@@ -4647,7 +4647,7 @@ CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
  * \param C A cursor that may be a specialization of a template or a member
  * of a template.
  *
- * \returns If the given cursor is a specialization or instantiation of a 
+ * \returns If the given cursor is a specialization or instantiation of a
  * template or a member thereof, the template or member that it specializes or
  * from which it was instantiated. Otherwise, returns a NULL cursor.
  */
@@ -4659,11 +4659,11 @@ CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
  *
  * \param C A cursor pointing to a member reference, a declaration reference, or
  * an operator call.
- * \param NameFlags A bitset with three independent flags: 
+ * \param NameFlags A bitset with three independent flags:
  * CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and
  * CXNameRange_WantSinglePiece.
- * \param PieceIndex For contiguous names or when passing the flag 
- * CXNameRange_WantSinglePiece, only one piece with index 0 is 
+ * \param PieceIndex For contiguous names or when passing the flag
+ * CXNameRange_WantSinglePiece, only one piece with index 0 is
  * available. When the CXNameRange_WantSinglePiece flag is not passed for a
  * non-contiguous names, this index can be used to retrieve the individual
  * pieces of the name. See also CXNameRange_WantSinglePiece.
@@ -4672,7 +4672,7 @@ CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
  * name, or if the PieceIndex is out-of-range, a null-cursor will be returned.
  */
 CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
-                                                unsigned NameFlags, 
+                                                unsigned NameFlags,
                                                 unsigned PieceIndex);
 
 enum CXNameRefFlags {
@@ -4681,7 +4681,7 @@ enum CXNameRefFlags {
    * range.
    */
   CXNameRange_WantQualifier = 0x1,
-  
+
   /**
    * Include the explicit template arguments, e.g. \ in x.f,
    * in the range.
@@ -4700,7 +4700,7 @@ enum CXNameRefFlags {
    */
   CXNameRange_WantSinglePiece = 0x4
 };
-  
+
 /**
  * @}
  */
@@ -5153,7 +5153,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
 /**
  * Determine the priority of this code completion.
  *
- * The priority of a code completion indicates how likely it is that this 
+ * The priority of a code completion indicates how likely it is that this
  * particular completion is the completion that the user will select. The
  * priority is selected by various internal heuristics.
  *
@@ -5164,7 +5164,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
  */
 CINDEX_LINKAGE unsigned
 clang_getCompletionPriority(CXCompletionString completion_string);
-  
+
 /**
  * Determine the availability of the entity that this code-completion
  * string refers to.
@@ -5173,7 +5173,7 @@ clang_getCompletionPriority(CXCompletionString completion_string);
  *
  * \returns The availability of the completion string.
  */
-CINDEX_LINKAGE enum CXAvailabilityKind 
+CINDEX_LINKAGE enum CXAvailabilityKind
 clang_getCompletionAvailability(CXCompletionString completion_string);
 
 /**
@@ -5206,7 +5206,7 @@ clang_getCompletionAnnotation(CXCompletionString completion_string,
 /**
  * Retrieve the parent context of the given completion string.
  *
- * The parent context of a completion string is the semantic parent of 
+ * The parent context of a completion string is the semantic parent of
  * the declaration (if any) that the code completion represents. For example,
  * a code completion for an Objective-C method would have the method's class
  * or protocol as its context.
@@ -5241,7 +5241,7 @@ clang_getCompletionBriefComment(CXCompletionString completion_string);
  */
 CINDEX_LINKAGE CXCompletionString
 clang_getCursorCompletionString(CXCursor cursor);
-  
+
 /**
  * Contains the results of code-completion.
  *
@@ -5378,12 +5378,12 @@ enum CXCompletionContext {
    * should be included. (This is equivalent to having no context bits set.)
    */
   CXCompletionContext_Unexposed = 0,
-  
+
   /**
    * Completions for any possible type should be included in the results.
    */
   CXCompletionContext_AnyType = 1 << 0,
-  
+
   /**
    * Completions for any possible value (variables, function calls, etc.)
    * should be included in the results.
@@ -5404,7 +5404,7 @@ enum CXCompletionContext {
    * included in the results.
    */
   CXCompletionContext_CXXClassTypeValue = 1 << 4,
-  
+
   /**
    * Completions for fields of the member being accessed using the dot
    * operator should be included in the results.
@@ -5420,7 +5420,7 @@ enum CXCompletionContext {
    * using the dot operator should be included in the results.
    */
   CXCompletionContext_ObjCPropertyAccess = 1 << 7,
-  
+
   /**
    * Completions for enum tags should be included in the results.
    */
@@ -5433,7 +5433,7 @@ enum CXCompletionContext {
    * Completions for struct tags should be included in the results.
    */
   CXCompletionContext_StructTag = 1 << 10,
-  
+
   /**
    * Completions for C++ class names should be included in the results.
    */
@@ -5448,7 +5448,7 @@ enum CXCompletionContext {
    * the results.
    */
   CXCompletionContext_NestedNameSpecifier = 1 << 13,
-  
+
   /**
    * Completions for Objective-C interfaces (classes) should be included
    * in the results.
@@ -5479,27 +5479,27 @@ enum CXCompletionContext {
    * the results.
    */
   CXCompletionContext_ObjCSelectorName = 1 << 19,
-  
+
   /**
    * Completions for preprocessor macro names should be included in
    * the results.
    */
   CXCompletionContext_MacroName = 1 << 20,
-  
+
   /**
    * Natural language completions should be included in the results.
    */
   CXCompletionContext_NaturalLanguage = 1 << 21,
-  
+
   /**
    * The current context is unknown, so set all contexts.
    */
   CXCompletionContext_Unknown = ((1 << 22) - 1)
 };
-  
+
 /**
  * Returns a default set of code-completion options that can be
- * passed to\c clang_codeCompleteAt(). 
+ * passed to\c clang_codeCompleteAt().
  */
 CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
 
@@ -5562,7 +5562,7 @@ CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
  *
  * \param options Extra options that control the behavior of code
  * completion, expressed as a bitwise OR of the enumerators of the
- * CXCodeComplete_Flags enumeration. The 
+ * CXCodeComplete_Flags enumeration. The
  * \c clang_defaultCodeCompleteOptions() function returns a default set
  * of code-completion options.
  *
@@ -5581,7 +5581,7 @@ CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
                                             unsigned options);
 
 /**
- * Sort the code-completion results in case-insensitive alphabetical 
+ * Sort the code-completion results in case-insensitive alphabetical
  * order.
  *
  * \param Results The set of results to sort.
@@ -5590,13 +5590,13 @@ CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
 CINDEX_LINKAGE
 void clang_sortCodeCompletionResults(CXCompletionResult *Results,
                                      unsigned NumResults);
-  
+
 /**
  * Free the given set of code-completion results.
  */
 CINDEX_LINKAGE
 void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
-  
+
 /**
  * Determine the number of diagnostics produced prior to the
  * location where code completion was performed.
@@ -5620,7 +5620,7 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
 /**
  * Determines what completions are appropriate for the context
  * the given code completion.
- * 
+ *
  * \param Results the code completion results to query
  *
  * \returns the kinds of completions that are appropriate for use
@@ -5676,7 +5676,7 @@ CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
  */
 CINDEX_LINKAGE
 CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
-  
+
 /**
  * @}
  */
@@ -5700,7 +5700,7 @@ CINDEX_LINKAGE CXString clang_getClangVersion(void);
  *        value enables crash recovery, while 0 disables it.
  */
 CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled);
-  
+
  /**
   * Visitor invoked for each file in a translation unit
   *        (used with clang_getInclusions()).
@@ -5745,7 +5745,7 @@ typedef enum {
 typedef void * CXEvalResult;
 
 /**
- * If cursor is a statement declaration tries to evaluate the 
+ * If cursor is a statement declaration tries to evaluate the
  * statement and if its variable, tries to evaluate its initializer,
  * into its corresponding type.
  */
@@ -5844,7 +5844,7 @@ CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
 
 /**
  * Get the original and the associated filename from the remapping.
- * 
+ *
  * \param original If non-NULL, will be set to the original filename.
  *
  * \param transformed If non-NULL, will be set to the filename that the original
@@ -5896,7 +5896,7 @@ typedef enum {
 
 /**
  * Find references of a declaration in a specific file.
- * 
+ *
  * \param cursor pointing to a declaration or a reference of one.
  *
  * \param file to search for references.
@@ -6255,11 +6255,11 @@ typedef struct {
   const CXIdxEntityInfo *referencedEntity;
   /**
    * Immediate "parent" of the reference. For example:
-   * 
+   *
    * \code
    * Foo *var;
    * \endcode
-   * 
+   *
    * The parent of reference of type 'Foo' is the variable 'var'.
    * For references inside statement bodies of functions/methods,
    * the parentEntity will be the function/method.
@@ -6294,16 +6294,16 @@ typedef struct {
 
   CXIdxClientFile (*enteredMainFile)(CXClientData client_data,
                                      CXFile mainFile, void *reserved);
-  
+
   /**
    * Called when a file gets \#included/\#imported.
    */
   CXIdxClientFile (*ppIncludedFile)(CXClientData client_data,
                                     const CXIdxIncludedFileInfo *);
-  
+
   /**
    * Called when a AST file (PCH or module) gets imported.
-   * 
+   *
    * AST files will not get indexed (there will not be callbacks to index all
    * the entities in an AST file). The recommended action is that, if the AST
    * file is not already indexed, to initiate a new indexing job specific to
@@ -6405,7 +6405,7 @@ typedef enum {
    * Used to indicate that no special indexing options are needed.
    */
   CXIndexOpt_None = 0x0,
-  
+
   /**
    * Used to indicate that IndexerCallbacks#indexEntityReference should
    * be invoked for only one reference of an entity per source file that does
@@ -6492,16 +6492,16 @@ CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
 /**
  * Index the given translation unit via callbacks implemented through
  * #IndexerCallbacks.
- * 
+ *
  * The order of callback invocations is not guaranteed to be the same as
  * when indexing a source file. The high level order will be:
- * 
+ *
  *   -Preprocessor callbacks invocations
  *   -Declaration/reference callbacks invocations
  *   -Diagnostic callback invocations
  *
  * The parameters are the same as #clang_indexSourceFile.
- * 
+ *
  * \returns If there is a failure from which there is no recovery, returns
  * non-zero, otherwise returns 0.
  */
diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h
index 53b88e9eb5..731307f24e 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -41,7 +41,7 @@ class FileRemapper {
 public:
   FileRemapper();
   ~FileRemapper();
-  
+
   bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
                     bool ignoreIfFilesChanged);
   bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 7a50ce8d52..a9ab687a8d 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1528,7 +1528,7 @@ public:
   /// The sizeof operator requires this (C99 6.5.3.4p4).
   CanQualType getSizeType() const;
 
-  /// Return the unique signed counterpart of 
+  /// Return the unique signed counterpart of
   /// the integer type corresponding to size_t.
   CanQualType getSignedSizeType() const;
 
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index b08865dde3..2534272da3 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -23,11 +23,11 @@ namespace clang {
       NUM_BUILTIN_AST_DIAGNOSTICS
     };
   }  // end namespace diag
-  
+
   /// DiagnosticsEngine argument formatting function for diagnostics that
   /// involve AST nodes.
   ///
-  /// This function formats diagnostic arguments for various AST nodes, 
+  /// This function formats diagnostic arguments for various AST nodes,
   /// including types, declaration names, nested name specifiers, and
   /// declaration contexts, into strings that can be printed as part of
   /// diagnostics. It is meant to be used as the argument to
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 6e6a192625..2e9a8775a8 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -63,7 +63,7 @@ class Attr;
   private:
     /// The contexts we're importing to and from.
     ASTContext &ToContext, &FromContext;
-    
+
     /// The file managers we're importing to and from.
     FileManager &ToFileManager, &FromFileManager;
 
@@ -72,11 +72,11 @@ class Attr;
 
     /// Whether the last diagnostic came from the "from" context.
     bool LastDiagFromFrom = false;
-    
+
     /// Mapping from the already-imported types in the "from" context
     /// to the corresponding types in the "to" context.
     llvm::DenseMap ImportedTypes;
-    
+
     /// Mapping from the already-imported declarations in the "from"
     /// context to the corresponding declarations in the "to" context.
     llvm::DenseMap ImportedDecls;
@@ -93,11 +93,11 @@ class Attr;
     ///  the "from" source manager to the corresponding CXXBasesSpecifier
     ///  in the "to" source manager.
     ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers;
-    
+
     /// Declaration (from, to) pairs that are known not to be equivalent
     /// (which we have already complained about).
     NonEquivalentDeclSet NonEquivalentDecls;
-    
+
   public:
     /// Create a new AST importer.
     ///
@@ -115,13 +115,13 @@ class Attr;
     ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
                 ASTContext &FromContext, FileManager &FromFileManager,
                 bool MinimalImport);
-    
+
     virtual ~ASTImporter();
-    
+
     /// Whether the importer will perform a minimal import, creating
     /// to-be-completed forward declarations when possible.
     bool isMinimalImport() const { return Minimal; }
-    
+
     /// Import the given type from the "from" context into the "to"
     /// context.
     ///
@@ -142,10 +142,10 @@ class Attr;
     /// \returns the equivalent attribute in the "to" context.
     Attr *Import(const Attr *FromAttr);
 
-    /// Import the given declaration from the "from" context into the 
+    /// Import the given declaration from the "from" context into the
     /// "to" context.
     ///
-    /// \returns the equivalent declaration in the "to" context, or a NULL type 
+    /// \returns the equivalent declaration in the "to" context, or a NULL type
     /// if an error occurred.
     Decl *Import(Decl *FromD);
     Decl *Import(const Decl *FromD) {
@@ -163,7 +163,7 @@ class Attr;
     /// \returns the equivalent declaration context in the "to"
     /// context, or a NULL type if an error occurred.
     DeclContext *ImportContext(DeclContext *FromDC);
-    
+
     /// Import the given expression from the "from" context into the
     /// "to" context.
     ///
@@ -195,7 +195,7 @@ class Attr;
     /// Import the goven template name from the "from" context into the
     /// "to" context.
     TemplateName Import(TemplateName From);
-    
+
     /// Import the given source location from the "from" context into
     /// the "to" context.
     ///
@@ -229,7 +229,7 @@ class Attr;
     /// \returns the equivalent selector in the "to" context.
     Selector Import(Selector FromSel);
 
-    /// Import the given file ID from the "from" context into the 
+    /// Import the given file ID from the "from" context into the
     /// "to" context.
     ///
     /// \returns the equivalent file ID in the source manager of the "to"
@@ -252,13 +252,13 @@ class Attr;
     /// Import the definition of the given declaration, including all of
     /// the declarations it contains.
     ///
-    /// This routine is intended to be used 
+    /// This routine is intended to be used
     void ImportDefinition(Decl *From);
 
     /// Cope with a name conflict when importing a declaration into the
     /// given context.
     ///
-    /// This routine is invoked whenever there is a name conflict while 
+    /// This routine is invoked whenever there is a name conflict while
     /// importing a declaration. The returned name will become the name of the
     /// imported declaration. By default, the returned name is the same as the
     /// original name, leaving the conflict unresolve such that name lookup
@@ -270,7 +270,7 @@ class Attr;
     /// \param Name the name of the declaration being imported, which conflicts
     /// with other declarations.
     ///
-    /// \param DC the declaration context (in the "to" AST context) in which 
+    /// \param DC the declaration context (in the "to" AST context) in which
     /// the name is being imported.
     ///
     /// \param IDNS the identifier namespace in which the name will be found.
@@ -286,25 +286,25 @@ class Attr;
                                                unsigned IDNS,
                                                NamedDecl **Decls,
                                                unsigned NumDecls);
-    
+
     /// Retrieve the context that AST nodes are being imported into.
     ASTContext &getToContext() const { return ToContext; }
-    
+
     /// Retrieve the context that AST nodes are being imported from.
     ASTContext &getFromContext() const { return FromContext; }
-    
+
     /// Retrieve the file manager that AST nodes are being imported into.
     FileManager &getToFileManager() const { return ToFileManager; }
 
     /// Retrieve the file manager that AST nodes are being imported from.
     FileManager &getFromFileManager() const { return FromFileManager; }
-    
+
     /// Report a diagnostic in the "to" context.
     DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
-    
+
     /// Report a diagnostic in the "from" context.
     DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
-    
+
     /// Return the set of declarations that we know are not equivalent.
     NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
 
@@ -313,7 +313,7 @@ class Attr;
     ///
     /// \param D A declaration in the "to" context.
     virtual void CompleteDecl(Decl* D);
-    
+
     /// Subclasses can override this function to observe all of the \c From ->
     /// \c To declaration mappings as they are imported.
     virtual Decl *Imported(Decl *From, Decl *To) { return To; }
@@ -328,7 +328,7 @@ class Attr;
     /// RecordDecl can be found, we can complete it without the need for
     /// importation, eliminating this loop.
     virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; }
-    
+
     /// Determine whether the given types are structurally
     /// equivalent.
     bool IsStructurallyEquivalent(QualType From, QualType To,
diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
index 2fe4e2563b..6fedcb8d38 100644
--- a/include/clang/AST/ASTLambda.h
+++ b/include/clang/AST/ASTLambda.h
@@ -40,7 +40,7 @@ inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) {
   if (!MD) return false;
   const CXXRecordDecl *LambdaClass = MD->getParent();
   if (LambdaClass && LambdaClass->isGenericLambda())
-    return isLambdaCallOperator(MD) && 
+    return isLambdaCallOperator(MD) &&
                     MD->isFunctionTemplateSpecialization();
   return false;
 }
@@ -51,11 +51,11 @@ inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
 
 inline bool isLambdaConversionOperator(Decl *D) {
   if (!D) return false;
-  if (CXXConversionDecl *Conv = dyn_cast(D)) 
-    return isLambdaConversionOperator(Conv);  
-  if (FunctionTemplateDecl *F = dyn_cast(D)) 
-    if (CXXConversionDecl *Conv = 
-        dyn_cast_or_null(F->getTemplatedDecl())) 
+  if (CXXConversionDecl *Conv = dyn_cast(D))
+    return isLambdaConversionOperator(Conv);
+  if (FunctionTemplateDecl *F = dyn_cast(D))
+    if (CXXConversionDecl *Conv =
+        dyn_cast_or_null(F->getTemplatedDecl()))
       return isLambdaConversionOperator(Conv);
   return false;
 }
@@ -71,7 +71,7 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
 inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
   if (isLambdaCallOperator(DC))
     return DC->getParent()->getParent();
-  else 
+  else
     return DC->getParent();
 }
 
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index 31ae2b111e..80184e1cc7 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -134,13 +134,13 @@ public:
   /// \param M The containing module in which the definition was made visible,
   ///        if any.
   virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {}
-  
+
   /// An attribute was added to a RecordDecl
   ///
   /// \param Attr The attribute that was added to the Record
   ///
   /// \param Record The RecordDecl that got a new attribute
-  virtual void AddedAttributeToRecord(const Attr *Attr, 
+  virtual void AddedAttributeToRecord(const Attr *Attr,
                                       const RecordDecl *Record) {}
 
   // NOTE: If new methods are added they should also be added to
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 32a61c59d2..20922742f6 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -86,7 +86,7 @@ public:
   attr::Kind getKind() const {
     return static_cast(AttrKind);
   }
-  
+
   unsigned getSpellingListIndex() const { return SpellingListIndex; }
   const char *getSpelling() const;
 
diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h
index 56807b4590..2087ecc0e7 100644
--- a/include/clang/AST/AttrIterator.h
+++ b/include/clang/AST/AttrIterator.h
@@ -106,7 +106,7 @@ public:
                          specific_attr_iterator Right) {
     assert((Left.Current == nullptr) == (Right.Current == nullptr));
     if (Left.Current < Right.Current)
-      Left.AdvanceToNext(Right.Current); 
+      Left.AdvanceToNext(Right.Current);
     else
       Right.AdvanceToNext(Left.Current);
     return Left.Current == Right.Current;
diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h
index fdb7e718fe..2b702c76b2 100644
--- a/include/clang/AST/BaseSubobject.h
+++ b/include/clang/AST/BaseSubobject.h
@@ -24,21 +24,21 @@ namespace clang {
 
 class CXXRecordDecl;
 
-// BaseSubobject - Uniquely identifies a direct or indirect base class. 
+// BaseSubobject - Uniquely identifies a direct or indirect base class.
 // Stores both the base class decl and the offset from the most derived class to
 // the base class. Used for vtable and VTT generation.
 class BaseSubobject {
   /// Base - The base class declaration.
   const CXXRecordDecl *Base;
-  
+
   /// BaseOffset - The offset from the most derived class to the base class.
   CharUnits BaseOffset;
-  
+
 public:
   BaseSubobject() = default;
   BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
       : Base(Base), BaseOffset(BaseOffset) {}
-  
+
   /// getBase - Returns the base class declaration.
   const CXXRecordDecl *getBase() const { return Base; }
 
@@ -74,7 +74,7 @@ template<> struct DenseMapInfo {
                                                      Base.getBaseOffset()));
   }
 
-  static bool isEqual(const clang::BaseSubobject &LHS, 
+  static bool isEqual(const clang::BaseSubobject &LHS,
                       const clang::BaseSubobject &RHS) {
     return LHS == RHS;
   }
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 2ae1d8b258..f5e23f8e85 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -34,10 +34,10 @@ namespace clang {
 
 class ASTContext;
 class NamedDecl;
-  
+
 /// Represents an element in a path from a derived class to a
-/// base class. 
-/// 
+/// base class.
+///
 /// Each step in the path references the link from a
 /// derived class to one of its direct base classes, along with a
 /// base "number" that identifies which base subobject of the
@@ -47,12 +47,12 @@ struct CXXBasePathElement {
   /// class to a base class, which will be followed by this base
   /// path element.
   const CXXBaseSpecifier *Base;
-  
+
   /// The record decl of the class that the base is a base of.
   const CXXRecordDecl *Class;
-  
+
   /// Identifies which base class subobject (of type
-  /// \c Base->getType()) this base path element refers to. 
+  /// \c Base->getType()) this base path element refers to.
   ///
   /// This value is only valid if \c !Base->isVirtual(), because there
   /// is no base numbering for the zero or one virtual bases of a
@@ -64,7 +64,7 @@ struct CXXBasePathElement {
 /// (which is not represented as part of the path) to a particular
 /// (direct or indirect) base class subobject.
 ///
-/// Individual elements in the path are described by the \c CXXBasePathElement 
+/// Individual elements in the path are described by the \c CXXBasePathElement
 /// structure, which captures both the link from a derived class to one of its
 /// direct bases and identification describing which base class
 /// subobject is being used.
@@ -121,7 +121,7 @@ class CXXBasePaths {
 
   /// The type from which this search originated.
   CXXRecordDecl *Origin = nullptr;
-  
+
   /// Paths - The actual set of paths that can be taken from the
   /// derived class to the same base class.
   std::list Paths;
@@ -160,12 +160,12 @@ class CXXBasePaths {
   /// ambiguous paths while it is looking for a path from a derived
   /// type to a base type.
   bool FindAmbiguities;
-  
+
   /// RecordPaths - Whether Sema::IsDerivedFrom should record paths
   /// while it is determining whether there are paths from a derived
   /// type to a base type.
   bool RecordPaths;
-  
+
   /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
   /// if it finds a path that goes across a virtual base. The virtual class
   /// is also recorded.
@@ -181,7 +181,7 @@ public:
   using paths_iterator = std::list::iterator;
   using const_paths_iterator = std::list::const_iterator;
   using decl_iterator = NamedDecl **;
-  
+
   /// BasePaths - Construct a new BasePaths structure to record the
   /// paths for a derived-to-base search.
   explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
@@ -193,31 +193,31 @@ public:
   paths_iterator end()   { return Paths.end(); }
   const_paths_iterator begin() const { return Paths.begin(); }
   const_paths_iterator end()   const { return Paths.end(); }
-  
+
   CXXBasePath&       front()       { return Paths.front(); }
   const CXXBasePath& front() const { return Paths.front(); }
-  
+
   using decl_range = llvm::iterator_range;
 
   decl_range found_decls();
-  
+
   /// Determine whether the path from the most-derived type to the
   /// given base type is ambiguous (i.e., it refers to multiple subobjects of
   /// the same base type).
   bool isAmbiguous(CanQualType BaseType);
-  
+
   /// Whether we are finding multiple paths to detect ambiguities.
   bool isFindingAmbiguities() const { return FindAmbiguities; }
-  
+
   /// Whether we are recording paths.
   bool isRecordingPaths() const { return RecordPaths; }
-  
+
   /// Specify whether we should be recording paths or not.
   void setRecordingPaths(bool RP) { RecordPaths = RP; }
-  
+
   /// Whether we are detecting virtual bases.
   bool isDetectingVirtual() const { return DetectVirtual; }
-  
+
   /// The virtual base discovered on the path (if we are merely
   /// detecting virtuals).
   const RecordType* getDetectedVirtual() const {
@@ -228,11 +228,11 @@ public:
   /// began
   CXXRecordDecl *getOrigin() const { return Origin; }
   void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
-  
+
   /// Clear the base-paths results.
   void clear();
-  
-  /// Swap this data structure's contents with another CXXBasePaths 
+
+  /// Swap this data structure's contents with another CXXBasePaths
   /// object.
   void swap(CXXBasePaths &Other);
 };
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 63a0af66ee..0e738da43a 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -85,8 +85,8 @@ public:
 
   /// Retrieve the underlying type pointer, which refers to a
   /// canonical type, or nullptr.
-  const T *getTypePtrOrNull() const { 
-    return cast_or_null(Stored.getTypePtrOrNull()); 
+  const T *getTypePtrOrNull() const {
+    return cast_or_null(Stored.getTypePtrOrNull());
   }
 
   /// Implicit conversion to a qualified type.
@@ -94,7 +94,7 @@ public:
 
   /// Implicit conversion to bool.
   explicit operator bool() const { return !isNull(); }
-  
+
   bool isNull() const {
     return Stored.isNull();
   }
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index ddead6046a..0aadf06fff 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -61,7 +61,7 @@ namespace clang {
 
       /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
       static CharUnits fromQuantity(QuantityType Quantity) {
-        return CharUnits(Quantity); 
+        return CharUnits(Quantity);
       }
 
       // Compound assignment.
@@ -87,7 +87,7 @@ namespace clang {
       CharUnits operator-- (int) {
         return CharUnits(Quantity--);
       }
-       
+
       // Comparison operators.
       bool operator== (const CharUnits &Other) const {
         return Quantity == Other.Quantity;
@@ -97,21 +97,21 @@ namespace clang {
       }
 
       // Relational operators.
-      bool operator<  (const CharUnits &Other) const { 
-        return Quantity <  Other.Quantity; 
+      bool operator<  (const CharUnits &Other) const {
+        return Quantity <  Other.Quantity;
       }
-      bool operator<= (const CharUnits &Other) const { 
+      bool operator<= (const CharUnits &Other) const {
         return Quantity <= Other.Quantity;
       }
-      bool operator>  (const CharUnits &Other) const { 
-        return Quantity >  Other.Quantity; 
+      bool operator>  (const CharUnits &Other) const {
+        return Quantity >  Other.Quantity;
       }
-      bool operator>= (const CharUnits &Other) const { 
-        return Quantity >= Other.Quantity; 
+      bool operator>= (const CharUnits &Other) const {
+        return Quantity >= Other.Quantity;
       }
 
       // Other predicates.
-      
+
       /// isZero - Test whether the quantity equals zero.
       bool isZero() const     { return Quantity == 0; }
 
@@ -172,7 +172,7 @@ namespace clang {
         return CharUnits(-Quantity);
       }
 
-      
+
       // Conversions.
 
       /// getQuantity - Get the raw integer representation of this quantity.
@@ -205,7 +205,7 @@ namespace clang {
   }; // class CharUnit
 } // namespace clang
 
-inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale, 
+inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
                                    const clang::CharUnits &CU) {
   return CU * Scale;
 }
@@ -223,8 +223,8 @@ template<> struct DenseMapInfo {
   static clang::CharUnits getTombstoneKey() {
     clang::CharUnits::QuantityType Quantity =
       DenseMapInfo::getTombstoneKey();
-    
-    return clang::CharUnits::fromQuantity(Quantity);    
+
+    return clang::CharUnits::fromQuantity(Quantity);
   }
 
   static unsigned getHashValue(const clang::CharUnits &CU) {
@@ -232,7 +232,7 @@ template<> struct DenseMapInfo {
     return DenseMapInfo::getHashValue(Quantity);
   }
 
-  static bool isEqual(const clang::CharUnits &LHS, 
+  static bool isEqual(const clang::CharUnits &LHS,
                       const clang::CharUnits &RHS) {
     return LHS == RHS;
   }
@@ -241,7 +241,7 @@ template<> struct DenseMapInfo {
 template <> struct isPodLike {
   static const bool value = true;
 };
-  
+
 } // end namespace llvm
 
 #endif // LLVM_CLANG_AST_CHARUNITS_H
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index e3a427d8aa..f5538dec2a 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -98,7 +98,7 @@ protected:
     unsigned RenderKind : 2;
     unsigned CommandID : CommandInfo::NumCommandIDBits;
   };
-  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + 
+  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
                                        CommandInfo::NumCommandIDBits };
 
   class HTMLTagCommentBitfields {
@@ -146,7 +146,7 @@ protected:
     /// Contains values from CommandMarkerKind enum.
     unsigned CommandMarker : 1;
   };
-  enum { NumBlockCommandCommentBits = NumCommentBits + 
+  enum { NumBlockCommandCommentBits = NumCommentBits +
                                       CommandInfo::NumCommandIDBits + 1 };
 
   class ParamCommandCommentBitfields {
@@ -987,7 +987,7 @@ struct DeclInfo {
   /// Declaration the comment is actually attached to (in the source).
   /// Should not be NULL.
   const Decl *CommentDecl;
-  
+
   /// CurrentDecl is the declaration with which the FullComment is associated.
   ///
   /// It can be different from \c CommentDecl.  It happens when we decide
@@ -997,7 +997,7 @@ struct DeclInfo {
   ///
   /// The information in the DeclInfo corresponds to CurrentDecl.
   const Decl *CurrentDecl;
-  
+
   /// Parameters that can be referenced by \\param if \c CommentDecl is something
   /// that we consider a "function".
   ArrayRef ParamVars;
@@ -1119,21 +1119,21 @@ public:
   }
 
   child_iterator child_end() const {
-    return reinterpret_cast(Blocks.end()); 
+    return reinterpret_cast(Blocks.end());
   }
 
   const Decl *getDecl() const LLVM_READONLY {
     return ThisDeclInfo->CommentDecl;
   }
-  
+
   const DeclInfo *getDeclInfo() const LLVM_READONLY {
     if (!ThisDeclInfo->IsFilled)
       ThisDeclInfo->fill();
     return ThisDeclInfo;
   }
-  
+
   ArrayRef getBlocks() const { return Blocks; }
-  
+
 };
 } // end namespace comments
 } // end namespace clang
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index bac4e99dc7..4fd007872c 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -107,17 +107,17 @@ struct CommandInfo {
   ///   \fn void f(int a);
   /// \endcode
   unsigned IsDeclarationCommand : 1;
-  
+
   /// True if verbatim-like line command is a function declaration.
   unsigned IsFunctionDeclarationCommand : 1;
 
   /// True if block command is further describing a container API; such
   /// as \@coclass, \@classdesign, etc.
   unsigned IsRecordLikeDetailCommand : 1;
-  
+
   /// True if block command is a container API; such as \@interface.
   unsigned IsRecordLikeDeclarationCommand : 1;
-  
+
   /// True if this command is unknown.  This \c CommandInfo object was
   /// created during parsing.
   unsigned IsUnknownCommand : 1;
@@ -150,7 +150,7 @@ public:
   }
 
   const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
-  
+
   const CommandInfo *getCommandInfo(unsigned CommandID) const;
 
   const CommandInfo *registerUnknownCommand(StringRef CommandName);
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index 52c4eb9e30..3ef5b7c8c9 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -76,7 +76,7 @@ class Token {
   /// unused (command spelling can be found with CommandTraits).  Otherwise,
   /// contains the length of the string that starts at TextPtr.
   unsigned IntVal;
-  
+
 public:
   SourceLocation getLocation() const LLVM_READONLY { return Loc; }
   void setLocation(SourceLocation SL) { Loc = SL; }
@@ -228,7 +228,7 @@ private:
   llvm::BumpPtrAllocator &Allocator;
 
   DiagnosticsEngine &Diags;
-  
+
   const CommandTraits &Traits;
 
   const char *const BufferStart;
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 0e94c33970..632eba782b 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -191,11 +191,11 @@ public:
   void checkBlockCommandDuplicate(const BlockCommandComment *Command);
 
   void checkDeprecatedCommand(const BlockCommandComment *Comment);
-  
+
   void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment);
-  
+
   void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment);
-  
+
   void checkContainerDecl(const BlockCommandComment *Comment);
 
   /// Resolve parameter names to parameter indexes in function declaration.
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index dde9459963..ebdb2890da 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -98,7 +98,7 @@ public:
 
   /// Return the TypeLoc wrapper for the type source info.
   TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
-  
+
   /// Override the type stored in this TypeSourceInfo. Use with caution!
   void overrideType(QualType T) { Ty = T; }
 };
@@ -488,7 +488,7 @@ public:
                            SourceLocation IdentL, IdentifierInfo *II,
                            SourceLocation GnuLabelL);
   static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   LabelStmt *getStmt() const { return TheStmt; }
   void setStmt(LabelStmt *T) { TheStmt = T; }
 
@@ -511,8 +511,8 @@ public:
 };
 
 /// Represent a C++ namespace.
-class NamespaceDecl : public NamedDecl, public DeclContext, 
-                      public Redeclarable 
+class NamespaceDecl : public NamedDecl, public DeclContext,
+                      public Redeclarable
 {
   /// The starting location of the source range, pointing
   /// to either the namespace or the inline keyword.
@@ -523,7 +523,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
 
   /// A pointer to either the anonymous namespace that lives just inside
   /// this namespace or to the first namespace in the chain (the latter case
-  /// only when this is not the first in the chain), along with a 
+  /// only when this is not the first in the chain), along with a
   /// boolean value indicating whether this is an inline namespace.
   llvm::PointerIntPair AnonOrFirstNamespaceAndInline;
 
@@ -1931,7 +1931,7 @@ public:
                               bool isConstexprSpecified = false);
 
   static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-                       
+
   DeclarationNameInfo getNameInfo() const {
     return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
   }
@@ -2598,7 +2598,7 @@ public:
                            InClassInitStyle InitStyle);
 
   static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   /// Returns the index of this field within its record,
   /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
   unsigned getFieldIndex() const;
@@ -2754,7 +2754,7 @@ public:
                                   QualType T, Expr *E,
                                   const llvm::APSInt &V);
   static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   const Expr *getInitExpr() const { return (const Expr*) Init; }
   Expr *getInitExpr() { return (Expr*) Init; }
   const llvm::APSInt &getInitVal() const { return Val; }
@@ -3812,7 +3812,7 @@ public:
 
   /// Finds the first data member which has a name.
   /// nullptr is returned if no named data member exists.
-  const FieldDecl *findFirstNamedDataMember() const;  
+  const FieldDecl *findFirstNamedDataMember() const;
 
 private:
   /// Deserialize just the fields.
@@ -3835,7 +3835,7 @@ public:
                                   SourceLocation RParenLoc);
 
   static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   SourceLocation getAsmLoc() const { return getLocation(); }
   SourceLocation getRParenLoc() const { return RParenLoc; }
   void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -3927,9 +3927,9 @@ protected:
         IsConversionFromLambda(false), DoesNotEscape(false) {}
 
 public:
-  static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); 
+  static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
   static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   SourceLocation getCaretLocation() const { return getLocation(); }
 
   bool isVariadic() const { return IsVariadic; }
@@ -4009,7 +4009,7 @@ public:
    }
 
    Decl *getBlockManglingContextDecl() const {
-     return ManglingContextDecl;    
+     return ManglingContextDecl;
    }
 
   void setBlockMangling(unsigned Number, Decl *Ctx) {
@@ -4145,16 +4145,16 @@ class ImportDecl final : public Decl,
 
   /// The imported module, along with a bit that indicates whether
   /// we have source-location information for each identifier in the module
-  /// name. 
+  /// name.
   ///
   /// When the bit is false, we only have a single source location for the
   /// end of the import declaration.
   llvm::PointerIntPair ImportedAndComplete;
-  
+
   /// The next import in the list of imports local to the translation
   /// unit being parsed (not loaded from an AST file).
   ImportDecl *NextLocalImport = nullptr;
-  
+
   ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
              ArrayRef IdentifierLocs);
 
@@ -4162,26 +4162,26 @@ class ImportDecl final : public Decl,
              SourceLocation EndLoc);
 
   ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
-  
+
 public:
   /// Create a new module import declaration.
-  static ImportDecl *Create(ASTContext &C, DeclContext *DC, 
+  static ImportDecl *Create(ASTContext &C, DeclContext *DC,
                             SourceLocation StartLoc, Module *Imported,
                             ArrayRef IdentifierLocs);
-  
+
   /// Create a new module import declaration for an implicitly-generated
   /// import.
-  static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, 
-                                    SourceLocation StartLoc, Module *Imported, 
+  static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
+                                    SourceLocation StartLoc, Module *Imported,
                                     SourceLocation EndLoc);
-  
+
   /// Create a new, deserialized module import declaration.
-  static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, 
+  static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                         unsigned NumLocations);
-  
+
   /// Retrieve the module that was imported by the import declaration.
   Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
-  
+
   /// Retrieves the locations of each of the identifiers that make up
   /// the complete module name in the import declaration.
   ///
@@ -4218,7 +4218,7 @@ public:
   static ExportDecl *Create(ASTContext &C, DeclContext *DC,
                             SourceLocation ExportLoc);
   static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   SourceLocation getExportLoc() const { return getLocation(); }
   SourceLocation getRBraceLoc() const { return RBraceLoc; }
   void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index f99bd62787..d6b89d971d 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -302,7 +302,7 @@ private:
   /// global variable, etc.) that is lexically inside an objc container
   /// definition.
   unsigned TopLevelDeclInObjCContainer : 1;
-  
+
   /// Whether statistic collection is enabled.
   static bool StatisticsEnabled;
 
@@ -629,7 +629,7 @@ protected:
     assert(isFromASTFile() && "Only works on a deserialized declaration");
     *((unsigned*)this - 2) = ID;
   }
-  
+
 public:
   /// Determine the availability of the given declaration.
   ///
@@ -879,7 +879,7 @@ public:
 
   /// Whether this particular Decl is a canonical one.
   bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
-  
+
 protected:
   /// Returns the next redeclaration or itself if this is the only decl.
   ///
@@ -956,10 +956,10 @@ public:
   /// Retrieve the previous declaration that declares the same entity
   /// as this declaration, or NULL if there is no previous declaration.
   Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
-  
+
   /// Retrieve the most recent declaration that declares the same entity
   /// as this declaration, or NULL if there is no previous declaration.
-  const Decl *getPreviousDecl() const { 
+  const Decl *getPreviousDecl() const {
     return const_cast(this)->getPreviousDeclImpl();
   }
 
@@ -974,7 +974,7 @@ public:
 
   /// Retrieve the most recent declaration that declares the same entity
   /// as this declaration (which may be this declaration).
-  const Decl *getMostRecentDecl() const { 
+  const Decl *getMostRecentDecl() const {
     return const_cast(this)->getMostRecentDeclImpl();
   }
 
@@ -1159,13 +1159,13 @@ protected:
 inline bool declaresSameEntity(const Decl *D1, const Decl *D2) {
   if (!D1 || !D2)
     return false;
-  
+
   if (D1 == D2)
     return true;
-  
+
   return D1->getCanonicalDecl() == D2->getCanonicalDecl();
 }
-  
+
 /// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
 /// doing something to a specific decl.
 class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
@@ -1517,7 +1517,7 @@ public:
   /// connected to this declaration context.
   ///
   /// For declaration contexts that have multiple semantically connected but
-  /// syntactically distinct contexts, such as C++ namespaces, this routine 
+  /// syntactically distinct contexts, such as C++ namespaces, this routine
   /// retrieves the complete set of such declaration contexts in source order.
   /// For example, given:
   ///
@@ -1921,7 +1921,7 @@ public:
   /// Determine whether the given declaration is stored in the list of
   /// declarations lexically within this context.
   bool isDeclInLexicalTraversal(const Decl *D) const {
-    return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl || 
+    return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
                  D == LastDecl);
   }
 
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 1d0489912c..4353f66a34 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -264,7 +264,7 @@ public:
     return EllipsisLoc;
   }
 
-  /// Returns the access specifier for this base specifier. 
+  /// Returns the access specifier for this base specifier.
   ///
   /// This is the actual base specifier as used for semantic analysis, so
   /// the result can never be AS_none. To retrieve the access specifier as
@@ -564,7 +564,7 @@ class CXXRecordDecl : public RecordDecl {
     CXXRecordDecl *Definition;
 
     /// The first friend declaration in this class, or null if there
-    /// aren't any. 
+    /// aren't any.
     ///
     /// This is actually currently stored in reverse order.
     LazyDeclPtr FirstFriend;
@@ -606,14 +606,14 @@ class CXXRecordDecl : public RecordDecl {
 
     /// Whether this lambda is known to be dependent, even if its
     /// context isn't dependent.
-    /// 
+    ///
     /// A lambda with a non-dependent context can be dependent if it occurs
     /// within the default argument of a function template, because the
     /// lambda will have been created with the enclosing context as its
     /// declaration context, rather than function. This is an unfortunate
-    /// artifact of having to parse the default arguments before. 
+    /// artifact of having to parse the default arguments before.
     unsigned Dependent : 1;
-    
+
     /// Whether this lambda is a generic lambda.
     unsigned IsGenericLambda : 1;
 
@@ -626,28 +626,28 @@ class CXXRecordDecl : public RecordDecl {
     /// The number of explicit captures in this lambda.
     unsigned NumExplicitCaptures : 13;
 
-    /// The number used to indicate this lambda expression for name 
+    /// The number used to indicate this lambda expression for name
     /// mangling in the Itanium C++ ABI.
     unsigned ManglingNumber = 0;
-    
+
     /// The declaration that provides context for this lambda, if the
     /// actual DeclContext does not suffice. This is used for lambdas that
     /// occur within default arguments of function parameters within the class
     /// or within a data member initializer.
     LazyDeclPtr ContextDecl;
-    
-    /// The list of captures, both explicit and implicit, for this 
+
+    /// The list of captures, both explicit and implicit, for this
     /// lambda.
     Capture *Captures = nullptr;
 
     /// The type of the call method.
     TypeSourceInfo *MethodTyInfo;
 
-    LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, 
-                         bool Dependent, bool IsGeneric, 
-                         LambdaCaptureDefault CaptureDefault) 
-      : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), 
-        CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), 
+    LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
+                         bool Dependent, bool IsGeneric,
+                         LambdaCaptureDefault CaptureDefault)
+      : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
+        CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
         MethodTyInfo(Info) {
       IsLambda = true;
 
@@ -1205,22 +1205,22 @@ public:
     return DD && DD->IsLambda;
   }
 
-  /// Determine whether this class describes a generic 
+  /// Determine whether this class describes a generic
   /// lambda function object (i.e. function call operator is
-  /// a template). 
-  bool isGenericLambda() const; 
+  /// a template).
+  bool isGenericLambda() const;
 
   /// Retrieve the lambda call operator of the closure type
   /// if this is a closure type.
-  CXXMethodDecl *getLambdaCallOperator() const; 
+  CXXMethodDecl *getLambdaCallOperator() const;
 
   /// Retrieve the lambda static invoker, the address of which
   /// is returned by the conversion operator, and the body of which
-  /// is forwarded to the lambda call operator. 
-  CXXMethodDecl *getLambdaStaticInvoker() const; 
+  /// is forwarded to the lambda call operator.
+  CXXMethodDecl *getLambdaStaticInvoker() const;
 
   /// Retrieve the generic lambda's template parameter list.
-  /// Returns null if the class does not represent a lambda or a generic 
+  /// Returns null if the class does not represent a lambda or a generic
   /// lambda.
   TemplateParameterList *getGenericLambdaTemplateParameterList() const;
 
@@ -1345,11 +1345,11 @@ public:
   /// not overridden.
   bool isAbstract() const { return data().Abstract; }
 
-  /// Determine whether this class is standard-layout per 
+  /// Determine whether this class is standard-layout per
   /// C++ [class]p7.
   bool isStandardLayout() const { return data().IsStandardLayout; }
 
-  /// Determine whether this class was standard-layout per 
+  /// Determine whether this class was standard-layout per
   /// C++11 [class]p7, specifically using the C++11 rules without any DRs.
   bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; }
 
@@ -1900,25 +1900,25 @@ public:
   /// If this is the closure type of a lambda expression, retrieve the
   /// number to be used for name mangling in the Itanium C++ ABI.
   ///
-  /// Zero indicates that this closure type has internal linkage, so the 
+  /// Zero indicates that this closure type has internal linkage, so the
   /// mangling number does not matter, while a non-zero value indicates which
   /// lambda expression this is in this particular context.
   unsigned getLambdaManglingNumber() const {
     assert(isLambda() && "Not a lambda closure type!");
     return getLambdaData().ManglingNumber;
   }
-  
-  /// Retrieve the declaration that provides additional context for a 
+
+  /// Retrieve the declaration that provides additional context for a
   /// lambda, when the normal declaration context is not specific enough.
   ///
-  /// Certain contexts (default arguments of in-class function parameters and 
+  /// Certain contexts (default arguments of in-class function parameters and
   /// the initializers of data members) have separate name mangling rules for
   /// lambdas within the Itanium C++ ABI. For these cases, this routine provides
-  /// the declaration in which the lambda occurs, e.g., the function parameter 
+  /// the declaration in which the lambda occurs, e.g., the function parameter
   /// or the non-static data member. Otherwise, it returns NULL to imply that
   /// the declaration context suffices.
   Decl *getLambdaContextDecl() const;
-  
+
   /// Set the mangling number and context declaration for a lambda
   /// class.
   void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
@@ -2799,7 +2799,7 @@ public:
   /// Determine whether this conversion function is a conversion from
   /// a lambda closure type to a block pointer.
   bool isLambdaToBlockPointerConversion() const;
-  
+
   CXXConversionDecl *getCanonicalDecl() override {
     return cast(FunctionDecl::getCanonicalDecl());
   }
@@ -2812,7 +2812,7 @@ public:
   static bool classofKind(Kind K) { return K == CXXConversion; }
 };
 
-/// Represents a linkage specification. 
+/// Represents a linkage specification.
 ///
 /// For example:
 /// \code
@@ -2862,7 +2862,7 @@ public:
                                  SourceLocation LangLoc, LanguageIDs Lang,
                                  bool HasBraces);
   static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   /// Return the language specified by this linkage specification.
   LanguageIDs getLanguage() const { return LanguageIDs(Language); }
 
@@ -3770,7 +3770,7 @@ public:
                                   Expr *AssertExpr, StringLiteral *Message,
                                   SourceLocation RParenLoc, bool Failed);
   static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
   const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
 
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 47fb68bf42..a8de8ed168 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -254,7 +254,7 @@ inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
   FD->NextFriend = data().FirstFriend;
   data().FirstFriend = FD;
 }
-  
+
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_DECLFRIEND_H
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index 64eb3f24b3..9627f440d4 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -54,7 +54,7 @@ public:
       ++It;
     } while (It != End &&
              It->first == DeclarationName::getUsingDirectiveName());
-             
+
     return *this;
   }
 
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index c81a5f805f..c1cc726e31 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -587,7 +587,7 @@ class ObjCTypeParamDecl : public TypedefNameDecl {
   /// explicitly specified.
   SourceLocation ColonLoc;
 
-  ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc, 
+  ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
                     ObjCTypeParamVariance variance, SourceLocation varianceLoc,
                     unsigned index,
                     SourceLocation nameLoc, IdentifierInfo *name,
@@ -659,7 +659,7 @@ class ObjCTypeParamList final
     unsigned End;
   };
 
-  union { 
+  union {
     /// Location of the left and right angle brackets.
     PODSourceRange Brackets;
 
@@ -1123,7 +1123,7 @@ public:
                      ObjCPropertyDecl *>;
   using ProtocolPropertySet = llvm::SmallDenseSet;
   using PropertyDeclOrder = llvm::SmallVector;
-  
+
   /// This routine collects list of properties to be implemented in the class.
   /// This includes, class's and its conforming protocols' properties.
   /// Note, the superclass's properties are not included in the list.
@@ -1195,15 +1195,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
   /// TypeForDecl - This indicates the Type object that represents this
   /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
   mutable const Type *TypeForDecl = nullptr;
-  
+
   struct DefinitionData {
-    /// The definition of this class, for quick access from any 
+    /// The definition of this class, for quick access from any
     /// declaration.
     ObjCInterfaceDecl *Definition = nullptr;
-    
+
     /// When non-null, this is always an ObjCObjectType.
     TypeSourceInfo *SuperClassTInfo = nullptr;
-    
+
     /// Protocols referenced in the \@interface  declaration
     ObjCProtocolList ReferencedProtocols;
 
@@ -1247,11 +1247,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
 
     /// One of the \c InheritedDesignatedInitializersState enumeratos.
     mutable unsigned InheritedDesignatedInitializers : 2;
-    
+
     /// The location of the last location in this declaration, before
-    /// the properties/methods. For example, this will be the '>', '}', or 
-    /// identifier, 
-    SourceLocation EndLoc; 
+    /// the properties/methods. For example, this will be the '>', '}', or
+    /// identifier,
+    SourceLocation EndLoc;
 
     DefinitionData()
         : ExternallyCompleted(false), IvarListMissingImplementation(true),
@@ -1285,7 +1285,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
 
   /// Allocate the definition data for this class.
   void allocateDefinitionData();
-  
+
   using redeclarable_base = Redeclarable;
 
   ObjCInterfaceDecl *getNextRedeclarationImpl() override {
@@ -1334,7 +1334,7 @@ public:
   SourceRange getSourceRange() const override LLVM_READONLY {
     if (isThisDeclarationADefinition())
       return ObjCContainerDecl::getSourceRange();
-    
+
     return SourceRange(getAtStartLoc(), getLocation());
   }
 
@@ -1390,7 +1390,7 @@ public:
     // FIXME: Should make sure no callers ever do this.
     if (!hasDefinition())
       return protocol_iterator();
-    
+
     if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
@@ -1453,7 +1453,7 @@ public:
     if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return data().AllReferencedProtocols.empty()  
+    return data().AllReferencedProtocols.empty()
              ? protocol_begin()
              : data().AllReferencedProtocols.begin();
   }
@@ -1462,11 +1462,11 @@ public:
     // FIXME: Should make sure no callers ever do this.
     if (!hasDefinition())
       return all_protocol_iterator();
-    
+
     if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return data().AllReferencedProtocols.empty() 
+    return data().AllReferencedProtocols.empty()
              ? protocol_end()
              : data().AllReferencedProtocols.end();
   }
@@ -1476,17 +1476,17 @@ public:
 
   ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
 
-  ivar_iterator ivar_begin() const { 
+  ivar_iterator ivar_begin() const {
     if (const ObjCInterfaceDecl *Def = getDefinition())
-      return ivar_iterator(Def->decls_begin()); 
-    
+      return ivar_iterator(Def->decls_begin());
+
     // FIXME: Should make sure no callers ever do this.
     return ivar_iterator();
   }
 
-  ivar_iterator ivar_end() const { 
+  ivar_iterator ivar_end() const {
     if (const ObjCInterfaceDecl *Def = getDefinition())
-      return ivar_iterator(Def->decls_end()); 
+      return ivar_iterator(Def->decls_end());
 
     // FIXME: Should make sure no callers ever do this.
     return ivar_iterator();
@@ -1546,10 +1546,10 @@ public:
 
   /// Determine whether this particular declaration of this class is
   /// actually also a definition.
-  bool isThisDeclarationADefinition() const { 
+  bool isThisDeclarationADefinition() const {
     return getDefinition() == this;
   }
-                          
+
   /// Determine whether this class has been defined.
   bool hasDefinition() const {
     // If the name of this class is out-of-date, bring it up-to-date, which
@@ -1561,16 +1561,16 @@ public:
 
     return Data.getPointer();
   }
-                        
-  /// Retrieve the definition of this class, or NULL if this class 
-  /// has been forward-declared (with \@class) but not yet defined (with 
+
+  /// Retrieve the definition of this class, or NULL if this class
+  /// has been forward-declared (with \@class) but not yet defined (with
   /// \@interface).
   ObjCInterfaceDecl *getDefinition() {
     return hasDefinition()? Data.getPointer()->Definition : nullptr;
   }
 
-  /// Retrieve the definition of this class, or NULL if this class 
-  /// has been forward-declared (with \@class) but not yet defined (with 
+  /// Retrieve the definition of this class, or NULL if this class
+  /// has been forward-declared (with \@class) but not yet defined (with
   /// \@interface).
   const ObjCInterfaceDecl *getDefinition() const {
     return hasDefinition()? Data.getPointer()->Definition : nullptr;
@@ -1579,7 +1579,7 @@ public:
   /// Starts the definition of this Objective-C class, taking it from
   /// a forward declaration (\@class) to a definition (\@interface).
   void startDefinition();
-  
+
   /// Retrieve the superclass type.
   const ObjCObjectType *getSuperClassType() const {
     if (TypeSourceInfo *TInfo = getSuperClassTInfo())
@@ -1593,7 +1593,7 @@ public:
     // FIXME: Should make sure no callers ever do this.
     if (!hasDefinition())
       return nullptr;
-    
+
     if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
@@ -1604,7 +1604,7 @@ public:
   // does not include any type arguments that apply to the superclass.
   ObjCInterfaceDecl *getSuperClass() const;
 
-  void setSuperClass(TypeSourceInfo *superClass) { 
+  void setSuperClass(TypeSourceInfo *superClass) {
     data().SuperClassTInfo = superClass;
   }
 
@@ -1618,7 +1618,7 @@ public:
     ObjCCategoryDecl *Current = nullptr;
 
     void findAcceptableCategory();
-    
+
   public:
     using value_type = ObjCCategoryDecl *;
     using reference = value_type;
@@ -1659,7 +1659,7 @@ private:
   ///
   /// Used in the \c visible_categories_iterator.
   static bool isVisibleCategory(ObjCCategoryDecl *Cat);
-                        
+
 public:
   /// Iterator that walks over the list of categories and extensions
   /// that are visible, i.e., not hidden in a non-imported submodule.
@@ -1765,7 +1765,7 @@ private:
   ///
   /// Used in the \c known_extensions_iterator.
   static bool isKnownExtension(ObjCCategoryDecl *Cat);
-  
+
 public:
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
@@ -1787,7 +1787,7 @@ public:
   known_extensions_iterator known_extensions_begin() const {
     return known_extensions_iterator(getCategoryListRaw());
   }
-  
+
   /// Retrieve an iterator to the end of the known-extensions list.
   known_extensions_iterator known_extensions_end() const {
     return known_extensions_iterator();
@@ -1804,7 +1804,7 @@ public:
     // FIXME: Should make sure no callers ever do this.
     if (!hasDefinition())
       return nullptr;
-    
+
     if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
@@ -1831,7 +1831,7 @@ public:
     while (I != nullptr) {
       if (declaresSameEntity(this, I))
         return true;
-      
+
       I = I->getSuperClass();
     }
     return false;
@@ -1841,7 +1841,7 @@ public:
   /// to be incompatible with __weak references. Returns true if it is.
   bool isArcWeakrefUnavailable() const;
 
-  /// isObjCRequiresPropertyDefs - Checks that a class or one of its super 
+  /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
   /// classes must not be auto-synthesized. Returns class decl. if it must not
   /// be; 0, otherwise.
   const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
@@ -1854,7 +1854,7 @@ public:
   }
 
   ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
-                          
+
   // Lookup a method. First, we search locally. If a method isn't
   // found, we search referenced protocols and class categories.
   ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
@@ -1893,14 +1893,14 @@ public:
                         true /* followsSuper */,
                         Cat);
   }
-                          
-  SourceLocation getEndOfDefinitionLoc() const { 
+
+  SourceLocation getEndOfDefinitionLoc() const {
     if (!hasDefinition())
       return getLocation();
-    
-    return data().EndLoc; 
+
+    return data().EndLoc;
   }
-                          
+
   void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
 
   /// Retrieve the starting location of the superclass.
@@ -1909,7 +1909,7 @@ public:
   /// isImplicitInterfaceDecl - check that this is an implicitly declared
   /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
   /// declaration without an \@interface declaration.
-  bool isImplicitInterfaceDecl() const { 
+  bool isImplicitInterfaceDecl() const {
     return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
   }
 
@@ -1987,7 +1987,7 @@ public:
                               bool synthesized=false);
 
   static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   /// Return the class interface that this ivar is logically contained
   /// in; this is either the interface where the ivar was declared, or the
   /// interface the ivar is conceptually a part of in the case of synthesized
@@ -2045,7 +2045,7 @@ public:
                                      QualType T, Expr *BW);
 
   static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-  
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
@@ -2087,7 +2087,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
     ObjCProtocolDecl *Definition;
 
     /// Referenced protocols
-    ObjCProtocolList ReferencedProtocols;    
+    ObjCProtocolList ReferencedProtocols;
   };
 
   /// Contains a pointer to the data associated with this class,
@@ -2107,7 +2107,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
     assert(Data.getPointer() && "Objective-C protocol has no definition!");
     return *Data.getPointer();
   }
-  
+
   void allocateDefinitionData();
 
   using redeclarable_base = Redeclarable;
@@ -2152,15 +2152,15 @@ public:
   protocol_iterator protocol_begin() const {
     if (!hasDefinition())
       return protocol_iterator();
-    
+
     return data().ReferencedProtocols.begin();
   }
 
-  protocol_iterator protocol_end() const { 
+  protocol_iterator protocol_end() const {
     if (!hasDefinition())
       return protocol_iterator();
-    
-    return data().ReferencedProtocols.end(); 
+
+    return data().ReferencedProtocols.end();
   }
 
   using protocol_loc_iterator = ObjCProtocolList::loc_iterator;
@@ -2173,22 +2173,22 @@ public:
   protocol_loc_iterator protocol_loc_begin() const {
     if (!hasDefinition())
       return protocol_loc_iterator();
-    
+
     return data().ReferencedProtocols.loc_begin();
   }
 
   protocol_loc_iterator protocol_loc_end() const {
     if (!hasDefinition())
       return protocol_loc_iterator();
-    
+
     return data().ReferencedProtocols.loc_end();
   }
 
-  unsigned protocol_size() const { 
+  unsigned protocol_size() const {
     if (!hasDefinition())
       return 0;
-    
-    return data().ReferencedProtocols.size(); 
+
+    return data().ReferencedProtocols.size();
   }
 
   /// setProtocolList - Set the list of protocols that this interface
@@ -2235,12 +2235,12 @@ public:
     return hasDefinition()? Data.getPointer()->Definition : nullptr;
   }
 
-  /// Determine whether this particular declaration is also the 
+  /// Determine whether this particular declaration is also the
   /// definition.
   bool isThisDeclarationADefinition() const {
     return getDefinition() == this;
   }
-  
+
   /// Starts the definition of this Objective-C protocol.
   void startDefinition();
 
@@ -2251,10 +2251,10 @@ public:
   SourceRange getSourceRange() const override LLVM_READONLY {
     if (isThisDeclarationADefinition())
       return ObjCContainerDecl::getSourceRange();
-   
+
     return SourceRange(getAtStartLoc(), getLocation());
   }
-   
+
   using redecl_range = redeclarable_base::redecl_range;
   using redecl_iterator = redeclarable_base::redecl_iterator;
 
@@ -2316,7 +2316,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
   /// class extension may have private ivars.
   SourceLocation IvarLBraceLoc;
   SourceLocation IvarRBraceLoc;
-  
+
   ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
                    SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
                    IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
@@ -2431,7 +2431,7 @@ public:
 
   SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
   void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
-  
+
   void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
   SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
   void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
@@ -2576,7 +2576,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
   /// \@implementation may have private ivars.
   SourceLocation IvarLBraceLoc;
   SourceLocation IvarRBraceLoc;
-  
+
   /// Support for ivar initialization.
   /// The arguments used to initialize the ivars
   LazyCXXCtorInitializersPtr IvarInitializers;
@@ -2594,7 +2594,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
                          ObjCInterfaceDecl *superDecl,
                          SourceLocation nameLoc, SourceLocation atStartLoc,
                          SourceLocation superLoc = SourceLocation(),
-                         SourceLocation IvarLBraceLoc=SourceLocation(), 
+                         SourceLocation IvarLBraceLoc=SourceLocation(),
                          SourceLocation IvarRBraceLoc=SourceLocation())
       : ObjCImplDecl(ObjCImplementation, DC, classInterface,
                      classInterface ? classInterface->getIdentifier()
@@ -2616,7 +2616,7 @@ public:
                                         SourceLocation nameLoc,
                                         SourceLocation atStartLoc,
                                      SourceLocation superLoc = SourceLocation(),
-                                        SourceLocation IvarLBraceLoc=SourceLocation(), 
+                                        SourceLocation IvarLBraceLoc=SourceLocation(),
                                         SourceLocation IvarRBraceLoc=SourceLocation());
 
   static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2700,7 +2700,7 @@ public:
   std::string getNameAsString() const {
     return getName();
   }
-    
+
   /// Produce a name to be used for class's metadata. It comes either via
   /// class's objc_runtime_name attribute or class name.
   StringRef getObjCRuntimeNameAsString() const;
@@ -2715,7 +2715,7 @@ public:
   SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
   void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
   SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
-  
+
   using ivar_iterator = specific_decl_iterator;
   using ivar_range = llvm::iterator_range>;
 
@@ -2760,9 +2760,9 @@ public:
                                          SourceLocation L, IdentifierInfo *Id,
                                          ObjCInterfaceDecl* aliasedClass);
 
-  static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, 
+  static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
                                                      unsigned ID);
-  
+
   const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
   ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
   void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index a2f00ec9ff..e0ea7cb8b1 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -734,8 +734,8 @@ public:
 };
 
 /// Declaration of a redeclarable template.
-class RedeclarableTemplateDecl : public TemplateDecl, 
-                                 public Redeclarable 
+class RedeclarableTemplateDecl : public TemplateDecl,
+                                 public Redeclarable
 {
   using redeclarable_base = Redeclarable;
 
@@ -823,7 +823,7 @@ protected:
   /// Pointer to the common data shared by all declarations of this
   /// template.
   mutable CommonBase *Common = nullptr;
-  
+
   /// Retrieves the "common" pointer shared by all (re-)declarations of
   /// the same template. Calling this routine may implicitly allocate memory
   /// for the common pointer.
@@ -888,10 +888,10 @@ public:
   }
 
   /// Retrieve the member template from which this template was
-  /// instantiated, or nullptr if this template was not instantiated from a 
+  /// instantiated, or nullptr if this template was not instantiated from a
   /// member template.
   ///
-  /// A template is instantiated from a member template when the member 
+  /// A template is instantiated from a member template when the member
   /// template itself is part of a class template (or member thereof). For
   /// example, given
   ///
@@ -1178,7 +1178,7 @@ public:
                                       unsigned D, unsigned P,
                                       IdentifierInfo *Id, bool Typename,
                                       bool ParameterPack);
-  static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, 
+  static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
                                                   unsigned ID);
 
   /// Whether this template type parameter was declared with
@@ -1312,12 +1312,12 @@ public:
          QualType T, TypeSourceInfo *TInfo, ArrayRef ExpandedTypes,
          ArrayRef ExpandedTInfos);
 
-  static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, 
+  static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
                                                      unsigned ID);
-  static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, 
+  static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
                                                      unsigned ID,
                                                      unsigned NumExpandedTypes);
-    
+
   using TemplateParmPosition::getDepth;
   using TemplateParmPosition::setDepth;
   using TemplateParmPosition::getPosition;
@@ -1495,7 +1495,7 @@ public:
   static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
                                                       unsigned ID,
                                                       unsigned NumExpansions);
-  
+
   using TemplateParmPosition::getDepth;
   using TemplateParmPosition::setDepth;
   using TemplateParmPosition::getPosition;
@@ -2442,7 +2442,7 @@ public:
 
   static ClassScopeFunctionSpecializationDecl *
   CreateDeserialized(ASTContext &Context, unsigned ID);
-  
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
 
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 9d3dad6bbd..c9adcbbcde 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -211,14 +211,14 @@ public:
   /// getNameKind - Determine what kind of name this is.
   NameKind getNameKind() const;
 
-  /// Determines whether the name itself is dependent, e.g., because it 
+  /// Determines whether the name itself is dependent, e.g., because it
   /// involves a C++ type that is itself dependent.
   ///
   /// Note that this does not capture all of the notions of "dependent name",
-  /// because an identifier can be a dependent name if it is used as the 
+  /// because an identifier can be a dependent name if it is used as the
   /// callee in a call expression with dependent arguments.
   bool isDependentName() const;
-  
+
   /// getNameAsString - Retrieve the human-readable string for this name.
   std::string getAsString() const;
 
@@ -543,7 +543,7 @@ public:
 
   /// Determine whether this name involves a template parameter.
   bool isInstantiationDependent() const;
-  
+
   /// Determine whether this name contains an unexpanded
   /// parameter pack.
   bool containsUnexpandedParameterPack() const;
diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h
index a514326c6c..c21ef7907b 100644
--- a/include/clang/AST/DependentDiagnostic.h
+++ b/include/clang/AST/DependentDiagnostic.h
@@ -101,9 +101,9 @@ private:
   friend class DependentStoredDeclsMap;
 
   DependentDiagnostic(const PartialDiagnostic &PDiag,
-                      PartialDiagnostic::Storage *Storage) 
+                      PartialDiagnostic::Storage *Storage)
     : Diag(PDiag, Storage) {}
-  
+
   static DependentDiagnostic *Create(ASTContext &Context,
                                      DeclContext *Parent,
                                      const PartialDiagnostic &PDiag);
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index e00986dbe9..1aec5ae842 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -21,9 +21,9 @@
 #include "clang/AST/StmtVisitor.h"
 
 namespace clang {
-  
+
 class ASTContext;
-  
+
 /// Given a potentially-evaluated expression, this visitor visits all
 /// of its potentially-evaluated subexpressions, recursively.
 template